应用关闭时广播接收器不工作

9

我有两个不同的应用程序,一个发送广播,另一个接收它并显示toast。然而,当我关闭接收器应用时,即使我在清单文件中定义了接收器,第二个应用程序也不再接收广播。

在app1的MainActivity中是广播发送方。

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button b = (Button)findViewById(R.id.button2);
    b.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent i = new Intent();
            i.setAction("com.example.ali.rrr");
            i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
            sendBroadcast(i);
            Log.e("Broadcast","sent");
        }
    });
}

应用程序2广播接收器:

public class MyReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    // TODO: This method is called when the BroadcastReceiver is receiving
    // an Intent broadcast.
    Toast.makeText(context, "Broadcast has been recieved!", Toast.LENGTH_SHORT).show();
    Log.e("SUCCESS", "IN RECIEVER");
    //throw new UnsupportedOperationException("Not yet implemented");
}

App 2s清单:

<?xml version="1.0" encoding="utf-8"?>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <receiver
        android:name=".MyReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="com.example.ali.rrr" />
        </intent-filter>
    </receiver>

    <activity
        android:name=".MainActivity"
        android:label="@string/title_activity_main"
        android:theme="@style/AppTheme.NoActionBar" />
    <activity
        android:name=".Main2Activity"
        android:label="@string/title_activity_main2"
        android:theme="@style/AppTheme.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>


打开应用程序2(接收器应用程序)时它是否正常工作? - Jd Prajapati
@MohitKacha 我正在尝试将其作为广播接收器工作,静态注册的接收器在清单中应该可以在应用关闭时工作。 - kumail
@JdPrajapati 是的,当我将App2保持在后台运行时它是有效的。 - kumail
@kumail,你只能通过使用Service和Receiver的组合来实现这一点。但是你的代码使用Activity进行广播,因此在后台运行Activity时无法提供上下文,因为Activity需要上下文。 - Pratik Vyas
你确定广播没有被接收到吗?你是怎么验证的?Toast不是一个可靠的调试方法。检查一下你的logcat! - David Wasser
显示剩余7条评论
5个回答

26
在清单文件中静态注册我的广播接收器(BR),应用适当的意图过滤器,使用JobIntentService(并在清单文件中注册它)处理从我的BR调用的工作后,我仍然得到不一致的结果。
完成上述所有步骤后,即使应用程序关闭,您应该能够发送ADB命令来激活您的广播并在服务中处理工作。这对我来说有时有效,但并非总是如此。 这篇文章描述了BRs的限制。 “自Android 3.1以来,如果相应的应用程序从未被用户启动过或者用户通过Android菜单明确停止应用程序,则默认情况下,Android系统排除所有接收器接收意图”(也就是用户执行强制停止)。
当我通过调试启动应用程序,然后在设备上将其关闭时,我的ADB命令从未激活我的BR。然而,在我的调试会话结束后,当我在设备上打开应用程序并将其滑动关闭时,我可以通过ADB命令激活我的BR。这是因为当您在设备上调试应用程序,然后手动将其关闭时,Android会认为这是强制停止,因此我的BR在没有调试的情况下重新打开应用程序之前无法被激活
我在互联网上搜索了几个小时,但未能找到解决方案,所以我想在这里发布,以防一些不幸的人遇到与我相同的奇怪功能。
快乐编码 :)

我刚刚注意到我正在调试应用程序。在我手动打开应用程序后,BR(业务逻辑)正常工作。谢谢! - Ticherhaz FreePalestine
在找到这个答案之前,我花了很多时间来调试应用程序。非常感谢您分享这个。否则,我会浪费更多的时间!;-) - Yogesh
1
有没有解决这个问题的办法? 我想在应用程序被强制关闭后仍然调用BroadcastReceiver。 - shaby
@shaby,很遗憾,我不知道Android操作系统会更改这种行为,而且我认为他们不太可能这样做。从用户的角度来看,如果您强制停止一个应用程序,您不希望它在您没有重新启用该应用程序的情况下随机执行(可能是长时间运行的)后台操作,对吧? - MedievalCoder

4

我最近遇到了这个问题。即使在模拟器和三星手机中将应用程序从后台中删除,BroadcastReceiver仍然可以正常工作。但是在像Realme、Mi等中国制造的手机中无法启动我的应用程序。在努力寻找解决方法时,我发现在应用程序详细信息页面中有电池优化设置,其中自动启动功能被禁用。当我启用它之后,应用程序就可以正常工作,并且BroadcastReceiver能够启动应用程序。我无法找到一种以编程方式启用此设置的方法,但我发现这个问题帮助我将用户引导到该设置页面。


4

首先,您需要使用服务才能使此功能正常工作。

在活动中,您可以使用以下代码启动和停止服务。

// to start a service
Intent service = new Intent(context, MyBrodcastRecieverService.class);
context.startService(service);

// to Stop service
Intent service = new Intent(context, MyBrodcastRecieverService.class);
context.stopService(service);

那么,您可以使用以下服务

public class MyBrodcastRecieverService extends Service
{
    private static BroadcastReceiver br_ScreenOffReceiver;

    @Override
    public IBinder onBind(Intent arg0)
    {
        return null;
    }

    @Override
    public void onCreate()
    {
        registerScreenOffReceiver();
    }

    @Override
    public void onDestroy()
    {
        unregisterReceiver(br__ScreenOffReceiver);
        m_ScreenOffReceiver = null;
    }

    private void registerScreenOffReceiver()
    {
        br_ScreenOffReceiver = new BroadcastReceiver()
        {
            @Override
            public void onReceive(Context context, Intent intent)
            {
                Log.d(TAG, "ACTION_SCREEN_OFF");
                // do something, e.g. send Intent to main app
            }
        };
        
        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        registerReceiver(br_ScreenOffReceiver, filter);
    }
}

1
有没有什么方法只使用广播接收器来完成它? - kumail
如果您在清单文件中注册自己的BroadcastReceiver作为接收器,它将始终被调用。 - Sujith Ks
不必使用“Service”来实现此目的。 - David Wasser
3
@SujithKs 我已经在清单文件中注册了它,但只有在应用程序打开时才会调用它。 - kumail
从Android 7开始(Android 8更加严格),在大多数情况下,声明在清单文件中的广播将不再起作用,必须用定时任务或服务来替换它。 - alexanderdavide
显示剩余3条评论

1
你可以参考以下解决方案;

Activity.java

Intent intent=new Intent(MainActivity.this,BroadcastService.class);
startService(intent);

BroadcastService.java

public class BroadcastService extends Service {

private static MusicIntentReceiver br_ScreenOffReceiver;

@Override
public IBinder onBind(Intent arg0)
{
    return null;
}

@Override
public void onCreate()
{
    registerScreenOffReceiver();
}

@Override
public void onDestroy()
{

}

private void registerScreenOffReceiver()
{
    br_ScreenOffReceiver = new MusicIntentReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
                int state = intent.getIntExtra("state", -1);
                switch (state) {
                    case 0:
                        Log.e("AAAAAAAAAA", "Headset is unplugged");
                        break;
                    case 1:
                        Log.e("AAAAAAAAA", "Headset is plugged");
                        break;
                    default:
                        Log.e("AAAAAAAAAAAA", "I have no idea what the headset state is");
                }
            }
        }
    };
    IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
    registerReceiver(br_ScreenOffReceiver, filter);
}


}

"Menifest"翻译成中文是“清单”,保留HTML格式不变。
<service android:enabled="true" android:name=".BroadcastService" />

0

尝试这种方式...

Intent i = new Intent();
i.setAction("com.example.ali.rrr");
i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
i.setComponent(  
        new ComponentName("PackageNameApp2","PackageNameApp2.MainActivity"));  
sendBroadcast(i);

我改变了操作,请您现在试一下? - Jd Prajapati
在你的清单中,你添加了另一个接收器。这是错误的...请将MyReceiver6更改为MyReceiver。 - Jd Prajapati
不幸的是,问题仍然存在。 - kumail

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