广播接收者

1.BroadcastReceiver简介

BroadcastReceiver 是用于接收广播的组件用于组件与组件之间进行通信,可以跨应用程序传递 . 如操作系统电池电量低会发送一个广播,这样我们的程序里面可以去监听这个广播,可以关闭程序里面比较耗电的功能 , 提示用户注意保存进度什么的 , 还如其它安装新应用等 , 还有普通应用程序 , 例如启动特定线程 , 文件下载完毕等 .

Android中的广播机制设计的非常出色,很多事情原本需要开发者亲自操作的,现在只需等待广播告知自己就可以了,大大减少了开发的工作量和开发周期。而作为应用开发者,就需要熟练掌握Android系统提供的一个开发利器,那就是BroadcastReceiver

注意点

1,发送频率低的可以使用

2,数据量小在可使用

面试题  Android引入广播的用意

a:从MVC的角度考虑(应用程序内)其实回答这个问题的时候还可以这样问,android为什么要有那4大组件,现在的移动开发模型基本上也是照搬的web那一套MVC架构,只不过是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的MVC架构,它们之间有时候是一种相互依存的关系,有时候又是一种补充关系,引入广播机制可以方便几大组件的信息和数据交互。

b:程序间互通消息(例如在自己的应用程序内监_听系统来电)

c:效率上(参考UDP的广播协议在局域网的方便性)

d:设计模式上(反转控制的一种应用,类似监_听者模式)

2.广播接收者的创建

要创建自己的 BroadcastReceiver 对象,我们需要继承 android.content.BroadcastReceiver ,并实现其 onReceive 方法。
 public class MyReceiver2 extends BroadcastReceiver {
   @Override
   public void onReceive(Context context, Intent intent) {
       // TODO Auto-generated method stub
       Toast.makeText(context, "接收到广播就下课", Toast.LENGTH_SHORT).show();
   }
 }

onReceive 方法内,我们可以获取随广播而来的 Intent 中的数据,这非常重要,就像无线电一样,包含很多有用的信息。
在创建完我们的BroadcastReceiver之后,还不能够使它进入工作状态,我们需要为它注册一个指定的广播地址。没有注册广播地址的BroadcastReceiver就像一个缺少选台按钮的收音机,虽然功能俱备,但也无法收到电台的信号

注册

静态注册

特点当程序退出后,广播依然存在,直至应用被卸载

静态注册是在AndroidManifest.xml文件中配置的 自己写
 <receiver android:name="com.example.bcreceiver.MyBroadcastReceiver">
             <intent-filter>
                 <action android:name="android.intent.action.MY_BROADCAST" />    //这里的name可以随便写
                 <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
 </receiver
也可以通过AS创建BroadcastReceive,AS会自动帮你静态注册
<receiver
    android:name=".JudgeNetIsConnectedReceiver"
    android:enabled="true"
    android:exported="true"></receiver>
// android:exported="true"   是否只接收本应用的广播

动态注册

特点:该广播只在应用中有效,退出后不再接收广播

         动态注册需要在代码中动态的指定广播地址并注册

注意, registerReceiver android.content.ContextWrapper 类中的方法, Activity Service 都继承了 ContextWrapper ,所以可以直接调用。在实际应用中,我们在 Activity Service 中注册了一个 BroadcastReceiver ,当这个 Activity Service 被销毁时如果没有解除注册,系统会报一个异常,提示我们是否忘记解除注册了。所以,记得在特定的地方执行解除注册操作
MyBroadcastReceiver mbcr = new MyBroadcastReceiver();

项目中常用代码(重点)

/**
 * 自定义BaseActivity用来创建广播和销毁广播
 * @author dell
 *
 */
public abstract class BaseActivity extends FragmentActivity {

      /**
       * 声明判断网络是否连接成功的接受者对象
       */
      private JudgeNetIsConnectedReceiver judgeNetIsConnectedReceiver;

      @Override
      protected void onCreate(Bundle bundle) {
            // TODO Auto-generated method stub
            super.onCreate(bundle);
            this.judgeNetIsConnectedReceiver=new JudgeNetIsConnectedReceiver();

      }

      @Override
      protected void onResume() {
            // TODO Auto-generated method stub
            super.onResume();

            IntentFilter intentFilter=new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
            this.registerReceiver(judgeNetIsConnectedReceiver, intentFilter);
      }

      @Override
      protected void onPause() {
            // TODO Auto-generated method stub
            super.onPause();
            if(this.judgeNetIsConnectedReceiver!=null){
                  this.unregisterReceiver(judgeNetIsConnectedReceiver);
            }
      }
}

连接管理器对象

ConnectivityManager 主要管理网络连接的相关的类
它主要负责的是
1 监视网络连接状态 包括(Wi-Fi, GPRS, UMTS, etc)
2 当网络状态改变时发送广播通知
3 当网络连接失败尝试连接其他网络
4提供API,允许应用程序获取可用的网络状态

获取方法是 Context.getSystemService(Context.CONNECTIVITY_SERVICE)

常用方法 
NetworkInfo  getActiveNetworkInfo()  
  返回当前网络的详细信息
boolean  getBackgroundDataSetting()  
  API上说在1.4以后已经被启用了,调用后总返回的是true
NetworkInfo  getNetworkInfo(int networkType) 
  这个方法是获取networkType的状态信息,例如获取手机WIFI信息可以这样写
  ConnectivityManager mConnectivity  = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
        System.out.println(mConnectivity.getNetworkInfo(ConnectivityManager.TYPE_WIFI));
 如果手机有WIFI的话返回的结果如下
 NetworkInfo: type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: (none), roaming: false,  

failover: false, isAvailable: true

 没有WIFI:
 NetworkInfo: type: WIFI[], state: DISCONNECTED/DISCONNECTED, reason: (unspecified), extra: (none), roaming: false,  

failover: false, isAvailable: false


状态类型networkType常用的还有:
 TYPE_BLUETOOTH 蓝牙
 TYPE_MOBILE ‍默认网络连接
其他的可以去看官方API
=========================================================================================================================
String CONNECTIVITY_ACTION
  在网络连接中出现的一个变化。已被建立或断开的一个连接。
  如果当前网络是从无法连接的网络切换到可连接的网络,那么FAILOVER_CONNECTION被设置为true。NetworkInfo会受网络影响而被额外地发送,它可以查询到网络连接的相关信息。
  当网络连接失败,连接管理器试图去连接(或已连接)到另一个网络,那么NetworkInfo会因为这个新网络而被额外的通过。这种情况下,广播的接收类不需要告诉使用者们当前没有数据流量。反之,这个接收类立即等待另一个指示网络切换成功(整体数据连接)或切换失败(所有的数据连接已丢失)的广播。
  返回的常数值:”android.net.conn.CONNECTIVITY_CHANGE”
String EXTRA_EXTRA_INFO
  说明:提供网络状态的额外信息查询关键字符串。这些信息可能从脚底的网络层传出,对于特定的网络类型来说它的意义可能是特定的。通过 getStringExtra(String)来获取。
  返回的常数值:”extraInfo”
String EXTRA_IS_FAILOVER
String EXTRA_EXTRA_INFO
  说明:是一个获取布尔值的查询关键字。它指的是在网络断开时,网络连接管理器是否成功切换到另一个可用网络。通过getBooleanExtra(String, boolean)查询。
  返回的常数值:”isFailover”
String EXTRA_NETWORK_INFO
  这个常数在API14(Android 4.0)时已弃用。
  说明:由于NetworkInfo基于UID(每个软件安装在手机的时候,手机都会分配一个UID为唯一标示)的不同而不同,应用程序可以通过getActiveNetworkInfo()或getAllNetworkInfo()来获取网络信息。
  可以通过getParcelableExtra(String)获取NetworkInfo的对象的查找键。参见EXTRA_NETWORK_TYPE。
  返回的常数值:”EXTRA_NETWORK_TYPE”
String EXTRA_NETWORK_INFO
  说明:可以出发CONNECTIVITY_ACTION广播的网络类型。在调用应用程序的基础上与 getNetworkInfo(int)一起使用来获取NetworkInfo的状态。参见getIntExtra(String, int)。
  返回的常数值:”networkType”
String EXTRA_NO_CONNECTIVITY
  说明:一个布尔值的查找键,指是否存在一个完整的连接缺陷,即没有网络可以。通过getBooleanExtra(String, boolean)来查找。
  返回的常数值:”noConnectivity”
String EXTRA_OTHER_NETWORK_INFO
  说明:一个NetworkInfo的对象查找键。当存在另一个可连接的网络时被提供。通过getParcelableExtra(String)获取。
  返回的常数值:”otherNetwork”
String EXTRA_REASON
  说明:用于表示网络连接失败的字符串查找键。该字符串没有特定的结构。它的目的是用于向用户提交的通知。通过getStringExtra(String)获取。
  返回的常数值:”reason”
int DEFAULT_NETWORK_PREFERENCE
  这个常数在API18(Android 4.3)时已弃用。
  说明:由于现在支持的网络较多,默认的单一网络偏好不能真正地表达网络层次。默认值在config.xml中通过networkAttributes来定义的。在应用程序中通过调用getNetworkPreference()来获取当前值。
  如果你想设置默认的网络偏好,那么可以直接搞遍框架中config.xml中的networkAttributes。
  返回的常数值:1 (0x00000001)
int TYPE_BLUETOOTH
  说明:蓝牙数据连接。当被使用时,所有的数据流将默认使用这个网络类型的接口。
  返回的常数值:7 (0x00000007)
int TYPE_DUMMY
  说明:虚拟数据连接。这个不应该是使用在运输设备上。
  返回的常数值:8 (0x00000008)
int TYPE_ETHERNET
  说明:以太网(局域网的一种)数据连接。当被使用时,所有数据流将默认使用这个网络类型的接口(它有一个默认的路径)。
  返回的常数值:9 (0x00000009)
int TYPE_MOBILE
  说明:移动数据连接。当被使用时,所有数据流将默认使用这个网络类型的接口(它有一个默认的路径)。
  返回的常数值:0 (0x00000000)
int TYPE_MOBILE_DUN
  说明:特殊拨号联网的移动数据连接。这个网络类型可以使用与TYPE_MOBILE相同的网络接口,也可以使用不同的。
  返回的常数值:4 (0x00000004)
int TYPE_MOBILE_HIPRI
  说明:高优先级的移动数据连接。这种网络类型使用的网络接口与TYPE_MOBILE相同但路由设置不同。只有在请求的过程中才会获取移动的DNS服务器(Domain Name Server,域名服务器),如果没有没有默认路径存在,那么只能通过IP的明确要求通过requestRouteToHost(int, int)方法来导入这个接口。
  返回的常数值:5 (0x00000005)
int TYPE_MOBILE_MMS
  说明:多媒体移动数据连接。这个网络类型可以使用与TYPE_MOBILE相同的网络接口,也可以使用不同的。这个在应用系统需要与运营商的多媒体消息服务的服务器进行通话时使用。
  返回的常数值:2 (0x00000002)
int TYPE_MOBILE_SUPL
  说明:SUPL移动数据连接。(SUPL,secure user plane location, 用于移动电话和定位服务器之间进行通信的协议标准,作为OMA的标准。)这个网络类型可以使用与TYPE_MOBILE相同的网络接口,也可以使用不同的。这个在应用程序需要通过与运营商的SUPL服务通话来请求定位时使用。
  返回的常数值:3 (0x00000003)
int TYPE_WIFI
  说明:无线数据连接。当被使用时,所有数据流将默认使用这个网络类型的接口(它有一个默认的路径)。
  返回的常数值:1 (0x00000001)
int TYPE_WIMAX
  WIMAX(Worldwide Interoperability for Microwave Access,即全球微波互联接入)数据连接。当被使用时,所有数据流将默认使用这个网络类型的接口(它有一个默认的路径)。
  返回的常数值:6 (0x00000006)

  • 公共方法
NetworkInfo getActiveNetworkInfo()
  说明:返回当前活动的默认数据网络的详细信息。当连接时,对于其它网络,这个网络是默认的路径。你只要在使用网络流量前通过isConnected()来查询是否连接。当它返回的是null,那么当前没有默认的网络。
  返回一个当前默认网络的NetworkInfo对象或者在网络时返回null。
  该方法需要持有ACCESS_NETWORK_STATE的许可。
NetworkInfo[] getAllNetworkInfo()
  说明:返回设备支持的所有网络类型的连接状态信息。
  返回一个NetworkInfo数组。通过getType()来获取每一个应用的类型。
  该方法需要持有ACCESS_NETWORK_STATE的许可。
boolean getBackgroundDataSetting ()
  说明:该方法在API14(Android 4.0)时已弃用。
NetworkInfo getNetworkInfo (int networkType)
  说明:返回一个请求网络类型的NetworkInfo连接状态的对象,如果当前设备不支持这个networkType参数指定的网络类型那么返回null。
  该方法需要持有ACCESS_NETWORK_STATE的许可。
int getNetworkPreference ()
  说明:获取当前首选的网络类型。要注意的是,该方法只有在两个网络类型的情况下有意义,随着默认的网络类型越来越多,我们需要一个数组来列出它们的顺序。这个方法将很快被淘汰。
  该方法需要持有ACCESS_NETWORK_STATE的许可。
boolean isActiveNetworkMetered ()
  说明:当用户在该连接上使用大量数据,由于成本、数据的局限性和电池/性能的问题,这个网络被归类于计量。在做大量数据传输之前,您应该要检查并警告用户或延迟的另一个网络可用时再操作。
  如果要避免大量的传输,那么返回true,否则返回false。
  该方法需要持有ACCESS_NETWORK_STATE的许可。
static boolean isNetworkTypeValid (int networkType)
  说明:测试一个指定的网络类型是否是有效。
boolean requestRouteToHost (int networkType, int hostAddress)
  说明:添加指定的网络接口向指定的主机提供流量的网络路由。添加已存在的路由会被忽略,但视为成功。
  该方法需要持有CHANGE_NETWORK_STATE的许可。
void setNetworkPreference (int preference)
  说明:设置首选的网络类型。当设备有一个以上的网络可用,那么首选的网络类型将被使用。要注意的是,该方法只有在两个网络类型的情况下有意义,随着默认的网络类型越来越多,我们需要一个数组来列出它们的顺序。这个方法将很快被淘汰。
int startUsingNetworkFeature (int networkType, String feature)
  说明:告诉顶层网络系统,调用方希望开始使用指定的功能。功能的特征完全取决于每一个网络的实现。
  返回一个表示请求结果的整数值。此值的解释是特定于每一个网络实现+功能的组合,除了-1表示的是失败。
  该方法需要持有CHANGE_NETWORK_STATE的许可。
int stopUsingNetworkFeature (int networkType, String feature)
  说明:告诉顶层网络系统,调用方使用指定的功能完成。功能的特征完全取决于每一个网络的实现。
  返回一个表示请求结果的整数值。此值的解释是特定于每一个网络实现+功能的组合,除了-1表示的是失败。
  该方法需要持有CHANGE_NETWORK_STATE的许可。

利用广播接收者判断网络连接

public class JudgeNetIsConnectedReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        //得到网络是否连接成功
        /**
        * 下面的判断是要支持网络请求的时候才会发送广播,是有延时的
        * 而上面的是网络一断开系统就立即发送广播,是即时的
        * 将这2个判断连中一起就是完美的判断
        * ConnectivityManager.EXTRA_NO_CONNECTIVITY:
        * 一个布尔值的查找键,指是否存在一个完整的连接缺陷,即没有网络可以。
        * 通过getBooleanExtra(String, boolean)来查找。
        */
        boolean isNotConnected = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,false);

        if (!isNotConnected || judgeNetIsConnected(context)){
            Toast.makeText(context, "网络连接成功!", Toast.LENGTH_SHORT).show();
        }else {
            Toast.makeText(context, "您的网络不给力,请检查网络!", Toast.LENGTH_LONG).show();
        }
    }

    /**
    * 判断网络连接是否成功
    * @param context  上下文对象
    * @return  网络连接是否成功
    */
    public static boolean judgeNetIsConnected(Context context) {
        //得到连接管理器对象
        ConnectivityManager  connectivityManager= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        //返回当前网络的详细信息
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if(info==null){
            return false;
        }
        return info.isConnected();
    }
}


在activity中动态注册和注销

public class BaseActivity extends FragmentActivity{

    //声明一个(判断网是否连接的)广播接收者
    private JudgeNetIsConnectedReceiver judgeNetIsConnectedReceiver;

    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);

        //实例化广播接收者
        JudgeNetIsConnectedReceiver judgeNetIsConnectedReceiver = new JudgeNetIsConnectedReceiver();
    }

    @Override
    protected void onResume() {
        super.onResume();

        //动态注册广播接收者
        IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        this.registerReceiver(judgeNetIsConnectedReceiver,intentFilter);
    }

//ConnectivityManager.CONNECTIVITY_ACTION)  :在网络连接中出现的一个变化。已被建立或断开的一个连接。

    @Override
    protected void onPause() {
        super.onPause();
        //取消广播的发送
        this.unregisterReceiver(judgeNetIsConnectedReceiver);
    }
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值