静态的系统广播,例如:开机广播,用户开屏广播,USB插入和拔出广播等这类广播在app运行期间可以用静态注册的广播正常接收,但是在app被杀死后就无法收到了,android系统做了屏蔽,把被杀死的app的系统静态广播都过滤了,所以想让app被杀死后仍然通过静态注册的广播接收系统广播是做不到的
我们一般发广播都是局限在app内部,所以通常都是这么发的:
Intent intent = new Intent();
intent.setAction("my.broadcast.test");
sendBroadcast(intent);
或者这么发:
Intent intent = new Intent(context, TestBroadcastReceiver.class);
sendBroadcast(intent);
上面这两种广播的发送方式在app被杀死后都无法收到广播
但是采用下面这种方式发送广播即使app被杀死后,静态广播也能正常收到:
发送广播方的app,包名:com.syncpush.demo
Intent intent = new Intent();
Context c = null;
try {
c = createPackageContext("com.example.broadcasttest", Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
// intent.setPackage(getPackageName());
// intent.setComponent(pkgName, className);
// intent.setComponent(pkgNameContext, className);
intent.setClassName(c, "com.example.broadcasttest.TestBroadcastReceiver");
// intent.setClassName("com.example.broadcasttest", "com.example.broadcasttest.TestBroadcastReceiver");
intent.setAction("my.broadcast.test");
intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
sendBroadcast(intent);
intent.setClassName(“com.example.broadcasttest”, “com.example.broadcasttest.TestBroadcastReceiver”)声明接收的广播或者用intent.setClassName(c, “com.example.broadcasttest.TestBroadcastReceiver”),但是这个Context是接收广播方app的Context,所以通过createPackageContext(“com.example.broadcasttest”, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY)根据包名来获取到app的Context
接收广播方的app,包名com.example.broadcasttest
public class TestBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Toast.makeText(context, "action:" + action, Toast.LENGTH_LONG).show();
Log.i("TestBroadcastReceiver", "action:" + action);
}
}
// 配置文件
<receiver android:name="com.example.broadcasttest.TestBroadcastReceiver"
android:exported="true"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
intent-filter>
<intent-filter>
<action android:name="my.broadcast.test" />
intent-filter>
receiver>
接收放广播的配置要把exported设置成true,否则就无法收到app以外的广播发送,只能收到app内部的广播发送
以上通过广播唤醒在一些手机上可以正常唤醒app,例如小米3;但是在魅族手机上就没办法唤醒了,需要到安全中心把app的自启动权限开启后才能正常唤醒,由此可见,一些手机厂商可能对于静态广播的接收做了一些优化导致静态广播还是没办法被接收,所以会唤醒失败
这个网上说是设置了就能保证即使app被杀死后,也能正常接收广播,但是我在小米手机上测了下,没有用,即使没设置,但是采用intent.setClassName()后,app杀死后也能正常接收广播,后来怀疑是不是默认就是Intent.FLAG_INCLUDE_STOPPED_PACKAGES,于是就intent.setFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES),意思是app被杀死后就不接收广播,但是广播照样能正常接收,所以跟intent.setFlags()貌似没关系,但是小米手机系统是定制的,我不敢保证他们是不是对这方面做了修改,目前没有在原生的android系统上试过intent.setFlags()的有效性
Intent serviceIntent = new Intent();
serviceIntent.setComponent(new ComponentName(componentPckName, serviceName));
serviceIntent.setPackage(context.getPackageName());
serviceIntent.setAction("action");
context.startService(serviceIntent);