Android四大组件之BroadCastReceive使用总结

  • BroadCast的定义:

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

    BroadCast的分类:

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

    BroadCase的使用:

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

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

    AndroidManifest.xml 如下:
    view source print ?
    01. <?xml version="1.0" encoding="utf-8"?>
    02. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    03. package="com.xjp.mybroadcast">
    04.  
    05. <application
    06. android:allowBackup="true"
    07. android:icon="@drawable/ic_launcher"
    08. android:label="@string/app_name"
    09. 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.广播接收者实现如下:

    view source print ?
    01. package com.xjp.mybroadcast;
    02.  
    03. import android.content.BroadcastReceiver;
    04. import android.content.Context;
    05. import android.content.Intent;
    06.  
    07. /**
    08. * Description:静态广播接收器
    09. * 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.广播发送者实现如下:

    view source print ?
    01. package com.xjp.mybroadcast;
    02.  
    03. import android.content.Intent;
    04. import android.os.Bundle;
    05. import android.support.v7.app.ActionBarActivity;
    06. import android.view.View;
    07. import android.widget.Button;
    08.  
    09.  
    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行为的广播,此应用还是能接收到该广播的,也就是还会打印上面的 结果。 

    二.动态广播:

    示例

    view source print ?
    001. <pre name="code" class="java">package com.xjp.mybroadcast;
    002.  
    003. import android.content.BroadcastReceiver;
    004. import android.content.Context;
    005. import android.content.Intent;
    006. import android.content.IntentFilter;
    007. import android.os.Bundle;
    008. import android.support.v4.content.LocalBroadcastManager;
    009. import android.support.v7.app.ActionBarActivity;
    010. import android.view.View;
    011. import android.widget.Button;
    012.  
    013.  
    014. public class MainActivity extends ActionBarActivity implements View.OnClickListener {
    015.  
    016. private Button btnSend;
    017.  
    018. private BroadCastReceive2 myReceive;
    019.  
    020. private IntentFilter filter;
    021.  
    022. private final static String ACTION = "com.xjp.mybroadcast.BroadCastReceive2";
    023.  
    024. @Override
    025. protected void onCreate(Bundle savedInstanceState) {
    026. super.onCreate(savedInstanceState);
    027. setContentView(R.layout.activity_main);
    028.  
    029. btnSend = (Button) findViewById(R.id.button);
    030. btnSend.setOnClickListener(this);
    031.  
    032. myReceive = new BroadCastReceive2();
    033. filter = new IntentFilter();
    034. filter.addAction(ACTION);
    035.  
    036. }
    037.  
    038.  
    039. @Override
    040. protected void onResume() {
    041. /**
    042. * 注册广播
    043. */
    044.  
    045. LocalBroadcastManager.getInstance(this).registerReceiver(myReceive, filter);//官方建议使用
    046.  
    047. //        this.registerReceiver(myReceive, filter);
    048.  
    049. super.onResume();
    050. }
    051.  
    052.  
    053. @Override
    054. protected void onPause() {
    055. /**
    056. * 注销广播
    057. */
    058.  
    059. LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceive);//官方建议使用
    060.  
    061. //        this.unregisterReceiver(myReceive);
    062.  
    063. super.onPause();
    064. }
    065.  
    066. @Override
    067. public void onClick(View v) {
    068. switch (v.getId()) {
    069. case R.id.button:
    070. sendBraodCast();
    071. break;
    072. }
    073. }
    074.  
    075. private void sendBraodCast() {
    076.  
    077. /**
    078. * 申明广播的 action 行为
    079. */
    080. Intent intent = new Intent(ACTION);
    081. intent.putExtra("key""动态广播测试");
    082.  
    083. /**
    084. * 官方提倡使用如下发送广播,原因是更快,更安全,不会导致内存泄漏
    085. */
    086. LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    087.  
    088. //        this.sendBroadcast(intent);
    089. }
    090.  
    091.  
    092. /**
    093. * 内部类实现广播接收器
    094. */
    095. private class BroadCastReceive2 extends BroadcastReceiver {
    096.  
    097. @Override
    098. public void onReceive(Context context, Intent intent) {
    099. //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. }

    view source print ?
    1.  
    打印结果如下: 

    动态广播特点:

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

    三.有序广播:

    示例:

    view source print ?
    001. <pre name="code" class="java">package com.xjp.mybroadcast;
    002.  
    003. import android.content.BroadcastReceiver;
    004. import android.content.Context;
    005. import android.content.Intent;
    006. import android.content.IntentFilter;
    007. import android.os.Bundle;
    008. import android.support.v7.app.ActionBarActivity;
    009. import android.view.View;
    010. import android.widget.Button;
    011.  
    012.  
    013. public class MainActivity extends ActionBarActivity implements View.OnClickListener {
    014.  
    015. private Button btnSend;
    016.  
    017. private BroadCastReceive2 myReceive;
    018.  
    019. private BroadCastReceive3 myReceive3;
    020.  
    021. private IntentFilter filter;
    022.  
    023. private IntentFilter filter3;
    024.  
    025. private final static String ACTION = "com.xjp.mybroadcast.BroadCastReceive2";
    026.  
    027. @Override
    028. protected void onCreate(Bundle savedInstanceState) {
    029. super.onCreate(savedInstanceState);
    030. setContentView(R.layout.activity_main);
    031.  
    032. btnSend = (Button) findViewById(R.id.button);
    033. btnSend.setOnClickListener(this);
    034.  
    035. myReceive = new BroadCastReceive2();
    036. filter = new IntentFilter();
    037. filter.addAction(ACTION);
    038. filter.setPriority(2);//设置广播的优先级, -1000~1000 ,数字越大,优先级越高。
    039.  
    040. myReceive3 = new BroadCastReceive3();
    041. filter3 = new IntentFilter();
    042. filter3.addAction(ACTION);
    043. filter3.setPriority(1);
    044.  
    045.  
    046. }
    047.  
    048.  
    049. @Override
    050. protected void onResume() {
    051. /**
    052. * 注册广播
    053. */
    054. registerReceiver(myReceive, filter);
    055. registerReceiver(myReceive3, filter3);
    056.  
    057.  
    058. super.onResume();
    059. }
    060.  
    061.  
    062. @Override
    063. protected void onPause() {
    064. /**
    065. * 注销广播
    066. */
    067.  
    068. unregisterReceiver(myReceive);
    069. unregisterReceiver(myReceive3);
    070.  
    071. super.onPause();
    072. }
    073.  
    074. @Override
    075. public void onClick(View v) {
    076. switch (v.getId()) {
    077. case R.id.button:
    078. sendBraodCast();
    079. break;
    080. }
    081. }
    082.  
    083. private void sendBraodCast() {
    084.  
    085. /**
    086. * 申明广播的 action 行为
    087. */
    088. Intent intent = new Intent(ACTION);
    089. intent.putExtra("key""有序广播测试");
    090.  
    091. this.sendOrderedBroadcast(intent, null);
    092. }
    093.  
    094.  
    095. /**
    096. * 内部类实现广播接收器
    097. */
    098. private class BroadCastReceive2 extends BroadcastReceiver {
    099.  
    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. }

    view source print ?
    1.  

    有序广播特点:

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

    四.粘性广播:

    示例 需要在 AndroidManifest.xml中添加 权限
    view source print ?
    1. <uses-permission android:name="android.permission.BROADCAST_STICKY"></uses-permission>

    发送广播的Activity
    view source print ?
    01. package com.xjp.mybroadcast;
    02.  
    03. import android.content.Intent;
    04. import android.os.Bundle;
    05. import android.support.v7.app.ActionBarActivity;
    06. import android.view.View;
    07. import android.widget.Button;
    08.  
    09.  
    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
    view source print ?
    01. package com.xjp.mybroadcast;
    02.  
    03. import android.app.Activity;
    04. import android.content.BroadcastReceiver;
    05. import android.content.Context;
    06. import android.content.Intent;
    07. import android.content.IntentFilter;
    08. import android.os.Bundle;
    09.  
    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中添加权限
    view source print ?
    1. <uses-permission android:name="android.permission.BROADCAST_STICKY"></uses-permission>
    2.粘性广播发送除了调用方法不同sendStickyBroadcast(intent1),其他都一样。
    3.一般广播都是先注册广播,才能接收到广播,而粘性广播可以做到先发送广播,哪里需要接收该广播就哪里注册,可以后注册广播拿到广播的结果。这就是 普通广播和粘性广播的区别。从示例中也看出了普通广播在跳转到ReceiveActivity中是接受不到广播发送者发出的广播的,只有粘性广播才能接收到。 
    有人会奇怪,平时也没看到哪里使用粘性广播??其实我也是看到Android 系统中 监测电池电量部分发现的。贴上代码如下: 
    view source print ?
    01. // Register for the battery changed event
    02. IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    03.  
    04. / Intent is sticky so using null as receiver works fine
    05. // return value contains the status
    06. Intent batteryStatus = this.registerReceiver(null, filter);
    07.  
    08. // Are we charging / charged?
    09. 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系统中有很多系统广播,比如:
Event Description
Intent.ACTION_BOOT_COMPLETED Boot completed. Requires the android.permission.RECEIVE_BOOT_COMPLETEDpermission.
Intent.ACTION_POWER_CONNECTED Power got connected to the device.
Intent.ACTION_POWER_DISCONNECTED Power got disconnected to the device.
Intent.ACTION_BATTERY_LOW Triggered on low battery. Typically used to reduce activities in your app which consume power.
Intent.ACTION_BATTERY_OKAY Battery status good again.
系统广播具体怎么用?网络上一搜一大把,这里就不讲了。和我们写的广播使用都差不多。 

延伸阅读:

  • 1、Intent方式调用系统蓝牙组件传输文件
  • 2、android四大组件之Intent(意图)
  • 3、android第三方组件实现总结
  • 4、Android四大组件之Activity
  • 5、Android中更新View组件
  • 6、Android组件间通信机制对面向对象特性的影响
  • 7、seekbar组件实现android三档自定义滑动开关,禁止点击功能的实现
  • 8、Android常用组件之RadoiButton

你可能感兴趣的:(Android四大组件之BroadCastReceive使用总结)