2015-08-27 2 views
7

У меня есть компонент TrackingService для отслеживания местоположения автобусов в моем городе на основе Crowdsourcing. Служба TrackingService работает в фоновом режиме, затем данные передаются на сервер. У меня есть активность карты для отображения местоположения шин, пользователя, выбранного в MainActivity (в качестве фильтра).java.lang.IllegalArgumentException: Получатель не зарегистрирован

Фоновая отслеживающая служба запускается в MainActivity при запуске приложения.

Я не отмечаю map деятельность по обновлению lcoation с помощью BroadcastReceiver, как в коде ниже. Данные извлекаются на активность карты, но мне приходится сталкиваться с проблемой, чтобы отменить регистрацию моего bReceiver. Я хочу отменить регистрацию широковещательной передачи, когда приложение переходит в фоновом режиме или когда пользователь нажимает кнопку «Назад», но я получаю сообщение об ошибке ниже:

Как это можно исправить?

Ошибка:

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 

TrackingService класс:

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

    } 

} 

Карта активности:

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

ответ

35

Если у ou зарегистрироваться в onCreate(), вам необходимо удалить регистрацию в onDestroy(). Если вы хотите отменить регистрацию в onStop(), вам необходимо зарегистрироваться в onStart().

Посмотрите на жизненном цикле активности здесь http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

Причиной этого является то, что onStop() вызывается, когда Activity идет на задний план, но не обязательно уничтожен. Когда Activity возвращается на передний план, onStart() вызывается, но неonCreate() поэтому BroadcastReceiver не перерегистрирован. Затем, когда Activity возвращается на задний план, onStop() пытается снова отменить регистрацию, но приемник не был зарегистрирован.

Вы также должны использовать LocalBroadcastManager чтобы отменить приемник, если вы использовали его, чтобы зарегистрировать его как так:

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

LocalBroadcastManager класс от support library:

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

Это отличается из тех же методов на Context, которые позволяют широковещательные системы.

Также см. Аналогичный вопрос/ответ here.

+0

Так что я зарегистрировал 'bReceiver' в OnStart(), но я все еще получаю ошибку. –

+0

@Mr Asker Можете ли вы показать новый код и новую стеклу? –

+0

Спасибо, даже не заметил этого. Я обновил ответ сейчас. Я по-прежнему считаю, что комментарии, которые я сделал в отношении методов жизненного цикла, также действительны, поэтому я оставляю их там. –

3

(Конечно, если вы хотите) Вы можете зарегистрироваться или отменить их в onStop() и onResume() просто обернуть его примерки уловом:

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

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

0

Имейте в виду, что вы должны зарегистрироваться и отменить регистрацию в том же контексте. Например, не регистрируйте w/контекст приложения и не регистрируйте w/контекст активности.

Не делайте этого

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

Сделайте это вместо того, чтобы (в деятельности)

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

Я обычно зарегистрировать внутри onPostResume() или onResume() и разрегистрировать в onPause()послеsuper.onPause() вызова.

Примеры:

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

    registerReceiver(myReceiver, myIntentFilter); 
} 

protected void onPause() { 
    unregisterReceiver(tripInCartReceiver1); 

    //called after unregistering 
    super.onPause(); 
} 
Смежные вопросы