Awareness API & Android O 使用 BroadcastReceiver

Awareness API & Android O using BroadcastReceiver

我有一个 Android 应用程序,它在插入耳机时使用 Awareness API 设置围栏。

我已经使用与以下示例中的代码非常相似的代码实现了 AwarenessFence:https://developers.google.com/awareness/android-api/fence-register

我有一个 PendingIntent 定义为:

PendingIntent.getBroadcast(context, 0, new Intent("my.application.packageFENCE_RECEIVER_ACTION"), 0)

然后在我的 AndroidManifest.xml 文件中

<receiver android:name=".fence.FenceDetector$MyFenceReceiver">
<intent-filter>
    <action android:name="my.application.packageFENCE_RECEIVER_ACTION" />
</intent-filter>

这是在清单中声明的​​,因为即使我的应用程序处于后台,我也想接收广播。

这一切在 Android 7.0 及以下版本上运行良好,但是当我在 Android 8.0 上 运行 时,我收到错误消息:

BroadcastQueue: Background execution not allowed: receiving Intent { act=my.application.packageFENCE_RECEIVER_ACTION

我认为这是由于 Android O.

后台执行的新限制所致

谁能告诉我如何在 Android 设备 运行ning API 26.[=16 上注册一个可以在后台收听感知栅栏触发器的广播接收器=]

如果有什么不清楚的地方或者我需要详细说明的地方,请告诉我。

提前致谢

你的理解很正确。

Apps that target Android 8.0 or higher can no longer register broadcast receivers for implicit broadcasts in their manifest. An implicit broadcast is a broadcast that does not target that app specifically.

Apps can continue to register for explicit broadcasts in their manifests.

Source

如果您只对插入耳机时设置围栏感兴趣。您可以使用

Note: A number of implicit broadcasts are currently exempted from this limitation. Apps can continue to register receivers for these broadcasts in their manifests, no matter what API level the apps are targeting. For a list of the exempted broadcasts, see Implicit Broadcast Exceptions.

您可以在 Android Manifest 中抵制 ACTION_HEADSET_PLUG。在 onReceive 中,您可以:

  • 启动 NotificationManager.startServiceInForeground() 以便您可以继续在后台工作。
  • 想办法用计划的作业复制服务的功能。如果该服务没有立即引起用户注意,您通常应该能够使用计划作业来代替。参考 Job Scheduler
  • 推迟后台工作,直到应用程序自然地在前台运行。

如果需要完成较长的 运行 工作,我建议结合使用 Job SchedulerACTION_HEADSET_PLUG

否则,如果需要在 onReceive 中完成短期工作 你们中的一些人可以从以下方面获得帮助:

A BroadcastReceiver that uses goAsync() to flag that it needs more time to finish after onReceive() is complete. This is especially useful if the work you want to complete in your onReceive() is long enough to cause the UI thread to miss a frame (>16ms), making it better suited for a background thread.

you should not start long running background threads from a broadcast receiver. After onReceive(), the system can kill the process at any time to reclaim memory, and in doing so, it terminates the spawned thread running in the process. To avoid this, you should either call goAsync() (if you want a little more time to process the broadcast in a background thread) or schedule a JobService from the receiver using the JobScheduler, so the system knows that the process continues to perform active work.

Source

我做了一些挖掘并偶然发现了 this blog post by CommonsWare。它说明了您所面临的问题。

从上面post :-

One of the more controversial changes in Android O — for apps with a sufficiently-high targetSdkVersion — is the effective ban on implicit broadcasts.

所以,据此,我认为您的问题与意识没有任何关系API。相反,这是因为 Android 8.

中引入的新行为

不幸的是,目前似乎还没有可行的解决方案。同样,措辞相同 post :-

If you are receiving system-sent implicit broadcasts (e.g., ACTION_PACKAGE_ADDED), keep your targetSdkVersion at 25 or lower, until we figure out better workarounds that (hopefully) do not involve polling.

所以,希望在不久的将来会有更好的 8 解决方案。同时,您可以考虑其他选择,或者可以考虑降低您的 targetSDK。

我现在无法在设备上对其进行测试,但据我所知,限制仅在于隐式广播。这意味着,如果您改为创建一个显式广播,这就是让它工作所需的全部内容。

这意味着不是这个:

// implicit intent matching action
PendingIntent.getBroadcast(context, 0,
    new Intent("my.application.packageFENCE_RECEIVER_ACTION"), 0)

你这样做:

// explicit intent directly targeting your class
PendingIntent.getBroadcast(context, 0,
    new Intent(context, FenceDetector.MyFenceReceiver.class), 0)