BroadcastReceiver 应用详解

1. BroadcastReceiver广播介绍
   部分内容摘自: http://blog.csdn.net/liuhe688/article/details/6955668
    BroadcastReceiver也就是“广播接收者”的意思,顾名思义,它就是用来接收来自系统和应用中的广播。
    在Android系统中,广播体现在方方面面,例如当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的功能;当网络状态改变时系统会产生一条广播,接收到这条广播就能及时地做出提示和保存数据等操作;当电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度,等等。
 要注册广播有两种方法:一种是在class中用Context.registerReceiver()注册。另一种是在AndroidManifest.xml清单文件中通过<receiver>注册。
  1)要创建自己的BroadcastReceiver对象,我们需要继承android.content.BroadcastReceiver,并实现其onReceive方法。下面我们就创建一个名为MyReceiver广播接收者:   
public class MyReceiver extends BroadcastReceiver {    
    @Override  
    public void onReceive(Context context, Intent intent) {  
        String msg = intent.getStringExtra("msg");  
        Log.i(TAG, msg);  
    }    
} 
  在onReceive方法内,我们可以获取随广播而来的Intent中的数据,这非常重要,就像无线电一样,包含很多有用的信息。

在创建完我们的BroadcastReceiver之后,还不能够使它进入工作状态,我们需要为它注册一个指定的广播地址。没有注册广播地址的BroadcastReceiver就像一个缺少选台按钮的收音机,虽然功能俱备,但也无法收到电台的信号。下面我们就来介绍一下如何为BroadcastReceiver注册广播地址。

 1) 静态注册:静态注册就是在AndroidManifest.xml文件中配置,我们就来为MyReceiver注册一个广播地址: 
<receiver android:name=".MyReceiver">  
    <intent-filter>  
        <action android:name="android.intent.action.MY_BROADCAST"/>  
        <category android:name="android.intent.category.DEFAULT" />  
    </intent-filter>  
</receiver> 
   配置了以上信息之后,只要是android.intent.action.MY_BROADCAST这个地址的广播,MyReceiver都能够接收的到。注意,这种方式的注册是常驻型的,也就是说当应用关闭后,如果有广播信息传来,MyReceiver也会被系统调用而自动运行。
2) 动态注册:动态注册需要在代码中动态的指定广播地址并注册,通常我们是在Activity或Service注册一个广播,下面我们就来看一下注册的代码:
MyReceiver receiver = new MyReceiver();           
IntentFilter filter = new IntentFilter();  
filter.addAction("android.intent.action.MY_BROADCAST");           
registerReceiver(receiver, filter); 
  注意,registerReceiver是android.content.ContextWrapper类中的方法,Activity和Service都继承了ContextWrapper,所以可以直接调用。在实际应用中,我们在Activity或Service中注册了一个BroadcastReceiver,当这个Activity或Service被销毁时如果没有解除注册,系统会报一个异常,提示我们是否忘记解除注册了。所以,记得在特定的地方执行解除注册操作:
@Override  
protected void onDestroy() {  
    super.onDestroy();  
    unregisterReceiver(receiver);  
} 

执行这样行代码就可以解决问题了。注意,这种注册方式与静态注册相反,不是常驻型的,也就是说广播会跟随程序的生命周期。

我们可以根据以上任意一种方法完成注册,当注册完成之后,这个接收者就可以正常工作了。我们可以用以下方式向其发送一条广播:

public void send(View view) {  
    Intent intent = new Intent("android.intent.action.MY_BROADCAST");  //写入了广播地址
    intent.putExtra("msg", "hello receiver.");  
    sendBroadcast(intent);  
} 
注意,sendBroadcast也是android.content.ContextWrapper类中的方法,它可以将一个指定地址和参数信息的Intent对象以广播的形式发送出去。
点击发送按钮,执行send方法,控制台打印如下:

上面的例子只是一个接收者来接收广播,如果有多个接收者都注册了相同的广播地址,又会是什么情况呢,能同时接收到同一条广播吗,相互之间会不会有干扰呢?这就涉及到普通广播和有序广播的概念了。

 广播有两个主要的类,一个是Normal broadcasts 普通广播,另一种是Ordered broadcasts有序广播。
1) 普通广播(Normal Broadcast)
普通广播对于多个接收者来说是完全异步的,通常每个接收者都无需等待即可以接收到广播,接收者相互之间不会有影响。对于这种广播,接收者无法终止广播,即无法阻止其他接收者的接收动作。
示例:接收到广播时,就弹出一个通知。
1. 实现一个MyReceiver类
/** 广播的生命周期: onReceive 方法执行开始到执行结束 */
public class MyReceiver extends BroadcastReceiver {
	private NotificationManager manager;
	private Notification.Builder builder;
	public void onReceive(Context context, Intent intent) {
	manager = (NotificationManager) context
				.getSystemService(Context.NOTIFICATION_SERVICE);
	builder = new Notification.Builder(context);
	builder.setContentTitle("有短信来啦");
	builder.setContentText("晚上有时间吗?");
	builder.setSmallIcon(R.drawable.ic_launcher);
	manager.notify(1001, builder.build());
	}
}
注意:在广播里面不要有对话框,也不要有 service.不要有耗时的操作。
2. 在MainActivity.java,点击按钮时发送一个广播
button.setOnClickListener(new View.OnClickListener() {
	public void onClick(View v) {
	Intent intent = new Intent(MainActivity.this, MyReceiver.class);
	sendBroadcast(intent); //把广播发送出去。
	}
});
3. 广播在要AndroidManifest.xml中注册
 <receiver android:name="com.example.android_broadcast_normal.MyReceiver" >  </receiver>
2)有序广播(Ordered Broadcast)
   有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。
1.先定义多个广播接收者Broadcast1.java,Broadcast2.java,Broadcast3.java
<pre name="code" class="java">public class Broadcast1 extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
       String msg = intent.getStringExtra("msg");  
        Log.i(TAG, "FirstReceiver: " + msg);  
          
        Bundle bundle = new Bundle();  
        bundle.putString("msg", msg + "@FirstReceiver");  
        setResultExtras(bundle);
    }
}
 
<pre name="code" class="java">public class Broadcast2 extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
     String msg = getResultExtras(true).getString("msg");  
     Log.i(TAG, "SecondReceiver: " + msg);  
       
     Bundle bundle = new Bundle();  
     bundle.putString("msg", msg + "@SecondReceiver");  
     setResultExtras(bundle); 
     abortBroadcast(); //可以在有序广播中停止广播
    }
}
 
<pre name="code" class="java">public class Broadcast3 extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
     String msg = getResultExtras(true).getString("msg");  
     Log.i(TAG, "SecondReceiver: " + msg);  
    }
}
 

  我们注意到,在Broadcast1和Broadcast2中最后都使用了setResultExtras方法将一个Bundle对象设置为结果集对象,传递到下一个接收者那里,这样以来,优先级低的接收者可以用getResultExtras获取到最新的经过处理的信息集合。

2. 在MainActivity中分别发送 无序和有序广播

button.setOnClickListener(new View.OnClickListener() {
	public void onClick(View v) {
		// 给多个广播接受者发送广播
		Intent intent = new Intent();
		intent.putExtra("msg", "jack");
		intent.setAction("com.mybroadcast.sender");// 设置一个动作
		sendBroadcast(intent);
	}
});
button2.setOnClickListener(new View.OnClickListener() {
	public void onClick(View v) {
		Intent intent = new Intent();
		intent.putExtra("msg", "rose");
		intent.setAction("com.mybroadcast.sender");
		//发送有序广播
		sendOrderedBroadcast(intent, null);
	}
});
sendOrderedBroadcast(intent, null);   注意,使用sendOrderedBroadcast方法发送有序广播时,第二个参数是一个权限参数如果为null则表示不要求接收者声明指定的权限,如果不为null,如:sendOrderedBroadcast(intent, "scott.permission.MY_BROADCAST_PERMISSION"); 则表示接收者若要接收此广播,需声明指定权限。这样做是从安全角度考虑的,例如系统的短信就是有序广播的形式,一个应用可能是具有拦截垃圾短信的功能,当短信到来时它可以先接受到短信广播,必要时终止广播传递,这样的软件就必须声明接收短信的权限。

所以我们在AndroidMainfest.xml中定义一个权限:

<permission android:protectionLevel="normal"  android:name="scott.permission.MY_BROADCAST_PERMISSION" />  
然后声明使用了此权限:
<uses-permission android:name="scott.permission.MY_BROADCAST_PERMISSION" /> 
3. 在AndroidManifest.xml中注册
<receiver android:name="com.example.android_broadcast_order.Broadcast1" >
    <intent-filter android:priority="999" >
        <action android:name="com.mybroadcast.sender" >
        </action>
    </intent-filter>
</receiver>
<receiver android:name="com.example.android_broadcast_order.Broadcast2" >
    <intent-filter android:priority="1000" >
        <action android:name="com.mybroadcast.sender" >
        </action>
    </intent-filter>
</receiver>
<receiver android:name="com.example.android_broadcast_order.Broadcast3" >
    <intent-filter android:priority="998" >
        <action android:name="com.mybroadcast.sender" >
        </action>
    </intent-filter>
</receiver>
在<receiver>当中,添加意图过滤器<intent-filter>,里面添加<action>,只有当intent.setAction的标签与<action>中的name一致时,就会被该<receiver>接收到。
注:无序广播调用 abortBroadcast()方法后出错是,只有有序广播才可以。
 <intent-filter android:priority="998" >这个属性的范围在-1000到1000,数值越大,优先级越高,就先收到广播。

上面就是BroadcastReceiver的介绍,下面我将会举几个常见的例子加深一下大家对广播的理解和应用:
3. Broadcast判断网络状况
   在某些场合,比如用户浏览网络信息时,网络突然断开,我们要及时地提醒用户网络已断开。要实现这个功能,我们可以接收网络状态改变这样一条广播,当由连接状态变为断开状态时,系统就会发送一条广播,我们接收到之后,再通过网络的状态做出相应的操作。
直接在MainActivity当中完成:
public class MainActivity extends Activity {
private ConnectivityManager manager;// 判断网络的状况
private NotificationManager notificationManager;// 需要通知去提醒用户
private BroadcastReceiver receiver = new BroadcastReceiver() {
	public void onReceive(Context context, Intent intent) {
	// 提醒用户网络状况有异常
	// 分别获得2G和3G、wifi的网络状况
	//提醒用户的两种方式:吐司、通知
	NetworkInfo mobileInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
	NetworkInfo wifiInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
	if (!mobileInfo.isConnected() || !wifiInfo.isConnected()) {
             Notification.Builder builder = new Notification.Builder(MainActivity.this);
             builder.setContentText("提示信息");
             builder.setContentText("网络状况有异常");
             builder.setSmallIcon(R.drawable.ic_launcher);
             notificationManager.notify(1001,builder.build());
		}
	}
};
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
	notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
// 注册广播
protected void onResume() {
	super.onResume();
	IntentFilter filter = new IntentFilter();
	filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
	registerReceiver(receiver, filter);
}
// 卸载广播
protected void onPause() {
	super.onPause();
	if (receiver != null) {
		unregisterReceiver(receiver);
	}
}
}
在清单文件中添加wifi权限:
    <!-- 添加网络授权 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值