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异常】
更多相关文章
- Android操作JNI函数以及复杂对象传递
- Activity 生命周期(一)
- Android(安卓)组件系列-----Activity保存状态
- Android(安卓)带清除功能的输入框控件ClearEditText
- android: 接收和发送短信
- Android自学笔记-14-意图(Intent)
- Android(安卓)程序在系统中如何完成启动
- Activity从屏幕底部滑出、滑入、处理黑色背景和状态栏
- Android之AsyncTask的用法