android – 后台执行不允许接收意图BOOT_COMPLETED
作者:互联网
我已经阅读了有关Android Oreo后台执行限制的内容,并且明确指出BOOT_COMPLETED广播不会受到影响,但我无法让它在Android Oreo上运行.
首先,我正在编译SDK 27.其次,我在清单文件中声明了接收器:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver
android:name="helpers.StartDetectionAtBoot"
android:label="StartDetectionAtBoot"
android:enabled="true"
android:exported="true">
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<!--For HTC devices-->
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
<!--For MIUI devices-->
<action android:name="android.intent.action.REBOOT"/>
</intent-filter>
</receiver>
然后就是接收器的实现,它也可以很简单:
public class StartDetectionAtBoot extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("test", "test");
Intent intent0 = new Intent( context, ActivityRecognitionService.class );
PendingIntent pendingIntent = PendingIntent.getService(context, 111, intent0, PendingIntent.FLAG_UPDATE_CURRENT);
ActivityRecognitionClient activityRecognitionClient = ActivityRecognition.getClient(context);
activityRecognitionClient.requestActivityUpdates(5000, pendingIntent);
}
}
onReceive方法没有被调用,我将永远在Android Oreo设备/模拟器上获得logcat错误:
W/BroadcastQueue: Background execution not allowed: receiving Intent {
act=android.intent.action.BOOT_COMPLETED flg=0x400010 }
阅读其他答案,他们说在清单中注册显式意图时存在一些问题,但这不是BOOT_COMPLETED的情况.
this都没有帮助,因为接收器根本没有被调用.
在运行时注册广播意图,让它工作(在模拟器上,从adb shell激发意图),但我不确定这是正确的方法:
registerReceiver(new StartDetectionAtBoot(), new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
这有什么已知的错误吗?
解决方法:
在代码中自行注册接收器以获得所需的隐含意图,这实际上是开始接收该意图的正确方法.这不需要任何服务(在大多数情况下,见下文……).
但是你需要注意以下内容,以免在测试过程中混淆,而不是破坏早期的实现:
>每次应用程序运行时应自行注册一次.就Java / Kotlin应用程序数据而言:每静态场生命一次.因此,一个静态布尔字段应该允许您知道:如果您需要自行注册(例如,在重新引导之后或者在Android系统之后杀死您的应用程序之后……)或者不是(我引用此提交的工作代码:https://github.com/andstatus/todoagenda/commit/74ffc1495f2c4bebe5c43aab13389ea0ea821fde):
private static volatile boolean receiversRegistered = false;
private static void registerReceivers(Context contextIn) {
if (receiversRegistered) return;
Context context = contextIn.getApplicationContext();
EnvironmentChangedReceiver receiver = new EnvironmentChangedReceiver();
IntentFilter providerChanged = new IntentFilter();
providerChanged.addAction("android.intent.action.PROVIDER_CHANGED");
providerChanged.addDataScheme("content");
providerChanged.addDataAuthority("com.android.calendar", null);
context.registerReceiver(receiver, providerChanged);
IntentFilter userPresent = new IntentFilter();
userPresent.addAction("android.intent.action.USER_PRESENT");
context.registerReceiver(receiver, userPresent);
Log.i(EventAppWidgetProvider.class.getName(), "Registered receivers from " + contextIn.getClass().getName());
receiversRegistered = true;
}
>将registerReceivers方法的调用插入应用程序的所有可能入口点,以便最大化接收者注册的机会,即使您的应用程序仅由Android系统启动一次,例如:
@Override
public void onUpdate(Context baseContext, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
registerReceivers(baseContext);
...
}
>您可以在AndroidManifest.xml文件中将您的接收器注册到相同的意图(因为这适用于V.7之前的Android …),但请注意,在这种情况下,在logcat中您仍会看到“不允许后台执行”提到您的接收器.这只意味着通过AndroidManifest.xml注册不起作用(如预期的Android 8),但无论如何都应该调用自注册的接收器!
>如上所述,轻量级小部件通常不需要启动前台服务.此外,用户不会喜欢不断看到您的“小部件”在前台运行的通知(从而不断地吃掉资源).唯一的情况是,当真正需要这种情况时,Android会经常杀死你的应用程序,从而删除重启后完成的自我注册.
我认为让您的“小部件应用程序”尽可能轻(需要尽可能少的内存和CPU资源……)是确保您的小部件应用程序仅在您的设备的关键情况下被杀死的正确方法.也许你应该将你的大型应用程序分成两部分,使得一个小部件成为需要不时工作的重量级应用程序的启动器……
标签:android-8-0-oreo,android,broadcastreceiver,android-background 来源: https://codeday.me/bug/20191006/1861457.html