2013-06-21 3 views
18

मैं पृष्ठभूमि सेवा पर काम कर रहा हूं कि सर्वर के लिए कुछ समय के लिए मतदान। मुद्दा यह है कि: मेरे पास एक इरादा सेवा है (जिसे अधिसूचना सेवा कहा जाता है) जो एक और सेवा कहता है, लेकिन इस अनुरोध की प्रतिक्रिया वापस नहीं आती है। और 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); 

} 
} 

के लिए कोड है! चीयर्स!

संपादित करें: मुझे लगता है कि समस्या यह है कि लॉग "प्रतिक्रिया प्राप्त हुई" यह प्रकट नहीं होती है।

उत्तर

24

IntentService एस onHandleIntent विधि को कॉल करते समय एक नया धागा बनाते हैं, और उसके बाद उस 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 परिभाषित हैंडलर वस्तु पोस्ट - क्यों एक गतिविधि है कि हैंडलर ऑब्जेक्ट टाई नहीं (प्रक्रिया) और यदि उसके बाद कोड टूट जाता है देखते हैं? अनिवार्य रूप से, एक नए हैंडलर ऑब्जेक्ट के बजाय एक हैंडलर वैरिएबल में गुज़रना।

इस तरह, सभी परिणाम रिसीवर एक निजी हैंडलर के बजाय एक ही हैंडलर ऑब्जेक्ट का उपयोग करेंगे।

3

मैं वापस जवाब नहीं दे सकता क्योंकि मैं नया हूं, लेकिन मूल रूप से 'jpalm' का उल्लेख सबसे सटीक उत्तर है।

असल में ऐसी चीज है जिसे मैं सेवा के साथ खेलना समझता हूं: वे तुरंत खत्म हो जाएंगे। मतलब यह है कि यदि आप ढांचे में एक काम जमा करते हैं (जैसे गतिविधि शुरू करना); फ्रेमवर्क तुरंत आपको वापस जाने के लिए वापस जा सकता है 'startService (intentaux)' ठीक है या जो भी हो (मैं एक विशेषज्ञ नहीं हूं, मैं भी इस पर नया हूं: पी), क्योंकि यह पाया गया कि आपका धागा पहले से ही मर चुका है! !!।

जब आप अपनी गतिविधि शुरू करते हैं, यदि आप जानबूझकर अपने धागे को तब तक जीवित करते हैं जब तक आप प्रतिक्रिया प्राप्त न करें, यह त्रुटियां नहीं होती हैं।

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 के प्रलेखन बहुत अच्छी है लेकिन बहुत संक्षिप्त (अल्ट्रा ज़िप), जिसका अर्थ है कि आप, पढ़ सकते हैं और शब्द से शब्द पढ़ने के लिए होगा है, और फिर आप एक शब्दकोश में देखो जब निराश होने के बाद ... आप कहते हैं: यह हमेशा यहाँ था!: हे

यह एक बाइबिल की तरह है, लेकिन डेवलपर्स के लिए :) और किसी भी तरह हम Android भविष्यद्वक्ताओं होते जा रहे हैं: पी

0

मुख्य कारण आप एक कतार जो पाश के लिए looper नहीं है पर एक संदेश दिया है है। हालांकि, आप "getMainLooper()" को "हैंडलर" बनाने के लिए एक पैरा के रूप में पास करने के लिए उपयोग कर सकते हैं।

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

और आप इस तरह AutoHandler का एक उदाहरण बना सकते हैं:

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

प्रत्येक Handler एक Looper है, और एक Looper एक HandlerThread है। सामान्य समस्या तब होती है जब Handler थ्रेड से जुड़ा होता है जो चलना बंद कर देता है। अगर कोई Handler का उपयोग करने का प्रयास करता है, तो यह संदेश "मृत थ्रेड पर हैंडलर को संदेश भेजना" संदेश में विफल हो जाएगा।

यदि आप new Handler() करते हैं तो यह वर्तमान धागे से जुड़ा हुआ है (बल्कि, यह Looper संबंधित डब्ल्यू/वर्तमान धागे से जुड़ा हुआ है)। यदि आप इसे थ्रेड पर करते हैं जो दूर जाने जा रहा है (जैसे IntentService के लिए वर्कर थ्रेड) तो आपको समस्या होगी। पाठ्यक्रम की समस्या इस मूल कारण तक ही सीमित नहीं है, यह किसी भी तरीके से हो सकती है।

कोई आसान ठीक निर्माण करने के लिए है अपने Handler की तरह,

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

यह मुख्य looper, या मुख्य आवेदन धागा जो मर कभी नहीं होगा साथ Handler एकत्रित करती है। एक और अधिक जटिल ठीक, Handler के लिए एक समर्पित धागा बनाने के लिए

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

ध्यान दें कि आप स्पष्ट रूप से quit()HandlerThread करने की जरूरत है जब आप जुड़े Handler के साथ किया जाता है।

संबंधित मुद्दे