Android发送广播时报错:Sending non-protected broadcast xxxxxxx from system xxxxxxxxxx

简介: Android发送广播时报错:Sending non-protected broadcast xxxxxxx from system xxxxxxxxxx

带android:sharedUserId=“android.uid.system” 发送广播时,会出现 Sending non-protected broadcast 异常提醒;

原因:

Ams在发送广播时,对于systemApp(系统应用),会要求发送广播必须是声明在frameworks\base\core\res\AndroidManifest.xml里面的protected-broadcast。这是为了提醒 系统应用开发者要将 broadcast 添加到protected-broadcast,因为非 protexted-broadcast 广播是可以被三方应用发送的。定义为 proected-broadcast 可以避免三方垃圾应用也发送这些广播来捣蛋。

查找问题

首先去搜索问题出现的位置 ,去AndroidXRef网站搜索下

定位到frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

类中,在checkBroadcastFromSystem中抛出该异常。

checkBroadcastFromSytem是用于检测系统应用发出的广播是否安全,如果发出的广播不安全,就会抛出no-protected broadcast异常,提醒系统应用开发者。

为什么要有这个机制?

这是为了提醒 系统应用开发者去将 broadcast添加为protected-broadcast,因为非 protected-broadcast 广播是可以被三方应用发送的。 而定义为 proected-broadcast 就能防止恶意的三方应用模仿系统应用去发出该广播。

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)
                || 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)) {
            // Broadcast is either protected, or it's a public action that
            // we've relaxed, so it's fine for system internals to send.
            return;
        }
 
        // This broadcast may be a problem...  but there are often system components that
        // want to send an internal broadcast to themselves, which is annoying to have to
        // explicitly list each action as a protected broadcast, so we will check for that
        // one safe case and allow it: an explicit broadcast, only being received by something
        // that has protected itself.
        if (intent.getPackage() != null || intent.getComponent() != null) {
            if (receivers == null || receivers.size() == 0) {
                // Intent is explicit and there's no receivers.
                // This happens, e.g. , when a system component sends a broadcast to
                // its own runtime receiver, and there's no manifest receivers for it,
                // because this method is called twice for each broadcast,
                // for runtime receivers and manifest receivers and the later check would find
                // no receivers.
                return;
            }
            boolean allProtected = true;
            for (int i = receivers.size()-1; i >= 0; i--) {
                Object target = receivers.get(i);
                if (target instanceof ResolveInfo) {
                    ResolveInfo ri = (ResolveInfo)target;
                    if (ri.activityInfo.exported && ri.activityInfo.permission == null) {
                        allProtected = false;
                        break;
                    }
                } else {
                    BroadcastFilter bf = (BroadcastFilter)target;
                    if (bf.requiredPermission == null) {
                        allProtected = false;
                        break;
                    }
                }
            }
            if (allProtected) {
                // All safe!
                return;
            }
        }
 
        // The vast majority of broadcasts sent from system internals
        // should be protected to avoid security holes, so yell loudly
        // to ensure we examine these cases.
        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());
        }
    }


如上代码, 对于广播,checkBroadcastFromSystem方法有三种检测。


  1. 如果Action 是Shell 发出的,则直接返回,不发出警告


  1. 如果Action 是protected-broadcast广播或一些指定的Action,不发出警告


  1. 如果Action 是指定了包名或者Compononent信息,只有特定应用能接收,则当所有receiver 均根据receiverPermisson 对权限进行了顾虑,则不发出警告


如果系统应用不满足以上三种情况,则发送公共广播时会被警告

如何解决 non-protected broadcast警告


从系统源码层面


1.在checkBroadcastFromSystem 处修改

 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)) {
            // Broadcast is either protected, or it's a public action that
            // we've relaxed, so it's fine for system internals to send.
            return;
        }
复制代码


2在/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java#isProtectedBroadcast方法处修改

3.在/frameworks/base/core/res/AndroidManifest.xml 处增加 protected-broadcast 标签

在应用层面修改

  1. 在系统应用的 AndroidManifest.xml 处增加 protected-broadcast 标签,且apk放在 /system/priv-app 目录下
  2. 指定接收者.获取所有接收该广播的ResolveInfo,发送广播。
目录
相关文章
|
1天前
|
存储 Android开发
Android插件化-Broadcast篇,2024年最新安卓面试自我介绍
Android插件化-Broadcast篇,2024年最新安卓面试自我介绍
|
4天前
|
API Android开发
Android12 内置应用问题 mismatch in the <uses-library> tags between the build system and the manifest
Android12 内置应用问题 mismatch in the <uses-library> tags between the build system and the manifest
20 0
|
4天前
|
Android开发
Android修改默认system/bin/下可执行程序拥有者和权限,使用实例,只有root和系统app权限才能执行某个命令。
Android修改默认system/bin/下可执行程序拥有者和权限,使用实例,只有root和系统app权限才能执行某个命令。 【5月更文挑战第2天】
18 0
|
存储 Linux Shell
【Android 逆向】Android 系统文件分析 ( /system/ 系统命令和系统应用数据目录 | /system/app/ 系统应用目录 | sys Linux 系统内核文件目录 )
【Android 逆向】Android 系统文件分析 ( /system/ 系统命令和系统应用数据目录 | /system/app/ 系统应用目录 | sys Linux 系统内核文件目录 )
394 0
【Android 逆向】Android 系统文件分析 ( /system/ 系统命令和系统应用数据目录 | /system/app/ 系统应用目录 | sys Linux 系统内核文件目录 )
|
4天前
|
XML Java Android开发
Android Studio App开发之监听系统广播Broadcast的讲解及实战(包括接收分钟到达广播、网络变更广播、定时管理器等 附源码)
Android Studio App开发之监听系统广播Broadcast的讲解及实战(包括接收分钟到达广播、网络变更广播、定时管理器等 附源码)
114 0
|
4天前
|
XML 安全 Java
Android Studio App开发之广播组件Broadcast的讲解及实战(包括收发标准、有序、静态广播实现手机震动功能 附源码)
Android Studio App开发之广播组件Broadcast的讲解及实战(包括收发标准、有序、静态广播实现手机震动功能 附源码)
60 0
|
11月前
|
Android开发
Android:四大组件之 Broadcast(广播)
Broadcast 是一种广泛运用的、在应用程序之间传输信息的机制,Android 中的广播与传统意义上的电台广播类似,一个广播可以有任意个接收者,当然也可能不被任何应用程序所接收。广播机制是一个典型的发布-订阅模式,也就是观察者模式。
75 0
Android:四大组件之 Broadcast(广播)
|
开发工具 Android开发
Android App开发超实用实例 | ​Broadcast
介绍Broadcast的静态注册、动态注册及有序广播。 Broadcast(广播)分为发送者和接收者,可实现跨应用的消息传递。重启手机、闹钟、来电、接收短信等都会发出广播,通过BroadcastReceiver就可以接收广播并进行相应处理。
140 0
Android App开发超实用实例 | ​Broadcast
|
开发工具 Android开发
Android Studio 报错Emulator: PANIC: Cannot find AVD system path. Please define ANDROID_SDK_ROOT(解决方案)
Android Studio 报错Emulator: PANIC: Cannot find AVD system path. Please define ANDROID_SDK_ROOT(解决方案)
Android Studio 报错Emulator: PANIC: Cannot find AVD system path. Please define ANDROID_SDK_ROOT(解决方案)