29

私は、一定期間サーバーに何かをポーリングするバックグラウンド サービスに取り組んでいます。ポイントは、別のサービスを呼び出す IntentService (NotificationsService と呼ばれる) がありますが、この要求の応答が返されないということです。そしてlogcatに表示されます:

06-19 05:12:00.151: W/MessageQueue(6436): Handler (android.os.Handler) {416659f0} sending message to a Handler on a dead thread
06-19 05:12:00.151: W/MessageQueue(6436): java.lang.RuntimeException: Handler (android.os.Handler) {416659f0} sending message to a Handler on a dead thread
06-19 05:12:00.151: W/MessageQueue(6436):   at android.os.MessageQueue.enqueueMessage(MessageQueue.java:196)
06-19 05:12:00.151: W/MessageQueue(6436):   at android.os.Handler.sendMessageAtTime(Handler.java:473)
06-19 05:12:00.151: W/MessageQueue(6436):   at android.os.Handler.sendMessageDelayed(Handler.java:446)
06-19 05:12:00.151: W/MessageQueue(6436):   at android.os.Handler.post(Handler.java:263)
06-19 05:12:00.151: W/MessageQueue(6436):   at android.os.ResultReceiver$MyResultReceiver.send(ResultReceiver.java:50)

ここで同様の問題を見ましたが、混乱しました(AsyncTaskを使用しておらず、CommonsWareコードwakefullIntentを探しましたが、理解できませんでした)。

ここに NotificationsService.java のコードがあります

public class NotificationsService extends IntentService {
private static  int TIME_INTERVAL_MILIS=90000;
private static final int REFRESH=10;
private  NotificationManager noteManager;
private static List<FlightStatusNote> flights= new ArrayList<FlightStatusNote>();



public NotificationsService(){
    super("NotificationsService");

}

@Override
public void onCreate(){
    Log.d("notificationsSservice","onCreate");
    super.onCreate();
    noteManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
}



@Override
protected void onHandleIntent(Intent intent) {
    Log.d("NotificationsService","Me llamaron");

    Log.d("NotificationsService", "intervalo:"+NotificationsService.TIME_INTERVAL_MILIS);
        Log.d("NotificationsService","Itero por cada vuelo registrado para notificar");
        for(FlightStatusNote f: flights){
            FlightStatus fly=f.getFlight();
            Log.d("NotificationsService","Vuelo id:"+fly.getAirlineId()+fly.getNumberFlight());
            Intent intentaux=new Intent(Intent.ACTION_SYNC,null,getBaseContext(),FlightStatusService.class);
            intentaux.putExtra("airlineFlight", fly.getAirlineId());
            intentaux.putExtra("numberFlight",fly.getNumberFlight() );
            intentaux.putExtra("receiver", new ResultReceiver(new Handler()) {

                @Override
                protected void onReceiveResult(int resultCode, Bundle resultData) {
                    super.onReceiveResult(resultCode, resultData);
                    Log.d("notificationsService","response received");
                    if (resultCode == FlightStatusService.STATUS_OK) {
                        List<FlightStatus> fly =  (List<FlightStatus>)resultData.getSerializable("return");
                        for(FlightStatus f: fly){
                            int indexNote=flights.indexOf(new FlightStatusNote(f,null));
                            FlightStatusNote fsNote=flights.get(indexNote);
                            List<String> changes=fsNote.hasChanged(f);
                            if(changes==null){
                                Log.d("notificationsService","changes is null");
                            }
                            else{
                                Log.d("notficationsService", "comething changed");
                                createNotification(f, changes);
                            }

                        }


                    }

                }

            });
            startService(intentaux);
    }

        AlarmManager alarmMgr = (AlarmManager) getBaseContext().getSystemService(Context.ALARM_SERVICE);
          PendingIntent pendingIntent =  PendingIntent.getBroadcast(getBaseContext(), 0, new Intent(getBaseContext(), DealAlarmReceiver.class), 0);
          alarmMgr.set(AlarmManager.RTC, System.currentTimeMillis()+NotificationsService.TIME_INTERVAL_MILIS, pendingIntent);

}
}

誰かが私を助けることができれば、私はそれを感謝します!乾杯!

編集:問題は、ログ「応答受信」が表示されないことだと思います。

4

5 に答える 5

28

IntentService■ メソッドを呼び出したときに新しいスレッドを作成し、onHandleIntentそのメソッドが戻るとすぐにそのスレッドを強制終了しonHandleIntentます。

リスナーを別の場所に作成する必要があります。リスナーIntentServiceは死んでいるため、リスナーを設定するのは安全ではありません。これらは主に、メイン スレッドの外部で短いタスクを実行するために使用されます。ここで同様の質問を参照してください。

編集: IntentServiceのドキュメントも参照してください。

于 2013-06-21T14:37:45.690 に答える
10

それぞれHandlerに がありLooper、は(通常は)Looperに関連付けられています。一般的な問題は、が実行を停止するスレッドに関連付けられる場合です。誰かが を使用しようとすると、「デッド スレッドのハンドラにメッセージを送信しています」というメッセージが表示されて失敗します。ThreadHandlerThreadHandlerHandler

そのまま実行new Handler()すると、現在のスレッドに関連付けられます(むしろ、現在のスレッドに関連付けられたスレッドにLooper関連付けられます)。停止するスレッド(のワーカースレッドなどIntentService)でこれを行うと、問題が発生します。もちろん、問題はこの根本原因に限定されず、さまざまな方法で発生する可能性があります。

簡単な修正は、Handler好きなように構築することです。

Handler h = new Handler(Looper.getMainLooper());

これはHandler、 をメイン ルーパー、または死ぬことのないメイン アプリケーション スレッドに関連付けます (コールバックなどには適していますが、明らかにブロッキング作業には適していません)。もう 1 つのより複雑な修正は、専用のスレッドを作成することですHandler

HandlerThread ht = new HandlerThread(getClass().getName());
ht.start();
Handler handler = new Handler(ht.getLooper());

関連付けられquit()た.HandlerThreadHandler

于 2016-12-27T21:43:02.333 に答える
5

新参者なのでお返しできませんが、基本的には「jpalm」さんの回答が一番正確です。

基本的に、ServiceIntent で遊んで理解したことがあります。それらは終了するとすぐに死んでしまいます。つまり、フレームワークで作業を送信した場合 (アクティビティの開始など); フレームワークはすぐにあなたに戻って、'startService(intentaux)' が OK などを返したことを伝えることができます (私は専門家ではありません。これも初めてです:P )。 !!.

アクティビティを開始するときに、応答を取得するまで意図的にスレッドを強制的にアクティブにすると、このエラーは発生しません。

http://developer.android.com/guide/components/services.htmlを参照してください。待機しないように例を変更すると、ASYNC メソッドを使用していないと思われる場合でも、Toast がこのような明確なメッセージを送信してクラッシュし始めます。

07-24 08:03:16.309: W/MessageQueue(1937): java.lang.RuntimeException: Handler (android.os.Handler) {b1016d80} sending message to a Handler on a dead thread
07-24 08:03:16.309: W/MessageQueue(1937):   at android.os.MessageQueue.enqueueMessage(MessageQueue.java:320)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.os.Handler.enqueueMessage(Handler.java:626)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.os.Handler.sendMessageAtTime(Handler.java:595)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.os.Handler.sendMessageDelayed(Handler.java:566)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.os.Handler.post(Handler.java:326)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.widget.Toast$TN.hide(Toast.java:370)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.app.ITransientNotification$Stub.onTransact(ITransientNotification.java:55)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.os.Binder.execTransact(Binder.java:404)
07-24 08:03:16.309: W/MessageQueue(1937):   at dalvik.system.NativeStart.run(Native Method)

android.developers のドキュメントはかなり良いですが、非常に簡潔 (ULTRA ZIP) であると言わざるを得ません。言う: それはいつもここにあった! :O

それは聖書のようなものですが、開発者にとっては:)そしてどういうわけか私たちはAndroidの預言者になりつつあります:P

于 2014-07-24T12:29:35.963 に答える
0

ここを見て

             intentaux.putExtra("receiver", new ResultReceiver(new Handler()) {

            @Override
            protected void onReceiveResult(int resultCode, Bundle resultData) {
                super.onReceiveResult(resultCode, resultData);
                Log.d("notificationsService","response received");
                if (resultCode == FlightStatusService.STATUS_OK) {
                    List<FlightStatus> fly =  (List<FlightStatus>)resultData.getSerializable("return");
                    for(FlightStatus f: fly){
                        int indexNote=flights.indexOf(new FlightStatusNote(f,null));
                        FlightStatusNote fsNote=flights.get(indexNote);
                        List<String> changes=fsNote.hasChanged(f);
                        if(changes==null){
                            Log.d("notificationsService","changes is null");
                        }
                        else{
                            Log.d("notficationsService", "comething changed");
                            createNotification(f, changes);
                        }

                    }


                }

            }

匿名で定義されたハンドラー オブジェクトを投稿します。そのハンドラー オブジェクトをアクティビティ (プロセス) に結び付けて、コードが壊れるかどうかを確認してみませんか? 基本的に、新しいハンドラー オブジェクトの代わりにハンドラー変数を渡します。

そうすれば、すべての ResultReceiver がプライベート オブジェクトではなく同じ Handler オブジェクトを使用します。

于 2013-06-21T14:37:30.030 に答える