diff --git a/app/build.gradle b/app/build.gradle
index 0ea0f4dba..943970949 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -128,7 +128,6 @@ dependencies {
implementation 'org.nanohttpd:nanohttpd:2.3.1'
implementation('org.simpleframework:simple-xml:2.7.1') { exclude group: 'stax', module: 'stax-api' exclude group: 'xpp3', module: 'xpp3' }
implementation(ext: 'aar', name: 'dlna-core', group: 'fongmi', version: 'release')
- implementation(ext: 'aar', name: 'go-proxy-video', group: 'fongmi', version: 'release')
leanbackImplementation(ext: 'aar', name: 'dlna-dmr', group: 'fongmi', version: 'release')
leanbackImplementation 'androidx.leanback:leanback:1.2.0-alpha04'
leanbackImplementation 'me.jessyan:autosize:1.2.1'
diff --git a/app/libs/go-proxy-video.aar b/app/src/main/assets/go_proxy_video
old mode 100644
new mode 100755
similarity index 50%
rename from app/libs/go-proxy-video.aar
rename to app/src/main/assets/go_proxy_video
index 6c128eebc..e050ad7e8
Binary files a/app/libs/go-proxy-video.aar and b/app/src/main/assets/go_proxy_video differ
diff --git a/app/src/main/java/com/fongmi/android/tv/server/Go.java b/app/src/main/java/com/fongmi/android/tv/server/Go.java
new file mode 100644
index 000000000..a3c1f8752
--- /dev/null
+++ b/app/src/main/java/com/fongmi/android/tv/server/Go.java
@@ -0,0 +1,45 @@
+package com.fongmi.android.tv.server;
+
+import com.fongmi.android.tv.App;
+import com.fongmi.android.tv.utils.ShellUtil;
+import com.github.catvod.Init;
+import com.github.catvod.utils.Path;
+
+import java.io.File;
+
+public class Go {
+
+ public static void prepare() {
+ App.execute(() -> {
+ try {
+ File file = new File(Init.context().getFilesDir().getAbsolutePath() + "/go_proxy_video");
+ if (file.exists()) return;
+ file.createNewFile();
+ Path.copy(Init.context().getAssets().open("go_proxy_video"), file);
+ file.setExecutable(true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ public void start() {
+ new Thread(() -> {
+ try {
+ File file = new File(Init.context().getFilesDir().getAbsolutePath() + "/go_proxy_video");
+ if (!file.exists()) return;
+ file.setExecutable(true);
+ ShellUtil.execCommand("nohup " + file.getAbsolutePath(), false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }).start();
+ }
+
+ public void stop() {
+ new Thread(() -> {
+ ShellUtil.execCommand(new String[]{"killall -9 go_proxy_video"}, false);
+ }).start();
+ }
+
+}
diff --git a/app/src/main/java/com/fongmi/android/tv/server/Server.java b/app/src/main/java/com/fongmi/android/tv/server/Server.java
index 2a8dd7610..821bab7b8 100644
--- a/app/src/main/java/com/fongmi/android/tv/server/Server.java
+++ b/app/src/main/java/com/fongmi/android/tv/server/Server.java
@@ -3,13 +3,10 @@ package com.fongmi.android.tv.server;
import com.github.catvod.Proxy;
import com.github.catvod.utils.Util;
-import go_proxy_video.Go_proxy_video;
-
public class Server {
private Nano nano;
private int port;
-
- private Thread goThread;
+ private Go go;
private static class Loader {
static volatile Server INSTANCE = new Server();
@@ -40,9 +37,12 @@ public class Server {
}
public void go() {
- if (goThread != null) goThread.interrupt();
- goThread = new Thread(Go_proxy_video::start);
- goThread.start();
+ if (go != null) {
+ go.start();
+ return;
+ }
+ go = new Go();
+ go.start();
}
public void start() {
@@ -59,6 +59,7 @@ public class Server {
nano = null;
}
} while (port < 9999);
+ Go.prepare();
}
public void stop() {
@@ -66,9 +67,9 @@ public class Server {
nano.stop();
nano = null;
}
- if (goThread != null) {
- goThread.interrupt();
- goThread = null;
+ if (go != null) {
+ go.stop();
+ go = null;
}
}
}
diff --git a/app/src/main/java/com/fongmi/android/tv/utils/ShellUtil.java b/app/src/main/java/com/fongmi/android/tv/utils/ShellUtil.java
new file mode 100644
index 000000000..2d2495401
--- /dev/null
+++ b/app/src/main/java/com/fongmi/android/tv/utils/ShellUtil.java
@@ -0,0 +1,222 @@
+package com.fongmi.android.tv.utils;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.List;
+
+/**
+ * ShellUtil
+ *
+ * Check root
+ * - {@link ShellUtil#checkRootPermission()}
+ *
+ *
+ * Execte command
+ * - {@link ShellUtil#execCommand(String, boolean)}
+ * - {@link ShellUtil#execCommand(String, boolean, boolean)}
+ * - {@link ShellUtil#execCommand(List, boolean)}
+ * - {@link ShellUtil#execCommand(List, boolean, boolean)}
+ * - {@link ShellUtil#execCommand(String[], boolean)}
+ * - {@link ShellUtil#execCommand(String[], boolean, boolean)}
+ *
+ *
+ * @author Trinea 2013-5-16
+ */
+public class ShellUtil {
+
+ public static final String COMMAND_SU = "su";
+ public static final String COMMAND_SH = "sh";
+ public static final String COMMAND_EXIT = "exit\n";
+ public static final String COMMAND_LINE_END = "\n";
+
+ private ShellUtil() {
+ throw new AssertionError();
+ }
+
+ /**
+ * check whether has root permission
+ *
+ * @return
+ */
+ public static boolean checkRootPermission() {
+ return execCommand("echo root", true, false).result == 0;
+ }
+
+ /**
+ * execute shell command, default return result msg
+ *
+ * @param command command
+ * @param isRoot whether need to run with root
+ * @return
+ * @see ShellUtil#execCommand(String[], boolean, boolean)
+ */
+ public static CommandResult execCommand(String command, boolean isRoot) {
+ return execCommand(new String[] {command}, isRoot, true);
+ }
+
+ /**
+ * execute shell commands, default return result msg
+ *
+ * @param commands command list
+ * @param isRoot whether need to run with root
+ * @return
+ * @see ShellUtil#execCommand(String[], boolean, boolean)
+ */
+ public static CommandResult execCommand(List commands, boolean isRoot) {
+ return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, true);
+ }
+
+ /**
+ * execute shell commands, default return result msg
+ *
+ * @param commands command array
+ * @param isRoot whether need to run with root
+ * @return
+ * @see ShellUtil#execCommand(String[], boolean, boolean)
+ */
+ public static CommandResult execCommand(String[] commands, boolean isRoot) {
+ return execCommand(commands, isRoot, true);
+ }
+
+ /**
+ * execute shell command
+ *
+ * @param command command
+ * @param isRoot whether need to run with root
+ * @param isNeedResultMsg whether need result msg
+ * @return
+ * @see ShellUtil#execCommand(String[], boolean, boolean)
+ */
+ public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) {
+ return execCommand(new String[] {command}, isRoot, isNeedResultMsg);
+ }
+
+ /**
+ * execute shell commands
+ *
+ * @param commands command list
+ * @param isRoot whether need to run with root
+ * @param isNeedResultMsg whether need result msg
+ * @return
+ * @see ShellUtil#execCommand(String[], boolean, boolean)
+ */
+ public static CommandResult execCommand(List commands, boolean isRoot, boolean isNeedResultMsg) {
+ return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, isNeedResultMsg);
+ }
+
+ /**
+ * execute shell commands
+ *
+ * @param commands command array
+ * @param isRoot whether need to run with root
+ * @param isNeedResultMsg whether need result msg
+ * @return
+ * - if isNeedResultMsg is false, {@link CommandResult#successMsg} is null and
+ * {@link CommandResult#errorMsg} is null.
+ * - if {@link CommandResult#result} is -1, there maybe some excepiton.
+ *
+ */
+ public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) {
+ int result = -1;
+ if (commands == null || commands.length == 0) {
+ return new CommandResult(result, null, null);
+ }
+
+ Process process = null;
+ BufferedReader successResult = null;
+ BufferedReader errorResult = null;
+ StringBuilder successMsg = null;
+ StringBuilder errorMsg = null;
+
+ DataOutputStream os = null;
+ try {
+ process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
+ os = new DataOutputStream(process.getOutputStream());
+ for (String command : commands) {
+ if (command == null) {
+ continue;
+ }
+
+ // donnot use os.writeBytes(commmand), avoid chinese charset error
+ os.write(command.getBytes());
+ os.writeBytes(COMMAND_LINE_END);
+ os.flush();
+ }
+ os.writeBytes(COMMAND_EXIT);
+ os.flush();
+
+ result = process.waitFor();
+ // get command result
+ if (isNeedResultMsg) {
+ successMsg = new StringBuilder();
+ errorMsg = new StringBuilder();
+ successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+ String s;
+ while ((s = successResult.readLine()) != null) {
+ successMsg.append(s);
+ }
+ while ((s = errorResult.readLine()) != null) {
+ errorMsg.append(s);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (os != null) {
+ os.close();
+ }
+ if (successResult != null) {
+ successResult.close();
+ }
+ if (errorResult != null) {
+ errorResult.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ if (process != null) {
+ process.destroy();
+ }
+ }
+ return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null
+ : errorMsg.toString());
+ }
+
+ /**
+ * result of command
+ *
+ * - {@link CommandResult#result} means result of command, 0 means normal, else means error, same to excute in
+ * linux shell
+ * - {@link CommandResult#successMsg} means success message of command result
+ * - {@link CommandResult#errorMsg} means error message of command result
+ *
+ *
+ * @author Trinea 2013-5-16
+ */
+ public static class CommandResult {
+
+ /** result of command **/
+ public int result;
+ /** success message of command result **/
+ public String successMsg;
+ /** error message of command result **/
+ public String errorMsg;
+
+ public CommandResult(int result) {
+ this.result = result;
+ }
+
+ public CommandResult(int result, String successMsg, String errorMsg) {
+ this.result = result;
+ this.successMsg = successMsg;
+ this.errorMsg = errorMsg;
+ }
+ }
+}