BroadcastReceiver onReceive方法没有被调用?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BroadcastReceiver onReceive方法没有被调用?相关的知识,希望对你有一定的参考价值。

我有一个运行的服务,我正在获取位置更新。该服务成功返回该位置。但之后我试图将该位置广播到任何可能正在收听的活动。我在我的活动中注册了接收器但由于某种原因没有调用onReceive方法。这是我服务中的onLocationChanged方法内的代码。

@Override
public void onLocationChanged(Location location) {
    Intent intent = new Intent();
    intent.setAction("LocationBroadcast");
    double lat = location.getLatitude();
    double lng = location.getLongitude();
    intent.putExtra("lat", lat);
    intent.putExtra("lng", lng);
    //I am initializing the broadcaster object in onCreate method of my service but I am putting it here for simplicity
    broadcaster = LocalBroadcastManager.getInstance(this);
    //This Toast successfully shows my coordinates so I know the problem is not with this method
    Toast.makeText(GoogleFusedLocationApiService.this, ""+lat+", "+lng+"", Toast.LENGTH_SHORT).show();
    broadcaster.sendBroadcast(intent);
}

在我的onCreate方法的活动中,我正在注册LocationBroadcast

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    ...
    IntentFilter intentFilter = new IntentFilter("LocationBroadcast");
    super.registerReceiver(mMessageReceiver, intentFilter);
    startService(new Intent(MyApp.getAppContext(), GoogleFusedLocationApiService.class));
}

我尝试过this.registerReceiver(mMessageReceiver, intentFilter);LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, intentFilter);,但都没有奏效。

这是我的mMessageReceiver定义的,

public BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        double lat = intent.getDoubleExtra("lat", 0);
        double lng = intent.getDoubleExtra("lng", 0);
        // This Toast never shows and neither can I debug this method at all
        // so for now the only conclusion is the broadcast is not being received
        Toast.makeText(MyApp.getAppContext(), "Cordinates are "+lat+", "+lng+"", Toast.LENGTH_SHORT).show();
    }
};

此外,经过一些研究后,我可能认为有些细节很重要。我没有在receiver中声明manifest,因为我读到你只在你希望你的应用程序在收到广播时启动但我只希望我的应用程序在它已经运行时做出反应时才这样做。服务发送广播时不启动。

我没有将活动扩展到BroadcastReceiver,因为活动已经扩展到FragmentActivity

应用程序不会崩溃,onLocationChanged位于注册BroadcastReceiver后正在启动的服务内部,因此在广播已注册之前不会调用onLocationChanged

答案

我设法解决了这个问题。我会发布我的发现和答案,以便将来面对这个问题。我可能在这里贬低了很多概念,但为了理解这个具体问题,我会尽量准确地理解我的理解。

答案:

问题是我没有发送广播和接收广播与相同的Context。我的意思是,这就是我在Manifest文件中声明我的服务的方式

<service
        android:name=".GoogleFusedLocationApiService"
        android:process=":google_fused_location_api_service"/>

android:process属性意味着此服务将在与运行应用程序的进程不同的进程上运行。因此,当我调用时,super.registerReceiver(mMessageReceiver, intentFilter);是从Activity的上下文中调用的,当我在这里调用broadcaster = LocalBroadcastManager.getInstance(this); broadcaster.sendBroadcast(intent);时,sendBroadcast正在从服务的上下文中调用,该服务具有不同的进程。所以你看到我从不同的上下文注册接收器并从不同的上下文发送广播。

LocalBroadcastManager仅在从同一进程(即上下文)发送和接收广播时起作用。所以在这种情况下,由于我的服务和我的应用程序/活动正在运行或单独的进程,即上下文我不能使用LocalBroadcastManager。我需要使用全球广播,并确保我正在注册广播并从相同的上下文发送广播。

现在,因为我有一个静态的应用程序环境,我可以通过简单地调用MyApp.getAppContext()在任何地方使用,如果我注册广播接收器并使用此上下文发送广播,你可以从this answer学习如何做,这意味着两者都是从与MyApp.getAppContext()相同的背景,现在我开始成功接收广播。

总而言之,如果您有单独的服务流程,请使用MyApp.getAppContext().registerReceiver()MyApp.getAppContext().sendBroadcast()

如果您的服务具有相同的过程,或者在Manifest文件中的服务标签中没有android:process属性,则可以使用LocalBroadcastManager.getInstance(this).registerReceiver()LocalBroadcastManager.getInstance(this).sendBroadcast()

你仍然可以在这里使用MyApp.getAppContext,但在第二种情况下使用LocalBroadcastManager是最好的做法和正确的做事方式。

以上是关于BroadcastReceiver onReceive方法没有被调用?的主要内容,如果未能解决你的问题,请参考以下文章

BroadcastReceiver 是不是只监听变化?

为啥 BroadcastReceiver 需要一个默认构造函数?

Android中BroadcastReceiver组件具体解释

Android_组件_BroadcastReceiver基础

转Android BroadcastReceiver介绍

赵雅智_BroadcastReceiver