关于Broadcast

前言

广播分类

标准广播:异步收发,所有的广播接收器几乎可以同时收到广播。
有序广播:同步收发,当上一个广播接收器处理逻辑之行完毕后才会继续传递给下一个广播接收器。这样上一个接收器就可以拦截广播,使其中断传递,或者篡改数据继续传递。

本地广播

前面所有广播都是系统全局广播,即发出的广播可以被其他任何应用程序接收到,并且我们也可以接收来自其他任何应用程序的广播。这样就很容易引起安全问题,比附说我们发送一些携带关键性数据的广播可能被其他应用程序所截获,或者其他应用程序不停地向我们的应用发各种垃圾信息。为了能简单地解决广播的安全性问题,android引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收本应用的广播。只能动态注册。

LocalBroadcastManager.getInstance(this).registerReceiver(myBroadcastReceiver, inFilter);
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("com.hdib.broadcast.TEST"));
LocalBroadcastManager.getInstance(this).unregisterReceiver(myBroadcastReceiver);

粘性广播

粘性广播在发送后就一直存在于系统的广播容器里面,等待对应的处理器去处理,如果暂时没有处理器处理这个消息则一直在广播容器里面处于等待状态,粘性广播的Receiver如果被销毁,那么下次重建时会自动接收到广播数据。
注意只能保存最后一次广播数据。
发布粘性广播需要权限:<uses-permission android:name="android.permission.BROADCAST_STICKY" />

已过时,官方不建议使用。

@deprecated Sticky broadcasts should not be used. They provide no security (anyone
can access them), no protection (anyone can modify them), and many other problems.
The recommended pattern is to use a non-sticky broadcast to report that <em>something</em>
has changed, with another mechanism for apps to retrieve the current value whenever
desired.

广播接收者(BroadcastReceiver)

接受来自各处的广播,广播接收者的 onReceive() 方法是在主线程中执行的。

一、简单使用

定义广播接受者

/**
 * 需要注意的是,Receiver被注册(包括静态和动态注册)了几次,就会有几个Receiver对象生成,同时也意味着同一个广播被接收几次。
 */
public class MyBroadcastReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {//这里intent也可以传递参数,但不能被篡改。
        Log.d("MyBroadcastReceiver", "onReceive: " + intent.getAction());
        Bundle bundle = getResultExtras(true); //获取可被篡改的参数
        if (isOrderedBroadcast()) {
            //  篡改参数
            bundle.putString("KEY", "edf");
            setResult(Activity.RESULT_OK, "", bundle);

            //  中断广播
            //  abortBroadcast(); 
        }
    }
}

广播接受者动态注册和取消注册

//动态注册广播,一般在宿主的onCreate()方法中调用
IntentFilter infilter = new IntentFilter();//监听网络状态变化
infilter.addAction("com.hdib.broadcast.TEST");
mbr = new MyBroadcastReceiver();
registerReceiver(mbr, infilter);

//取消动态注册广播,一般在宿主的onDestroy()方法中调用
unregisterReceiver(mbr);

静态注册广播

// 静态注册
<receiver android:name=".receivers.BootCompletedReceiver"
    android:exported="true"
    android:enabled="true">
    <intent-filter>
        <action android:name="com.hdib.broadcast.TEST"/>
    </intent-filter>
</receiver>

发送/中断广播

Intent intent = new Intent("com.hdib.broadcast.TEST");

sendBroadcast(intent); //发送无序广播,所有匹配的广播接收者都会收到广播

sendOrderedBroadcast(intent,null);//发送有序广播,第二个参数是权限,能接受该广播的接收者必须有相应权限,如无需权限传null即可。
sendOrderedBroadcast(intent, null, null, null, Activity.RESULT_OK, "", bundle);//发送有序广播,可以指定广播接收者,以及传递一些可被拦截篡改的参数bundle。

isOrderedBroadcast()//判断是否是有序广播
abortBroadcast()//中断有序广播,只有有序广播才能被中断否则抛异常
clearAbortBroadcast()//清除中断标识,也就是恢复广播

sendStickyBroadcast(new Intent("com.hdib.broadcast.TEST"));//发送粘性广播
sendStickyOrderedBroadcast(intent, null, null, null, Activity.RESULT_OK, "", bundle);//发送粘性有序广播
isInitialStickyBroadcast()//判断是否是粘性广播
context.removeStickyBroadcast(intent);//移除粘性广播

二、常见系统广播

广播名 说明 备注
Intent.ACTION_AIRPLANE_M 关闭或打开飞行模式时的广播
Intent.ACTION_BATTERY_CH 充电状态,或者电池的电量发生变化 电荷级别改变,只能在代码注册
Intent.ACTION_BATTERY_LO 电池电量低
Intent.ACTION_BATTERY_OK 电池电量充足
Intent.ACTION_AIRPLANE_MODE_CHANGED 关闭或打开飞行模
Intent.ACTION_BATTERY_CHANGED 充电状态,或者电池的电量发生变化 电荷级别改变,只能在代码注册
Intent.ACTION_BATTERY_LOW 电池电量低
Intent.ACTION_BATTERY_OKAY 电池电量充足 从电池电量低变化到饱满时会发出广播
Intent.ACTION_BOOT_COMPLETED 在系统启动完成后,这个动作被广播一次 只有一次
Intent.ACTION_CAMERA_BUTTON 按下照相时的拍照按键时发出的广播 硬件按键
Intent.ACTION_CLOSE_SYSTEM_DIALOGS 当屏幕超时进行锁屏时,当用户按下电源按钮,长按或短按(不管有没跳出话框),进行锁屏
Intent.ACTION_CONFIGURATION_CHANGED 设备当前设置被改变时发出的广播 界面语言,设备方向,等 请参考Configuration.java
Intent.ACTION_DATE_CHANGED 设备日期发生改变时
Intent.ACTION_DEVICE_STORAGE_LOW 设备内存不足时发出的广播 此广播只能由系统使用,其它APP不可用
Intent.ACTION_DEVICE_STORAGE_OK 设备内存从不足到充足时发出的广播 此广播只能由系统使用,其它APP不可用
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE 移动APP完成之后,发出的广播 移动是指:APP2SD
Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE 正在移动APP时,发出的广播 移动是指:APP2SD
Intent.ACTION_GTALK_SERVICE_CONNECTED Gtalk已建立连接时发出的广播
Intent.ACTION_GTALK_SERVICE_DISCONNECTED Gtalk已断开连接时发出的广播
Intent.ACTION_HEADSET_PLUG 在耳机口上插入耳机时发出的广播
Intent.ACTION_INPUT_METHOD_CHANGED 改变输入法时发出的广播
Intent.ACTION_LOCALE_CHANGED 设备当前区域设置已更改时发出的广播
Intent.ACTION_MANAGE_PACKAGE_STORAGE 表示用户和包管理所承认的低内存状态通知应该开始
Intent.ACTION_MEDIA_BAD_REMOVAL 未正确移除SD卡 扩展卡已经从SD卡插槽拔出,但是挂载点 (mount point) 还没解除 (unmount)
Intent.ACTION_MEDIA_BUTTON 按下”Media Button” 按键时发出的广播 有”Media Button” 按键的话(硬件按键)
Intent.ACTION_MEDIA_CHECKING 插入外部储存装置 比如SD卡时,系统会检验SD卡,此时发出的广播
Intent.ACTION_MEDIA_EJECT 已拔掉外部大容量储存设备发出的广播 不管有没有正确卸载
Intent.ACTION_MEDIA_MOUNTED 插入SD卡并且已正确安装 扩展介质被插入而且已经被挂载
Intent.ACTION_MEDIA_NOFS 拓展介质存在,但使用不兼容FS(或为空)的路径安装点检查介质包含在Intent.mData领域
Intent.ACTION_MEDIA_REMOVED 外部储存设备已被移除,扩展介质被移除 不管有没正确卸载,都会发出此广播
Intent.ACTION_MEDIA_SCANNER_FINISHED 已经扫描完介质的一个目录
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE 请求媒体扫描仪扫描文件并将其添加到媒体数据库
Intent.ACTION_MEDIA_SCANNER_STARTED 开始扫描介质的一个目录
Intent.ACTION_MEDIA_SHARED 扩展介质的挂载被解除 (unmount) 它已经作为 USB 大容量存储被共享
Intent.ACTION_PACKAGE_ADDED 成功的安装APK 数据包括包名(最新安装的包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_CHANGED 一个已存在的应用程序包已经改变 包括包名
Intent.ACTION_PACKAGE_DATA_CLEARED 清除一个应用程序的数据时发出的广播 清除包程序不能接收到这个广播
Intent.ACTION_PACKAGE_INSTALL 触发一个下载并且完成安装时发出的广播 比如在电子市场里下载应用
Intent.ACTION_PACKAGE_REMOVED 成功的删除某个APK之后发出的广播 正在被安装的包程序不能接收到这个广播
Intent.ACTION_PACKAGE_REPLACED 替换一个现有的安装包时发出的广播(不管现在安装的APP比之前的新还是旧)
Intent.ACTION_PACKAGE_RESTARTED 用户重新开始一个包 重新开始包程序不能接收到这个广播
Intent.ACTION_POWER_CONNECTED 插上外部电源时发出的广播
Intent.ACTION_POWER_DISCONNECTED 已断开外部电源连接时发出的广播
Intent.ACTION_REBOOT 重启设备时的广播
Intent.ACTION_SCREEN_OFF 屏幕被关闭之后的广播
Intent.ACTION_SCREEN_ON 屏幕被打开之后的广播
Intent.ACTION_SHUTDOWN 关闭系统时发出的广播
Intent.ACTION_TIMEZONE_CHANGED 时区发生改变时发出的广播
Intent.ACTION_TIME_CHANGED 时间被设置时发出的广播
Intent.ACTION_TIME_TICK 当前时间已经变化(正常的时间流逝) 每分钟都发送,只能通过来注册
Intent.ACTION_UID_REMOVED 一个用户ID已经从系统中移除发出的广播
Intent.ACTION_UMS_CONNECTED 设备已进入USB大容量储存状态时发出的广播
Intent.ACTION_UMS_DISCONNECTED 设备已从USB大容量储存状态转为正常状态时发出的广播
Intent.ACTION_WALLPAPER_CHANGED 设备墙纸已改变时发出的广播
Intent.ACTION_USER_PRESENT 用户唤醒设备
Intent.ACTION_NEW_OUTGOING_CALL 拨打电话

附:参考

官方文档
CSDN cc_want 博文

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容