概述
前言
最近有一个需求,要求实现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) {
// Don't yell about broadcasts sent via shell
return;
}
final String action = intent.getAction();
if (isProtectedBroadcast
|| Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
******
|| AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION.equals(action)) {
// Broadcast is either protected, or it's a public action that
// we've relaxed, so it's fine for system internals to send.
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());
}
}
于是在上面的判断中加入自定义的系统广播,但是验证发现还是会报错:
java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.xxx from pid=11072, uid=10013
根据报错信息,找到了对应的代码(ActivityManagerService
):
final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
******
if (!isCallerSystem) {
if (isProtectedBroadcast) {
String msg = "Permission Denial: not allowed to send broadcast "
+ action + " from pid="
+ callingPid + ", uid=" + callingUid;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
******
}
******
}
于是又在isProtectedBroadcast
的判断中添加了新增的自定义广播的判断,再验证就没问题了。
综上,要添加一个自定义的系统广播,首先要在frameworksbasecoreresAndroidManifest.xml
中注册成protected-broadcast
,然后需要在ActivityManagerService
中添加判断;这样才能在framework中使用这个广播。
最后,可以根据具体需求,看是否要添加到Intent
类中作为常量,比如需求提供给第三方SDK时,可以添加一下。
注意:这种方式添加的自定义系统广播,任何应用都可以发送相同的广播(与protected-broadcast
设计初衷背道而驰),所以不适用于非常精准和严谨的情况。
后记
单纯是20秒无操作,也许还有其它的实现思路,这里结合自己查到的资料提一下,因为InputEvent
的直接子类只有MotionEvent
以及KeyEvent
,对应了按键输入和“点触”设备输入,所以也可以利用这两点来解决,可能会稍微复杂一点,工作要注意效率,故未深入研究,这里说出思路供有相似需求的小伙伴参考:
PointerEventDispatcher
类及PointerEventListener
接口可以实现触摸以及鼠标点击等touch事件的监听,但是也需要在framework做修改KeyEvent
老生常谈,可以在PhoneWindowManager
做处理
最后
以上就是迷路眼睛为你收集整理的Android P添加自定义系统广播的全部内容,希望文章能够帮你解决Android P添加自定义系统广播所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复