Android 四大组件之 BroadCastReceiver

BroadCastReceiver是一种全局的监听器。用于监听系统全局的广播消息。由于他是一种全局的监听器,所以他可以轻松实现,系统中不同组件之间的通信。

 

1.创建BroadCastReceiver

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        
        // 当监听到广播消息时,执行这个方法。
        String content=intent.getStringExtra("content");
        Toast.makeText(context, "你发送的是:"+content, Toast.LENGTH_SHORT).show();

    }

}
View Code

BroadCastReceiver接收到广播,就会执行onReceive方法。可以使用Intent接收数据信息。

 

2.注册BroadCastReceiver

(1)静态注册

静态注册,就是在AndroidManifest.xml文件中,注册BroadCastReceiver。

<receiver android:name=".MyReceiver">
   <intent-filter>
       <action android:name="com.example.MY_LISTENER"></action>
   </intent-filter>
</receiver>

(2)动态注册

动态注册,就是在代码中注册BroadCastReceiver, 如果使用动态注册,可以在Activity的onResume()中注册,onPause中注销,或者在onCreate()中注册,onDestory注销。

//实例化广播接收器
    MyReceiver myReceiver = new MyReceiver();
    //过滤广播,这里“com.example.MY_LISTENER”是我自定义的,可以随便写,广播时候保持一致就可以
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("com.example.MY_LISTENER");
    //注册广播
    registerReceiver(myReceiver, intentFilter);
  //注销广播
  //unregisterReceiver(myReceiver)
View Code

 

关于registerReceiver方法有两种重载。

 

第一种:registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

第一个参数:负责接收广播的BroadcastReceiver(广播接收器);

第二个参数:是意图过滤器;

 

第二种:registerReceiver(receiver, filter, broadcastPermission, scheduler)

第一个参数:负责接收广播的BroadcastReceiver(广播接收器);

第二个参数:意图过滤器(哪些广播可以被这个接收器接收);

第三个参数:广播权限;

第四个参数:Hander;

 

(3)关于“静态注册”和“动态注册”的区别!

当静态注册一个BroadcastReceiver时,不论应用程序启动与否,都可以接收对应的的广播。 
动态注册的时候,如果不执行unregisterReceiver();方法取消注册,跟静态是一样的。但是如果执行该方法,当执行过以后,就不能接受广播了。

 

(4)注意:权限重复现象

如果AndroidManifest.xml(功能清单文件)里注册了权限,在该方法再注册,则 receiver 无法收到广播;

如果AndroidManifest.xml(功能清单文件)里没有注册了权限,该方法注册也无法收到。当该方法没有注册权限,功能清单里注册的时候, receiver能收到广播。

 

3.广播的类型与发送

 

普通广播:对于Receiver(接收者)来说,普通广播是完全异步的,可以在同一时刻被所有Receiver(接收者)接收到,消息传递速度表较快。

发送广播:

button_start.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //发送广播依然需要使用Intent
                Intent intent = new Intent();
                //这个Action是我们在AndroidManifest.xml中为Receiver配置的
                intent.setAction("com.example.MY_LISTENER");
                //给Receiver传入参数
                intent.putExtra("content", "Hello Receiver");
                //发送广播
                sendBroadcast(intent);
            }
        });
View Code

接收广播:

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        
        // 当监听到广播消息时,执行这个方法。
        String content=intent.getStringExtra("content");
        Toast.makeText(context, "你发送的是:"+content, Toast.LENGTH_SHORT).show();

    }

}
View Code

 

 

有序广播:通过给Receiver(接收者)指定优先级,系统会安排优先级高的Receiver接收广播,然后优先级高的Receiver再把广播传播到优先级较低的Receiver中。可以在优先级高的Receiver中使用abortBroadcast(),终止广播的传递,这样就不会被优先级较低Receiver接收到。

不仅如此,也可以在优先级高的Receiver中,把处理的结果及相关信息,通过setResultExtras(Bundle)方法,传递到下一个Receiver中(使用getResultExtras(true)接收上一个接收者存入的数据)。

注意:当具有相同优先级的Receiver,系统执行哪个Receiver是随机的。如果都没有指定优先级,动态注册(代码注册)的最先收到广播。

 

指定Receiver的优先级

(1)在AndroidManifest.xml文件中,通过 android:priority=""来指定优先级。

  <receiver android:name=".MyReceiver">
      <intent-filter android:priority="10">
           <action android:name="com.example.MY_LISTENER"></action>
      </intent-filter>
  </receiver>

(2)通过 IntentFilter 的setPriority() 指定。

注意:优先级的范围 -1000~1000

 

例:

定义三个接收者

MyReceiver1

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        // 把接收到的num,乘以10。
        int num = intent.getIntExtra("num", 0);
        num = num * 10;

        Bundle b = new Bundle();
        b.putInt("num", num);
        //把处理结果传递给下一个接收者
        setResultExtras(b);

        Toast.makeText(context, "1,接收到的是:" + String.valueOf(num),
                Toast.LENGTH_SHORT).show();
    }

}
View Code

 

MyReceiver2

public class MyReceiver2 extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // 把接收到的num,乘以10。
        int num = getResultExtras(true).getInt("num");
        num = num * 10;

        Bundle b = new Bundle();
        b.putInt("num", num);
        //把处理结果传递给下一个接收者
        setResultExtras(b);

        Toast.makeText(context, "2,接收到的是:" + String.valueOf(num),
                Toast.LENGTH_SHORT).show();
        
        //终止广播向下一个接收者传递。
        //abortBroadcast();

    }

}
View Code

 

MyReceiver3 

public class MyReceiver3 extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        
        // 把接收到的num,乘以10。
        int num = getResultExtras(true).getInt("num");
        num = num * 10;

        Toast.makeText(context, "3,接收到的是:" + String.valueOf(num),
                Toast.LENGTH_SHORT).show();
    }

}
View Code

 

发送有序广播:

button_start = (Button) findViewById(R.id.button1);
        button_start.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

                Intent intent = new Intent();
                intent.setAction("com.example.MY_LISTENER");
                //给第一个Receiver传入参数
                intent.putExtra("num",1);
                //发送广播,注意:这里使用的是sendOrderedBroadcast
                sendOrderedBroadcast(intent, null);
            }
        });
View Code

 

这里使用了sendOrderedBroadcast()发送有序广播,该方法有两个参数,第一个参数是Intent。第二个参数是权限,如果给广播指定权限,那么只有具备该权限的Receiver,才能接收到。

 

4生命周期

BroadCastReceiver的生命周期非常简短:接收到广播→onReceive()→结束;

所以在onReceive方法中,不要执行耗时的任务,如果该方法执行时间超过10秒,Android就会认为该程序无响应,并弹出ANR的对话框。如果必须执行耗时任务可以考虑,在onReceive中开启服务来执行,但不要使用线程,因为BroadCastReceiver的生命周期很短,可能出现子线程还没有结束,BroadCastReceiver就已经退出了。

如果当BroadCastReceiver所在的进程结束,虽然该进程中可能有用户启动的新线程,但是由于该进程内没有活动的组件,系统会在内存紧张的时候,优先结束掉该进程,这就会导致BroadCastReceiver启动的子线程不能执行完。

 

 

提示:我们还可以监听系统广播。例如系统的“启动完成”广播,我可以实现开机启动项。网络变化等等。

 

特殊的BroadcastReceiver

LocalBroadcastManager本地广播

Sticky Broadcast粘性广播

OrderedBroadcastReceiver有序广播

StickyOrderedBroadcast粘性有序广播

相关资料:

http://www.cnblogs.com/trinea/archive/2012/11/09/2763182.html

http://yangguangfu.iteye.com/blog/1063732

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。