安卓:应用程序父进程结束后(app),子进程(logcat)仍在运行

8
我们的安卓应用程序生成了一个logcat shell进程,然后读取其结果进行处理。但是,当应用程序停止(例如在开发期间重新编译后重新启动)时,logcat进程将继续运行。以下是此行为的示例:
processes = new ArrayList<Process>();

try {
  processes.add(Runtime.getRuntime().exec("logcat -v time"));
  processes.add(Runtime.getRuntime().exec("logcat -v time"));
  processes.add(Runtime.getRuntime().exec("logcat -v time"));
  processes.add(Runtime.getRuntime().exec("logcat -v time"));
} catch (IOException e) {
  // oh no!
}

Runtime.getRuntime().addShutdownHook(new Thread() {
  public void run() {
    for (Process p : processes) {
      p.destroy();
    }
  };
});

将以下代码添加到测试应用程序的onCreate()方法中,启动它,然后使用设置管理器强制停止它。子进程将继续运行,现在具有父ID 1。

如何杀死由Android应用程序启动的logcat进程?中建议使用ProcessBuilder,但这不是一个解决方案,该进程也将继续运行。

当父进程停止时停止子进程中建议使用关闭挂钩 - 如上所示,这也不起作用。

谢谢!


你尝试过在p.destroy()之后调用p.waitFor()吗?前者会等待子进程终止并获取返回状态,然后再继续销毁下一个进程。 - Vikdor
@Vikdor 谢谢,但是不行。实际上,在关闭挂钩中添加一个日志调用会显示当应用程序(强制)停止时根本没有被调用。 - hez
我猜new Thread()中的processes副本是空的。你是从for循环内部还是外部记录日志的?你能将processes标记为易失性,这样线程就不会缓存副本,然后再检查一下吗? - Vikdor
我在for循环之前记录了日志,因此关闭钩子的run()方法从未被调用。 - hez
1个回答

2

你可以做的是生成另一个脚本,其唯一目的是监视你的Java程序。每当它停止运行时,也要杀死所有子进程。

一个脆弱的例子:

int pid = android.os.Process.myPid();
String script = "while [ -d /proc/" + pid + " ];do sleep 1;done; killall logcat";
Process p = Runtime.getRuntime().exec("/system/bin/sh", "-c", script);

假设您的进程不以root身份运行,因此仅会终止其自己的logcat进程。在您的关闭函数中,您应该先终止其他进程(logcat),然后运行p.destroy();来停止这个killer脚本。
通过使用反射(这个答案指向http://www.golesny.de/p/code/javagetpid)获取您的logcat进程的进程ID,并将它们传递给kill,可以改进上面的脚本,从而消除对killall的使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接