2015-08-27 11 views
7

Ich habe TrackingService-Komponente, um den Standort der Busse in meiner Stadt basierend auf Crowdsourcing zu verfolgen. Der TrackingService läuft im Hintergrund, dann werden die Daten an den Server übertragen. Ich habe eine Map-Aktivität, um den Standort der Busse anzuzeigen, den Benutzer, der in MainActivity (als Filter) ausgewählt wurde.java.lang.IllegalArgumentException: Empfänger nicht registriert

Der Hintergrund TrackingService wird in der MainActivity gestartet, wenn die App gestartet wird.

Ich notify die map Aktivität über die aktualisierte lcoation mit Hilfe des BroadcastReceiver wie im folgenden Code. Die Daten werden zu der Kartenaktivität abgerufen, aber ich habe ein Problem, um meine Registrierung aufzuheben bReceiver. Ich möchte die Übertragung der Registrierung aufheben, wenn die App in den Hintergrund wechselt oder wenn der Benutzer die Zurück-Taste drückt, aber ich erhalte den folgenden Fehler:

Wie kann ich das beheben?

Fehler:

08-27 22:43:04.594: E/AndroidRuntime(19588): FATAL EXCEPTION: main 
08-27 22:43:04.594: E/AndroidRuntime(19588): Process: com.bustracker, PID: 19588 
08-27 22:43:04.594: E/AndroidRuntime(19588): java.lang.RuntimeException: Unable to stop activity {com.bustracker/com.bustracker.Map}: java.lang.IllegalArgumentException: Receiver not registered: [email protected] 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:4156) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:4219) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.app.ActivityThread.access$1500(ActivityThread.java:177) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1502) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.os.Handler.dispatchMessage(Handler.java:102) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.os.Looper.loop(Looper.java:145) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.app.ActivityThread.main(ActivityThread.java:5944) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at java.lang.reflect.Method.invoke(Native Method) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at java.lang.reflect.Method.invoke(Method.java:372) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1389) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1184) 
08-27 22:43:04.594: E/AndroidRuntime(19588): Caused by: java.lang.IllegalArgumentException: Receiver not registered: [email protected] 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:822) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:2038) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:528) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at com.bustracker.Map.onStop(Map.java:418) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.app.Instrumentation.callActivityOnStop(Instrumentation.java:1275) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.app.Activity.performStop(Activity.java:6493) 
08-27 22:43:04.594: E/AndroidRuntime(19588): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:4151) 
08-27 22:43:04.594: E/AndroidRuntime(19588): ... 10 more 

Tracking Klasse:

public class TrackingService extends Service implements 
     LocationListener { 
    public double pLong; 
    public double pLat; 
    ... 
     @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     detectLocation(); 
     return START_STICKY; 
    } 
    private void detectLocation() { 
     lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
     lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30 * 1000, 0, 
       this); 
    } 
    @Override 
    public void onLocationChanged(Location location) { 

     if (location != null) { 
     pLong = location.getLongitude(); 
     pLat = location.getLatitude(); 

     Intent intent = new Intent(Map.RECEIVE_latLng); 
     intent.putExtra("location",location); 
     LocalBroadcastManager.getInstance(this).sendBroadcast(intent); 
      ..... 

    } 

} 

Karte Aktivität:

public class Map extends FragmentActivity implements OnMapReadyCallback { 
    public static final String RECEIVE_latLng = "com.bustracker.RECEIVE_latLng"; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.map); 

     LocalBroadcastManager bManager = LocalBroadcastManager.getInstance(this); 
     IntentFilter intentFilter = new IntentFilter(); 
     intentFilter.addAction(RECEIVE_latLng); 
     bManager.registerReceiver(bReceiver, intentFilter); 

    } 


    private BroadcastReceiver bReceiver = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      if(intent.getAction().equals(RECEIVE_latLng)) { 
           Location location = intent.getParcelableExtra("location"); 
      double lng = location.getLongitude(); 
      double lat = location.getLatitude(); 
      LatLng ll = new LatLng(lat, lng); 
      MarkerOptions markerOpt = new MarkerOptions().title("My Location") 
         .position(ll); 
      System.out.println("ABC map: "+ lat + " ; " + lng); 
      myLocatMarker = map.addMarker(markerOpt); 
      } 
      } 
     };  
     } 
@Override 
protected void onStop() { 
    super.onStop(); 
    unregisterReceiver(bReceiver);  
} 

Antwort

35

Wenn y Oder melden Sie sich unter onCreate() an, Sie müssen sich in onDestroy() abmelden. Wenn Sie sich in onStop() abmelden möchten, müssen Sie sich in onStart() registrieren.

Werfen Sie einen Blick auf die Aktivität Lifecycle hier http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

Der Grund dafür ist, dass onStop(), wenn sie aufgerufen wird, die Activity in den Hintergrund geht, aber nicht unbedingt zerstört wird. Wenn der Activity wieder in den Vordergrund kommt, wird onStart() aufgerufen, aber nichtonCreate(), so dass die BroadcastReceiver nicht erneut registriert wird. Wenn dann die Activity wieder in den Hintergrund tritt, versucht onStop(), die Registrierung wieder aufzuheben, aber der Empfänger wurde nicht registriert.

Sie müssen auch die LocalBroadcastManager verwenden Sie den Receiver abzumelden, wenn Sie es verwendet, es zu registrieren, wie so:

LocalBroadcastManager.getInstance(this).unregisterReceiver(bReceiver); 

LocalBroadcastManager ist eine Klasse aus dem support library:

Helper to register for and send broadcasts of Intents to local objects within your process.

Dies ist anders von den gleichen Methoden auf Context, die systemweite Broadcasts ermöglichen.

Siehe auch eine ähnliche Frage/Antwort here.

+0

So habe ich die 'bReceiver' im onStart() registriert, aber ich bin immer noch den Fehler. –

+0

@Mr Asker Können Sie den neuen Code und das neue StackTrace anzeigen? –

+0

Danke, habe das nicht einmal entdeckt. Ich habe die Antwort jetzt aktualisiert. Ich glaube immer noch, dass die Kommentare, die ich zu den Lebenszyklus-Methoden gemacht habe, auch gültig sind, also lasse ich sie da drin. –

3

(Natürlich, wenn Sie möchten) Sie können sie in onStop() registrieren oder deregistrieren und onResume() wickeln Sie es nur mit try-catch:

try{ getActivity().registerReceiver(receiver,filter); } catch (Exception e){ // already registered } Oder

try{ getActivity().unregisterReceiver(receiver); } catch (Exception e){ // already unregistered }

0

Haltungsart daran, dass Sie müssen sich im selben Kontext registrieren und die Registrierung aufheben. Beispiel: Registrieren Sie sich nicht mit dem Anwendungskontext und heben Sie nicht die Registrierung mit dem Aktivitätskontext auf.

Diese Mitteilung dieser Stelle nicht tun

getApplicationContext().registerReceiver(myReceiver, myIntentFilter); 
unregisterReceiver(myReceiver); 

Sie (innerhalb einer Aktivität)

registerReceiver(myReceiver, myIntentFilter); 
unregisterReceiver(myReceiver); 

melde ich mich normalerweise innerhalb onPostResume() oder onResume() und in onPause()nach der super.onPause() Anruf deregistrieren.

Beispiele:

protected void onPostResume() { 
    super.onPostResume(); 

    registerReceiver(myReceiver, myIntentFilter); 
} 

protected void onPause() { 
    unregisterReceiver(tripInCartReceiver1); 

    //called after unregistering 
    super.onPause(); 
} 
Verwandte Themen