简介:
BroadcastReceiver: 广播接收器,一个专门接收广播的东东,它需要在系统中进行注册,注册方式有静态注册(在manifest.xml中注册)和动态注册(在Activity或service中注册)两种, 注册的作用就是告诉系统,我只接收什么样的广播(具体通过action属性设置),如果有这样的广播,就叫我一声,我来处理下。
静态注册:在manifest.xml中进行注册,表示只要是android.intent.action.mybroadcast_action这个地址的广播,MyBroadcastReceiverS1都能够接收的到。注意,这种方式的注册是常驻型的,也就是说当应用关闭后,如果有广播信息传来,MyBroadcastReceiverS1也会被系统调用而自动运行。
<!-- 在manifest。xml中注册广播接收者 -->
<receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS1" >
<intent-filter android:priority="1000" >
<action android:name="android.intent.action.mybroadcast_action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
动态注册:在代码中动态的指定广播地址并注册,通常我们是在Activity或Service注册一个广播,这种注册方式与静态注册相反,不是常驻型的,也就是说广播会跟随程序的生命周期,当Activity或service销毁时,我们必须对Receiver解除注册,否则会报异常,因此我们要在特定的方法中对Receiver进行解除注册。
//在Activity中动态的注册广播接收器
battertChangeReceiver = new MyBroadcastReceiverD4();
IntentFilter filter = new IntentFilter(
"android.intent.action.MY_BROADCAST");
registerReceiver(battertChangeReceiver, filter);
//在Activity的destroy方法解除注册
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(battertChangeReceiver);
}
如果有多个接收者都注册了相同的广播地址,又会是什么情况呢,能同时接收到同一条广播吗,相互之间会不会有干扰呢?这就涉及到普通广播和有序广播的概念了。
普通广播:对于多个接收者来说是完全异步的,通常每个接收者都无需等待即可以接收到广播,接收者相互之间不会有影响。对于这种广播,接收者无法终止广播,即无法阻止其他接收者的接收动作。
有序广播:有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。静态注册的有序广播要加上android:priority="1000"属性来定义优先级,动态的可以在代码中设置setPriority();发送有序广播调用方法sendOrderedBroadcast(Intent intent,String permission);
<!-- 在manifest。xml中注册广播接收者,有序广播需要指定priority属性,同时注意,一个接收器可以注册多种类型的广播,如下面定义的MyBroadcastReceiverS3 -->
<receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS1" >
<intent-filter android:priority="1000" >
<action android:name="android.intent.action.mybroadcast_action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS2" >
<intent-filter android:priority="999" >
<action android:name="android.intent.action.mybroadcast_action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!--定义两个action,该Receiver可以接收多种类型的广播 -->
<receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS3" >
<intent-filter android:priority="998" >
<action android:name="android.intent.action.mybroadcast_action" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
在发送的有序广播的前提下,在广播的Receiver方法里面调用setResultExtras(bundle),那么优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,然后传给下一个接收者,非有序广播即使设置了也无效。
//如果是发送的有序广播,那么优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,然后传给下一个接收者
Bundle bundle = new Bundle();
bundle.putString("msg", msg + "@MyBroadcastReceiverS2");
setResultExtras(bundle);
调用abortBroadcast()可以停止广播的传播,此方法只对有序广播有效,普通广播无效。高优先级的Receiver调用该方法之后,低优先级的Receiver将不会接收到广播。
使用sendOrderedBroadcast方法发送有序广播时,需要一个权限参数,如果为null则表示不要求接收者声明指定的权限,如果不为null,则表示接收者若要接收此广播,需声明指定权限。这样做是从安全角度考虑的,例如系统的短信就是有序广播的形式,一个应用可能是具有拦截垃圾短信的功能,当短信到来时它可以先接受到短信广播,必要时终止广播传递,这样的软件就必须声明接收短信的权限。
case R.id.button2:// 有序广播
intent = new Intent("android.intent.action.mybroadcast_action");
intent.putExtra("type", 2);
intent.putExtra("msg", "发送有序广播 ");
//发送有序广播
sendOrderedBroadcast(intent,"scott.permission.mybroadcast_permission");
break;
所以我们在AndroidMainfest.xml中定义一个权限(关于权限定义,声明与使用,请参照:http://blog.csdn.net/liuhe688/article/details/6417983),然后使用该权限:
<!-- 自定义权限 -->
<permission
android:name="scott.permission.mybroadcast_permission"
android:protectionLevel="normal" >
</permission>
<!-- 使用自定义的权限 -->
<uses-permission android:name="scott.permission.mybroadcast_permission" />
以下是我做的project,实现静态注册,动态注册等功能。
1. 静态注册的MyBroadcastReceiverS1
package com.androidstudydemo.broadcastReceiver;
import com.androidstudydemo.common.util.DisPlayUtil;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.sax.StartElementListener;
import android.util.Log;
import android.widget.TextView;
/**
* broadcastreceiver注册有两种方法,一种静态注册,一种动态注册,此对象采用静态注册,即 在manifest.xml文件中进行注册。
*
* @author zkx016
*
*/
public class MyBroadcastReceiverS1 extends BroadcastReceiver {
String TAG = "MyBroadcastReceiverS1";
@Override
public void onReceive(Context arg0, Intent arg1) {
int type = arg1.getIntExtra("type", 1);
String msg = arg1.getStringExtra("msg");
msg += getResultExtras(true).getString("msg");
Log.i(TAG, "MyBroadcastReceiverS1:" + type + "/" + msg);
String info = TAG + "==> action is:" + arg1.getAction()
+ " message is:" + msg;
DisPlayUtil.ShowToastMessage(arg0, info);
Handler handler = MyBroadcastSenderActivity.getHandler();// 将信息发送给activity更新textView
Message message = handler.obtainMessage();
message.what = 1;
message.obj = info;
message.sendToTarget();
// 如果是发送的有序广播,那么优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,然后传给下一个接收者,若是普通广播,下面的请直接忽略
Bundle bundle = new Bundle();
bundle.putString("msg", msg + "@MyBroadcastReceiverS1");
setResultExtras(bundle);
}
}
2.静态注册的MyBroadcastReceiverS2.java
package com.androidstudydemo.broadcastReceiver;
import com.androidstudydemo.common.util.DisPlayUtil;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
public class MyBroadcastReceiverS2 extends BroadcastReceiver {
String TAG = "MyBroadcastReceiverS2";
@Override
public void onReceive(Context arg0, Intent arg1) {
int type = arg1.getIntExtra("type", 1);
String msg = arg1.getStringExtra("msg");
Bundle bundle1 = getResultExtras(true);
msg += bundle1.getString("msg");
Log.i(TAG, msg);
String info = TAG + "==> action is:" + arg1.getAction()
+ " message is:" + msg;
DisPlayUtil.ShowToastMessage(arg0, info);
Handler handler = MyBroadcastSenderActivity.getHandler();// 将信息发送给activity更新textView
Message message = handler.obtainMessage();
message.what = 1;
message.obj = info;
message.sendToTarget();
// 如果是发送的有序广播,那么优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,然后传给下一个接收者
Bundle bundle = new Bundle();
bundle.putString("msg", msg + "@MyBroadcastReceiverS2");
setResultExtras(bundle);
abortBroadcast();//终止广播的继续传播,可以看见,broadCastReceiverS3没有接收到广播
}
}
package com.androidstudydemo.broadcastReceiver;
import com.androidstudydemo.common.util.DisPlayUtil;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
public class MyBroadcastReceiverS3 extends BroadcastReceiver {
String TAG = "MyBroadcastReceiverS3";
@Override
public void onReceive(Context arg0, Intent arg1) {
int type = arg1.getIntExtra("type", 1);
String msg = arg1.getStringExtra("msg");
msg += getResultExtras(true).getString("msg");
Log.i(TAG, msg);
String info = TAG + "==> action is:" + arg1.getAction()
+ " message is:" + msg;
DisPlayUtil.ShowToastMessage(arg0, info);
Handler handler = MyBroadcastSenderActivity.getHandler();// 将信息发送给activity更新textView
Message message = handler.obtainMessage();
message.what = 1;
message.obj = info;
message.sendToTarget();
// 如果是发送的有序广播,那么优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,然后传给下一个接收者
Bundle bundle = new Bundle();
bundle.putString("msg", msg + "@MyBroadcastReceiverS3");
setResultExtras(bundle);
//当网络可用发生变化时,系统会发出一个广播,所以我们在断开网络或重启网络时不用我们自己手动的发一个广播。
if (!isNetworkAvailable(arg0)) {
Toast.makeText(arg0, "network disconnected!", 0).show();
}
}
/**
* 网络是否可用
*
* @param context
* @return
*/
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager mgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo[] info = mgr.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
return false;
}
}
4.动态注册的MyBroadcastReceiverD4.java,在BatteryChangeActivity中动态注册,一进入页面即提示当前电量。
package com.androidstudydemo.broadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
import android.util.Log;
import android.widget.Toast;
public class MyBroadcastReceiverD4 extends BroadcastReceiver {
String TAG = "MyBroadcastReceiverD4";
@Override
public void onReceive(Context arg0, Intent intent) {
int currLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); // 当前电量
int total = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1); // 总电量
int percent = currLevel * 100 / total;
Toast.makeText(arg0, "当前电量:" + percent, 0).show();
Log.i(TAG, "battery: " + percent + "%");
}
}
5.主界面MyBroadcastSenderActivity,里面包含三个按钮:发送普通广播,发送有序广播,动态注册示例 三个按钮。
package com.androidstudydemo.broadcastReceiver;
import java.util.HashMap;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.androidstudydemo.common.BaseActivity;
import com.androidstudydemo.common.MyTitleView;
import com.androidstudydemo.common.R;
import com.androidstudydemo.common.util.DisPlayUtil;
public class MyBroadcastSenderActivity extends BaseActivity implements
OnClickListener {
static TextView textView = null;
MyTitleView title = null;
// MyBroadcastReceiver1 receiver1; receiver1通过在manifest。xml中进行注册
MyBroadcastReceiverS2 receiver2;// 在代码中动态注册。
int i = 1;
static Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 1:
if (textView != null) {
String info = (String) msg.obj;
textView.append(info);
}
break;
default:
break;
}
};
};
public static Handler getHandler() {
return handler;
}
@Override
protected void onStart() {
super.onStart();
// 静态注册,一般是在onstart方法进行注册,在onstop方法进行销毁
receiver2 = new MyBroadcastReceiverS2();
IntentFilter filter2 = new IntentFilter();
filter2.addAction("myaction");
registerReceiver(receiver2, filter2);
}
@Override
protected void onStop() {
super.onStop();
if (receiver2 != null) {// 动态注册,在activity销毁时要解除注册,否则会报错。
unregisterReceiver(receiver2);
}
}
public void initTitle(MyTitleView title) {
HashMap<String, Object> datas = new HashMap<String, Object>();
datas.put("title", R.string.broadcastReceiver_title);
datas.put("instration", R.string.broadcastReceiver_isntration);
title.setInitDatas(datas);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mybroadcastsenderdemo);
textView = (TextView) this.findViewById(R.id.textView1);
title = (MyTitleView) this.findViewById(R.id.title);
initTitle(title);
}
public void initInstration() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("title", "broadcastReceiver讲解");
map.put("message",
getResources().getString(R.string.broadcastReceiver_isntration));
DisPlayUtil.showAlertDialog(MyBroadcastSenderActivity.this, map);
}
@Override
public void onClick(View arg0) {
Intent intent;
switch (arg0.getId()) {
case R.id.button1:// 普通广播
intent = new Intent("android.intent.action.mybroadcast_action");
intent.putExtra("type", 1);
intent.putExtra("msg", "发送普通广播 ");
sendBroadcast(intent);
break;
case R.id.button2:// 有序广播
intent = new Intent("android.intent.action.mybroadcast_action");
intent.putExtra("type", 2);
intent.putExtra("msg", "发送有序广播 ");
sendOrderedBroadcast(intent,"scott.permission.mybroadcast_permission");
break;
case R.id.button3:
intent = new Intent(this, BatteryChangeActivity.class);
startActivity(intent);
break;
case R.id.button4:
break;
default:
break;
}
}
}
package com.androidstudydemo.broadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import com.androidstudydemo.common.BaseActivity;
public class BatteryChangeActivity extends BaseActivity {
MyBroadcastReceiverD4 battertChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
battertChangeReceiver = new MyBroadcastReceiverD4();
IntentFilter filter = new IntentFilter(
"android.intent.action.MY_BROADCAST");
registerReceiver(battertChangeReceiver, filter);
Intent batteryIntent = new Intent("android.intent.action.MY_BROADCAST");
sendBroadcast(batteryIntent);
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
unregisterReceiver(battertChangeReceiver);
}
}
<?xml version="1.0" encoding="utf-8"?>
<!-- android:installLocation="auto" 自动选择安装位置(sd卡或手机内存) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.androidstudydemo.common"
android:installLocation="auto"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<!-- 自定义权限 -->
<permission
android:name="scott.permission.mybroadcast_permission"
android:protectionLevel="normal" >
</permission>
<!-- 使用自定义的权限 -->
<uses-permission android:name="scott.permission.mybroadcast_permission" />
<!-- 使用网络功能所需权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
</uses-permission>
<uses-permission android:name="android.permission.INTERNET" >
</uses-permission>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<uses-library android:name="android.test.runner" />
<!-- 在manifest.xml中注册广播接收者 -->
<receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS1" >
<intent-filter android:priority="1000" >
<action android:name="android.intent.action.mybroadcast_action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS2" >
<intent-filter android:priority="999" >
<action android:name="android.intent.action.mybroadcast_action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastReceiverS3" >
<intent-filter android:priority="998" >
<action android:name="android.intent.action.mybroadcast_action" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity
android:name="com.androidstudydemo.main.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.androidstudydemo.broadcastReceiver.MyBroadcastSenderActivity"
android:label="@string/app_name" >
</activity>
<activity
android:name="com.androidstudydemo.broadcastReceiver.BatteryChangeActivity"
android:label="@string/app_name" >
</activity>
</application>
</manifest>