Android8.0 静态receiver接收不到隐式广播 Background execution not allowed: receiving Intent

Android8.0的新特性值得注意一下,不然会出现很多莫名的问题。。。

后台执行限制
Android 8.0 为提高电池续航时间而引入的变更之一是,当您的应用进入已缓存状态时,如果没有活动的组件,系统将解除应用具有的所有唤醒锁。

此外,为提高设备性能,系统会限制未在前台运行的应用的某些行为。具体而言:

现在,在后台运行的应用对后台服务的访问受到限制。
应用无法使用其清单注册大部分隐式广播(即,并非专门针对此应用的广播)。
默认情况下,这些限制仅适用于针对 O 的应用。不过,用户可以从 Settings 屏幕为任意应用启用这些限制,即使应用并不是以 O 为目标平台。

Android 8.0 还对特定函数做出了以下变更:

如果针对 Android 8.0 的应用尝试在不允许其创建后台服务的情况下使用 startService() 函数,则该函数将引发一个 IllegalStateException。
新的 Context.startForegroundService() 函数将启动一个前台服务。现在,即使应用在后台运行,系统也允许其调用 Context.startForegroundService()。不过,应用必须在创建服务后的五秒内调用该服务的 startForeground() 函数。

以下这个就是Android8.0的后台限制新特性导致的,果然要踩过坑,才印象深刻。

自己编写了一个demo跟踪广播的发送流程。

demo:注册一个静态receiver,然后发送广播。

Activity中发送广播的代码:

public class MainActivity extends Activity {
    public static final String TAG = "TEST";
    public final String TEST_ACTION = "com.maureen.test.TEST_ACTION";
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
 
    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG,"onResume");
        Log.d(TAG,">>sendBroadcast");
        Intent intent = new Intent(TEST_ACTION);
        sendBroadcast(intent);
        Log.d(TAG,"<<sendBroadcast");
    }
 
    private BroadcastReceiver mTestReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            Log.d(TAG,"Dynamic receiver:action="+action);
        }
    };
 
}

AndroidManifest.xml中注册静态receiver:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.atc6111.testswitchicon">
 
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
 
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
 
 
        <receiver android:name=".MyTestReceiver">
            <intent-filter>
                <action android:name="com.maureen.test.TEST_ACTION"/>
            </intent-filter>
        </receiver>
    </application>
 
</manifest>

Receiver对应的java文件:

public class MyTestReceiver extends BroadcastReceiver {
    private final String TAG = "TEST-MyTestReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG,"Static receiver:action=" + intent.getAction());
    }
}

好的,现在开始运行这个demo。结果这个receiver一直都没有收到广播。。。。。

查看log,发现了warning信息:

W BroadcastQueue: Background execution not allowed: receiving Intent { act=com.maureen.test.TEST_ACTION flg=0x10 } to com.example.atc6111.testswitchicon/.MyTestReceiver
“Background execution not allowed” 打印出该warning的代码:

即是以下两种情况静态receiver不会接收到广播:

发送的intent设置了FLAG --FLAG_RECEIVER_EXCLUDE_BACKGROUND;
以下情况的均满足时:
①intent没有指定接收组件,也就是没有setComponent

     ②intent没有执行接收的package,也就是没有setPackage

    ③发送的intent没有设置FLAG-FLAG_RECEIVER_INCLUDE_BACKGROUND

    ④给定的权限并不都是签名权限。

根据这两种情况,即是说静态receiver接收不了隐式广播。本来打算采用最简单的方法添加Flag来解决的。

但是奇怪的是,Android Studio里没有FLAG_RECEIVER_INCLUDE_BACKGROUND!!!!

然后,只好在发送intent的时候setPackage。

   @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG,"onResume");
        Log.d(TAG,">>sendBroadcast");
        Intent intent = new Intent(TEST_ACTION);
        intent.setPackage(getPackageName());
        sendBroadcast(intent);
        Log.d(TAG,"<<sendBroadcast");
    }

修改之后,静态Receiver就能收到广播了。

但是如果就是想让静态receiver接收到隐式广播呢?应该还有其他方法,待学。。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值