问题: 我注册了以下系统广播 ,为啥在Receiver中接受不到广播呢?
<receiver android:name=".RebootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SCREEN_ON" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF" />
</intent-filter>
</receiver>
原因是: Android 7.0(API 级别 24)对系统事件的广播施加了一些限制,在Androidmanifest静态注册有无效.
如果应用注册为接收广播,则在每次发送广播时,应用的接收器都会消耗资源。 如果多个应用注册为接收基于系统事件的广播,则会引发问题:触发广播的系统事件会导致所有应用快速地连续消耗资源,从而降低用户体验。 为了缓解这一问题,Android 7.0(API 级别 24)对广播施加了一些限制,如后台优化中所述。 Android 8.0(API 级别 26)让这些限制更为严格。
-
适配 Android 8.0 或更高版本的应用无法继续在其清单中为隐式广播注册广播接收器。 隐式广播是一种不专门针对该应用的广播。 例如, ACTION_PACKAGE_REPLACED 就是一种隐式广播,因为该广播将被发送给所有已注册侦听器,让后者知道设备上的某些软件包已被替换。 不过, ACTION_MY_PACKAGE_REPLACED 不是隐式广播,因为不管已为该广播注册侦听器的其他应用有多少,它都会只被发送给软件包已被替换的应用。
-
应用可以继续在它们的清单中注册显式广播。
-
应用可以在运行时使用 Context.registerReceiver() 为任意广播(不管是隐式还是显式)注册接收器。
-
需要 签名权限的广播不受此限制所限,因为这些广播只会发送到使用相同证书签名的应用,而不是发送到设备上的所有应用。
解决办法有二:
1.如果是系统应用,可以让系统指定广播对象的包名,显性广播.
2.采用动态注册的方式,Context.registerReceiver() .案例如下
public class RebootServices extends Service {
public static final String TAG = "RebootServices";
public static final String HDMI_CONTROL_ENABLED = "hdmi_control_enabled";
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "intent.getAction():" + intent.getAction());
if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
Log.d(TAG, "ACTION_SCREEN_ON");
}
if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
Log.d(TAG, "ACTION_SCREEN_OFF");
}
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.SCREEN_ON");
intentFilter.addAction("android.intent.action.SCREEN_OFF");
intentFilter.addAction("com.nes.intent.action.PERIODIC_REBOOT");
registerReceiver(mReceiver, intentFilter);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "RebootServices started");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}
//调用处
Log.d(TAG, "add RebootServices");
intent = new Intent(context,RebootServices.class);
context.startService(intent);