android - start - Excepción extraña "Receptor no registrado"
start broadcast receiver android (5)
En onResume () hago:
registerReceiver(timeTickReceiver, new IntentFilter(Intent.ACTION_TIME_TICK));
y en onPause ():
unregisterReceiver(timeTickReceiver);
Veo los informes "java.lang.IllegalArgumentException: Receiver no registrado" en la Consola de desarrollador de Android (solo hay 2 informes y mi aplicación tiene miles de usuarios). La excepción es activada por unregisterReceiver (). ¿Qué puede estar pasando? No me siento muy seguro de rodearlo con try-catch.
Hemos visto este error al hacer una pulsación larga en una pantalla en particular, y luego realizar dos cambios de orientación (por ejemplo, voltear el dispositivo al revés).
La documentación API para unregisterReceiver dice:
Anular el registro de un BroadcastReceiver previamente registrado.
No lo dice explícitamente, pero como ha visto, IllegalArgumentException: Receiver not registered
si aún no está registrado.
La solución que estoy usando es almacenar mi Receiver como un campo miembro, y tenerlo configurado como nulo cuando no está registrado, es decir, lo inicializo como nulo, y luego lo configuro solo cuando lo registro. ¡Esto podría no ser perfecto, pero soluciona mis choques!
private Receiver mReceiver = null;
Desde mi onServiceConnected:
sLog.debug("Registering receiver");
mReceiver = new Receiver();
registerReceiver(mReceiver, filter);
Desde mi onServiceDisconnected:
if (mReceiver == null)
{
sLog.info("Do not unregister receiver as it was never registered");
}
else
{
sLog.debug("Unregister receiver");
unregisterReceiver(mReceiver);
mReceiver = null;
}
La opción más fácil sería envolver el bloque try / catch alrededor del código.
try{
...
this.unregisterReceiver(reciever);
}
catch(IllegalArgumentException e)
{
// TODO: handle exception
}
catch (Exception e) {
// TODO: handle exception
}
Supongo que puede haber algunos estados donde el receptor no está realmente registrado antes, por ejemplo, un usuario sale de la aplicación.
Es posible que desee intentar agregar un cheque para el receptor antes de ejecutar anular el registro, (lo he hecho en varios casos):
protected void onPause() {
if(timeTickReceiver != null) {
unregisterReceiver(timeTickReceiver);
}
}
Un BroadcastReceiver
debe registrarse en el método del ciclo de vida de onCreate()
:
private BroadcastReceiver receiver;
@Overrride
public void onCreate(Bundle savedInstanceState){
IntentFilter filter = new IntentFilter();
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
...
}
}
registerReceiver(receiver, filter);
}
Y un BroadcastReceiver
debe desregistrar en el método de ciclo de vida onDestory()
:
@Override
protected void onDestroy() {
unregisterReceiver(receiver);
}
Esto evitará el escenario de anular el registro de BroadcastReceiver
que aún no se ha registrado.
Un receptor de difusión debe anular el registro en el método de ciclo de vida onPause()
protected void onPause() {
this.unregisterReceiver(reciever);
super.onPause();
}