广播接收两次

17
我正在使用本地广播告知我的服务,AsyncTask已完成其工作,但我有一个小问题:广播只发送一次(它是由仅在应用启动时调用的函数创建的),但我收到了两次。
简化的代码:
@Override
protected void onPostExecute(HttpResponse result) {
    LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(getBaseContext());
    localBroadcastManager.sendBroadcast(new Intent(getString(R.string.bc_CONNECTED)));
}

在服务中:

private BroadcastReceiver connectedBroadcastReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(getString(R.string.app_tag), "broadcast received !!");
    }
};

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    LocalBroadcastManager.getInstance(this).registerReceiver(connectedBroadcastReceiver, new IntentFilter(getString(R.string.bc_CONNECTED)));
    return START_STICKY;
}

有人遇到过这样奇怪的行为吗?

5个回答

27

我遇到了同样的问题,问题在于我在onCreate方法和onResume方法中都注册了接收器。将其从onCreate中移除后,问题得到解决。


1
谢谢,这就是我的问题。 - Robby Smet
这也适用于BroadcastReceiver吗?随着新的SDK发布(26),现在我们必须手动注册接收器。我想知道调用registerReceiver方法两次是否安全?由于我的应用程序工作方式,我需要确保在不同情况下注册接收器,但是由于没有“isReceiverRegistered”方法,唯一的方法就是简单地注册接收器,但我担心可能会注册两次并收到两条消息。 - Roger

12

在响应广播之前,您应始终检查意图操作。

public void onReceive(Context context, Intent intent){
      if(intent.getAction() != null && intent.getAction().equals(getString(R.string.bc_CONNECTED))){
      Log.d(getString(R.string.app_tag), "broadcast received !!");
 }
}

请查看文档。文档提到您可能会收到不确定的调用。因此,始终检查操作。

在registerReceiver(BroadcastReceiver, IntentFilter)和应用程序清单中使用的Intent过滤器不能保证是互斥的。它们只是向操作系统提供有关如何查找合适接收者的提示。发送方可以强制将Intent传递给特定接收者,从而绕过过滤器解析。出于这个原因,onReceive()实现应仅响应已知操作,忽略任何意外接收到的Intent。


啊,我以为我的IntentFilter会防止虚假调用,因为它包含了我的包名,但可能不是这样。我将重现此问题以验证其来源。谢谢! - Teovald
@nandeesh,if(intent.getAction() != null && intent.getAction().equals(getString(R.string.bc_CONNECTED)))和if(intent.getAction().equals(getString(R.string.bc_CONNECTED)))之间有什么区别? - Sazzad Hissain Khan
@Hissain 只是一些 NPE 保护。 - Teovald
R.string.bc_CONNECTED 的值是多少? - hasnain_ahmad

1

请确保在任何组件 (Activity、Fragment、Service 等) 的 onCreate 方法中注册 BroadcastReceiver,而不是在 onResume 或者(在 Fragment 的情况下)onViewCreated 中注册。

例如:

val receiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        Log.d("TAGGg",intent?.getBooleanExtra("ext", false).toString())
    }
}

// On Create method of component
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    LocalBroadcastManager.getInstance(requireActivity()).registerReceiver(receiver, IntentFilter("test-event"))
}

同时确保在onStop()onDestroy()中注销广播接收器。

LocalBroadcastManager.getInstance(requireActivity()).unregisterReceiver(receiver)

1
我遇到了这个问题,因为我注册了两次,因为我有两个intent过滤器。所以系统会传递相同的intent两次。
  LocalBroadcastManager.getInstance(this).registerReceiver(mLocalReceiver,intentFilterNews);
  LocalBroadcastManager.getInstance(this).registerReceiver(mLocalReceiver,intentFilterWeather);

1
你是否在退出应用程序时注销了接收器?否则,每次启动应用程序时都会注册另一个接收器。或者,在注册接收器之前,您必须检查接收器是否已经在先前的应用程序调用中注册过。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接