最近有一个需求,要求实现20秒无操作就跳转到一个界面,因为开发初期没有添加BaseActivity,所以再想在APP中实现事件监听就比较难修改,查阅资料发现可以在framework的ViewRootImpl 类的内部类WindowInputEventReceiver 的onInputEvent 方法中添加广播实现,但是添加后发现会有Sending non-protected broadcast 的报错,于是又查阅资料,将添加的广播在AndroidManifest.xml中注册为protected-broadcast :
<protected-broadcast android:name="android.intent.action.xxx" />
添加了之后,又发现非系统应用再点击任何按键时都会闪退,查看报错以及查阅资料发现,protected-broadcast 是为了防止三方垃圾应用也发送这些广播,会进行权限检查,不通过时,会抛出一个异常,具体代码在ActivityManagerService 中的checkBroadcastFromSystem 方法中:
private void checkBroadcastFromSystem(Intent intent, ProcessRecord callerApp,
String callerPackage, int callingUid, boolean isProtectedBroadcast, List receivers) {
if ((intent.getFlags() & Intent.FLAG_RECEIVER_FROM_SHELL) != 0) {
return;
}
final String action = intent.getAction();
if (isProtectedBroadcast
|| Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
|| Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS.equals(action)
|| Intent.ACTION_MEDIA_BUTTON.equals(action)
|| Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action)
|| Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS.equals(action)
|| Intent.ACTION_MASTER_CLEAR.equals(action)
|| Intent.ACTION_FACTORY_RESET.equals(action)
|| AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
|| AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)
|| LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION.equals(action)
|| TelephonyIntents.ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE.equals(action)
|| SuggestionSpan.ACTION_SUGGESTION_PICKED.equals(action)
|| AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION.equals(action)
|| AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION.equals(action)) {
return;
}
******
if (callerApp != null) {
Log.wtf(TAG, "Sending non-protected broadcast " + action
+ " from system " + callerApp.toShortString() + " pkg " + callerPackage,
new Throwable());
} else {
Log.wtf(TAG, "Sending non-protected broadcast " + action
+ " from system uid " + UserHandle.formatUid(callingUid)
+ " pkg " + callerPackage,
new Throwable());
}
}
所以问题就简单了,在上面的判断中加入自定义的系统广播即可,根据具体需求,看是否要添加到Intent 类中作为常量,比如需求提供给第三方SDK时,可以添加一下。
综上,要添加一个自定义的系统广播,首先要在frameworks\base\core\res\AndroidManifest.xml 中注册成protected-broadcast ,然后需要在ActivityManagerService 中添加判断;这样才能在framework中使用这个广播。
|