Vas Vas - 4 months ago 15
Android Question

Unregistering a BroadcastReceiver outside of a subscription when activity is destroyed

public static Observable<Integer> getBluetoothStateObservable(Context context) {
final Context appContext = context.getApplicationContext();
return Observable.create(observer -> {
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
switch (btState) {
case BluetoothAdapter.ERROR:
observer.onError(new IllegalArgumentException("Error occurred while changing bluetooth state"));
break;
case BluetoothAdapter.STATE_OFF:
case BluetoothAdapter.STATE_ON:
observer.onCompleted();
break;
default:
observer.onNext(btState);
break;
}
}
};
observer.add(Subscriptions.create(() -> appContext.unregisterReceiver(broadcastReceiver)));
appContext.registerReceiver(broadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
})
}


I've got this little util method that gets me an
Observable
to monitor bluetooth state. When I use this method in my activity, I get the user to enable the bluetooth. This works fine, but it leaks when activity suddenly gets killed. I can unsubscribe in
onDestroy
, but how can I unregister the
BroadcastReceiver
?

Any ideas?

Answer

Given how the getBluetoothStateObservable is setup, the BroadcastReceiver will be unregistered when the Subscriber unsubscribes. The only trick is to ensure that it does, in fact, get unsubscribed when the Android Activity lifecycle comes into play.

In this case, you can either retain a Subscription instance, or use a CompositeSubscription.

In onCreate or onStart (for example):

mSubscription = getBluetoothStateObservable(this).subscribe();
or 
mCompositeSubscription.add(getBluetoothStateObservable(this).subscribe());

in onDestroy or onStop:

mSubscription.unsubscribe();
or
mCompositeSubscription.clear();

As always, Dan Lew has great explanations of how Android Lifecycles should work with RxJava (http://blog.danlew.net/2014/10/08/grokking-rxjava-part-4/)