zoukankan      html  css  js  c++  java
  • 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 //发出此广播的地方frameworksaseservicesjavacomandroidserverDockObserver.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()+"
    intent::"+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() + "
    intent:"
     8                         + intent.toString() + "
    mine", 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

  • 相关阅读:
    DataList小结(转载)
    ISAPI筛选器及对ASP源文件的保护
    VC中静态变量Static
    其他
    Android TabHost的使用
    有关Android线程的学习
    android 中LayoutInflater 的使用
    Java与VC中的基本数据类型的相关知识
    Java中的finalize()、final、fianlly
    Animations介绍及实例
  • 原文地址:https://www.cnblogs.com/erhai/p/4989468.html
Copyright © 2011-2022 走看看