安卓开发之广播机制

来源:互联网 发布:sql的意义和应用 编辑:程序博客网 时间:2024/05/20 07:18

概述

BroadcastReceiver是安卓四大组件之一,开发过程中经常会用到。我们可以用它来监听系统发出的广播,比如开机启动,网络状态变化,蓝牙设备连接成功。也可以发送自定义的广播,传递数据。

1,广播的分类

广播分为两种,分别是标准广播(Normal broadcast),有序广播(Ordered broadcast)。

  1. 标准广播:是一种完全异步的广播,广播发出后,几乎所有的广播接收器都同时接收到广播消息,没有顺序,也无法拦断。
  2. 有序广播:是一种同步执行的广播,广播发出后,在同一时刻只能有一个广播接收器接收到广播,然后广播按照接收器的优先级依次传播,是有顺序的。并且可以在广播接收器中终止该广播的传播。

    标准广播的优点是效率高,但因为广播是跨进程的,也就是标准广播发出的广播所有的程序都可以收到,因此存在一些安全隐患。

    有序广播的优点是,发出的广播可以被拦截,保证发出的广播只被特定的接收器接收,其他应用的接收器无法接收。要做到这一点,需要将该接收器的优先级设置为100,保证它是第一个接收到广播的,接收广播后的逻辑处理结束后,只需添加这么一句代码,截断广播的传播:

abortBroadcast();

自定义的广播接收器需要继承BroadcastReceiver,并且重写onReceive(Context context, Intent intent)方法。在该方法里,我们可以通过intent取得广播发送的数据。
广播接收器有两种注册方式,一种是静态注册,另一种是动态注册。静态注册在程序未启动时就可以接收广播,在AndroidManifest.xml文件中注册。动态注册方式直接在代码里面注册,只有程序启动后才可以接收广播。
下面以接收开机启动为例

  1. 动态注册
void register(){        IntentFilter intentFilter=new IntentFilter();        intentFilter.addAction("android.intent.action.BOOT_COMPLETED");        MyReceiver myReceiver=new MyReceiver();        registerReceiver(myReceiver,intentFilter);    }

当然,我们需要一个广播接收器:

class MyReceiver extends BroadcastReceiver{    @Override    public void onReceive(Context context, Intent intent) {        Toast.makeText(context,"开机啦",Toast.LENGTH_SHORT).show();    }}

最后,动态注册的广播一定要取消注册,因为广播是比较浪费资源的。

   @Override    protected void onDestroy() {        super.onDestroy();        unregisterReceiver(myReceiver);    }
  1. 静态注册
    在清单文件中添加:
 <receiver android:name=".MyReceiver">            <intent-filter>                <action android:name="android.intent.action.BOOT_COMPLETED"/>            </intent-filter>        </receiver>

当然,监听开机启动需要权限:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

最后,我们需要一个广播接收器来接收广播:

  class MyReceiver extends BroadcastReceiver{    @Override    public void onReceive(Context context, Intent intent) {        Toast.makeText(context,"开机啦",Toast.LENGTH_SHORT).show();    }}

3,发送标准广播

发送标准广播,需要构建一个intent,并且自定义一个action作为该intent的参数,然后调用sendBroadcast(intent)方法即可发送广播:

button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent=new Intent("com.example.MY_BROADCAST");                /**                 * 发送广播最重要的一个目的就是传送数据,我们可以通过intent发送数据                 */                intent.putExtra("myData","这是我发的广播");                sendBroadcast(intent);            }        });

广播发出去了,还需要一个广播接收器来接收广播,否则这样的广播没什么意义。
为了方便,我们采用静态注册的方式来接收广播吧。

  class MyReceiver extends BroadcastReceiver{    @Override    public void onReceive(Context context, Intent intent) {        String data=intent.getStringExtra("myData");        Toast.makeText(context,data+"这是我收到的数据",Toast.LENGTH_SHORT).show();    }}

注册:

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

4,发送有序广播

发送有序广播和发送标准广播没有太大区别。在发送时,我们采用 sendOrderedBroadcast(intent)来发送,注册广播时,需要设置优先级,一般设为最高优先级100,如果不想被其他的广播接收器收到的话。收到广播以后,调用abortBroadcast()拦截该广播继续传递。

发送广播:

button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent=new Intent("com.example.MY_BROADCAST");                /**                 * 发送广播最重要的一个目的就是传送数据,我们可以通过intent发送数据                 */                intent.putExtra("myData","这是我发的有序广播");                sendOrderedBroadcast(intent,null);            }        });

注册,需要设置优先级。设置为100,该广播接收器是最先接收到广播的。

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

广播接收器:

  class MyReceiver extends BroadcastReceiver{    @Override    public void onReceive(Context context, Intent intent) {        String data=intent.getStringExtra("myData");        Toast.makeText(context,data+"这是我收到的数据",Toast.LENGTH_SHORT).show();        /**         * 拦截广播,使其不能继续传播         */        abortBroadcast();    }}

5,使用本地广播

本地广播只能被本程序内的接收器接收到,其他程序的中的广播接收器是无法接收到的。而前面列举的两种广播都是系统全局的广播,其他的程序都可以接收(如果不拦截有序广播的话)。

发送本地广播:

button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                LocalBroadcastManager localBroadcastManager=LocalBroadcastManager.getInstance(MainActivity.this);                Intent intent=new Intent("com.example.MY_BROADCAST");                /**                 * 发送广播最重要的一个目的就是传送数据,我们可以通过intent发送数据                 */                intent.putExtra("myData","这是我发的本地广播");                localBroadcastManager.sendBroadcast(intent);            }        });

注册,只能通过动态注册的方式实现注册:

  void register(){        IntentFilter intentFilter=new IntentFilter();        intentFilter.addAction("com.example.MY_BROADCAST");        MyReceiver myReceiver=new MyReceiver();        localBroadcastManager. registerReceiver(myReceiver,intentFilter);    }

广播接收器:

  class MyReceiver extends BroadcastReceiver{    @Override    public void onReceive(Context context, Intent intent) {        String data=intent.getStringExtra("myData");        Toast.makeText(context,data+"这是我收到的数据",Toast.LENGTH_SHORT).show();    }}

反注册:

   @Override    protected void onDestroy() {        super.onDestroy();        localBroadcastManager.unregisterReceiver(myReceiver);    }

6,其他

发送广播可以很方便的传递数据,比如有一个场景:
有一个线程在下载数据,我们需要在数据下载结束后,将 下载好的数据显示在界面上。
我们可能会这么做:

  1. 定义一个接口实现回调方法。
  2. 使用handler.
    除此之外,我们还可以这样做:数据下载结束后,我们就发送一个广播,并且通过intent传递已经下载好的数据。然后在Activity里面用内部类的形式写一个BroadcastReceiver接收广播发送的数据,然后就可以显示到界面了,是不是很方便呢?
0 0
原创粉丝点击