简介:
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>