2013-06-21 2 views
18

일정 기간 동안 서버에 폴링하는 백그라운드 서비스로 작업하고 있습니다. 요점은 : 나는 다른 서비스를 호출하는 IntentService (NotificationsService)가 있지만이 요청의 응답은 반환되지 않습니다. 그리고 로그 캣에 나타납니다죽은 스레드의 처리기에 메시지 보내기

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); 

} 
} 

의 코드입니다! 건배!

편집 : 문제는 Log "응답을 받았습니다"가 나타나지 않는다고 생각합니다. 활동에 그 핸들러 객체를 묶지 이유 (공정) 다음 코드를 나누기 있는지 -

답변

24

IntentServiceonHandleIntent 메서드를 호출 할 때 새 스레드를 만든 다음 onHandleIntent 메서드가 반환되는 즉시 해당 스레드를 종료합니다.

청취자를 다른 곳에서 만들어야하는데, IntentService은 청취자가 사망하기 때문에 설정하기에 안전하지 않습니다. 주로 주 스레드 외부의 짧은 작업을 실행하는 데 사용됩니다. 비슷한 질문을보십시오 here.

편집 : IntentService에 대한 문서를 참조하십시오.

+3

나는 비슷한 질문을 이미 읽었지만 아직도 붙어 있습니다. 어디에서 청취자를 만들어야할까요? – Mitodina

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); 
         } 

        } 


       } 

      } 

는 당신이 annonimously 정의 핸들러 객체를 게시 이쪽을 봐? 기본적으로 새로운 핸들러 객체 대신 핸들러 변수를 전달합니다.

그런 식으로 모든 ResultReceiver는 개인용 핸들러 오브젝트 대신 동일한 Handler 오브젝트를 사용합니다.

3

나는 새롭기 때문에 나는 대답 할 수 없다. 그러나 기본적으로 언급 한 'jpalm'이 가장 정확한 답변이다.

기본적으로 ServiceIntent를 가지고 노는 것을 이해했습니다. 그들은 곧 죽을 것입니다. 활동을 시작하는 것과 같이 프레임 워크에서 작품을 제출하는 경우를 의미합니다. 프레임 워크는 즉시 당신에게 돌아가서 'startService (intentaux)'가 OK를 반환했는지 (나는 전문가가 아니며, 이것 역시 새롭다 : P), 스레드가 이미 죽었다는 것을 알았 기 때문에! !! !!

활동을 시작할 때 응답을 얻을 때까지 의도적으로 스레드를 강제로 실행하면이 오류가 발생하지 않습니다.

http://developer.android.com/guide/components/services.html을 참조하십시오. 당신이 ASYNC 방법을 사용하고 있지 않다고 생각할 때조차도, 기다리지 않도록 예제를 수정하십시오.

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

는 성경 유사하지만, 개발자를위한 :) 어떻게 든 우리는 안드로이드 선지자되고있다 : P

0

주된 이유는 루프 루퍼되지 않은 큐에 메시지를 넣어 가지고 있습니다. 그러나 "getMainLooper()"를 사용하여 생성 한 "처리기"에 매개 변수로 전달할 수 있습니다.

public AutoHandler(Context context, Looper looper) { 
    super(looper); 
    this.context = context; 
} 

당신은 다음과 같이 AutoHandler의 인스턴스를 만들 수 있습니다

autoHandler = new AutoHandler(this, getMainLooper()); 
4

HandlerLooper을 가지고 있으며, LooperHandlerThread 있습니다. 일반적인 문제는 Handler이 실행을 중지하는 스레드와 연결될 때입니다. 누군가가 Handler을 사용하려고 시도하면 "dead thread에서 핸들러로 메시지 보내기"메시지와 함께 실패합니다.

new Handler()하면 현재 스레드와 연결됩니다 (오히려 현재 스레드와 연관된 Looper과 연결됨). IntentService의 작업자 스레드와 같이 사라질 스레드에서이 작업을 수행하면 문제가 발생합니다. 문제는이 근본 원인에 국한되지 않고 여러 가지 방법으로 발생할 수 있습니다.

모든 쉽게 수정 구축하는 것입니다 Handler

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

이 메인 루퍼, 또는 죽지 않을 것이다 주요 응용 프로그램 스레드와 Handler를 연결, 같은. 또 다른 더 복잡한 수정은 Handler 당신이 관련 Handler 함께 할 때 당신이 명시 적으로 quit()HandlerThread 필요

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

참고 전용 스레드를 만드는 것입니다.

관련 문제