1

アプリの 1 つに小さな問題があります。を使用しBroadCastReceiverて通話が終了したことを検出し、いくつかの簡単なハウスキーピング タスクを実行します。ユーザーが一部のデータを表示できるようにし、通話ログが更新されたことを確認するために、これらは数秒間遅延する必要があります。私は現在handler.postDelayed()、この目的のために使用しています:

public class CallEndReceiver extends BroadcastReceiver {

@Override
public void onReceive(final Context context, final Intent intent) {
    if (DebugFlags.LOG_OUTGOING)
        Log.v("CallState changed "
                + intent.getStringExtra(TelephonyManager.EXTRA_STATE));
    if (intent.getStringExtra(TelephonyManager.EXTRA_STATE)
            .equalsIgnoreCase(TelephonyManager.EXTRA_STATE_IDLE)) {
        SharedPreferences prefs = Utils.getPreferences(context);
        if (prefs.getBoolean("auto_cancel_notification", true)) {
            if (DebugFlags.LOG_OUTGOING)
                Log.v("Posting Handler to remove Notification ");
            final Handler mHandler = new Handler();
             final Runnable mCancelNotification = new Runnable() {
                   public void run() {
                        NotificationManager notificationMgr = (NotificationManager) context
                        .getSystemService(Service.NOTIFICATION_SERVICE);
                notificationMgr.cancel(12443);
                if (DebugFlags.LOG_OUTGOING)
                    Log.v("Removing Notification ");
                   }
                };
                mHandler.postDelayed(mCancelNotification, 4000);


        }
        final Handler updateHandler = new Handler();
         final Runnable mUpdate = new Runnable() {
               public void run() {
        if (DebugFlags.LOG_OUTGOING)
            Log.v("Starting updateService");
        Intent newBackgroundService = new Intent(context,
                CallLogUpdateService.class);
        context.startService(newBackgroundService);
               }
               };
               updateHandler.postDelayed(mUpdate, 5000);

        if (DebugFlags.TRACE_OUTGOING)
            Debug.stopMethodTracing();
        try
        {
        // Stopping old Service
        Intent backgroundService = new Intent(context,
                NetworkCheckService.class);
        context.stopService(backgroundService);
        context.unregisterReceiver(this);
        }
        catch(Exception e)
        {
            Log.e("Fehler beim Entfernen des Receivers", e);
        }
    }

}

}

ここで、このセットアップが約 90% の確率で機能するという問題があります。約 10% のケースで、通知は削除されません。メッセージキューがメッセージ/ランナブルを処理する前に、スレッドが死んでいると思われます。

私は現在、代替案を考えていますpostDelayed()が、私の選択肢の 1 つは明らかに AlarmManager です。ただし、パフォーマンスへの影響 (または使用するリソース) についてはわかりません。

おそらく、スレッドが終了する前にすべてのメッセージが処理されたことを確認するより良い方法や、これら 2 ビットのコードの実行を遅らせる別の方法があるでしょう。

ありがとうございました

4

4 に答える 4

4

私は現在、この目的のために handler.postDelayed() を使用しています:

BroadcastReceiverがマニフェストのフィルターによってトリガーされていると仮定すると、それは良い考えではありません。

ここで、このセットアップが約 90% の確率で機能するという問題があります。約 10% のケースで、通知は削除されません。メッセージキューがメッセージ/ランナブルを処理する前に、スレッドが死んでいると思われます。

より正確には、プロセスは終了し、すべてが取り除かれます。

私は現在、postDelayed() の代替案を考えています。私の選択肢の 1 つは、明らかに AlarmManager です。ただし、パフォーマンスへの影響 (または使用するリソース) についてはわかりません。

それは悪いことではありません。もう 1 つの可能性は、遅延した作業をIntentService-- への呼び出しによってトリガーされてstartService()-- バックグラウンド スレッドで数秒間スリープさせることです。

于 2011-03-31T19:53:56.103 に答える
1

最初の答えに加えて、APIドキュメントがonReceiveメソッドについて何を言っているかを検討することをお勧めします。

[...]関数は通常、そのプロセスのメインスレッド内で呼び出されるため、長時間実行される操作を実行しないでください[...]

したがって、一般的には、数時間以内に待機するものを開始することはお勧めできませんonReceive(ただし、あなたの場合は10秒の制限未満です)。

BroadcastReceiverでも同様の問題が発生しました。onReceive実行していたものとまったく同じように呼び出されたにもかかわらず、結果を処理できませんでした。BroadastReceiver結果の処理が完了する前に、が実行されていたスレッドが強制終了されたようです。私の解決策は、すべての処理を実行するために新しいスレッドを開始することでした。

于 2012-03-26T10:12:23.973 に答える