Android四大组件之 BroadCastReceive 使用总结

来源:互联网 发布:蒸汽巴士八戒有淘宝店 编辑:程序博客网 时间:2024/06/05 09:34

BroadCast的定义:

广播是一种订阅--通知 事件,广播接收者向Android系统 register (订阅广播),广播发送者向Adnroid系统 sendBroadCast(发送广播),然后Android 系统通知所有注册该广播的接收者,广播接收者收到自己注册的广播之后实现自己想做的事情(该事情一般不超过10s,否则应用会出现ANR)。

BroadCast的分类:

1.无序广播:也就是普通广播,只要注册了该action的广播接收者都能收到该广播,且没有先后顺序。
2.有序广播:广播接收者按照优先级高低依次接受该广播,并且优先接收的广播可以通过setResultExtras(Bundle)方法,将处理好的结果传送到下一个广播接收者那里。
3.粘性广播:发送广播调用的方法 sendStickyBroadcast(Intent),和sendBroadcast(Intent)不同。
粘性广播会一直保留在内存当中,直到有广播接收者注册该广播,该广播才算结束。不好解释,等会具体看例子

BroadCase的使用:

一.普通广播:根据注册方式不同可以分为 静态注册广播和动态注册广播。

1.静态注册广播使用实例

AndroidManifest.xml 如下:
[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.xjp.mybroadcast">  
  4.   
  5.     <application  
  6.         android:allowBackup="true"  
  7.         android:icon="@drawable/ic_launcher"  
  8.         android:label="@string/app_name"  
  9.         android:theme="@style/AppTheme">  
  10.         <activity  
  11.             android:name=".MainActivity"  
  12.             android:label="@string/app_name">  
  13.             <intent-filter>  
  14.                 <action android:name="android.intent.action.MAIN" />  
  15.   
  16.                 <category android:name="android.intent.category.LAUNCHER" />  
  17.             </intent-filter>  
  18.         </activity>  
  19.   
  20.         <!--静态注册广播,此处需要添加广播的action-->  
  21.         <receiver android:name=".BroadCastReceive1">  
  22.             <intent-filter>  
  23.                 <action android:name="com.xjp.mybroadcast.BroadCastReceive1"></action>  
  24.             </intent-filter>  
  25.         </receiver>  
  26.     </application>  
  27.   
  28. </manifest>  

2.广播接收者实现如下:

[java] view plaincopy
  1. package com.xjp.mybroadcast;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6.   
  7. /** 
  8.  * Description:静态广播接收器 
  9.  * User: xjp 
  10.  * Date: 2015/5/14 
  11.  * Time: 14:56 
  12.  */  
  13.   
  14. public class BroadCastReceive1 extends BroadcastReceiver {  
  15.   
  16.     @Override  
  17.     public void onReceive(Context context, Intent intent) {  
  18.         //TODO 接收到广播之后处理自己的事情  
  19.         String action = intent.getAction();  
  20.         String result = intent.getStringExtra("key");  
  21.         MyLog.d("the BroadCast action is " + action + "   the BroadCast receive result is " + result);  
  22.     }  
  23. }  

3.广播发送者实现如下:

[java] view plaincopy
  1. package com.xjp.mybroadcast;  
  2.   
  3. import android.content.Intent;  
  4. import android.os.Bundle;  
  5. import android.support.v7.app.ActionBarActivity;  
  6. import android.view.View;  
  7. import android.widget.Button;  
  8.   
  9.   
  10. public class MainActivity extends ActionBarActivity implements View.OnClickListener {  
  11.   
  12.     private Button btnSend;  
  13.   
  14.     @Override  
  15.     protected void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.activity_main);  
  18.   
  19.         btnSend = (Button) findViewById(R.id.button);  
  20.         btnSend.setOnClickListener(this);  
  21.   
  22.     }  
  23.   
  24.     @Override  
  25.     public void onClick(View v) {  
  26.         switch (v.getId()) {  
  27.             case R.id.button:  
  28.                 sendBraodCast();  
  29.                 break;  
  30.         }  
  31.     }  
  32.   
  33.     private void sendBraodCast() {  
  34.   
  35.         /** 
  36.          * 申明静态广播的 action 行为 
  37.          */  
  38.         String action = "com.xjp.mybroadcast.BroadCastReceive1";  
  39.         Intent intent = new Intent(action);  
  40.         intent.putExtra("key""静态广播测试");  
  41.         sendBroadcast(intent);  
  42.     }  
  43. }  

打印结果如下:


4.静态注册广播特点:

1.注册广播在 AndroidManifest.xml中。
2.广播接收者需重新 继承 BroadcastReceiver 类来实现 onReceive()抽象方法。
3.应用退出无需 注销广播,因此导致:即使广播退出之后,如果有其他应用发送该action行为的广播,此应用还是能接收到该广播的,也就是还会打印上面的 结果。

二.动态广播:

示例

[java] view plaincopy
  1. <pre name="code" class="java">package com.xjp.mybroadcast;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.content.IntentFilter;  
  7. import android.os.Bundle;  
  8. import android.support.v4.content.LocalBroadcastManager;  
  9. import android.support.v7.app.ActionBarActivity;  
  10. import android.view.View;  
  11. import android.widget.Button;  
  12.   
  13.   
  14. public class MainActivity extends ActionBarActivity implements View.OnClickListener {  
  15.   
  16.     private Button btnSend;  
  17.   
  18.     private BroadCastReceive2 myReceive;  
  19.   
  20.     private IntentFilter filter;  
  21.   
  22.     private final static String ACTION = "com.xjp.mybroadcast.BroadCastReceive2";  
  23.   
  24.     @Override  
  25.     protected void onCreate(Bundle savedInstanceState) {  
  26.         super.onCreate(savedInstanceState);  
  27.         setContentView(R.layout.activity_main);  
  28.   
  29.         btnSend = (Button) findViewById(R.id.button);  
  30.         btnSend.setOnClickListener(this);  
  31.   
  32.         myReceive = new BroadCastReceive2();  
  33.         filter = new IntentFilter();  
  34.         filter.addAction(ACTION);  
  35.   
  36.     }  
  37.   
  38.   
  39.     @Override  
  40.     protected void onResume() {  
  41.         /** 
  42.          * 注册广播 
  43.          */  
  44.   
  45.         LocalBroadcastManager.getInstance(this).registerReceiver(myReceive, filter);//官方建议使用  
  46.   
  47. //        this.registerReceiver(myReceive, filter);  
  48.   
  49.         super.onResume();  
  50.     }  
  51.   
  52.   
  53.     @Override  
  54.     protected void onPause() {  
  55.         /** 
  56.          * 注销广播 
  57.          */  
  58.   
  59.         LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceive);//官方建议使用  
  60.   
  61. //        this.unregisterReceiver(myReceive);  
  62.   
  63.         super.onPause();  
  64.     }  
  65.   
  66.     @Override  
  67.     public void onClick(View v) {  
  68.         switch (v.getId()) {  
  69.             case R.id.button:  
  70.                 sendBraodCast();  
  71.                 break;  
  72.         }  
  73.     }  
  74.   
  75.     private void sendBraodCast() {  
  76.   
  77.         /** 
  78.          * 申明广播的 action 行为 
  79.          */  
  80.         Intent intent = new Intent(ACTION);  
  81.         intent.putExtra("key""动态广播测试");  
  82.   
  83.         /** 
  84.          * 官方提倡使用如下发送广播,原因是更快,更安全,不会导致内存泄漏 
  85.          */  
  86.         LocalBroadcastManager.getInstance(this).sendBroadcast(intent);  
  87.   
  88. //        this.sendBroadcast(intent);  
  89.     }  
  90.   
  91.   
  92.     /** 
  93.      * 内部类实现广播接收器 
  94.      */  
  95.     private class BroadCastReceive2 extends BroadcastReceiver {  
  96.   
  97.         @Override  
  98.         public void onReceive(Context context, Intent intent) {  
  99.             //TODO 接收到广播之后处理自己的事情  
  100.             String action = intent.getAction();  
  101.             String result = intent.getStringExtra("key");  
  102.             MyLog.d("the BroadCast action is " + action + "   the BroadCast receive result is " + result);  
  103.         }  
  104.     }  
  105. }  

打印结果如下:

动态广播特点:

1.在代码中调用registerReceiver()方法 注册广播。
2.广播接收者需重新 继承 BroadcastReceiver 类实现内部类。
3.动态广播在应用退出时需要 调用unregisterReceiver()方法来注销广播。如果应用退出时没有注销广播,会报如下错误:
因此,我们通常的做法是:在 onResume()中注册广播,在onPause中注销广播。
4.当广播注销之后就接收不到任何系统发送的广播了。

三.有序广播:

示例:

[java] view plaincopy
  1. <pre name="code" class="java">package com.xjp.mybroadcast;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.content.IntentFilter;  
  7. import android.os.Bundle;  
  8. import android.support.v7.app.ActionBarActivity;  
  9. import android.view.View;  
  10. import android.widget.Button;  
  11.   
  12.   
  13. public class MainActivity extends ActionBarActivity implements View.OnClickListener {  
  14.   
  15.     private Button btnSend;  
  16.   
  17.     private BroadCastReceive2 myReceive;  
  18.   
  19.     private BroadCastReceive3 myReceive3;  
  20.   
  21.     private IntentFilter filter;  
  22.   
  23.     private IntentFilter filter3;  
  24.   
  25.     private final static String ACTION = "com.xjp.mybroadcast.BroadCastReceive2";  
  26.   
  27.     @Override  
  28.     protected void onCreate(Bundle savedInstanceState) {  
  29.         super.onCreate(savedInstanceState);  
  30.         setContentView(R.layout.activity_main);  
  31.   
  32.         btnSend = (Button) findViewById(R.id.button);  
  33.         btnSend.setOnClickListener(this);  
  34.   
  35.         myReceive = new BroadCastReceive2();  
  36.         filter = new IntentFilter();  
  37.         filter.addAction(ACTION);  
  38.         filter.setPriority(2);//设置广播的优先级, -1000~1000 ,数字越大,优先级越高。  
  39.   
  40.         myReceive3 = new BroadCastReceive3();  
  41.         filter3 = new IntentFilter();  
  42.         filter3.addAction(ACTION);  
  43.         filter3.setPriority(1);  
  44.   
  45.   
  46.     }  
  47.   
  48.   
  49.     @Override  
  50.     protected void onResume() {  
  51.         /** 
  52.          * 注册广播 
  53.          */  
  54.         registerReceiver(myReceive, filter);  
  55.         registerReceiver(myReceive3, filter3);  
  56.   
  57.   
  58.         super.onResume();  
  59.     }  
  60.   
  61.   
  62.     @Override  
  63.     protected void onPause() {  
  64.         /** 
  65.          * 注销广播 
  66.          */  
  67.   
  68.         unregisterReceiver(myReceive);  
  69.         unregisterReceiver(myReceive3);  
  70.   
  71.         super.onPause();  
  72.     }  
  73.   
  74.     @Override  
  75.     public void onClick(View v) {  
  76.         switch (v.getId()) {  
  77.             case R.id.button:  
  78.                 sendBraodCast();  
  79.                 break;  
  80.         }  
  81.     }  
  82.   
  83.     private void sendBraodCast() {  
  84.   
  85.         /** 
  86.          * 申明广播的 action 行为 
  87.          */  
  88.         Intent intent = new Intent(ACTION);  
  89.         intent.putExtra("key""有序广播测试");  
  90.   
  91.         this.sendOrderedBroadcast(intent, null);  
  92.     }  
  93.   
  94.   
  95.     /** 
  96.      * 内部类实现广播接收器 
  97.      */  
  98.     private class BroadCastReceive2 extends BroadcastReceiver {  
  99.   
  100.         @Override  
  101.         public void onReceive(Context context, Intent intent) {  
  102.             //TODO 接收到广播之后处理自己的事情  
  103.             String action = intent.getAction();  
  104.             String result = intent.getStringExtra("key");  
  105.             MyLog.d("the BroadCast action is " + action + "   the BroadCast receive result is " + result);  
  106.   
  107.             Bundle bundle = new Bundle();  
  108.             bundle.putString("key""有序广播处理之后" + "\n" + "再次发送给下一个广播接收者");  
  109.             intent.putExtra("bundle", bundle);  
  110.             setResultExtras(bundle);  
  111.             //切断广播,不再让此广播继续往下发送。  
  112.             //  abortBroadcast();  
  113.         }  
  114.     }  
  115.   
  116.     /** 
  117.      * 内部类实现广播接收器 
  118.      */  
  119.     private class BroadCastReceive3 extends BroadcastReceiver {  
  120.   
  121.         @Override  
  122.         public void onReceive(Context context, Intent intent) {  
  123.             //TODO 接收到广播之后处理自己的事情  
  124.             String action = intent.getAction();  
  125.             //要不要接受上一个广播接收器receiver2传来的的数据  
  126.             Bundle bundle = getResultExtras(true);  
  127.             MyLog.d("the BroadCast action is " + action + "   the BroadCast receive result is " + bundle.getString("key"));  
  128.         }  
  129.     }  
  130. }  

有序广播特点:

1.所有广播接收者的action是一致的,发送有序广播调用 sendOrderedBroadcast()方法。
2.有序广播的接收者需要调用setPriority()方法设置广播接收者的优先级。数字越大,优先接受广播。
3.有序广播如果需要终止 广播继续往下发送,可以调用 abortBroadcast()方法切断广播。
4.先接收广播者可以将自己的处理结果通过setResultExtras()方法继续传递给下一个广播接收者。
5.后接收者可以调用 getResultExtras(true)来自己决定是否接收上一个广播传递过来的数据。

四.粘性广播:

示例  需要在 AndroidManifest.xml中添加 权限
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <uses-permission android:name="android.permission.BROADCAST_STICKY"></uses-permission>  

发送广播的Activity
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.xjp.mybroadcast;  
  2.   
  3. import android.content.Intent;  
  4. import android.os.Bundle;  
  5. import android.support.v7.app.ActionBarActivity;  
  6. import android.view.View;  
  7. import android.widget.Button;  
  8.   
  9.   
  10. /** 
  11.  * 发送广播的Activity 
  12.  */  
  13. public class MainActivity extends ActionBarActivity implements View.OnClickListener {  
  14.   
  15.     private Button btnSend;  
  16.   
  17.   
  18.     private final static String ACTION = "com.xjp.mybroadcast.BroadCastReceive1";  
  19.     private final static String ACTION1 = "com.xjp.mybroadcast.BroadCastReceive2";  
  20.   
  21.     @Override  
  22.     protected void onCreate(Bundle savedInstanceState) {  
  23.         super.onCreate(savedInstanceState);  
  24.         setContentView(R.layout.activity_main);  
  25.   
  26.         btnSend = (Button) findViewById(R.id.button);  
  27.         btnSend.setOnClickListener(this);  
  28.     }  
  29.   
  30.   
  31.     @Override  
  32.     public void onClick(View v) {  
  33.         switch (v.getId()) {  
  34.             case R.id.button:  
  35.                 sendBraodCast();  
  36.                 break;  
  37.         }  
  38.     }  
  39.   
  40.     private void sendBraodCast() {  
  41.   
  42.         /** 
  43.          * 申明广播的 action 行为 
  44.          */  
  45.         Intent intent = new Intent(ACTION);  
  46.         intent.putExtra("key""普通广播测试");  
  47.         sendBroadcast(intent);  
  48.   
  49.         Intent intent1 = new Intent(ACTION1);  
  50.         intent1.putExtra("key""粘性广播测试");  
  51.         sendStickyBroadcast(intent1);  
  52.         startActivity(new Intent(this, RecevieActivity.class));  
  53.     }  
  54. }  
接受广播的Activity
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.xjp.mybroadcast;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.BroadcastReceiver;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.IntentFilter;  
  8. import android.os.Bundle;  
  9.   
  10. /** 
  11.  * Description:接受广播的Activity 
  12.  * User: xjp 
  13.  * Date: 2015/5/14 
  14.  * Time: 17:03 
  15.  */  
  16.   
  17. public class RecevieActivity extends Activity {  
  18.   
  19.     private final static String ACTION1 = "com.xjp.mybroadcast.BroadCastReceive1";  
  20.     private final static String ACTION2 = "com.xjp.mybroadcast.BroadCastReceive2";  
  21.   
  22.     private Receive receive;  
  23.   
  24.     private IntentFilter filter1;  
  25.   
  26.     @Override  
  27.     protected void onCreate(Bundle savedInstanceState) {  
  28.         super.onCreate(savedInstanceState);  
  29.   
  30.         receive = new Receive();  
  31.   
  32.         filter1 = new IntentFilter();  
  33.         filter1.addAction(ACTION1);  
  34.         filter1.addAction(ACTION2);  
  35.   
  36.     }  
  37.   
  38.     @Override  
  39.     protected void onResume() {  
  40.         super.onResume();  
  41.         registerReceiver(receive, filter1);  
  42.     }  
  43.   
  44.     @Override  
  45.     protected void onPause() {  
  46.         super.onPause();  
  47.         unregisterReceiver(receive);  
  48.     }  
  49.   
  50.     private class Receive extends BroadcastReceiver {  
  51.         @Override  
  52.         public void onReceive(Context context, Intent intent) {  
  53.             String action = intent.getAction();  
  54.             String result = intent.getStringExtra("key");  
  55.             MyLog.d("the BroadCast action is " + action + "   the BroadCast receive result is " + result);  
  56.         }  
  57.     }  
  58. }  

打印结果如下:

从结果来看,只有粘性广播才能接收到广播信息。

粘性广播特点:

1.需要在AndroidManifest.xml中添加权限
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <uses-permission android:name="android.permission.BROADCAST_STICKY"></uses-permission>  
2.粘性广播发送除了调用方法不同sendStickyBroadcast(intent1),其他都一样。
3.一般广播都是先注册广播,才能接收到广播,而粘性广播可以做到先发送广播,哪里需要接收该广播就哪里注册,可以后注册广播拿到广播的结果。这就是 普通广播和粘性广播的区别。从示例中也看出了普通广播在跳转到ReceiveActivity中是接受不到广播发送者发出的广播的,只有粘性广播才能接收到。

有人会奇怪,平时也没看到哪里使用粘性广播??其实我也是看到Android 系统中 监测电池电量部分发现的。贴上代码如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. // Register for the battery changed event  
  2. IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);  
  3.   
  4. / Intent is sticky so using null as receiver works fine  
  5. // return value contains the status  
  6. Intent batteryStatus = this.registerReceiver(null, filter);  
  7.   
  8. // Are we charging / charged?  
  9. int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);  
  10. boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING  
  11.   || status == BatteryManager.BATTERY_STATUS_FULL;  
  12.   
  13. boolean isFull = status == BatteryManager.BATTERY_STATUS_FULL;  
  14.   
  15. // How are we charging?  
  16. int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);  
  17. boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;  
  18. boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;   

广播的生命周期:

当广播接收者接收到广播调用完onReceive()方法之后,广播的生命周期就结束了。

因此广播接收器不能执行超过10s耗时任务,也不能在onReceive()方法中创建Thread 来执行耗时任务,你可以开启一个Service来执行后台耗时任务,具体可以参考Android 四大组件之Service 的生命周期和使用。




广播的大概原理:

广播是怎么发送的?又是怎么接收的?

我们知道,只有先注册了某个广播之后,广播接收者才能收到该广播。广播注册的一个行为是将自己感兴趣的IntentFilter注册到Android系统的AMS(ActivityManagerService)中,里面保存了一个IntentFilter列表。广播发送者将自己的IntentFilter 的action行为发送到AMS中,然后遍历AMS中的IntentFilter列表,看谁订阅了该广播,然后将消息遍历发送到注册了相应IntentFilter的Activity或者Service中-----也就是会调用抽象方法onReceive()方法。其中AMS起到了中间桥梁作用。

系统广播:

Android系统中有很多系统广播,比如:
EventDescriptionIntent.ACTION_BOOT_COMPLETEDBoot completed. Requires the android.permission.RECEIVE_BOOT_COMPLETEDpermission.Intent.ACTION_POWER_CONNECTEDPower got connected to the device.Intent.ACTION_POWER_DISCONNECTEDPower got disconnected to the device.Intent.ACTION_BATTERY_LOWTriggered on low battery. Typically used to reduce activities in your app which consume power.Intent.ACTION_BATTERY_OKAYBattery status good again.
0 0