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 }
静态注册广播接收器——程序不运行都可接收
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 }
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