39

私のAndroidアプリケーションでは、非常に奇妙なクラッシュが発生します。UIのボタン(画像)を押すと、アプリケーション全体がフリーズし、数秒後に恐ろしい強制終了ダイアログが表示されます。

ログに出力される内容は次のとおりです。


WARN/WindowManager(88): Key dispatching timed out sending to package name/Activity
WARN/WindowManager(88): Dispatch state: {{KeyEvent{action=1 code=5 repeat=0 meta=0 scancode=231 mFlags=8} to Window{432bafa0 com.android.launcher/com.android.launcher.Launcher paused=false} @ 1281611789339 lw=Window{432bafa0 com.android.launcher/com.android.launcher.Launcher paused=false} lb=android.os.BinderProxy@431ee8e8 fin=false gfw=true ed=true tts=0 wf=false fp=false mcf=Window{4335fc58 package name/Activity paused=false}}}
WARN/WindowManager(88): Current state:  {{null to Window{4335fc58 package name/Activity paused=false} @ 1281611821193 lw=Window{4335fc58 package name/Activity paused=false} lb=android.os.BinderProxy@434c9bd0 fin=false gfw=true ed=true tts=0 wf=false fp=false mcf=Window{4335fc58 package name/Activity paused=false}}}
INFO/ActivityManager(88): ANR in process: package name (last in package name)
INFO/ActivityManager(88): Annotation: keyDispatchingTimedOut
INFO/ActivityManager(88): CPU usage:
INFO/ActivityManager(88): Load: 5.18 / 5.1 / 4.75
INFO/ActivityManager(88): CPU usage from 7373ms to 1195ms ago:
INFO/ActivityManager(88):   package name: 6% = 1% user + 5% kernel / faults: 7 minor
INFO/ActivityManager(88):   system_server: 5% = 4% user + 1% kernel / faults: 27 minor
INFO/ActivityManager(88):   tiwlan_wifi_wq: 3% = 0% user + 3% kernel
INFO/ActivityManager(88):   mediaserver: 0% = 0% user + 0% kernel
INFO/ActivityManager(88):   logcat: 0% = 0% user + 0% kernel
INFO/ActivityManager(88): TOTAL: 12% = 5% user + 6% kernel + 0% softirq
INFO/ActivityManager(88): Removing old ANR trace file from /data/anr/traces.txt
INFO/Process(88): Sending signal. PID: 1812 SIG: 3
INFO/dalvikvm(1812): threadid=7: reacting to signal 3
INFO/dalvikvm(1812): Wrote stack trace to '/data/anr/traces.txt'

これはボタン(画像)のコードです:


findViewById(R.id.endcallimage).setOnClickListener(new OnClickListener() {
                    public void onClick(View v) {
                        mNotificationManager.cancel(2);

                        Log.d("Handler", "Endcallimage pressed");

                        if(callConnected)
                        elapsedTimeBeforePause = SystemClock.elapsedRealtime() - stopWatch.getBase();

                        try {
                            serviceBinder.endCall(lineId);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        } 
                            dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.FLAG_SOFT_KEYBOARD));
                            dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
                    }
            });     

次のことをコメントすると、ボタン(画像)を押してもクラッシュは発生しません。


try {
      serviceBinder.endCall(lineId);
    } catch (RemoteException e) {
      e.printStackTrace();
    } 

上記のコードは、アプリのいくつかのレベルを介してネイティブレイヤー(NDK)に呼び出されますが、いくつかのオブジェクトを通過する呼び出しは、強制終了につながる可能性がありますか?他のいくつかのボタンが問題なく同じことをするので、それはありそうにないようです。

ネイティブレイヤーはどうですか?NDKで作成したコードが問題の原因になっている可能性がありますか?

問題の原因について他に何か考えはありますか?

4

4 に答える 4

50

onClickの実装はできるだけ速くする必要があります。一般に、高価な操作はバックグラウンドスレッドにオフロードする必要があります。

onClickで、次を試してください。

Thread t = new Thread(){
    public void run(){
        your_stuff();
    }
};
t.start();

ただの代わりに

your_stuff()
于 2011-01-06T01:46:39.957 に答える
5

メインスレッド(別名UIスレッド)を数秒間ブロックすると、このエラーが発生する可能性があります。一般に、高価な操作はバックグラウンドスレッドにオフロードする必要があります。このような場合、 AsyncTaskは非常に役立ちます。

あなたの場合、あなたは以下を行うことができます:

new AsyncTask<Void, Void, Void>() {
    @Override
    protected Void doInBackground(Void... params) {
        try {
            serviceBinder.endCall(lineId);
        } catch (RemoteException e) {
            e.printStackTrace();
        } 
    }
}.execute();
于 2012-10-04T00:38:12.413 に答える
2

別のスレッドで長い操作を実行するか、AsyncTaskを使用してANRを取り除きます。

ANR(Activity Not Responding)long operation takes place in the "main"は、スレッドが発生したときに発生します。これはイベントループスレッドであり、ビジー状態の場合、Androidはアプリケーションでそれ以上のGUIイベントを処理できないため、をスローしますANR dialog

あなたの活動はAndroidOSに「ねえ、私はまだ生きている」と言うのに長い時間がかかりました!(これはUIスレッドが行うことです)。

http://developer.android.com/guide/practices/design/responseness.html

基本的に、UIスレッドに複雑なタスクを実行させると、タスクの実行が忙しくなり、OSにまだ「生きている」ことを伝えることができません。

http://android-developers.blogspot.co.uk/2009/05/painless-threading.html

XML解析コードを別のスレッドに移動してから、コールバックを使用してUIスレッドに終了を通知し、結果を処理する必要があります。

http://developer.android.com/resources/articles/timed-ui-updates.html

ANRが発生する場所の検出は、それが永続的なブロック(たとえば、いくつかのロックを取得するデッドロック)の場合は簡単ですが、一時的な遅延の場合はより困難です。まず、コードを調べて、脆弱な場所と長時間実行される操作を探します。例としては、イベントスレッド内からのソケット、ロック、スレッドスリープ、およびその他のブロック操作の使用が含まれる場合があります。これらがすべて別々のスレッドで発生することを確認する必要があります。問題がない場合は、DDMSを使用してスレッドビューを有効にします。これにより、アプリケーション内のすべてのスレッドが、トレースと同様に表示されます。ANRを再現し、同時にメインスレッドを更新します。これにより、ANRの時点で何が起こっているかが正確に示されます。

Logcatが有用なものを何も出力しない場合は、/ data / anr/traces.txtからtraces.txtをプルしてみてください

adb pull /data/anr/traces.txt .

ANR例外が発生した場所に関する詳細情報が得られる可能性があるため

また、このリンクはAsyncTaskとスレッドの作成にも役立つ場合があります

于 2014-12-04T11:20:11.450 に答える
1

リソースを大量に消費するタスクを実行している場合は、それが発生する可能性があります。アクティビティを再開している間。1. onPauseでの集中的な作業をすべて停止してから、onResumeで再開してみてください。2.アクティビティ描画オーバーレイにマップを表示している場合は、スリープ中にオーバーレイの更新を停止します。そして、onResumeで再起動します。

于 2013-10-15T11:24:44.913 に答える