Android进阶之路 - 那些年忽视的系统广播

因为最近写了自启动、网络监听等功能,发现都是接收的系统广播,所以索性抽时间去整理了一下系统自带广播,顺带给自己补补课 ~

整理的资料是综合多篇Blog、Android SDK 、And Search 修修补补而来 ~

根据个人习惯划分了耳熟能详(常用)、寡闻少见(较少)、原始权威(SDK)、留心注意(注意点)、课外读物、寻踪觅迹(受限广播)、adb 模拟(shell 广播)

贴士:

//监听广播时前缀有Intent. 如下示例:开机广播
Intent.ACTION_BOOT_COMPLETED   

耳熟能详

广播 描述
ACTION_BOOT_COMPLETED 系统启动完成后发出,只有一次
ACTION_SHUTDOWN 系统关闭时发出 ,只有一次
ACTION_REBOOT 重启设备时的广播
ACTION_SCREEN_OFF 屏幕被关闭
ACTION_SCREEN_ON 屏幕已经被打开
ACTION_BATTERY_CH 电状态,或者电池的电量发生变化 电荷级别改变,只能在代码注册(老版)
ACTION_BATTERY_LO 电池电量低(老版)
ACTION_BATTERY_OK 电池电量充足(老版)
ACTION_BATTERY_CHANGED 电状态,或者电池的电量发生变化 电荷级别改变,只能在代码注册 (新版)
ACTION_BATTERY_LOW 电池电量低(新版)
ACTION_BATTERY_OKAY 电池电量充足 从电池电量低变化到饱满时会发出广播(新版)
ACTION_AIRPLANE_M 关闭或打开飞行模式 (老版)
ACTION_AIRPLANE_MODE_CHANGED 关闭或打开飞行模式(新版)
ACTION_CLOSE_SYSTEM_DIALOGS 当屏幕超时进行锁屏时,当用户按下电源按钮,长按或短按(不管有没跳出话框),进行锁屏时,android系统都会广播此Action消息
ACTION_CONFIGURATION_CHANGED 设备当前设置被改变时发出的广播(包括的改变:界面语言,设备方向,等,请参考Configuration.java)
ACTION_HEADSET_PLUG 在耳机口上插入耳机时发出的广播
ACTION_POWER_CONNECTED 插上外部电源时发出的广播
ACTION_POWER_DISCONNECTED 已断开外部电源连接时发出的广播
ACTION_DEVICE_STORAGE_LOW 设备内存不足时发出的广播,此广播只能由系统使用,其它APP不可用?
ACTION_DEVICE_STORAGE_OK; 设备内存从不足到充足时发出的广播,此广播只能由系统使用,其它APP不可用?
ACTION_TIMEZONE_CHANGED 时区发生改变时发出的广播
ACTION_TIME_CHANGED 时间被设置时发出的广播
ACTION_TIME_TICK 广播:当前时间已经变化(正常的时间流逝),当前时间改变,每分钟都发送,不能通过组件声明来接收,只有通过Context.registerReceiver()方法来注册
ACTION_LOCALE_CHANGED 设备当前区域设置已更改时发出的广播
ACTION_CAMERA_BUTTON 按下照相时的拍照按键(硬件按键)时发出的广播
ACTION_DATE_CHANGED 设备日期发生改变时会发出此广播
ACTION_INPUT_METHOD_CHANGED 改变输入法时发出的广播
ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE 正在移动APP时,发出的广播(移动是指:APP2SD)
ACTION_EXTERNAL_APPLICATIONS_AVAILABLE 移动APP完成之后,发出的广播(移动是指:APP2SD)
ACTION_NEW_OUTGOING_CALL 拨打电话
ACTION_USER_PRESENT 用户唤醒设备
ACTION_PACKAGE_REMOVED 成功的删除某个APK之后发出的广播;一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播)
ACTION_PACKAGE_REPLACED 替换一个现有的安装包时发出的广播(不管现在安装的APP比之前的新还是旧,都会发出此广播?)
ACTION_PACKAGE_RESTARTED 用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播)
ACTION_PACKAGE_CHANGED 一个已存在的应用程序包已经改变,包括包名
ACTION_PACKAGE_DATA_CLEARED 清除一个应用程序的数据时发出的广播(在设置--应用管理--选中某个应用,之后点清除数据时?)用户已经清除一个包的数据,包括包名(清除包程序不能接收到这个广播)
ACTION_PACKAGE_INSTALL 触发一个下载并且完成安装时发出的广播,比如在电子市场里下载应用?

寡闻少见

广播 描述
ACTION_WALLPAPER_CHANGED 设备墙纸已改变时发出的广播
ACTION_UID_REMOVED 一个用户ID已经从系统中移除发出的广播
ACTION_GTALK_SERVICE_CONNECTED Gtalk已建立连接时发出的广播
ACTION_GTALK_SERVICE_DISCONNECTED 已断开连接时发出的广播
ACTION_DOCK_EVENT 插入、拨出底座时广播
ACTION_MEDIA_BAD_REMOVAL 未正确移除SD卡(正确移除SD卡的方法:设置–SD卡和设备内存–卸载SD卡),但已把SD卡取出来时发出的广播;广播:扩展介质(扩展卡)已经从 SD 卡插槽拔出,但是挂载点 (mount point) 还没解除 (unmount)
ACTION_MEDIA_BUTTON 按下"Media Button" 按键时发出的广播,假如有"Media Button"按键的话(硬件按键)
ACTION_MEDIA_CHECKING 插入外部储存装置,比如SD卡时,系统会检验SD卡,此时发出的广播?
ACTION_MEDIA_EJECT 已拔掉外部大容量储存设备发出的广播(比如SD卡,或移动硬盘),不管有没有正确卸载都会发出此广播?广播:用户想要移除扩展介质(拔掉扩展卡)
ACTION_MEDIA_MOUNTED 插入SD卡并且已正确安装(识别)时发出的广播;广播:扩展介质被插入,而且已经被挂载
ACTION_MEDIA_REMOVED 外部储存设备已被移除,不管有没正确卸载,都会发出此广播?广播:扩展介质被移除
ACTION_MEDIA_SCANNER_FINISHED 已经扫描完介质的一个目录
ACTION_MEDIA_SCANNER_STARTED 开始扫描介质的一个目录
ACTION_MEDIA_SHARED 扩展介质的挂载被解除 (unmount),因为它已经作为 USB 大容量存储被共享
ACTION_MEDIA_UNMOUNTED 扩展介质存在,但是还没有被挂载 (mount)
ACTION_UMS_CONNECTED 设备已进入USB大容量储存状态时发出的广播
ACTION_UMS_DISCONNECTED 设备已从USB大容量储存状态转为正常状态时发出的广播

原始权威

Android SDK下有个Intent类,类内ACTION开头的代码我猜想都是广播了,我就不一 一赘述了哈 ~

当然这些广播是否就代表所有系统广播,这个我也不太确定,均是自己猜想…

ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";
ACTION_ALL_APPS = "android.intent.action.ALL_APPS";
ACTION_ANSWER = "android.intent.action.ANSWER";
ACTION_APPLICATION_PREFERENCES = "android.intent.action.APPLICATION_PREFERENCES";
ACTION_APPLICATION_RESTRICTIONS_CHANGED = "android.intent.action.APPLICATION_RESTRICTIO
ACTION_APP_ERROR = "android.intent.action.APP_ERROR";
ACTION_ASSIST = "android.intent.action.ASSIST";
ACTION_ATTACH_DATA = "android.intent.action.ATTACH_DATA";
ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";
ACTION_BATTERY_LOW = "android.intent.action.BATTERY_LOW";
ACTION_BATTERY_OKAY = "android.intent.action.BATTERY_OKAY";
ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
ACTION_BUG_REPORT = "android.intent.action.BUG_REPORT";
ACTION_CALL = "android.intent.action.CALL";
ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
ACTION_CHOOSER = "android.intent.action.CHOOSER";
ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
ACTION_CONFIGURATION_CHANGED = "android.intent.action.CONFIGURATION_CHANGED";
ACTION_CREATE_DOCUMENT = "android.intent.action.CREATE_DOCUMENT";
ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT";
ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED";
ACTION_DEFAULT = "android.intent.action.VIEW";
ACTION_DELETE = "android.intent.action.DELETE";
ACTION_DEVICE_STORAGE_LOW = "android.intent.action.DEVICE_STORAGE_LOW";
ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
ACTION_DIAL = "android.intent.action.DIAL";
ACTION_DOCK_EVENT = "android.intent.action.DOCK_EVENT";
ACTION_DREAMING_STARTED = "android.intent.action.DREAMING_STARTED";
ACTION_DREAMING_STOPPED = "android.intent.action.DREAMING_STOPPED";
ACTION_EDIT = "android.intent.action.EDIT";
ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_A
ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS
ACTION_FACTORY_TEST = "android.intent.action.FACTORY_TEST";
ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT";
ACTION_GET_RESTRICTION_ENTRIES = "android.intent.action.GET_RESTRICTION_ENTRIES";
ACTION_GTALK_SERVICE_CONNECTED = "android.intent.action.GTALK_CONNECTED";
ACTION_GTALK_SERVICE_DISCONNECTED = "android.intent.action.GTALK_DISCONNECTED";
ACTION_HEADSET_PLUG = "android.intent.action.HEADSET_PLUG";
ACTION_INPUT_METHOD_CHANGED = "android.intent.action.INPUT_METHOD_CHANGED";
ACTION_INSERT = "android.intent.action.INSERT";
ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
ACTION_INSTALL_FAILURE = "android.intent.action.INSTALL_FAILURE";
ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
ACTION_MAIN = "android.intent.action.MAIN";
ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
ACTION_MANAGED_PROFILE_AVAILABLE = "android.intent.action.MANAGED_PROFILE_AVAILABLE";
ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
ACTION_MANAGED_PROFILE_UNAVAILABLE = "android.intent.action.MANAGED_PROFILE_UNAVAILABLE
ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING";
ACTION_MEDIA_EJECT = "android.intent.action.MEDIA_EJECT";
ACTION_MEDIA_MOUNTED = "android.intent.action.MEDIA_MOUNTED";
ACTION_MEDIA_NOFS = "android.intent.action.MEDIA_NOFS";
ACTION_MEDIA_REMOVED = "android.intent.action.MEDIA_REMOVED";
ACTION_MEDIA_SCANNER_FINISHED = "android.intent.action.MEDIA_SCANNER_FINISHED";
ACTION_MEDIA_SCANNER_SCAN_FILE = "android.intent.action.MEDIA_SCANNER_SCAN_FILE";
ACTION_MEDIA_SCANNER_STARTED = "android.intent.action.MEDIA_SCANNER_STARTED";
ACTION_MEDIA_SHARED = "android.intent.action.MEDIA_SHARED";
ACTION_MEDIA_UNMOUNTABLE = "android.intent.action.MEDIA_UNMOUNTABLE";
ACTION_MEDIA_UNMOUNTED = "android.intent.action.MEDIA_UNMOUNTED";
ACTION_MY_PACKAGE_REPLACED = "android.intent.action.MY_PACKAGE_REPLACED";
ACTION_NEW_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
ACTION_OPEN_DOCUMENT = "android.intent.action.OPEN_DOCUMENT";
ACTION_OPEN_DOCUMENT_TREE = "android.intent.action.OPEN_DOCUMENT_TREE";
ACTION_PACKAGES_SUSPENDED = "android.intent.action.PACKAGES_SUSPENDED";
ACTION_PACKAGES_UNSUSPENDED = "android.intent.action.PACKAGES_UNSUSPENDED";
ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION";
ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED";
ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED";
ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED";
ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED";
ACTION_PASTE = "android.intent.action.PASTE";
ACTION_PICK = "android.intent.action.PICK";
ACTION_PICK_ACTIVITY = "android.intent.action.PICK_ACTIVITY";
ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED";
ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";
ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY";
ACTION_PROCESS_TEXT = "android.intent.action.PROCESS_TEXT";
ACTION_PROVIDER_CHANGED = "android.intent.action.PROVIDER_CHANGED";
ACTION_QUICK_CLOCK = "android.intent.action.QUICK_CLOCK";
ACTION_QUICK_VIEW = "android.intent.action.QUICK_VIEW";
ACTION_REBOOT = "android.intent.action.REBOOT";
ACTION_RUN = "android.intent.action.RUN";
ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
ACTION_SEARCH = "android.intent.action.SEARCH";
ACTION_SEARCH_LONG_PRESS = "android.intent.action.SEARCH_LONG_PRESS";
ACTION_SEND = "android.intent.action.SEND";
ACTION_SENDTO = "android.intent.action.SENDTO";
ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE";
ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER";
ACTION_SHOW_APP_INFO = "android.intent.action.SHOW_APP_INFO";
ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
ACTION_SYNC = "android.intent.action.SYNC";
ACTION_SYSTEM_TUTORIAL = "android.intent.action.SYSTEM_TUTORIAL";
ACTION_TIMEZONE_CHANGED = "android.intent.action.TIMEZONE_CHANGED";
ACTION_TIME_CHANGED = "android.intent.action.TIME_SET";
ACTION_TIME_TICK = "android.intent.action.TIME_TICK";
ACTION_UID_REMOVED = "android.intent.action.UID_REMOVED";
ACTION_UMS_CONNECTED = "android.intent.action.UMS_CONNECTED";
ACTION_UMS_DISCONNECTED = "android.intent.action.UMS_DISCONNECTED";
ACTION_UNINSTALL_PACKAGE = "android.intent.action.UNINSTALL_PACKAGE";
ACTION_USER_BACKGROUND = "android.intent.action.USER_BACKGROUND";
ACTION_USER_FOREGROUND = "android.intent.action.USER_FOREGROUND";
ACTION_USER_INITIALIZE = "android.intent.action.USER_INITIALIZE";
ACTION_USER_PRESENT = "android.intent.action.USER_PRESENT";
ACTION_USER_UNLOCKED = "android.intent.action.USER_UNLOCKED";
ACTION_VIEW = "android.intent.action.VIEW";
ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";

留心注意

补课与此:这些系统广播只能由系统发出,第三方应用是无法发送系统广播的,第三方应用如果尝试发送系统广播,会报下面的错误:

java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action. (这部分就看你发的是哪个系统广播了:BOOT_COMPLETED from pid=31204, uid=10076)
        at android.os.Parcel.readException(Parcel.java:1683)
        at android.os.Parcel.readException(Parcel.java:1636)
        at android.app.ActivityManagerProxy.broadcastIntent(ActivityManagerNative.java:3609)
        at android.app.ContextImpl.sendBroadcast(ContextImpl.java:893)
        at android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:421)

该异常由frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java的broadcastIntentLocked方法所发出的:

// First line security check before anything else: stop non-system apps from
        // sending protected broadcasts.
        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);
            }
        }

其实Intent里面所列举的系统广播可能并不全,系统广播的声明其实是在AndroidManifest.xml里面,利用protected-broadcast标签来声明,如下面所示:

<protected-broadcast android:name="android.intent.action.SCREEN_OFF" />

下面五个系统广播是只能动态注册而不支持静态注册:

android.intent.action.SCREEN_ON
android.intent.action.SCREEN_OFF
android.intent.action.BATTERY_CHANGED
android.intent.action.CONFIGURATION_CHANGED
android.intent.action.TIME_TICK

课外读物

整理拍照或从相册中取图片功能,拍照之后的图片立马能在相册中看到。我们都知道相册里的图片数据是在sd卡挂载的时候扫描的,如果要想拍照之后在相册中看到图片是不能的,但是呢,我们可以向系统发出一条sd挂载的广播,欺骗一下系统图库应用让其去扫描sd卡并加载图片。只要在拍照成功之后加如下代码即可:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

补课与此,也补课与此 :谷歌从4.4版本后保护了一些广播,不允许系统之外的应用发送这些广播,可以AndroidManifest.xml 中看到这条权限被保护了,只有系统能发送。同时给出了两种解决方法:

第一种:
4.4以上版本用(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)解决,4.4以下用原来的解决办法

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    
    //4.4版本以上
    Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    Uri contentUri = Uri.fromFile(outputFile); 
    scanIntent.setData(contentUri);
    sendBroadcast(scanIntent);
} else {
    
    4.4版本以下
    Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()));
    sendBroadcast(intent);
}

第二种:
此方法兼容4.4以下及以上(推荐使用)

MediaScannerConnection.scanFile(this, new String[] {
    
    file.getAbsolutePath()},null, null);

寻踪觅迹

主要来源于好奇心,看到AndroidManifest中有受限广播,果断去找找,然后果然没找到,此AndroidManifest好像非我们看到的那个AndroidManifest … 所以在补补课 ~
包含受限广播的AndroidManifestt.xml源自Android源码Telephony模块,文件里声明了大量的protected-broadcast:

<protected-broadcast android:name=
"android.intent.action.DATA_SMS_RECEIVED" />
 
<protected-broadcast android:name=
"android.provider.Telephony.SMS_RECEIVED" />
 
...

声明的都是一些广播action,比如新短信到达的广播"android.provider.Telephony.SMS_RECEIVED",显然这些广播action都是很重要的广播,并不能随随便便发送,所以android就做了限制。而直接从protected-broadcast字面意思来看,是受保护的广播,确实也是如此:

protected-broadcast用来指定一个广播,该广播只能被系统发送,如果普通APP在自己的xml里声明了这些广播,发送时也会被提示错误。"Permission Denial: not allowed to send broadcast"

那么谁有权限来发送这些广播呢?也就是说所谓的系统APP都有哪些呢?

这里直接说结论:

发送广播最终都会通过AMS(ActivityManagerService)来发送,而在最终调用里,会看到有关protected-broadcast的判断


/*
* Prevent non-system code (defined here to be non-persistent
* processes) from sending protected broadcasts.
*/
 
int callingAppId = UserHandle.getAppId(callingUid);
if (callingAppId == Process.SYSTEM_UID
||callingAppId == Process.PHONE_UID
||callingAppId == Process.SHELL_UID
||callingAppId == Process.BLUETOOTH_UID
||callingAppId == Process.NFC_UID
||callingUid == 0) {
    
    
// Always okay.
} else {
    
    
..........
}

所以可以看出是通过UID来过滤的,SYSTEM_UID,PHONE_UID,SHELL_UID,BLUETOOTH_UID,NFC_UID,以及root(uid == 0).

/**
* Defines the root UID.
* @hide
*/
public static final int ROOT_UID = 0;
 
/**
* Defines the UID/GID under which system code runs.
*/
 
public static final int SYSTEM_UID = 1000;
 
/**
* Defines the UID/GID under which the telephony code runs.
*/
public static final int PHONE_UID = 1001;
 
/**
* Defines the UID/GID for the user shell.
* @hide
*/
public static final int SHELL_UID = 2000;
 
/**
* Defines the UID/GID for the log group.
* @hide
*/
public static final int LOG_UID = 1007;

PID 和 UID

  • PID
    为Process Identifier,PID就是各进程的身份标识,程序一运行系统就会自动分配给进程一个独一无二的PID。linux中进程中止后PID被系统回收,可能会被继续分配给新运行的程序,但是在android系统中一般不会把已经kill掉的进程ID重新分配给新的进程,新产生进程的进程号,一般比产生之前所有的进程号都要大

  • UID
    一般理解为User Identifier,UID在linux中就是用户的ID,表明时哪个用户运行了这个程序,主要用于权限的管理。而在android 中又有所不同,除了进行权限控制之外,Android还使用它来进行一些数据的共享,这也就是在AndroidManifest.xml里使用android:sharedUserId的作用,使用同一个sharedUserId的两个不同APP,可以运行在同一个进程,并且可以相互访问数据。而普通的两个不同APP,是不能随意相互访问数据的,只能通过跨进程访问

如果连接真机通过ps命令查看所有进程,可以看到第一列是user,这就是UID的描述

adb 模拟

补课与此:模拟开机广播

adb shell am broadcast -a android.intent.action.BOOT_COMPLETED

当然你也可以直接指定自己定义BroadcastReceiver接收广播,如下

adb shell am broadcast -a android.intent.action.BOOT_COMPLETED -n com.him.mypkg/com.him.mypkg.receiver.BootReceiver

权限拒绝
在有些设备上可能会报类似java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.BOOT_COMPLETED from pid=3715, uid=2000这样的错误

遇到这个错误可以先执行adb root再执行发送广播的命令就可以了

adb root
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED

无法接收到广播可能是以下几个原因造成的

  • 未添加权限
  • 被系统自带或360手机助手等拦截,需在权限管理设置里放开开机自启动的权限
  • 应用安装到sd卡上,安装在sd卡上的应用是收不到BOOT_COMPLETED广播的
  • 系统开启了Fast Boot模式,这种模式下系统启动并不会发送BOOT_COMPLETED广播
  • 应用程序安装后重来没有启动过,这种情况下应用程序接收不到任何广播
    第一次安装无效,需重新启动
    收不到广播,被系统拦截

猜你喜欢

转载自blog.csdn.net/qq_20451879/article/details/106264174
今日推荐