简介:
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>
//如果是发送的有序广播,那么优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,然后传给下一个接收者 Bundle bundle = new Bundle(); bundle.putString("msg", msg + "@MyBroadcastReceiverS2"); setResultExtras(bundle);
使用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); } }
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; } }
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>