2013-04-23 40 views
6

Android appがlogcatシェルプロセスを生成し、処理のためにその結果を読み取ります。 しかし、アプリケーションの停止時(開発中の再コンパイル後に再起動した場合など)には、logcatプロセスは引き続き実行されます。ここでは、この動作の例です:Android:親プロセス(app)が終了した後、子プロセス(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()メソッドにこれを追加します。子プロセスは1の親IDで実行され続けます。

How to kill logcat process initiated by Android application?では、ProcessBuilderを使用することが推奨されていましたが、それは解決策ではなくプロセスも実行されます。

Stop child process when parent process stopsでは、シャットダウンフックを使用するためにサグステッドが使用されました。これは上記のように動作しません。

ありがとうございます!

+0

p.destroy()の後にp.waitFor()を呼び出してみましたか?前者の呼び出しは、子プロセスが終了するのを待って戻りステータスを取得してから、次のプロセスを破棄します。 – Vikdor

+0

@Vikdorありがとうございますが、これはうまくいきません。実際、シャットダウンフックでロギングコールを追加すると、アプリケーション(force-)が停止したときにコールされないことが明らかです。 – hez

+0

'new Thread()'の 'processes'のコピーが空であると思います。 'for'ループまたはループの外側からログを記録しましたか?スレッドがコピーをキャッシュしないようにプロセスを揮発性としてマークして確認できますか? – Vikdor

答えて

1

あなたはとなります。は、あなたの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); 

これによってのみ、独自のlogcatプロセスを殺し、あなたのプロセスはrootとして実行しないことを前提としています。シャットダウン機能では、まず他のプロセス(logcat)を終了し、p.destroy();を実行してこのキラースクリプトを停止する必要があります。

上記のスクリプトは、killallの使用を削除することで改善できます。代わりに、Reflection(this answerhttp://www.golesny.de/p/code/javagetpidを指している)を使用してlogcatプロセスのプロセスIDを取得し、killに渡します。

+0

華麗で、あなたはとてもスマートです。ありがとう、億人! – Krypton

関連する問題