Android广播机制详细介绍(广播分类、注册方式)
Android广播机制详细介绍(广播分类、注册方式)。
(一). 安卓广播的分类
a.标准广播
| 1 2 3 4 5 | 标准广播发出以后,所有的广播接收器,可以几乎在同一时刻同时接受到这条广播。优点:效率高缺点:不能被截断。 | 
b.有序广播
| 1 2 3 4 5 6 7 |     有序广播发出以后,同一时刻只能有一个广播接收器收到这条广播。优先级高的广播先接受到这条广播。在当前广播接收器处理完自己的逻辑以后,可以执行两种动作:    1.继续传递广播    2.将广播截断 | 
(二). 注册广播的方式
a. 动态注册
| 1 2 3 | 在代码中注册的广播,被称为动态注册。动态注册的广播,最后必须取消注册。这类广播,只有应用启动了,才能接收到广播。 | 
动态注册广播需要的东西
一个广播接收器类 —— 实质就是一个继承自BoradCastReceiver的类,只要继承这个类,就
具体接收广播的能力了,但是能接受什么广播由下面的第三条决定。
重写父类的onReceive()方法 —— 接收到广播的时候,就会回调这个方法。因此,广播接收
器的处理逻辑就写在这里
一个 IntentFilter 对象,广播接收器接收什么样的广播,由它的addAction()方法决定。
在代码中注册广播接收器,通过registerReceiver方法。方法接受两个参数,一个是广播接收
器实例,一个是IntentFilter实例。
取消注册广播 ,通过unregisterReceiver() 方法—— 在哪里取消注册无所谓,只要保证取
消注册就OK
如果需要权限,则在AndroidManifest.xml文件申明权限
代码 :
布局代码:
| 1 2 3 4 5 6 7 | <!--?xml version="1.0"encoding="utf-8"?--><linearlayout android:layout_height="match_parent"android:layout_width="match_parent"android:orientation="vertical"xmlns:android="https://schemas.android.com/apk/res/android"><button android:id="@+id/btn_isNetConnect"android:layout_gravity="center"android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="检测网络">    <textview android:gravity="center"android:id="@+id/txt_show"android:layout_height="80dp"android:layout_width="match_parent"android:textsize="30sp"></textview></button></linearlayout> | 
| 1 | 我们写一个简单的判断当前网络是否可用的广播。监听网络是一个敏感的动作,因此,需要在xml中申明权限。 | 
| 1 | <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission> | 
java 代码
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | publicclassMainActivity extendsAppCompatActivity {//     决定广播接收器接收什么广播    privateIntentFilter intentFilter ;    privateNetworkChangeReceiver networkChangeReceiver ;    privateTextView txt_show ;    privateButton btn_isNetConnect ;    @Override    protectedvoidonCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);//        获取控件实例        txt_show = (TextView) findViewById(R.id.txt_show);        btn_isNetConnect = (Button) findViewById(R.id.btn_isNetConnect);//        在按钮监听器中注册广播        btn_isNetConnect.setOnClickListener(newView.OnClickListener() {            @Override            publicvoidonClick(View v) {                intentFilter = newIntentFilter() ;//       字符串 android.net.conn.CONNECTIVITY_CHANGE//       表明广播接收器接收网络变化的广播                intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");//        网络变化广播接收器实例                networkChangeReceiver = newNetworkChangeReceiver() ;//        注册广播//        别忘了,申明权限                registerReceiver(networkChangeReceiver,intentFilter) ;            }        });    }    /**     * 动态注册的广播,必须在取消注册。     * 我们在create(),方法创建的时候,注册了广播     * 这里,我们在销毁活动中,取消注册,     * 当然也可以在onPause()方法取消注册。     */    @Override    protectedvoidonDestroy() {        super.onDestroy();        unregisterReceiver(networkChangeReceiver);    }    /**     * 用内部类实现一个网络变化广播接收器     */    classNetworkChangeReceiver extendsBroadcastReceiver {//        重写父类的onReceive()方法,接收到对应的广播的时候,就会回调这个方法//        广播接收器的处理逻辑,就写此方法中        @Override        publicvoidonReceive(Context context, Intent intent) {//            获取网络管理服务类,就跟findViewById()方法一样            ConnectivityManager connectivityManager =                    (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);//            记住这样写。就好了。用到的时候,百度一下,边边角角,谁也记不清            NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo() ;//          判断网络状态            if(networkInfo != null&& networkInfo.isAvailable()){                txt_show.setText("当前网络可用");            }else{                txt_show.setText("当前网络不可用");            }        }    }} | 
b.静态注册
| 1 2 3 | 在AndroidManifest.xml文件中注册的广播。这类广播,常驻广播,在应用未启动的时候,即可接收到广播,处理相应的逻辑。 | 
静态广播需要的东西
| 1 | 相比于动态注册的广播,静态广播需要的东西,就很少了。 | 
依然需要一个广播接收器类
继续需要重写父类的onReceive()方法
在AndroidManifest.xml文件中注册广播
如果需要权限,则在AndroidManifest.xml文件申明权限
| 1 | talk is cheap,show me code ! Or shut up | 
代码:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | /** * 这里写将广播写为内部类 * 目的;记住一个知识点: * 静态注册的广播,广播接收器为内部类的时候,必须是pubic static * 实现开机自启动 * Created by MaiBenBen on 2017/10/16. */publicclassOutter {// 必须是public static    publicstaticclassBootCompleteReceiver extendsBroadcastReceiver {        @Override        publicvoidonReceive(Context context, Intent intent) {//        调启主活动,来打开应用程序//        context参数,就是此时的上下文            Intent intent1 = newIntent(context,MainActivity.class);            context.startActivity(intent1);        }    }} | 
| 1 2 3 4 5 6 7 8 9 10 | <!--在AndroidManifest.xml文件中注册广播内部类广播接收器的名字,写全了--> <receiver android:enabled="true"android:exported="true"android:name=".Outter$BootCompleteReceiver">            <intent-filter>            <!--写明广播接收器接收的广播-->                </action>            </intent-filter>        </receiver> | 
| 1 2 | 监听开机广播 权限申明:<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission> | 
至此,已经成功完成了开机自启动。
(三). 发送广播
| 1 | 总是接受广播,也没劲。下面,我们自己来发送一些广播。发送的广播是自定义的。 | 
a. 发送标准广播
| 1 2 3 4 5 | 广播是使用Intent,进行传递的。因此,我们可以在Intent中携带一些数据传递给广播接收器。注意:这里只是在活动中发送广播,在服务或者广播中发送广播,代码有所不同:需要在intent中加上标志。 | 
| 1 | setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)。 | 
| 1 2 3 | 该标志表明:首先寻找是否有与要启动的activity具有相同affinity的task。若没有,则生成一个新的task,并将该activity放入其中;若有,则将该activity添加到该task的栈顶。 | 
| 1 2 3 4 5 6 | //        自定义广播内容       String broadcast = "allbet.broad.cn.broadcasttest.MY_BROADCAST";//        绑定到Intent中       Intent intent = newIntent(broadcast) ;//        发送广播,调用Context的sendBroadcast()方法       sendBroadcast(intent); | 
b. 发送有序广播
| 1 | 有序广播与标准广播的发送方式,在代码中只有一句代码有差别,就是发送广播的方法不同。 | 
| 1 2 3 4 5 6 7 8 | //         自定义广播内容      String broadcast = "allbet.broad.cn.broadcasttest.MY_BROADCAST";//         绑定到Intent中      Intent intent = newIntent(broadcast) ;//         发送有序广播//         第一个参数依然是Intent//         第二个参数是代表权限的字符串,这里写null就好了       sendOrderedBroadcast(intent,null); | 
有序广播发送完毕以后,优先级高的广播接收器会先收到这
个广播。它们甚至可以将广播截,下面我们讲一下优先级的
问题
<☆> 广播接收器优先级
1.) 静态广播的优先级
跟目录的顺序有关,如下所示,目录越靠前,优先级越高,其中,第三方APP都在data/app目
录下:
  system/framework
  
  system/app
vendor/app
data/app
drm/app-private
当处于同一目录下时:按照file.list()的返回顺序。因为在data/app下的应用都是用户安装的,
并且都是以com.xxx.xxx-1.apk 的形式出现,它们的顺序,就是包名的顺序,因此,想要你的
应用的静态广播优先级高,就需要好好研究包名了,让你的应用包名靠前。但是这个顺序不是
绝对的,还依赖被扫描的先后顺序,先扫描的当然优先级高一点啦。即同一优先级的静态广播
接收器,先扫描的优先级高。一般都是包名排在前面的先被扫描。但是有人也说,是按照应用
安装的先后顺序。。。。有待考证
上面说的都是静态注册的时候,使用了相同优先级的情况。设置了优先级的,优先级越高,越
先接收到广播。
2.) 动态广播的优先级
一大影响因素,动态广播的注册时间。同一优先级的动态广播,先注册的优先级高。
动态注册的广播接收器的优先级永远高于静态注册的广播接收器。
综上所述,做个总结:
其实当接收广播的时候,广播接收器都会排队,无论是标准广播,还是有序广播,都是要排队
的,只不过,有序广播可能会被截断。
因此我们可以将,所有能接收该广播的广播接收器,理解为排队等着广播传递,排在前面的
人,当然就先接收到广播啦。那么谁排在前面呢?毫无疑问,一定是动态注册的广播,动态注
册的广播接收器们根据优先级排队,相同优先级的,就按照被扫描的先后顺序排队。排在队伍
后面的就只剩下静态注册的广播接收器了,也先根据优先级排序,相同优先级的,按照被扫描
的先后顺序排队。
上述的情况是,所有的广播接收器都不缺席的情况,但是总有广播接收器,由于种种原因(比
如,动态注册的广播,应用未启用)会缺席,缺席的话,那后面的广播接收器就自动补全空
位。
(四).为广播接收器设定优先级
a.为静态广播接收器设定优先级
| 1 | 在xml文件中设定 | 
| 1 2 3 4 5 6 | <receiver android:enabled="true"android:exported="true"android:name=".Outter$BootCompleteReceiver">           <!--在这里添加属性-->           <intent-filter android:priority="100">               </action>           </intent-filter>       </receiver> | 
b.为动态广播设置优先级
| 1 | 在intentFilter对象上设置 | 
| 1 2 3 4 5 6 7 8 9 10 11 |         intentFilter = newIntentFilter() ;//       字符串 android.net.conn.CONNECTIVITY_CHANGE//       表明广播接收器接收网络变化的广播                intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");//         设置优先级                intentFilter.setPriority(1000);//        网络变化广播接收器实例                networkChangeReceiver = newNetworkChangeReceiver() ;//        注册广播//        别忘了,申明权限                registerReceiver(networkChangeReceiver,intentFilter) ; | 
(五).截断有序广播
| 1 2 3 | 有序广播在传送中,是可以被截断,甚至可以修改广播携带的数据。截断广播,就是在广播接收器的onReceive()方法中调用abortBroadcast(); | 
| 1 2 3 4 5 6 7 | publicvoidonReceive(Context context, Intent intent) {/*    处理逻辑*///     逻辑处理结束,截断广播。    abortBroadcast();} | 
(六) 本地广播
| 1 2 3 | 之前我们发送的广播,都是系统全局广播,即我们发送的广播,能被系统的其他程序也接收到。这样是很不安全的,因为,广播上说不定会携带着关键数据。或者,其他程序,不停的向我们发生垃圾广播。 | 
本地广播,是无法再通过静态注册的广播接收器收到的。很好理解,静态注册,是为了程序未启动的
时候接收广播,而本地广播,程序已然启动可了。当然,也不能注册本地广播。
因此,我们需要本地广播,顾名思义,广播,只能在本程序中发送和接收。
a.本地广播需要的东西
对比全局广播,本地广播需要一个LocalBroadcastManger对象,来对广播进行管理。| 1 2 3 4 5 6 | //       获取本地广播管理 实例        localBroadcastManager = LocalBroadcastManager.getInstance(this); intentFilter = newIntentFilter("com.yaz.QQQ") ;        myLocalBr  = newMyLocalBr() ;        localBroadcastManager.registerReceiver(myLocalBr,intentFilter);        break; | 
 
                    
                

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号