从接收者自己的 onReceive() 方法中注销 'dynamic' BroadcastReceiver 是否可以?
Is it OK to unregister 'dynamic' BroadcastReceiver from receiver's own onReceive() method?
也就是说,我有这个动态创建的 BroadcastReceiver 来收听一个广播,之后我希望它自行注销。
我没有找到任何以这种方式执行的示例代码,但我也没有在 android 在线文档中找到任何禁止这样做的规则。但是我不能让它在 activity 之前一直存在,而且它无论如何都是匿名的 class,所以包含 class 甚至不知道变量名。
也就是说,代码看起来像这样:
myInfoReceiver = new BroadcastReceiver() {
onReceive(Context ctx, Intent intt) {
// do some Notification when I get here
nm.notify("I got here") // obvious pseudo code
ctx.unregisterReceiver(myInfoReceiver);
} // end onReceive
ctx.registerReceiver),uInfoReceiver, new IntentFilter(...));
}; // end BroadcastReceiver
但是当我运行这个时,Android在它调用取消注册时抱怨,坚持认为接收者不在那里取消注册(我忘记了确切的措辞,但它抛出了 IllegalArgumentException)。
我还尝试修改代码以检查 'intt' 中的操作是否与预期相同 - 但它仍然执行 onReceive 但静默无法注销。
我会简单地说是,完全没问题。
例如,我将它用于一次性定位,也可以用于其他逻辑,我没有发现任何问题。
而且我已经看过很多次了。
您问题的答案是 "yes"。然而...
...您需要在调用 registerReceiver()
的同一 Context
上调用 unregisterReceiver()
。在您发布的代码中,您在作为参数传递给 onReceive()
的 Context
上调用 unregisterReceiver()
。这不一样 Context
这就是你得到异常的原因。
我尝试了各种解决方案,最后我这样做了:
正在注册:
MyApplication.getInstance().getApplicationContext().registerReceiver(sentReceiver, new IntentFilter(SENT));
发送接收者:
public class SentReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent arg1) {
switch (getResultCode()) {
case Activity.RESULT_OK:
Toast.makeText(context,
context.getString(R.string.sms_envoye), Toast.LENGTH_SHORT)
.show();
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Toast.makeText(context,
context.getString(R.string.sms_defaillance_generique),
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Toast.makeText(context,
context.getString(R.string.sms_pas_de_service),
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Toast.makeText(context,
context.getString(R.string.sms_pas_de_pdu),
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Toast.makeText(context,
context.getString(R.string.sms_radio_desactivee),
Toast.LENGTH_SHORT).show();
break;
}
MyApplication.getInstance().getApplicationContext().unregisterReceiver(this);
}
使用 MyApplication:
public class MyApplication extends Application {
private static MyApplication mInstance;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized MyApplication getInstance() {
return mInstance;
}
}
也就是说,我有这个动态创建的 BroadcastReceiver 来收听一个广播,之后我希望它自行注销。
我没有找到任何以这种方式执行的示例代码,但我也没有在 android 在线文档中找到任何禁止这样做的规则。但是我不能让它在 activity 之前一直存在,而且它无论如何都是匿名的 class,所以包含 class 甚至不知道变量名。
也就是说,代码看起来像这样:
myInfoReceiver = new BroadcastReceiver() {
onReceive(Context ctx, Intent intt) {
// do some Notification when I get here
nm.notify("I got here") // obvious pseudo code
ctx.unregisterReceiver(myInfoReceiver);
} // end onReceive
ctx.registerReceiver),uInfoReceiver, new IntentFilter(...));
}; // end BroadcastReceiver
但是当我运行这个时,Android在它调用取消注册时抱怨,坚持认为接收者不在那里取消注册(我忘记了确切的措辞,但它抛出了 IllegalArgumentException)。
我还尝试修改代码以检查 'intt' 中的操作是否与预期相同 - 但它仍然执行 onReceive 但静默无法注销。
我会简单地说是,完全没问题。
例如,我将它用于一次性定位,也可以用于其他逻辑,我没有发现任何问题。
而且我已经看过很多次了。
您问题的答案是 "yes"。然而...
...您需要在调用 registerReceiver()
的同一 Context
上调用 unregisterReceiver()
。在您发布的代码中,您在作为参数传递给 onReceive()
的 Context
上调用 unregisterReceiver()
。这不一样 Context
这就是你得到异常的原因。
我尝试了各种解决方案,最后我这样做了:
正在注册:
MyApplication.getInstance().getApplicationContext().registerReceiver(sentReceiver, new IntentFilter(SENT));
发送接收者:
public class SentReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent arg1) {
switch (getResultCode()) {
case Activity.RESULT_OK:
Toast.makeText(context,
context.getString(R.string.sms_envoye), Toast.LENGTH_SHORT)
.show();
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Toast.makeText(context,
context.getString(R.string.sms_defaillance_generique),
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Toast.makeText(context,
context.getString(R.string.sms_pas_de_service),
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Toast.makeText(context,
context.getString(R.string.sms_pas_de_pdu),
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Toast.makeText(context,
context.getString(R.string.sms_radio_desactivee),
Toast.LENGTH_SHORT).show();
break;
}
MyApplication.getInstance().getApplicationContext().unregisterReceiver(this);
}
使用 MyApplication:
public class MyApplication extends Application {
private static MyApplication mInstance;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized MyApplication getInstance() {
return mInstance;
}
}