web-dev-qa-db-ja.com

StrictModeポリシーに違反したものを見つける

アプリでStrictModeを有効にしましたが、予想どおりにクラッシュが発生します。コードのどこでこれらのポリシーに違反しているのかを知るにはどうすればよいですか?

これはスタックトレースです:

E/AndroidRuntime(19523): FATAL EXCEPTION: main
E/AndroidRuntime(19523): Android.os.StrictMode$StrictModeViolation: policy=95 violation=2
E/AndroidRuntime(19523):        at Android.os.StrictMode.executeDeathPenalty(StrictMode.Java:1326)
E/AndroidRuntime(19523):        at Android.os.StrictMode.access$1300(StrictMode.Java:111)
E/AndroidRuntime(19523):        at Android.os.StrictMode$AndroidBlockGuardPolicy.handleViolation(StrictMode.Java:1319)
E/AndroidRuntime(19523):        at Android.os.StrictMode$AndroidBlockGuardPolicy$1.run(StrictMode.Java:1206)
E/AndroidRuntime(19523):        at Android.os.Handler.handleCallback(Handler.Java:605)
E/AndroidRuntime(19523):        at Android.os.Handler.dispatchMessage(Handler.Java:92)
E/AndroidRuntime(19523):        at Android.os.Looper.loop(Looper.Java:137)
E/AndroidRuntime(19523):        at Android.app.ActivityThread.main(ActivityThread.Java:4424)
E/AndroidRuntime(19523):        at Java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(19523):        at Java.lang.reflect.Method.invoke(Method.Java:511)
E/AndroidRuntime(19523):        at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:787)
E/AndroidRuntime(19523):        at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:554)
E/AndroidRuntime(19523):        at dalvik.system.NativeStart.main(Native Method)

しかし、ご覧のとおり...あまり役に立ちません...誰が私のアプリを殺したのか知っています。理由を知る必要があります!

ありがとう。

12
copolii

StrictMode.ThreadPolicy.BuilderでpenaltyLog()を呼び出す必要があります。これにより、根本的な理由が表示され、アプリが停止します。

あなたがおそらく現在持っているものは次のとおりです。

_StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyDeath()
.build());
_

メインスレッドでネットワークを呼び出すと、理解しにくい次の例外が発生します。

_E/AndroidRuntime(8752): Android.os.StrictMode$StrictModeViolation: policy=71 violation=4
E/AndroidRuntime(8752):     at Android.os.StrictMode.executeDeathPenalty(StrictMode.Java:1311)
_

次に、ポリシーにpenaltyLog()を追加すると...

_StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.penaltyDeath()
.build());
_

次に、以下のようなはるかに役立つメッセージが表示されます。これはLogCat出力にあります。

_D/StrictMode(8810): StrictMode policy violation; ~duration=2956 ms: Android.os.StrictMode$StrictModeNetworkViolation: policy=87 violation=4
D/StrictMode(8810):     at Android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.Java:1090)
_

よく見ると、このスタックトレースが、StrictMode違反の原因となっているコードにつながることがわかります。

19
louielouie

StrictMode(Android.os.StrictMode)クラスを使用して、チェックおよびレポートできるさまざまなポリシーを有効にして適用できます。

これは、メインUIスレッドでディスク書き込みを実行しているときに発生するディスク書き込み違反の実行におけるStrictMode違反である可能性があります。これを解決するには、ディスク書き込みをメインスレッドから移動する必要があります。

この時点でコードを移動できない場合は、コードの一部のチェックを無効にすることができます。

問題のあるコードが実行される直前に特定のルール違反のチェックを停止するコードを明示的に追加し、問題のあるコードが完了した後にそのルールの検出を再度有効にします。

StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(old)
    .permitDiskWrites()
    .build());
doCorrectStuffThatWritesToDisk();
StrictMode.setThreadPolicy(old);

ここから取得したソースコード

1
Dimitri Dewaele

このようなスタックトレースが表示されるたびに、アクティビティライフサイクルイベントを常に調べます。 onCreate、onResume、onPauseメソッドで何が起こっているかを確認してください(ライフサイクルイベントは他にもありますが、これらは一般的なものです)。これらのメソッドにブレークポイントを設定し、この致命的なメッセージで終了するメソッドを確認します。次に、そこからそれを取ります。

を使用してこのエラーをキャッチしてみてください

protected void onResume() {
  super.onResume();
  try {
    codeThatCrashesBecauseOfStrictMode();
  } catch(Throwable tr) { Log.e(tr); }
}

これは、この問題をデバッグするためのかなり良い出発点になるはずです。

1
Jeremy Edwards