安卓 O : Background execution not allowed: Custom broadcast with permission

标签 android android-intent broadcastreceiver android-8.0-oreo

在我的应用程序中,我已经为另一个受权限保护的应用程序的隐式广播注册了一个广播接收器:

<receiver
    android:name=".receiver.MyReceiver"
    android:exported="true"
    android:permission="owner.custom.permission">
    <intent-filter>
        <action android:name="owner.custom.broadcast"/>
    </intent-filter>
</receiver>

MyReceiver#onReceive() 中,我正在使用 enqueueWork() 调用 JobIntentService MyService:

public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        Log.i(TAG, "Received the broadcast");
        MyService.enqueueWork(context, getServiceIntent(context));
    }

    private Intent getServiceIntent(final Context context) {
        final Intent intent = new Intent(context, MyService.class);
        intent.putExtra("someKey", true);
        return intent;
    }
}

我在 MyService 中有以下方法:

public static void enqueueWork(final Context context, final Intent work) {
        enqueueWork(context, MyService.class, 111, work);
    }

现在每当广播 owner.custom.broadcast 时,MyReceiver 都不会被触发,我可以看到以下日志:

07-23 03:56:29.755  3335  3361 W BroadcastQueue: Background execution not allowed: receiving Intent { act=owner.custom.broadcast flg=0x10 } to com.amazon.myApp/.receiver.MyReceiver

现在的问题是,我正在使用不同的广播接收器收听另一个这样的第 3 方隐式广播,并在那里调用 MyService,它工作正常。我还在另一个广播接收器中收听 BOOT_COMPLETED 广播,并在那里调用 MyService,它在那里也工作正常。
这个错误的可能原因是什么,这将帮助我确定我是否遗漏了什么。

更新:
我现在只是想让广播接收器触发,但我仍然遇到同样的错误。我正在尝试接收器中的日志行:

public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        Log.i(TAG, "Received the broadcast");
    }
}

最佳答案

Android O 限制了隐式广播,你不能在接收器中执行后台服务。

但是,它只限制静态接收器,你可以在代码中注册你的接收器来触发你的服务。

当然,在某些情况下,您不想“以编程方式”执行此操作,那么您应该检查错误情况,来自此链接 http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java#1275 (Line:1275),我发现错误(不确定这是否与您的系统版本相同)。

我们可以看到访问这个代码块的条件很少,我们一一分析,我们要做的就是让条件等于false:

(r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0

这意味着如果我们不希望后台接收到 Intent,则条件为真,通常我们不添加此标志,因为我们希望后台接收广播,继续吧。

r.intent.getComponent() == null

在我们的任何情况下都不应该为 null,继续吧。

r.intent.getPackage() == null

同上,继续。

r.intent.getFlags()&Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0

这意味着我们不能有一个名为 Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND 的标志,我想我们可以试试这个,但你会在 Intent 类中看到这个:

   /**
     * If set, the broadcast will always go to manifest receivers in background (cached
     * or not running) apps, regardless of whether that would be done by default.  By
     * default they will only receive broadcasts if the broadcast has specified an
     * explicit component or package name.
     *
     * NOTE: dumpstate uses this flag numerically, so when its value is changed
     * the broadcast code there must also be changed to match.
     *
     * @hide
     */
    public static final int FLAG_RECEIVER_INCLUDE_BACKGROUND = 0x01000000;

它是隐藏的,但您可以在您的项目中对整数进行硬编码,现在将此标志添加到您的 Intent 中以尝试您的代码是否有效。

   intent.addFlags(0x01000000)

祝你好运:)

注意:此解决方案不会解析接收系统隐式广播以运行后台任务。

关于安卓 O : Background execution not allowed: Custom broadcast with permission,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57160500/

相关文章:

Android:java.lang.SecurityException:没有 uri 0 @content://com.android.chrome.FileProvider/BlockedFile 的权限

android - 在 Broadcastreceiver 中访问 SQL

android - 我如何知道哪个应用程序版本正在被 Android 取代?

android - 将 LinkedHashMap 发送到 Intent

android - 字符串到资源路径转换器

android:检查应用程序中是否存在文件

java - Google Cloud Messaging 监听广播接收器

android - 收到fcm通知后自动启动activity?

java - 包内的字符串为空

android - 调用 startActivity 时在 onStop() 中查找下一个 Activity