Android中BroadcastReceiver的运用

BroadcastReceiver是用来接收广播通知的组件,广播是一种同时通知多个对象的事件通知机制。类似于日常生活中的广播,允许多人同时接收,也允许不收听。Android中的广播来源与系统事件,例如按下拍照按键,电池电量低,安装新应用,启动特定线程,文件下载完毕等。

BroadcastReceiver类是所有广播接收器的抽象基类,其实现类用来对发出来的广播进行筛选并做出响应。广播接收器的生命周期非常的简单,当消息到达时,接收器调用 onReceiver()方法,在该方法接收之后,BroadcastReceiver实例失效。

广播接收器通常初始化独立的组件或者在onReceiver()方法中发送通知给用户。如果广播接收器须要完成更加耗时的操作,它应该启动服务而不是一个线程,因为不活跃的广播接收器可能被系统停止。

接收广播的两种分类

用于接收的广播有两大类:即普通广播和有序广播

普通广播:使用Context.sendBroadcast()方法发送, 他们是完全异步的,广播的全部接收者以未定义的顺序运行,通常在同一时间,这种方法非常高效,但是接收者不能使用结果或者终止API。

有序广播:使用Context.sendOrderedBroadcast()方法发送,他们每次只发送给一个接收者,由于每个接收者依次运行,它能为下一个接收者生成一个结果,或者它能完全终止广播以便不传递给其他接收者,有序接收者运行顺序由匹配的intent-filter的android:priority属性控制,具有相同优先级的接收者运行顺序随机。

广播的两种注册机制

静态注册:在AndroidManifest.xml中用标签生命注册,并在标签内用标签设置过滤器。


  <receiver android:name="myRecevice">    //继承BroadcastReceiver,重写onReceiver方法

    <intent-filter>    

      <action android:name="com.xxxx.xxx"/>//使用过滤器,接收指定action广播

      </intent-filter>

  </receiver> 

动态注册:

  IntentFilter intentFilter = new IntentFilter();

  intentFilter.addAction(String);   //为BroadcastReceiver指定action,使之用于接收同action的广播

    registerReceiver(BroadcastReceiver,intentFilter);

  通过这种方式注册的广播为非常驻型广播,即它会跟随Activity的生命周期,所以在Activity结束前我们需要调用unregisterReceiver(receiver)方法移除它。

  指定广播目标Action:Intent intent = new Intent(actionString);

  并且可通过Intent携带消息 :intent.putExtra(“msg”, “hi,我通过广播发送消息了”);

  发送广播消息:Context.sendBroadcast(intent )

实例

获取系统广播

例如我们通过一个按钮的点击事件来获取 现在的电池电量:

我们在Activity中放一个按钮,在按钮的点击事件下注册并发送广播,在接收器中Toast出当前的电量:

点击事件下添加代码:

  registerReceiver(new TestReceiver(),new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

广播接收器为:

public class TestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals(Intent.ACTION_BATTERY_CHANGED)) ;//电量
        int level = intent.getIntExtra("level", 0);
        int scale = intent.getIntExtra("scale", 100);
        Toast.makeText(context, "剩余电量为:" + (level * 100 / scale) + "%", Toast.LENGTH_SHORT).show();
    }
}

这里须要注意的是,我们获取电量只能带代码中动态注册,如果是在 AndroidManifest.xml里面 静态注册 ,设置过滤器 为 android.intent.action.BATTERY_CHANGED 就不能成功,因为Android机制的原因,受保护的广播是只有系统才能发送的。哪些才是受保护的广播呢,传送门:http://www.cnblogs.com/xueqiang911226/p/3891852.html

我们发送自己的广播(静态注册)

首先我们先实现一个我们自己的广播接收者:

public class TestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals("android.intent.action.MY_BROADCAST")) ;
        Toast.makeText(context, intent.getStringExtra("msg"), Toast.LENGTH_SHORT).show();
    }
}

然后我们在配置文件中注册我们的广播:

  <receiver android:name=".TestReceiver">
            <intent-filter>
                <action android:name="android.intent.action.MY_BROADCAST"/>

                <category android:name="android.intent.category.DEFAULT"/>

            </intent-filter>
        </receiver>

然后我们在一个按钮的点击事件下发送一条广播,在上述的TestBraodcast的onReceiver()方法中匹配action并且读取我们传递的msg数据:

 btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent("android.intent.action.MY_BROADCAST");
                intent.putExtra("msg", "这是一条测试广播");
                sendBroadcast(intent);
            }
        });

监听网络状态的一个广播实例:http://blog.csdn.net/centralperk/article/details/7597516

动态注册一个广播:

我们的Activity的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注册广播" />

    <Button
        android:id="@+id/btn_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送广播" />
</LinearLayout>

我们的Activity 的代码为:

public class MainActivity extends PermissionActivity {

    private Button btn1, btn2;
    TestReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }


    private void initViews() {
        btn1 = (Button) findViewById(R.id.btn_1);
        btn2 = (Button) findViewById(R.id.btn_2);

        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //动态注册我们的广播
                receiver = new TestReceiver();
                IntentFilter filter = new IntentFilter();
                filter.addAction("android.intent.action.MY_BROADCAST");
                registerReceiver(receiver, filter);
            }
        });
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //发送一条带msg的广播
                Intent intent = new Intent("android.intent.action.MY_BROADCAST");
                intent.putExtra("msg", "我是动态注册的信息");
                sendBroadcast(intent);
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //销毁页面时候移除注册的广播。
        unregisterReceiver(receiver);
    }
}

广播接收器的代码为:

public class TestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        //为什么要验证,因为 我们可以在这个接收器里面接收好几种不同类型的广播
        //当然你也可以根据自己intent传递一个专门的标志参数来区分。
        if (action.equals("android.intent.action.MY_BROADCAST")) ;
        Toast.makeText(context, intent.getStringExtra("msg"), Toast.LENGTH_SHORT).show();
    }
}

一个有序广播的实例:

我们在Activity中分别注册三个不同优先级的广播。然后创建三个对应的广播接收器,然后打印Log看看顺序:
Activity代码:

public class MainActivity extends PermissionActivity {

    private Button btn1, btn2;
    TestReceiver receiver = new TestReceiver();
    TestReceiver1 receiver1 = new TestReceiver1();
    TestReceiver2 receiver2 = new TestReceiver2();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }


    private void initViews() {
        btn1 = (Button) findViewById(R.id.btn_1);
        btn2 = (Button) findViewById(R.id.btn_2);

        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //动态注册我们的广播

                IntentFilter filter = new IntentFilter();
                filter.addAction("android.intent.action.MY_BROADCAST");
                filter.setPriority(999);
                registerReceiver(receiver, filter);

                IntentFilter filter1 = new IntentFilter();
                filter1.addAction("android.intent.action.MY_BROADCAST");
                filter1.setPriority(998);
                registerReceiver(receiver1, filter1);

                IntentFilter filter2 = new IntentFilter();
                filter2.addAction("android.intent.action.MY_BROADCAST");
                filter2.setPriority(997);
                registerReceiver(receiver2, filter2);
            }
        });
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //发送一条带msg的广播
                Intent intent = new Intent("android.intent.action.MY_BROADCAST");
                intent.putExtra("msg", "我是动态注册的信息");
//                sendBroadcast(intent);
                MainActivity.this.sendOrderedBroadcast(intent,null);
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //销毁页面时候移除注册的广播。
        unregisterReceiver(receiver);
        unregisterReceiver(receiver1);
        unregisterReceiver(receiver2);
    }
}

Activity 的xml代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注册广播" />

    <Button
        android:id="@+id/btn_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送广播" />
</LinearLayout>

三个广播接收器的代码为:

public class TestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        //为什么要验证,因为 我们可以在这个接收器里面接收好几种不同类型的广播
        //当然你也可以根据自己intent传递一个专门的标志参数来区分。
        if (action.equals("android.intent.action.MY_BROADCAST")) ;
        //创建一个Bundle对象,并存入数据
        Bundle bundle = new Bundle();
        bundle.putString("msg", intent.getStringExtra("msg"));
        //将bundle放入结果中
        setResultExtras(bundle);
        //取消Broadcast的继续发送
        Log.i("receiver0",intent.getStringExtra("msg"));
    }
}
public class TestReceiver1 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        //为什么要验证,因为 我们可以在这个接收器里面接收好几种不同类型的广播
        //当然你也可以根据自己intent传递一个专门的标志参数来区分。
        if (action.equals("android.intent.action.MY_BROADCAST")) ;
        Bundle bundle = getResultExtras(true);
        //解析前一个BroadcastReceiver所存入的key为first的消息
        String first = bundle.getString("msg");
        Log.i("receiver1", first);
//可以更新新的数据往下传递
//        Bundle bundle1 = new Bundle();
//        bundle1.putString("msg", first);
//        //将bundle放入结果中
//        setResultExtras(bundle1);
    }
}
public class TestReceiver2 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        //为什么要验证,因为 我们可以在这个接收器里面接收好几种不同类型的广播
        //当然你也可以根据自己intent传递一个专门的标志参数来区分。
        if (action.equals("android.intent.action.MY_BROADCAST")) ;
        Bundle bundle = getResultExtras(true);//是否接收上一个广播的数据
        String str= bundle.getString("msg");
        Log.i("receiver2",str);
        abortBroadcast();//停止继续往下发送
    }
}

当然我们如果只是按顺序接收相同的信息。那么我们在每个接收器里面直接打印 Log.i(“receiver0/1/2”,intent.getStringExtra(“msg”)); 就可以看出来其是按照顺序发送了,然后我们在Activity中注释掉 filter.setPriority(999);的那几句,或者将里面的数值改为相同,那么就可以验证是否是无序的。【当然我们须要注释掉abortBroadcast()方法,否则会报BroadcastReceiver trying to return result during a non-ordered broadcast异常】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值