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 + * + * + * + * @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 + */ + 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 + * + * + * @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; + } + } +}