Background execution not allowed-----解决8.0以上发送的隐式广播无法被收到

target>=26时,APP发送的隐式广播连自己也收不到,0上限制。

Android 8.0 的广播无法接收 Background execution not allowed-PACKAGE_ADDED,该现象已经确认。

基于对广播的严格控制,大幅度减少了静态广播给第三方应用的使用,也是出于限制后台启动的作用。

故类似 android.intent.action.PACKAGE_ADDED 已经无法通过静态广播来监听,但是我们可以通过动态广播注册监听。当然动态广播要求应用要活着,如果被kill掉了,仍旧无法接受到。
1. 现象-广播无法接受日志

报错log如下:

BroadcastQueue: Background execution not allowed: receiving Intent { act=android.intent.action.PACKAGE_ADDED dat=package:com.android.cts.launcherapps.simpleapp flg=0x4000010 (has extras) } to com.android.lava.powersave/.recevier.LavaPowerSaveRecevier

08-23 21:45:38.271  1207  1225 W BroadcastQueue: Background execution not allowed: receiving Intent { act=com.xxx.xxx flg=0x10 (has extras) } to com.xx.xx/com.xx.xx.receiver.XxReceiver

BroadcastQueue.java中的限制代码:

        if (!skip) {
            final int allowed = mService.getAppStartModeLocked(
                    info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
                    info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false, false);
            if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                // We won't allow this receiver to be launched if the app has been
                // completely disabled from launches, or it was not explicitly sent
                // to it and the app is in a state that should not receive it
                // (depending on how getAppStartModeLocked has determined that).
                if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
                    Slog.w(TAG, "Background execution disabled: receiving "
                            + r.intent + " to "
                            + component.flattenToShortString());
                    skip = true;
                } else if (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
                        || (r.intent.getComponent() == null
                            && r.intent.getPackage() == null
                            && ((r.intent.getFlags()
                                    & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
                            && !isSignaturePerm(r.requiredPermissions))) {
                    mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
                            component.getPackageName());
                    Slog.w(TAG, "Background execution not allowed: receiving "
                            + r.intent + " to "
                            + component.flattenToShortString());
                    skip = true;
                }
            }
        }

代码说明:

1.只要intent的flag包含FLAG_RECEIVER_EXCLUDE_BACKGROUND则不允许该广播被接收。

2.对于隐式广播,如果没有包含FLAG_RECEIVER_INCLUDE_BACKGROUND也不允许被接收。

 

绕过的思路就是将所有发送出去的广播都加上FLAG_RECEIVER_INCLUDE_BACKGROUND标志:

代码如下:

public class BroadcastPassedby {
    public static void enableImplicit(){
        try {
            if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O){
                return;
            }
            ActivityManager am = (ActivityManager)EmmCore.getContext().getSystemService(Context.ACTIVITY_SERVICE);
            Object activityManager = Reflect.on(am).call("getService").get();
            Object proxy = Proxy.newProxyInstance(activityManager.getClass().getClassLoader(),activityManager.getClass().getInterfaces(),new ActivityManagerHandler(activityManager));
            Reflect.on(am).field("IActivityManagerSingleton").set("mInstance",proxy);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private static  class  ActivityManagerHandler implements InvocationHandler{
        private Object mActivityManager;

        public ActivityManagerHandler(Object activityManager) {
            mActivityManager = activityManager;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if(method.getName().equals("broadcastIntent")){
                for(Object o : args){
                    if(o == null){
                        continue;
                    }
                    if(o instanceof Intent){
                        Intent intent = (Intent)o;
                        int includeBackground = Reflect.on(Intent.class).field("FLAG_RECEIVER_INCLUDE_BACKGROUND").get();
                        intent.setFlags(intent.getFlags()| includeBackground);
                    }
                }
            }
            return method.invoke(mActivityManager,args);
        }
    }
}

原理是Hook了AMS,这样APP也不用做任何改动,只需要在Application中调用BroadcastPassedby.enableImplicit()即可。

解决方案:


引用自己声明的权限 ,可不引用
<uses-permission android:name="com.eestorm.cefsdk.receiver" />

<permission//声明自定义权限
    android:name="com.eestorm.cefsdk.receiver"
    android:protectionLevel="signature"/>

    1
    2
    3


<receiver android:name=".TestPush"
android:permission="com.eestorm.cefsdk.receiver"
android:exported="true">
<intent-filter>
<action android:name="xxx.xxx"/
<category android:name="${applicationId}" />
</intent-filter>
</receiver>


context.sendBroadcast(intent,"com.eestorm.cefsdk.receiver");
2.setComponent

`
intent.setComponent(new ComponentName(“package name”,”class name”));

`

/**
* Create a new component identifier.
*
* @param pkg The name of the package that the component exists in. Can
* not be null.
* @param cls The name of the class inside of <var>pkg</var> that
* implements the component. Can not be null.
*/
public ComponentName(@NonNull String pkg, @NonNull String cls) {
if (pkg == null) throw new NullPointerException("package name is null");
if (cls == null) throw new NullPointerException("class name is null");
mPackage = pkg;
mClass = cls;
}

package name:项目包名
class name:具体的receiver的全类名。

两种方法亲测有效。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值