分享

Android中BroadcastReceiver广播使用及注意点

 WindySky 2016-05-05

Android中的广播用途很广,是四大组件之一。在android中可以看到它的各种应用,从系统发出的广播,用户自定义的广播等。

这里详细记录下广播的分类以及使用方法。

广播,是由两方面组成一个流程:广播发送者、广播接收者。

有以下场景:

当网络状态发生变化时,系统(广播发送者)会发出一条广播,这条广播的标识是:android.net.conn.CONNECTIVITY_CHANGE。当开发人员(广播接收者)也添加了这个标识,那开发人员就可以在代码中接收到这条广播。广播接收者可以是多个。


一、广播的分类,按有无顺序区分,可以分为:标准广播、有序广播。

(1)标准广播。就是多个广播接收者,接收到广播是无序的,没有规定谁先谁后。按理想状况来说,是同一时间接收到系统发出的广播。

(2)有序广播。在广播接收者,注册添加这条广播时,有增加了优先熟悉的设置。优先级高的先接收,优先级高的广播接收者,还可以控制是否将广播往下继续传递;

二、广播的注册。

根据注册方式不同有静态注册、动态注册。下面以接收系统广播为例:

(1)静态注册:

有两种方式实现:AndroidManifest.xml中注册+内部类;AndroidManifest.xml中注册+外部类。

这两种的实现都是在AndroidManifest.xml中注册,在代码中写BroadCastReceive的重载即可。

以下是,AndroidManifest.xml中注册+内部类:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas./apk/res/android"  
  3.     package="com.example.broadcasttest_csdn"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="8"  
  9.         android:targetSdkVersion="18" />  
  10.   <span style="color:#cc0000;"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/></span>  
  11.     <application  
  12.         android:allowBackup="true"  
  13.         android:icon="@drawable/ic_launcher"  
  14.         android:label="@string/app_name"  
  15.         android:theme="@style/AppTheme" >  
  16.         <activity  
  17.             android:name="com.example.broadcasttest_csdn.MainActivity"  
  18.             android:label="@string/app_name" >  
  19.             <intent-filter>  
  20.                 <action android:name="android.intent.action.MAIN" />  
  21.   
  22.                 <category android:name="android.intent.category.LAUNCHER" />  
  23.             </intent-filter>  
  24.         </activity>  
  25.         <receiver android:name="com.example.broadcasttest_csdn.MainActivity$myBroadCast">  
  26.             <intent-filter >  
  27.                 <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>  
  28.             </intent-filter>  
  29.         </receiver>  
  30.     </application>  
  31.   
  32. </manifest>  

  1. package com.example.broadcasttest_csdn;  
  2.   
  3. import android.net.ConnectivityManager;  
  4. import android.net.NetworkInfo;  
  5. import android.os.Bundle;  
  6. import android.R.anim;  
  7. import android.app.Activity;  
  8. import android.content.BroadcastReceiver;  
  9. import android.content.Context;  
  10. import android.content.Intent;  
  11. import android.content.IntentFilter;  
  12. import android.view.Menu;  
  13. import android.widget.Toast;  
  14.   
  15. public class MainActivity extends Activity {  
  16.   
  17.       
  18.     BroadcastReceiver bReceiver;  
  19.     IntentFilter iFilter;  
  20.     @Override  
  21.     protected void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.         setContentView(R.layout.activity_main);  
  24.         /*  
  25.         iFilter=new IntentFilter();  
  26.         iFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);  
  27.         bReceiver=new myBroadCast();  
  28.         registerReceiver(bReceiver, iFilter);  
  29.         */  
  30.     }  
  31.     @Override  
  32.     protected void onDestroy() {  
  33.         // TODO Auto-generated method stub  
  34.         super.onDestroy();  
  35.         //unregisterReceiver(bReceiver);  
  36.     }  
  37.   
  38.      public static  class myBroadCast extends BroadcastReceiver  
  39.      {  
  40.         @Override  
  41.         public void onReceive(Context arg0, Intent arg1) {  
  42.             // TODO Auto-generated method stub  
  43.             ConnectivityManager connectivityManager=(ConnectivityManager)arg0.getSystemService(arg0.CONNECTIVITY_SERVICE);  
  44.             NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();  
  45.             if(networkInfo!=null&&networkInfo.isAvailable())  
  46.             {  
  47.                 Toast.makeText(arg0, "网络已连接", Toast.LENGTH_SHORT).show();  
  48.             }  
  49.             else {  
  50.                 Toast.makeText(arg0, "网络未连接", Toast.LENGTH_SHORT).show();  
  51.             }  
  52.         }  
  53.      }  
  54.       
  55. }  

有几个要注意的地方:

AndroidManifest.xml区域:

权限需要添加,因为我们测试的是网络变化(这个系统变化最容易模拟);

receiver中的name不是activity的name,是BroadcastReceiver继承类的name。如果是内部类,则要像上方写法一样,用$来得到方法name;

intent-filter中是要过滤下来的广播,就是你想要接收的广播标识。

代码红字标识区域:

广播接收的内部类,需要定义为static。否则会报错。


那如果我不想把广播接收类写为内部类,我要写在外面,方便android工程的其他页面调用,可行吗?

这个也是可以的,我们定义一个独立于activity的类,类名我们写为:BroadReceive。

类的内容,如下:

  1. package com.example.broadcasttest_csdn;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.net.ConnectivityManager;  
  7. import android.net.NetworkInfo;  
  8. import android.widget.Toast;  
  9.   
  10. public class BroadReceive extends BroadcastReceiver{  
  11.   
  12.     @Override  
  13.     public void onReceive(Context paramContext, Intent paramIntent) {  
  14.         // TODO Auto-generated method stub  
  15.         ConnectivityManager connectivityManager=(ConnectivityManager)paramContext.getSystemService(paramContext.CONNECTIVITY_SERVICE);  
  16.         NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();  
  17.         if(networkInfo!=null&&networkInfo.isAvailable())  
  18.         {  
  19.             Toast.makeText(paramContext, "网络已连接", Toast.LENGTH_SHORT).show();  
  20.         }  
  21.         else {  
  22.             Toast.makeText(paramContext, "网络未连接", Toast.LENGTH_SHORT).show();  
  23.         }  
  24.           
  25.       
  26.     }  
  27.   
  28. }  
AndroidManifest.xml的定义如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas./apk/res/android"  
  3.     package="com.example.broadcasttest_csdn"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="8"  
  9.         android:targetSdkVersion="18" />  
  10.    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
  11.     <application  
  12.         android:allowBackup="true"  
  13.         android:icon="@drawable/ic_launcher"  
  14.         android:label="@string/app_name"  
  15.         android:theme="@style/AppTheme" >  
  16.         <activity  
  17.             android:name="com.example.broadcasttest_csdn.MainActivity"  
  18.             android:label="@string/app_name" >  
  19.             <intent-filter>  
  20.                 <action android:name="android.intent.action.MAIN" />  
  21.   
  22.                 <category android:name="android.intent.category.LAUNCHER" />  
  23.             </intent-filter>  
  24.         </activity>  
  25.         <receiver android:name="com.example.broadcasttest_csdn.BroadReceive">  
  26.             <intent-filter >  
  27.                 <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>  
  28.             </intent-filter>  
  29.         </receiver>  
  30.     </application>  
  31.   
  32. </manifest>  
与内部类方式相比,区别在上方receive的name,用的是外部类name。
有些同学还会问,我如果在代码中,在activity类外,定义一个普通类继承BroadCastReceiver。能否在AndroidManifest.xml中静态注册。

答案是不行的,你会发现,这里需要static标识,而这个类没办法加这个static标识。


(2)动态注册。从上方的静态注册,我们看到还是有挺多要注意的,有的地方也不是很方便灵活。那我们可以考虑用动态注册。

动态注册,除了权限外,我们不需要在AndroidManifest.xml中操作其他内容,其他的都在代码中实现;

如下:

  1. package com.example.broadcasttest_csdn;  
  2.   
  3. import android.net.ConnectivityManager;  
  4. import android.net.NetworkInfo;  
  5. import android.os.Bundle;  
  6. import android.R.anim;  
  7. import android.app.Activity;  
  8. import android.content.BroadcastReceiver;  
  9. import android.content.Context;  
  10. import android.content.Intent;  
  11. import android.content.IntentFilter;  
  12. import android.view.Menu;  
  13. import android.widget.Toast;  
  14.   
  15. public class MainActivity extends Activity {  
  16.   
  17.       
  18.     BroadcastReceiver bReceiver;  
  19.     IntentFilter iFilter;  
  20.     @Override  
  21.     protected void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.         setContentView(R.layout.activity_main);  
  24.           
  25.         iFilter=new IntentFilter();  
  26.         iFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);  
  27.         bReceiver=new myBroadCast();  
  28.         registerReceiver(bReceiver, iFilter);  
  29.           
  30.     }  
  31.     @Override  
  32.     protected void onDestroy() {  
  33.         // TODO Auto-generated method stub  
  34.         super.onDestroy();  
  35.         unregisterReceiver(bReceiver);  
  36.     }  
  37.   
  38.      public static  class myBroadCast extends BroadcastReceiver  
  39.      {  
  40.         @Override  
  41.         public void onReceive(Context arg0, Intent arg1) {  
  42.             // TODO Auto-generated method stub  
  43.             ConnectivityManager connectivityManager=(ConnectivityManager)arg0.getSystemService(arg0.CONNECTIVITY_SERVICE);  
  44.             NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();  
  45.             if(networkInfo!=null&&networkInfo.isAvailable())  
  46.             {  
  47.                 Toast.makeText(arg0, "网络已连接", Toast.LENGTH_SHORT).show();  
  48.             }  
  49.             else {  
  50.                 Toast.makeText(arg0, "网络未连接", Toast.LENGTH_SHORT).show();  
  51.             }  
  52.         }  
  53.      }  
  54.       
  55. }  

AndroidManifest.xml的定义如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas./apk/res/android"  
  3.     package="com.example.broadcasttest_csdn"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="8"  
  9.         android:targetSdkVersion="18" />  
  10.    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
  11.     <application  
  12.         android:allowBackup="true"  
  13.         android:icon="@drawable/ic_launcher"  
  14.         android:label="@string/app_name"  
  15.         android:theme="@style/AppTheme" >  
  16.         <activity  
  17.             android:name="com.example.broadcasttest_csdn.MainActivity"  
  18.             android:label="@string/app_name" >  
  19.             <intent-filter>  
  20.                 <action android:name="android.intent.action.MAIN" />  
  21.   
  22.                 <category android:name="android.intent.category.LAUNCHER" />  
  23.             </intent-filter>  
  24.         </activity>  
  25.           
  26.     </application>  
  27.   
  28. </manifest>  


如代码中几个步骤,定义过滤器intent-filter、定义广播接收类、在activity开启的时候绑定二者、在activity销毁的时候解除绑定。

与静态注册相比,大家应该更习惯用动态注册。

二、广播使用实例

(1)标准广播。

上方例子中接收系统广播,都可以算是标准广播。因为没有做优先级设置。为了更好的说明,我们发送自定义广播,并接收。

  1. package com.example.broadcasttest_csdn;  
  2.   
  3. import android.net.ConnectivityManager;  
  4. import android.net.NetworkInfo;  
  5. import android.os.Bundle;  
  6. import android.R.anim;  
  7. import android.app.Activity;  
  8. import android.content.BroadcastReceiver;  
  9. import android.content.Context;  
  10. import android.content.Intent;  
  11. import android.content.IntentFilter;  
  12. import android.util.Log;  
  13. import android.view.Menu;  
  14. import android.widget.Toast;  
  15.   
  16. public class MainActivity extends Activity {  
  17.   
  18.       
  19.     BroadcastReceiver bReceiver;  
  20.     IntentFilter iFilter;  
  21.     @Override  
  22.     protected void onCreate(Bundle savedInstanceState) {  
  23.         super.onCreate(savedInstanceState);  
  24.         setContentView(R.layout.activity_main);  
  25.   
  26.         iFilter=new IntentFilter();  
  27.         iFilter.addAction("myAction");  
  28.         bReceiver=new myBroadCast();  
  29.         registerReceiver(bReceiver, iFilter);  
  30.           
  31.         Intent intent=new Intent();  
  32.         intent.setAction("myAction");  
  33.         intent.putExtra("info", "附带信息");  
  34.         sendBroadcast(intent);  
  35.           
  36.     }  
  37.     @Override  
  38.     protected void onDestroy() {  
  39.         // TODO Auto-generated method stub  
  40.         super.onDestroy();  
  41.         unregisterReceiver(bReceiver);  
  42.     }  
  43.   
  44.      public static  class myBroadCast extends BroadcastReceiver  
  45.      {  
  46.         @Override  
  47.         public void onReceive(Context arg0, Intent arg1) {  
  48.             // TODO Auto-generated method stub  
  49.             if(arg1!=null)  
  50.             {  
  51.                 Log.i("Action", arg1.getAction()) ;  
  52.                 Log.i("获取的信息", arg1.getStringExtra("info"));  
  53.             }  
  54.         }  
  55.      }  
  56.       
  57. }  

代码里没有做太多的修改。偷懒了,刚启动就先注册一个广播接收,然后直接就发送广播。

你在onReceive里,可以收到广播的信息。Intent我们知道可以附带一些内容的,我也一起传了个值过去。

(2)有序广播

  1. package com.example.broadcasttest_csdn;  
  2.   
  3. import android.net.ConnectivityManager;  
  4. import android.net.NetworkInfo;  
  5. import android.os.Bundle;  
  6. import android.R.anim;  
  7. import android.app.Activity;  
  8. import android.content.BroadcastReceiver;  
  9. import android.content.Context;  
  10. import android.content.Intent;  
  11. import android.content.IntentFilter;  
  12. import android.util.Log;  
  13. import android.view.Menu;  
  14. import android.widget.Toast;  
  15.   
  16. public class MainActivity extends Activity {  
  17.   
  18.       
  19.     BroadcastReceiver bReceiver;  
  20.     IntentFilter iFilter;  
  21.     @Override  
  22.     protected void onCreate(Bundle savedInstanceState) {  
  23.         super.onCreate(savedInstanceState);  
  24.         setContentView(R.layout.activity_main);  
  25.   
  26.         iFilter=new IntentFilter();  
  27.         iFilter.addAction("myAction");  
  1.        iFilter.setPriority(100);  
  2.         bReceiver=new myBroadCast();  
  3.         registerReceiver(bReceiver, iFilter);  
  4.           
  5.         Intent intent=new Intent();  
  6.         intent.setAction("myAction");  
  7.         intent.putExtra("info", "附带信息");  
  8.        sendOrderedBroadcast(intent, null);  
  9.           
  10.     }  
  11.     @Override  
  12.     protected void onDestroy() {  
  13.         // TODO Auto-generated method stub  
  14.         super.onDestroy();  
  15.         unregisterReceiver(bReceiver);  
  16.     }  
  17.   
  18.      public static  class myBroadCast extends BroadcastReceiver  
  19.      {  
  20.         @Override  
  21.         public void onReceive(Context arg0, Intent arg1) {  
  22.             // TODO Auto-generated method stub  
  23.             if(arg1!=null)  
  24.             {  
  25.                 Log.i("Action", arg1.getAction()) ;  
  26.                 Log.i("获取的信息", arg1.getStringExtra("info"));  
  27.                 abortBroadcast();  
  28.             }  
  29.         }  
  30.      }  
  31.       
  32. }  
和以前的代码相比,唯二的区别就在发送广播和截断广播的地方。一个是order、abort,按字面意思就是按顺序和截断。

这样的广播,到onReceive中就被截断了,不会再往下传递了。

至于广播出来后,谁第一个接收,是根据优先级来的。100->99->98....,类似这样的。

(3)本地广播

这是刚漏了,补上这个的说明。

本地广播和以上两个的区别在于:本地广播,只供本应用使用,有效的提高广播的安全性。

写法与以往的写法没有太大的区别:

  1. package com.example.broadcasttest_csdn;  
  2.   
  3. import android.os.Bundle;  
  4. import android.app.Activity;  
  5. import android.content.BroadcastReceiver;  
  6. import android.content.Context;  
  7. import android.content.Intent;  
  8. import android.content.IntentFilter;  
  9. import android.support.v4.content.LocalBroadcastManager;  
  10. import android.util.Log;  
  11.   
  12. public class MainActivity extends Activity {  
  13.   
  14.     LocalBroadcastManager localBroadcastManager;  
  15.       
  16.     BroadcastReceiver bReceiver;  
  17.     IntentFilter iFilter;  
  18.     @Override  
  19.     protected void onCreate(Bundle savedInstanceState) {  
  20.         super.onCreate(savedInstanceState);  
  21.         setContentView(R.layout.activity_main);  
  22.   
  23.         iFilter=new IntentFilter();  
  24.         iFilter.addAction("myAction");  
  25.         iFilter.setPriority(100);  
  26.         bReceiver=new myBroadCast();  
  27.         //registerReceiver(bReceiver, iFilter);  
  28.       localBroadcastManager=LocalBroadcastManager.getInstance(MainActivity.this);  
  29.         localBroadcastManager.registerReceiver(bReceiver, iFilter);  
  30.           
  31.         Intent intent=new Intent();  
  32.         intent.setAction("myAction");  
  33.         intent.putExtra("info", "附带信息");  
  34.         //sendOrderedBroadcast(intent, null);  
  35.         localBroadcastManager.sendBroadcastSync(intent);  
  36.     }  
  37.     @Override  
  38.     protected void onDestroy() {  
  39.         // TODO Auto-generated method stub  
  40.         super.onDestroy();  
  41.         //unregisterReceiver(bReceiver);  
  42.         localBroadcastManager.unregisterReceiver(bReceiver);  
  43.     }  
  44.   
  45.      public static  class myBroadCast extends BroadcastReceiver  
  46.      {  
  47.         @Override  
  48.         public void onReceive(Context arg0, Intent arg1) {  
  49.             // TODO Auto-generated method stub  
  50.             if(arg1!=null)  
  51.             {  
  52.                 Log.i("Action", arg1.getAction()) ;  
  53.                 Log.i("获取的信息", arg1.getStringExtra("info"));  
  54.                 //abortBroadcast();  
  55.             }  
  56.         }  
  57.      }  
  58.       
  59. }  
  1.   


将原来的BroadCastReceiver替换,就是修改的地方。将有些定义注释,用local的定义替换。这就得到我们要的本地广播。

以上,总结了我们会遇到的所有广播形式以及注册方式,仅供参考。

广播就到这里。O 。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多