Android的广播机制

一 广播机制

广播分为标准广播和有序广播,标准广播是异步执行的广播,没有先后顺序。而有序广播是一种同步执行的广播,有接收的先后顺序,所以可以被截断。

二 接收系统广播

1.动态注册(在代码中注册)

  广播接收器是一个类。继承自BroadcastReceiver类,重写了onReceiver()的方法,当有该广播传入,则执行方法里的内容。

实现方法:

  • 在mainactivity中建立一个内部类继承自broadcastreceiver类,重写onReceiver方法,显示一个提示符。
  • 在onCreate()方法中创建了IntentFilter实例并给他添加了要检测广播的值的action, 要监听什么广播就插入相应的广播值,然后创建一个内部类networkChangeReceiver的实例。
  • 最后调用registerReceiver方法注册。
 1 public class MainActivity extends AppCompatActivity {
 2 
 3     private IntentFilter intentFilter;
 4 
 5     private NetworkChangeReceiver networkChangeReceiver;
 6 
 7     @Override
 8     protected void onCreate(Bundle savedInstanceState) {
 9         super.onCreate(savedInstanceState);
10         setContentView(R.layout.activity_main);
11 //        实例化一个intentFilter 想监听什么广播就把他加到里面。
12         intentFilter = new IntentFilter();
13        
14 intentFilter.addAction("android.net.conn.CONNECTIVITY_CHAGNE");
15         networkChangeReceiver = new NetworkChangeReceiver();
16 //        调用registerReceiver方法注册
17         registerReceiver(networkChangeReceiver, intentFilter);
18     }
19 //    动态注册的广播接收器需要取消注册
20     @Override
21     protected void onDestroy(){
22         super.onDestroy();
23         unregisterReceiver(networkChangeReceiver);
24     }
25 
26     class NetworkChangeReceiver extends BroadcastReceiver {
27         @Override
28         public void onReceive(Context context, Intent intent) {
29             Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
30         }
31     }
32 }

 2.静态注册(在AndroidManifest.xml中注册)

与动态注册相比,静态注册没有那么灵活,但是可以在程序没有启动时候就接收到广播。

静态方法可以快捷创建一个广播接收器,在包名右键新建中,选择other,broadcast receiver。

弹出如下的窗口:

其中Exported表示是否允许接收本程序以外的广播,而Enabled属性表示是否启用这个广播。新建后在onReceiver()方法中再重写需要实现的步骤。

此外,静态广播需要在AndroidManifest,xml中注册才能使用。(已被as自动注册。

1        <receiver
2             android:name=".BootCompleteReceiver"
3             android:enabled="true"
4             android:exported="true">
5             <intent-filter>
           //加入要要接收的广播内容 6 <action android:name="android.intent.action.BOOT_COMPLETED" /> 7 </intent-filter> 8 </receiver>

然后在AndroidManifest.xml文件中加入要监听的广播。

注意:

  • 不要在onReceive中执行耗费时间的操作,因为他不允许开多线程。
  • 在接收系统广播的时候,有的广播需要一定的权限声明

三 自定义广播

1.发送标准广播

  新建一个广播接收器MyBroadcastReceiver。在onReceive()方法中加入一个toast的显示提示。然后在AndroidManifest.xml中加入要接收的action。要接收的action为:“com.example.broadcasttest.MY_BROADCAST”。

  所以我们要发广播的时候就需要发一条值为“com.example.broadcasttest.MY_BROADCAST”的广播。

  在布局文件中加入一个名为button的按键,在MainActivity中为button注册点击事件。具体为构建一个Intent对象,把要发送的广播传入,调用Context的sendBroadcast()方法将广播发送出去,这时所有监听该内容的广播接收器都会受到信息。这就是一条标准广播。

1         Button button = (Button) findViewById(R.id.button);
2         button.setOnClickListener(new View.OnClickListener() {
3             @Override
4             public void onClick(View view) {
5                 Intent intent = new
6                         Intent("com.example.boardcasttest.MY_BROADCAST");
7                 sendBroadcast(intent);
8             }
9         });

注:

在Android8以后为了管理系统和节约电量特别针对广播和服务发送intent的方式启动做出的改变,也就是说广播和服务不能随意收intent了,要对广播和服务更精确的指向。

所以在intent中需要加一句,ComponentName的第一个参数是自定义广播的包名,第二个参数是广播接收器的类。

1 intent.setComponent(new ComponentName("com.example.broadcasttest","com.example.broadcasttest.MyBroadcastReceiver"));

2.发送有序广播

广播可以跨进程,可以在不同的应用中接收到广播。所以只要有广播接收器,并在不同的项目中的Androidmanifest中添加对应的要接收的广播的值,就可以接收到不同项目的广播内容。

而有序广播与标准广播的区别只是在于在intent中 将sendbroadcast()改为sendOrderBroadcast(),而sendOrderBroadcast()中有两个参数,第一个还是intent,第二个是传入权限相关的字符串null。

而有序广播最重要的就是先后顺序,是根据注册时候设定的。通过intent中的 Android:priority=""来设置权值。如:

1 <receiver
2             android:name=".MyBroadcastReceiver"
3             android:enabled="true"
4             android:exported="true">
5             <intent-filter android:priority="100">
6                 <action android:name="com.example.boardcasttest.MY_BROADCAST"/>
7             </intent-filter>

其次如果想要在有序广播中截断广播,需要在广播接收器中的onReceive方法中调用abortBroadcast()方法。如果调用了这个方法则说明这条广播被截断。

四 本地广播

因为前面的发送广播和接收广播都是针对全局的,每个程序都能收到其他的广播和发送给其他程序广播。这样会在传送数据时候存在一定的危险。所以使用本地广播可以很好的保护安全。主要是通过一个LocalBroadcastManager来对广播进行管理。实例代码如下:

 1 public class MainActivity extends AppCompatActivity {
 2 
 3     private IntentFilter intentFilter;
 4     private LocalReceiver localReceiver;
 5     private LocalBroadcastManager localBroadcastManager;
 6 
 7     @Override
 8     protected void onCreate(Bundle savedInstanceState) {
 9         super.onCreate(savedInstanceState);
10         setContentView(R.layout.activity_main);
11         localBroadcastManager = localBroadcastManager.getInstance(this);//获取实例
12 
13         Button button = (Button) findViewById(R.id.button);
14         button.setOnClickListener(new View.OnClickListener() {
15             @Override
16             public void onClick(View view) {
17                 Intent intent = new
18                         Intent("com.example.boardcasttest.LOCAL_BROADCAST");
19                 intent.setComponent(new ComponentName
20                         ("com.example.broadcasttest","com.example.broadcasttest.MyBroadcastReceiver"));
21                 localBroadcastManager.sendBroadcast(intent);//发送本地广播
22             }
23         });
24         intentFilter=new IntentFilter();
25         intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
26         localReceiver = new LocalReceiver();
27         localBroadcastManager.registerReceiver(localReceiver,intentFilter);
28     }
29 
30 //    动态注册的广播接收器需要取消注册
31     @Override
32     protected void onDestroy(){
33         super.onDestroy();
34         localBroadcastManager.unregisterReceiver(localReceiver);
35     }
36 
37     class LocalReceiver extends BroadcastReceiver {
38         @Override
39         public void onReceive(Context context, Intent intent) {
40             Toast.makeText(context, "received local broadcast", Toast.LENGTH_SHORT).show();
41         }
42     }
43 }

其实可以看出来,本地广播其实和之前的动态注册很像,也是先做一个抽象的内部类作为接受器, 只不过先要通过LocalBroadcastManager先调用getInstance()方法得到实例。注册广播接收器时候和发送广播的时候,也是通过调用LocalBroadcastManager中的 registerReceiver()方法 和 sendBroadcast()方法。

另 本地广播都是动态注册的,没有静态注册的本地广播,因为本来静态广播就是为了在应用没有启动的时候接受广播,而本地广播是只局限于本程序的广播。

猜你喜欢

转载自www.cnblogs.com/Mask-D/p/9347156.html