Bootstrap

Background execution not allowed 广播无法接收问题的解决方法

Background execution not allowed 广播无法接收问题的解决方法

出现此报错的原因是Android O中对隐式广播做了限制,请看源码如下:

frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
829      final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
830          BroadcastRecord r;
...
1277                  } else if (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
1278                          || (r.intent.getComponent() == null
1279                              && r.intent.getPackage() == null
1280                              && ((r.intent.getFlags()
1281                                      & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
1282                              && !isSignaturePerm(r.requiredPermissions))) {
1283                      mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
1284                              component.getPackageName());
1285                      Slog.w(TAG, "Background execution not allowed: receiving "
1286                              + r.intent + " to "
1287                              + component.flattenToShortString());
1288                      skip = true;
1289                  }

从代码中看,如下四个条件同时满足,则该广播不能被正常收到。

1.r.intent.getComponent() == null
2.r.intent.getPackage() == null
3.r.intent.getFlags() & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0
4.!isSignaturePerm(r.requiredPermissions)

解决办法:

1.因为这是静态广播注册才会有的问题,所以可以考虑将静态广播修改为动态广播。

2.这里的AndroidO并不是运行的Android版本,而是在AndroidManifest文件中定义的targetSdkVersion的值,因此我们第一种方法也是最稳定的方法即把项目文件中的targetSdkVersion设置为25及以下的版本号,重新编译即可,如果用的AndroidStudio,还要修改module/build.gradle中的该项配置.

AndroidManifest.xml

<uses-sdk android:minSdkVersion="13"/>
<uses-sdk android:targetSdkVersion="19"/>

3.如果发送广播的地方是自己可以控制的,那么可以将发送广播的地方加上需要的packageName。参考如下:

        Intent playIntent = new Intent("com.android.wangwei.test");
        playIntent.setPackage("com.example.wangwei.myapplication");

4.如果发送广播的地方是自己可以控制的,那么可以将发送广播的地方加上需要的flag。参考如下:

        源码编译方式:
        Intent playIntent = new Intent("com.android.wangwei.test");
        playIntent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        或者:
        Android Studio 方式:
        Intent playIntent = new Intent("com.android.wangwei.test");
        playIntent.addFlags(0x01000000);    -> 使用需谨慎,万一谷歌修改了这个值的数字,就GG了。

此Flag的含义如下:

    public static final int FLAG_RECEIVER_BOOT_UPGRADE = 0x02000000;
    /**
     * 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;

;