我是靠谱客的博主 迷路眼睛,最近开发中收集的这篇文章主要介绍Android P添加自定义系统广播,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

最近有一个需求,要求实现20秒无操作就跳转到一个界面,因为开发初期没有添加BaseActivity,所以再想在APP中实现事件监听就比较难修改。

正文

查阅资料发现可以在framework的ViewRootImpl类的内部类WindowInputEventReceiveronInputEvent方法中添加广播实现,但是添加后发现会有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添加自定义系统广播所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部