当应用不是 运行 时,清单声明的 BroadcastReceiver 未接收显式广播
Manifest-declared BroadcastReceiver not picking up explicit broadcast when app is not running
我正在尝试让两个应用程序通过广播进行通信。第一个应用使用如下代码发送广播:
Intent outIntent = new Intent("org.example.WHATEVER");
PackageManager pm = this.getPackageManager();
List<ResolveInfo> receivers = pm.queryBroadcastReceivers(outIntent, 0);
if (receivers != null)
for (ResolveInfo receiver : receivers) {
Log.d("Sender", String.format("Polling %s", receiver.activityInfo.packageName));
outIntent = new Intent("org.example.WHATEVER");
outIntent.setPackage(receiver.activityInfo.packageName);
sendBroadcast(outIntent);
}
接收端在其manifest中注册一个BroadcastReceiver
:
<receiver android:name="org.example.receiverapp.WhateverReceiver" >
<intent-filter>
<action android:name="org.example.WHATEVER" />
</intent-filter>
</receiver>
onReceive()
方法在调用时写入日志条目。
当接收应用 运行 时(即我已经在屏幕上看到它的主 activity,然后导航离开它),它会处理广播。但是,如果接收器应用不是 运行(我通过长按返回来确保,在开发者设置中激活“长按返回杀死应用”),它不会被广播唤醒。
我特意为 Intent 设置了一个包名,以避免从 Android 8 开始出现 manifest-declared receivers no longer receiving implicit broadcasts 的问题。此外,我是 运行 Android 7,这两个应用程序都针对 API 23,因此 Android 8 中的任何限制无论如何在此设置中都不重要。
我遇到了一个 comment,其作者建议 Android 的某些风格可能不会唤醒广播应用程序,这似乎是我在这里遇到的情况 (运行 LineageOS 14.1)—尽管该评论不是很具体,而且我还没有找到任何其他支持此声明的内容。
这是这里发生的事情吗?如果是这样,我如何确保接收器应用程序被广播唤醒(至少如果它是定向的)?如果不是,这里有什么问题?
为了明确 Intent
,我通常 use setComponent()
,因为它保证有效(尽可能多):
Intent outIntent = new Intent("org.example.WHATEVER");
PackageManager pm = this.getPackageManager();
List<ResolveInfo> receivers = pm.queryBroadcastReceivers(outIntent, 0);
if (receivers != null)
for (ResolveInfo receiver : receivers) {
Log.d("Sender", String.format("Polling %s/%s",
receiver.activityInfo.applicationInfo.packageName,
receiver.activityInfo.name));
ComponentName cn = new ComponentName(
receiver.activityInfo.applicationInfo.packageName,
receiver.activityInfo.name);
outIntent = new Intent("org.example.WHATEVER");
outIntent.setComponent(cn);
sendBroadcast(outIntent);
}
在某些情况下,setPackage()
会生成 Intent
"explicit enough" 以满足某些 Android 标准。显然,在这种情况下,事实并非如此。 ¯\_(ツ)_/¯
我正在尝试让两个应用程序通过广播进行通信。第一个应用使用如下代码发送广播:
Intent outIntent = new Intent("org.example.WHATEVER");
PackageManager pm = this.getPackageManager();
List<ResolveInfo> receivers = pm.queryBroadcastReceivers(outIntent, 0);
if (receivers != null)
for (ResolveInfo receiver : receivers) {
Log.d("Sender", String.format("Polling %s", receiver.activityInfo.packageName));
outIntent = new Intent("org.example.WHATEVER");
outIntent.setPackage(receiver.activityInfo.packageName);
sendBroadcast(outIntent);
}
接收端在其manifest中注册一个BroadcastReceiver
:
<receiver android:name="org.example.receiverapp.WhateverReceiver" >
<intent-filter>
<action android:name="org.example.WHATEVER" />
</intent-filter>
</receiver>
onReceive()
方法在调用时写入日志条目。
当接收应用 运行 时(即我已经在屏幕上看到它的主 activity,然后导航离开它),它会处理广播。但是,如果接收器应用不是 运行(我通过长按返回来确保,在开发者设置中激活“长按返回杀死应用”),它不会被广播唤醒。
我特意为 Intent 设置了一个包名,以避免从 Android 8 开始出现 manifest-declared receivers no longer receiving implicit broadcasts 的问题。此外,我是 运行 Android 7,这两个应用程序都针对 API 23,因此 Android 8 中的任何限制无论如何在此设置中都不重要。
我遇到了一个 comment,其作者建议 Android 的某些风格可能不会唤醒广播应用程序,这似乎是我在这里遇到的情况 (运行 LineageOS 14.1)—尽管该评论不是很具体,而且我还没有找到任何其他支持此声明的内容。
这是这里发生的事情吗?如果是这样,我如何确保接收器应用程序被广播唤醒(至少如果它是定向的)?如果不是,这里有什么问题?
为了明确 Intent
,我通常 use setComponent()
,因为它保证有效(尽可能多):
Intent outIntent = new Intent("org.example.WHATEVER");
PackageManager pm = this.getPackageManager();
List<ResolveInfo> receivers = pm.queryBroadcastReceivers(outIntent, 0);
if (receivers != null)
for (ResolveInfo receiver : receivers) {
Log.d("Sender", String.format("Polling %s/%s",
receiver.activityInfo.applicationInfo.packageName,
receiver.activityInfo.name));
ComponentName cn = new ComponentName(
receiver.activityInfo.applicationInfo.packageName,
receiver.activityInfo.name);
outIntent = new Intent("org.example.WHATEVER");
outIntent.setComponent(cn);
sendBroadcast(outIntent);
}
在某些情况下,setPackage()
会生成 Intent
"explicit enough" 以满足某些 Android 标准。显然,在这种情况下,事实并非如此。 ¯\_(ツ)_/¯