Android——广播

谈到广播,必然会联想到观察者模式

注册广播就相当于主题的registerObserver

取消广播就相当于主题的removeObserver

发送广播就相当于主题的notifyObserver

接收广播就相当于观察者的update

至于什么是观察者模式,这篇文章写得很好啊:http://blog.csdn.net/lmj623565791/article/details/24179699

 

Android系统本身就内置了很多广播,可以注册监听

比如说开机,网络变化,时区变化等,具体如下

  1 //关闭或打开飞行模式时的广播
  2 Intent.ACTION_AIRPLANE_M;
  3 
  4 //充电状态,或者电池的电量发生变化;//电池的充电状态、电荷级别改变,不能通过组建声;
  5 Intent.ACTION_BATTERY_CH;
  6 
  7 //表示电池电量低
  8 Intent.ACTION_BATTERY_LO;
  9 
 10 //表示电池电量充足
 11 Intent.ACTION_BATTERY_OK;
 12 
 13 //关闭或打开飞行模式时的广播
 14 Intent.ACTION_AIRPLANE_MODE_CHANGED;
 15 
 16 //充电状态,或者电池的电量发生变化//电池的充电状态、电荷级别改变,不能通过组建声明接收这个广播,只有通过Context.registerReceiver()注册
 17 Intent.ACTION_BATTERY_CHANGED;
 18 
 19 //表示电池电量低
 20 Intent.ACTION_BATTERY_LOW;
 21 
 22 //表示电池电量充足,即从电池电量低变化到饱满时会发出广播
 23 Intent.ACTION_BATTERY_OKAY;
 24 
 25 //在系统启动完成后,这个动作被广播一次(只有一次)。
 26 Intent.ACTION_BOOT_COMPLETED;
 27 
 28 //按下照相时的拍照按键(硬件按键)时发出的广播
 29 Intent.ACTION_CAMERA_BUTTON;
 30 
 31 //当屏幕超时进行锁屏时,当用户按下电源按钮,长按或短按(不管有没跳出话框),进行锁屏时,android系统都会广播此Action消息
 32 Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
 33 
 34 //设备当前设置被改变时发出的广播(包括的改变:界面语言,设备方向,等,请参考Configuration.java)
 35 Intent.ACTION_CONFIGURATION_CHANGED;
 36 
 37 //设备日期发生改变时会发出此广播
 38 Intent.ACTION_DATE_CHANGED;
 39 
 40 //设备内存不足时发出的广播,此广播只能由系统使用,其它APP不可用
 41 Intent.ACTION_DEVICE_STORAGE_LOW;
 42 
 43 //设备内存从不足到充足时发出的广播,此广播只能由系统使用,其它APP不可用
 44 Intent.ACTION_DEVICE_STORAGE_OK;
 45 
 46 //发出此广播的地方frameworks\base\services\java\com\android\server\DockObserver.java
 47 Intent.ACTION_DOCK_EVENT;
 48 
 49 //移动APP完成之后,发出的广播(移动是指:APP2SD)
 50 Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE;
 51 
 52 //正在移动APP时,发出的广播(移动是指:APP2SD)
 53 Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
 54 
 55 //Gtalk已建立连接时发出的广播
 56 Intent.ACTION_GTALK_SERVICE_CONNECTED;
 57 
 58 //Gtalk已断开连接时发出的广播
 59 Intent.ACTION_GTALK_SERVICE_DISCONNECTED;
 60 
 61 //在耳机口上插入耳机时发出的广播
 62 Intent.ACTION_HEADSET_PLUG;
 63 
 64 //改变输入法时发出的广播
 65 Intent.ACTION_INPUT_METHOD_CHANGED;
 66 
 67 //设备当前区域设置已更改时发出的广播
 68 Intent.ACTION_LOCALE_CHANGED;
 69 
 70 //表示用户和包管理所承认的低内存状态通知应该开始。
 71 Intent.ACTION_MANAGE_PACKAGE_STORAGE;
 72 
 73 //未正确移除SD卡(正确移除SD卡的方法:设置--SD卡和设备内存--卸载SD卡),但已把SD卡取出来时发出的广播 ,扩展介质(扩展卡)已经从 SD 卡插槽拔出,但是挂载点 (mount point) 还没解除 (unmount)
 74 Intent.ACTION_MEDIA_BAD_REMOVAL;
 75 
 76 //按下"Media Button" 按键时发出的广播,假如有"Media Button" 按键的话(硬件按键)
 77 Intent.ACTION_MEDIA_BUTTON;
 78 
 79 //插入外部储存装置,比如SD卡时,系统会检验SD卡,此时发出的广播?
 80 Intent.ACTION_MEDIA_CHECKING;
 81 
 82 //已拔掉外部大容量储存设备发出的广播(比如SD卡,或移动硬盘),不管有没有正确卸载都会发出此广播, 用户想要移除扩展介质(拔掉扩展卡)。
 83 Intent.ACTION_MEDIA_EJECT;
 84 
 85 //插入SD卡并且已正确安装(识别)时发出的广播, 扩展介质被插入,而且已经被挂载。
 86 Intent.ACTION_MEDIA_MOUNTED;
 87 
 88 //拓展介质存在,但使用不兼容FS(或为空)的路径安装点检查介质包含在Intent.mData领域。
 89 Intent.ACTION_MEDIA_NOFS;
 90 
 91 //外部储存设备已被移除,不管有没正确卸载,都会发出此广播, 扩展介质被移除。
 92 Intent.ACTION_MEDIA_REMOVED;
 93 
 94 //广播:已经扫描完介质的一个目录
 95 Intent.ACTION_MEDIA_SCANNER_FINISHED;
 96 
 97 //请求媒体扫描仪扫描文件并将其添加到媒体数据库。
 98 Intent.ACTION_MEDIA_SCANNER_SCAN_FILE;
 99 
100 //广播:开始扫描介质的一个目录
101 Intent.ACTION_MEDIA_SCANNER_STARTED;
102 
103 // 广播:扩展介质的挂载被解除 (unmount),因为它已经作为 USB 大容量存储被共享。
104 Intent.ACTION_MEDIA_SHARED;
105 
106 Intent.ACTION_MEDIA_UNMOUNTABLE;//
107 
108 // 广播:扩展介质存在,但是还没有被挂载 (mount)
109 Intent.ACTION_MEDIA_UNMOUNTED
110 
111 Intent.ACTION_NEW_OUTGOING_CALL;
112 
113 //成功的安装APK之后//广播:设备上新安装了一个应用程序包。//一个新应用包已经安装在设备上,数据包括包名(最新安装的包程序不能接收到这个广播)
114 Intent.ACTION_PACKAGE_ADDED;
115 
116 //一个已存在的应用程序包已经改变,包括包名
117 Intent.ACTION_PACKAGE_CHANGED;
118 
119 //清除一个应用程序的数据时发出的广播(在设置--应用管理--选中某个应用,之后点清除数据时?)//用户已经清除一个包的数据,包括包名(清除包程序不能接收到这个广播)
120 Intent.ACTION_PACKAGE_DATA_CLEARED;
121 
122 //触发一个下载并且完成安装时发出的广播,比如在电子市场里下载应用?
123 Intent.ACTION_PACKAGE_INSTALL;
124 
125 //成功的删除某个APK之后发出的广播, 一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播)
126 Intent.ACTION_PACKAGE_REMOVED;
127 
128 //替换一个现有的安装包时发出的广播(不管现在安装的APP比之前的新还是旧,都会发出此广播?)
129 Intent.ACTION_PACKAGE_REPLACED;
130 
131 //用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播)
132 Intent.ACTION_PACKAGE_RESTARTED;
133 
134 //插上外部电源时发出的广播
135 Intent.ACTION_POWER_CONNECTED;
136 
137 //已断开外部电源连接时发出的广播
138 Intent.ACTION_POWER_DISCONNECTED;
139 
140 Intent.ACTION_PROVIDER_CHANGED;//
141 
142 //重启设备时的广播
143 Intent.ACTION_REBOOT;
144 
145 //屏幕被关闭之后的广播
146 Intent.ACTION_SCREEN_OFF;
147 
148 //屏幕被打开之后的广播
149 Intent.ACTION_SCREEN_ON;
150 
151 //关闭系统时发出的广播
152 Intent.ACTION_SHUTDOWN;
153 
154 //时区发生改变时发出的广播
155 Intent.ACTION_TIMEZONE_CHANGED;
156 
157 //时间被设置时发出的广播
158 Intent.ACTION_TIME_CHANGED;
159 
160 //广播:当前时间已经变化(正常的时间流逝), 当前时间改变,每分钟都发送,不能通过组件声明来接收
161 ,只有通过Context.registerReceiver()方法来注册
162 Intent.ACTION_TIME_TICK;
163 
164 //一个用户ID已经从系统中移除发出的广播
165 Intent.ACTION_UID_REMOVED;
166 
167 //设备已进入USB大容量储存状态时发出的广播?
168 Intent.ACTION_UMS_CONNECTED;
169 
170 //设备已从USB大容量储存状态转为正常状态时发出的广播?
171 Intent.ACTION_UMS_DISCONNECTED;
172 
173 Intent.ACTION_USER_PRESENT;//
174 
175 //设备墙纸已改变时发出的广播
176 Intent.ACTION_WALLPAPER_CHANGED;
系统广播

 

注册广播的方式:动态广播、静态广播

动态广播接收器——程序运行时可接收

1.新建一个广播接收器内部类继承BroadcastReceiver
2.实现onReceive方法,在这里只能进行简单的业务处理(因不允许开启线程 处理耗时操作将会报错 接收器主要用于打开其他组件)
如果需要获取系统关键信息如网络状态,必须在AndroidManifest.xml中声明权限
如:<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

3.创建接收器实例receiver————以registerReceiver(receiver,intentFilter)为主线
4.创建intentFilter实例intentFilter
5.intentFilter添加具体需要监听的广播action
如:intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
6.registerReceiver(...)

7.一定要有一个取消注册的动作,如:unregisterReceiver(..receiver)————在活动销毁的时候

 1 public class MainActivity extends Activity {
 2     private NetworkChangeBroadcaseReceiver networkChangeBroadcaseReceiver;
 3     private IntentFilter intentFilter;
 4 
 5     /**
 6      * 注册碎片:registerReceiver(..receiver,intentFilter) ..receiver为广播接收器实例
 7      * intentFilter为IntentFilter实例:注册 活动 、 服务 和 广播接收器 具有能在某种数据上执行一个动作的能力。
 8      */
 9     @Override
10     protected void onCreate(Bundle savedInstanceState) {
11         super.onCreate(savedInstanceState);
12         setContentView(R.layout.activity_main);
13 
14         intentFilter = new IntentFilter();
15         intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
16         networkChangeBroadcaseReceiver = new NetworkChangeBroadcaseReceiver();
17         // public Intent registerReceiver(BroadcastReceiver receiver,IntentFilter filter)
18         registerReceiver(networkChangeBroadcaseReceiver, intentFilter);
19         
20     }
21 
22     /** 一定要有一个销毁喇叭的动作 */
23     @Override
24     protected void onDestroy() {
25         super.onDestroy();
26         // 取消注册
27         unregisterReceiver(networkChangeBroadcaseReceiver);
28     }
29 
30     /**
31      * 
32      * 然而这样做了并不能运行程序,会直接报错:必须要在AndroidManifest.xml中声明系统权限
33      */
34     class NetworkChangeBroadcaseReceiver extends BroadcastReceiver {
35 
36         @Override
37         public void onReceive(Context context, Intent intent) {
38             // 为了能够知道网络是断了还是连上了——连通性管理器,管理action
39             ConnectivityManager connectivityManager =
40                     (ConnectivityManager) getSystemService(context.CONNECTIVITY_SERVICE);
41             // 通过管理器获得网络信息
42             NetworkInfo networkInfo =connectivityManager.getActiveNetworkInfo();
43             if (networkInfo!=null && networkInfo.isAvailable()) {
44                 Toast.makeText(context, "net work is available", Toast.LENGTH_SHORT).show();
45                 
46             } else {
47                 Toast.makeText(context, "net work is unavailable", Toast.LENGTH_SHORT).show();
48 
49             }
50         }
51 
52     }
53 }
MainActivity

静态注册广播接收器——程序不运行都可接收

1.定义一个广播接收器类,继承BroadcastReceiver,复写onReceive方法,进行简单业务处理
2.AndroidManifest声明权限<uses-permission>
3.AndroidManifest在<application>中添加<receiver>,name属性为定义的类
4.<receiver>中添加<intent-filter>,指明接收的<action>

静态注册广播开机启动

 1 public class BootBroadCastReceiver extends BroadcastReceiver {
 2 
 3     @Override
 4     public void onReceive(Context context, Intent intent) {
 5         Toast.makeText(context, "context::"+context.toString()+"\nintent::"+intent.toString(), Toast.LENGTH_LONG).show();
 6         // 每当一个新的广播到达的时候,框架都传递一个context对象到onReceive()。这个context是一个ReceiverRestrictedContext实例
 7         // 因此很容易想到,要开机启动这个应用程序,就应该通过context.startActivity(..intent)
 8         Intent intent2= new  Intent(context, MainActivity.class);
 9         
10         // 这一句的作用至关重要
11         intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
12         context.startActivity(intent2);
13 
14     }
15 
16 }

 

静态注册

1         <receiver android:name="com.example.broadcasetest.BootBroadCastReceiver">
2             <intent-filter >
3                 <action android:name="android.intent.action.BOOT_COMPLETED"/>
4             </intent-filter>
5         </receiver>

 

 


发送自定义标准广播

主线,通过sendBroadcast(intent)方法发送广播,所以

1.先定义好intent,其构造方法中有带action的,然后发送
2.通常,发广播是为了用的,所以需要定义广播接收器来接收

 1         // 自定义标准广播
 2         Button btn = (Button) findViewById(R.id.broad_button);
 3         btn.setOnClickListener(new OnClickListener() {
 4             
 5             @Override
 6             public void onClick(View v) {
 7                 Intent intent = new Intent("com.example.broadcasetest.MY_BROADCAST");
 8                 sendBroadcast(intent);
 9             }
10         });

 

定义一个广播接收器,静态注册

 1 public class MyBroadcastReceiver extends BroadcastReceiver {
 2 
 3     @Override
 4     public void onReceive(Context context, Intent intent) {
 5         Toast.makeText(
 6                 context,
 7                 "context:" + context.toString() + "\nintent:"
 8                         + intent.toString() + "\nmine", Toast.LENGTH_SHORT)
 9                 .show();
10 
11     }
12 
13 }
MyBroadcastReceiver

 

1         <receiver 
2             android:name="com.example.broadcasetest.MyBroadcastReceiver"
3             >
4             <intent-filter >
5                 <action 
6                     android:name="com.example.broadcasetest.MY_BROADCAST"
7                     />
8             </intent-filter>
9         </receiver>

 

发送有序广播

只需要将sendBroadcast(intent);改为sendOrderedBroadcast(intent,null);

有序广播就可以进行设置优先级和拦截广播

设置优先级为100,就可以优先接收到广播,接收到广播之后,可以拦截广播 
1         <receiver 
2             android:name="com.example.broadcasetest.MyBroadcastReceiver"
3             >
4             <intent-filter android:priority="100">
5                 <action 
6                     android:name="com.example.broadcasetest.MY_BROADCAST"
7                     />
8             </intent-filter>
9         </receiver>

  拦截广播:只需要在onReceive方法中添加一句:abortBroadcast();

本地广播

1.只在程序内部发送广播,其他程序无法将广播发送到本程序内部——安全

2.发送本地广播比发送全局广播更加高效

 1 public class MainActivity extends Activity {
 2     private IntentFilter intentFilter;
 3     private LocalReceiver localReceiver;
 4     private LocalBroadcastManager localBroadcastManager;
 5     
 6     @Override
 7     protected void onCreate(Bundle savedInstanceState) {
 8         super.onCreate(savedInstanceState);
 9         setContentView(R.layout.activity_main);
10         // 获取本地广播管理器的实例
11         localBroadcastManager = LocalBroadcastManager.getInstance(this);
12         Button btn = (Button) findViewById(R.id.send_broadcast);
13         
14         btn.setOnClickListener(new OnClickListener() {
15             
16             @Override
17             public void onClick(View arg0) {
18                 Intent intent = new Intent("com.example.broadcastlocal.LOCAL_BROADCAST");
19                 // 用本地广播管理器来发送广播
20                 localBroadcastManager.sendBroadcast(intent);
21             }
22         });
23         
24         // 注册本地广播接收器
25         intentFilter = new IntentFilter();
26         intentFilter.addAction("com.example.broadcastlocal.LOCAL_BROADCAST");
27         localReceiver = new LocalReceiver();
28         localBroadcastManager.registerReceiver(localReceiver, intentFilter);
29     }
30     
31     
32     @Override
33     protected void onDestroy() {
34         super.onDestroy();
35         // 取消注册
36         localBroadcastManager.unregisterReceiver(localReceiver);
37     }
38 
39     class LocalReceiver extends BroadcastReceiver{
40 
41         @Override
42         public void onReceive(Context arg0, Intent arg1) {
43             Toast.makeText(MainActivity.this, "received a local broadcast", Toast.LENGTH_LONG).show();
44         }
45         
46     }
47 
48 }

 

最后在来一个广播的最佳实例:通过广播实现强制下线

地址:https://github.com/callerge/broadcastbestpractice

 

 

 

参考:http://www.cnblogs.com/lwbqqyumidi/p/4168017.html

posted @ 2015-11-23 19:57  洱海  阅读(246)  评论(0编辑  收藏  举报
.First { margin: 10px 0; font-family: 'Microsoft Yahei'; text-align: left; padding: 6px 20px; color: #fff; background: #55895B; font-size: 20px; border-radius: 4px; clear: both; } .Second { margin: 10px 0; font-family: 'Microsoft Yahei'; padding: 6px 20px; background: #93C8A2; color: white; font-size: 18px; border-radius: 4px; clear: both; } .Third { margin: 10px 0; padding: 6px 20px; font-family: 'Microsoft Yahei'; margin: 15px 0; font-size: 16px; color: black; background: #C6EFD2; border-radius: 4px; clear: both; } .note { margin: 10px 0; padding: 15px 20px 15px 60px; background: #FCFAA9 url('http://images.cnblogs.com/cnblogs_com/libaoheng/305804/o_yellow-pin.png') no-repeat 20px 0; font-size: 15px; font-family: 'Microsoft Yahei'; box-shadow: 0 0 8px #aaa; clear: both; } .demo { text-align: left; padding: 6px 20px; overflow: auto; border-radius: 4px; background: orange; color: #fff; font-size: 16px; clear: both; } .cnblogs_Highlighter { border: solid 1px #ccc; clear: both; } .cnblogs_code { background: #EFFFF4; border: solid 0px #939393; font-size: 14px; clear: both; padding: 10px 20px; } .cnblogs_code pre { font-size: 14px; } .cnblogs_code span { font-family: Courier New; font-size: 14px; }