根底总结篇之五:BroadcastReceiver运用详解-Android-优质IT资源分享社区

admin
管理员
管理员
  • UID1
  • 粉丝26
  • 关注4
  • 发帖数581
  • 社区居民
  • 忠实会员
  • 原创写手
阅读:170回复:0

  根底总结篇之五:BroadcastReceiver运用详解

楼主#
更多 发布于:2016-05-31 16:31

听说程序员是最爱学习的集体,IT男都知道,这个职业一日千里,有必要不断地学习新常识,不断地为自个写入新鲜的血液,才能使自个跟上技能的步伐。

今日咱们来讲一下Android中BroadcastReceiver的有关常识。

BroadcastReceiver也即是“播送接纳者”的意思,顾名思义,它即是用来接纳来自体系和运用中的播送。

在Android体系中,播送体如今方方面面,例如当开机完结后体系会发生一条播送,接纳到这条播送就能完结开机发动效劳的功用;当网络状况改动时体系会发生一条播送,接纳到这条播送就能及时地做出提示和保存数据等操作;当电池电量改动时,体系会发生一条播送,接纳到这条播送就能在电量低时奉告用户及时保存进展,等等。

Android中的播送机制规划的十分出色,许多作业本来需求开发者亲身操作的,如今只需等候播送奉告自个就能够了,大大减少了开发的作业量和开发周期。而作为运用开发者,就需求数练把握Android体系供给的一个开发利器,那即是BroadcastReceiver。下面咱们就对BroadcastReceiver逐个地分析和演练,了解和把握它的各种功用和用法。

首要,咱们来演示一下创立一个BroadcastReceiver,并让这个BroadcastReceiver能够依据咱们的需求来运转。

要创立自个的BroadcastReceiver目标,咱们需求承继android.content.BroadcastReceiver,并完结其onReceive办法。下面咱们就创立一个名为MyReceiver播送接纳者:

package com.scott.receiver;import

android.content.BroadcastReceiver;import android.content.Context;import

android.content.Intent;import android.util.Log;public class MyReceiver extends

BroadcastReceiver {     private static final String TAG = "MyReceiver";    

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

 String msg = intent.getStringExtra("msg");          Log.i(TAG, msg);     }}

在onReceive办法内,咱们能够获取随播送而来的Intent中的数据,这十分重要,就像无线电一样,包括许多有用的信息。

在创立完咱们的BroadcastReceiver以后,还不能够使它进入作业状况,咱们需求为它注册一个指定的播送地址。没有注册播送地址的BroadcastReceiver就像一个缺少选台按钮的收音机,尽管功用俱备,但也无法收到电台的信号。下面咱们就来介绍一下怎么为BroadcastReceiver注册播送地址。

静态注册

静态注册是在AndroidManifest.xml文件中装备的,咱们就来为MyReceiver注册一个播送地址:

装备了以上信息以后,只要是android.intent.action.MY_BROADCAST这个地址的播送,MyReceiver都能够接纳的到。留意,这种办法的注册是常驻型的,也即是说当运用封闭后,假如有播送信息传来,MyReceiver也会被体系调用而主动运转。

动态注册

动态注册需求在代码中动态的指定播送地址并注册,一般咱们是在Activity或Service注册一个播送,下面咱们就来看一下注册的代码:

MyReceiver receiver = new

MyReceiver();IntentFilter filter = new

IntentFilter();filter.addAction("android.intent.action.MY_BROADCAST");registerReceiver(receiver,

filter);

留意,registerReceiver是android.content.ContextWrapper类中的办法,Activity和Service都承继了ContextWrapper,所以能够直接调用。在实际运用中,咱们在Activity或Service中注册了一个BroadcastReceiver,当这个Activity或Service被毁掉时假如没有免除注册,体系会报一个异常,提示咱们是不是忘掉免除注册了。所以,记得在特定的当地履行免除注册操作:

@Overrideprotected void onDestroy() {    

super.onDestroy();     unregisterReceiver(receiver);}

履行这么行代码就能够解决问题了。留意,这种注册办法与静态注册相反,不是常驻型的,也即是说播送会跟从程序的生命周期。

咱们能够依据以上恣意一种办法完结注册,当注册完结以后,这个接纳者就能够正常作业了。咱们能够用以下办法向其发送一条播送:

public void send(View view) {     Intent intent =

new Intent("android.intent.action.MY_BROADCAST");     intent.putExtra("msg",

"hello receiver.");     sendBroadcast(intent);}

留意,sendBroadcast也是android.content.ContextWrapper类中的办法,它能够将一个指定地址和参数信息的Intent目标以播送的方法发送出去。

点击发送按钮,履行send办法,操控台打印如下:

看到这么的打印信息,标明咱们的播送现已宣布去了,而且被MyReceiver准确无误的接纳到了。

上面的例子仅仅一个接纳者来接纳播送,假如有多个接纳者都注册了一样的播送地址,又会是啥状况呢,能一起接纳到同一条播送吗,相互之间会不会有搅扰呢?这就涉及到一般播送和有序播送的概念了。

一般播送(Normal Broadcast)

一般播送关于多个接纳者来说是完全异步的,一般每个接纳者都无需等候即能够接纳到播送,接纳者相互之间不会有影响。关于这种播送,接纳者无法停止播送,即无法阻挠别的接纳者的接纳动作。

为了验证以上结论,咱们新建三个BroadcastReceiver,演示一下这个进程,FirstReceiver、SecondReceiver和ThirdReceiver的代码如下:

package com.scott.receiver;import

android.content.BroadcastReceiver;import android.content.Context;import

android.content.Intent;import android.util.Log;public class FirstReceiver

extends BroadcastReceiver {     private static final String TAG =

"NormalBroadcast";     @Override     public void onReceive(Context context,

Intent intent) {          String msg = intent.getStringExtra("msg");        

 Log.i(TAG, "FirstReceiver: " + msg);     }}public class SecondReceiver extends

BroadcastReceiver {     private static final String TAG = "NormalBroadcast";    

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

 String msg = intent.getStringExtra("msg");          Log.i(TAG, "SecondReceiver:

" + msg);     }}public class ThirdReceiver extends BroadcastReceiver {    

private static final String TAG = "NormalBroadcast";     @Override     public

void onReceive(Context context, Intent intent) {          String msg =

intent.getStringExtra("msg");          Log.i(TAG, "ThirdReceiver: " + msg);    

}}

然后再次点击发送按钮,发送一条播送,操控台打印如下:

看来这三个接纳者都接纳到这条播送了,咱们略微修正一下三个接纳者,在onReceive办法的最终一行增加以下代码,试图停止播送:

abortBroadcast();

再次点击发送按钮,咱们会发现,操控台中三个接纳者依然都打印了自个的日志,标明接纳者并不能停止播送。

有序播送(Ordered Broadcast)

有序播送对比特殊,它每次只发送到优先级较高的接纳者那里,然后由优先级高的接受者再传播到优先级低的接纳者那里,优先级高的接纳者有能力停止这个播送。

为了演示有序播送的流程,咱们修正一下上面三个接纳者的代码,如下:

package com.scott.receiver;import

android.content.BroadcastReceiver;import android.content.Context;import

android.content.Intent;import android.os.Bundle;import android.util.Log;public

class FirstReceiver extends BroadcastReceiver {     private static final String

TAG = "OrderedBroadcast";     @Override     public void onReceive(Context

context, Intent intent) {          String msg = intent.getStringExtra("msg");  

       Log.i(TAG, "FirstReceiver: " + msg);          Bundle bundle = new

Bundle();          bundle.putString("msg", msg + "@FirstReceiver");        

 setResultExtras(bundle);     }}public class SecondReceiver extends

BroadcastReceiver {      private static final String TAG = "OrderedBroadcast";  

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

    String msg = getResultExtras(true).getString("msg");           Log.i(TAG,

"SecondReceiver: " + msg);           Bundle bundle = new Bundle();          

bundle.putString("msg", msg + "@SecondReceiver");          

setResultExtras(bundle);      }}public class ThirdReceiver extends

BroadcastReceiver {     private static final String TAG = "OrderedBroadcast";  

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

 String msg = getResultExtras(true).getString("msg");          Log.i(TAG,

"ThirdReceiver: " + msg);     }}

咱们留意到,在FirstReceiver和SecondReceiver中最终都运用了setResultExtras办法将一个Bundle目标设置为成果集目标,传递到下一个接纳者那里,这么以来,优先级低的接纳者能够用getResultExtras获取到最新的经过处理的信息调集。

代码改完以后,咱们需求为三个接纳者注册播送地址,咱们修正一下AndroidMainfest.xml文件:

咱们看到,如今这三个接纳者的多了一个android:priority特点,而且依次减小。这个特点的范围在-1000到1000,数值越大,优先级越高。

如今,咱们需求修正一下发送播送的代码,如下:

public void send(View view) {     Intent intent =

new Intent("android.intent.action.MY_BROADCAST");     intent.putExtra("msg",

"hello receiver.");     sendOrderedBroadcast(intent,

"scott.permission.MY_BROADCAST_PERMISSION");}

留意,运用sendOrderedBroadcast办法发送有序播送时,需求一个权限参数,假如为null则表明不请求接纳者声明指定的权限,假如不为null,则表明接纳者若要接纳此播送,需声明指定权限。这么做是从安全视点思考的,例如体系的短信即是有序播送的方法,一个运用可能是具有阻拦废物短信的功用,当短信到来时它能够先接遭到短信播送,必要时停止播送传递,这么的软件就有必要声明接纳短信的权限。

所以咱们在AndroidMainfest.xml中界说一个权限:

然后声明运用了此权限:

关于这有些假如有不明白的当地能够参阅我之前写过的一篇文章:Android声明和运用权限

然后咱们点击发送按钮发送一条播送,操控台打印如下:

咱们看到接纳是依照次序的,第一个和第二个都在成果会集加入了自个的符号,而且向优先级低的接纳者传递下去。

既然是次序传递,试着停止这种传递,看一看作用怎么,咱们修正FirstReceiver的代码,在onReceive的最终一行增加以下代码:

abortBroadcast();

然后再次运转程序,操控台打印如下:

这次,只要第一个接纳者履行了,其它两个都没能履行,由于播送被第一个接纳者停止了。

上面即是BroadcastReceiver的介绍,下面我将会举几个多见的例子加深一下大家对播送的了解和运用:

1.开机发动效劳

咱们常常会有这么的运用场合,比方音讯推送效劳,需求完结开机发动的功用。要完结这个功用,咱们就能够订阅体系“发动完结”这条播送,接纳到这条播送后咱们就能够发动自个的效劳了。咱们来看一下BootCompleteReceiver和MsgPushService的详细完结:

package com.scott.receiver;import

android.content.BroadcastReceiver;import android.content.Context;import

android.content.Intent;import android.util.Log;public class BootCompleteReceiver

extends BroadcastReceiver {     private static final String TAG =

"BootCompleteReceiver";     @Override     public void onReceive(Context context,

Intent intent) {          Intent service = new Intent(context,

MsgPushService.class);          context.startService(service);        

 Log.i(TAG, "Boot Complete. Starting MsgPushService...");     }}

package com.scott.receiver;import

android.app.Service;import android.content.Intent;import

android.os.IBinder;import android.util.Log;public class MsgPushService extends

Service {     private static final String TAG = "MsgPushService";     @Override

    public void onCreate() {          super.onCreate();          Log.i(TAG,

"onCreate called.");     }     @Override     public int onStartCommand(Intent

intent, int flags, int startId) {          Log.i(TAG, "onStartCommand called.");

         return super.onStartCommand(intent, flags, startId);     }    

@Override     public IBinder onBind(Intent arg0) {           return null;    

}}

然后咱们需求在AndroidManifest.xml中装备有关信息:

咱们看到BootCompleteReceiver注册了“android.intent.action.BOOT_COMPLETED”这个开机播送地址,从安全视点思考,体系请求有必要声明接纳开机发动播送的权限,所以咱们再声明运用下面的权限:

经过上面的几个过程以后,咱们就完结了开机发动的功用,将运用运转在模拟器上,然后重启模拟器,操控台打印如下:

假如咱们检查已运转的效劳就会发现,MsgPushService现已运转起来了。

2.网络状况改动

在某些场合,比方用户阅览网络信息时,网络俄然断开,咱们要及时地提醒用户网络已断开。要完结这个功用,咱们能够接纳网络状况改动这么一条播送,当由连接状况变为断开状况时,体系就会发送一条播送,咱们接纳到以后,再经过网络的状况做出相应的操作。下面就来完结一下这个功用:

package com.scott.receiver;import

android.content.BroadcastReceiver;import android.content.Context;import

android.content.Intent;import android.net.ConnectivityManager;import

android.net.NetworkInfo;import android.util.Log;import

android.widget.Toast;public class NetworkStateReceiver extends BroadcastReceiver

{      private static final String TAG = "NetworkStateReceiver";      @Override

     public void onReceive(Context context, Intent intent) {          

Log.i(TAG, "network state changed.");           if

(!isNetworkAvailable(context)) {                  Toast.makeText(context,

"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.getState() == NetworkInfo.State.CONNECTED) {          

                       return true;                          }                  

}            }            return false;     }}

再注册一下这个接纳者的信息:

由于在isNetworkAvailable办法中咱们运用到了网络状况有关的API,所以需求声明有关的权限才行,下面即是对应的权限声明:

咱们能够测试一下,比方封闭WiFi,看看有啥作用。

3.电量改动

假如咱们阅览软件,可能是全屏阅览,这个时分用户就看不到剩下的电量,咱们就能够为他们供给电量的信息。要想做到这一点,咱们需求接纳一条电量改动的播送,然后获取百分比信息,这听上去挺简略的,咱们就来完结以下:

package com.scott.receiver;import

android.content.BroadcastReceiver;import android.content.Context;import

android.content.Intent;import android.os.BatteryManager;import

android.util.Log;public class BatteryChangedReceiver extends BroadcastReceiver {

     private static final String TAG = "BatteryChangedReceiver";      @Override

     public void onReceive(Context context, Intent intent) {            int

currLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);  //当时电量          

 int total = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);      //总电量      

     int percent = currLevel * 100 / total;            Log.i(TAG, "battery: " +

percent + "%");      }}

然后再注册一下播送接地址信息就能够了:

当然,有些时分咱们是要当即获取电量的,而不是等电量改动的播送,比方当阅览软件翻开时当即显示出电池电量。咱们能够按以下办法获取:

Intent batteryIntent =

getApplicationContext().registerReceiver(null,  new

IntentFilter(Intent.ACTION_BATTERY_CHANGED));int currLevel =

batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);int total =

batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);int percent = currLevel

* 100 / total;Log.i("battery", "battery: " + percent + "%");

优质IT资源分享社区为你提供此文。

站有大量优质android教程视频,资料等资源,包含android基础教程,高级进阶教程等等,教程视频资源涵盖传智播客,极客学院,达内,北大青鸟,猎豹网校等等IT职业培训机构的培训教学视频,价值巨大。欢迎点击下方链接查看。

android教程视频

优质IT资源分享社区(www.itziyuan.top)
一个免费,自由,开放,共享,平等,互助的优质IT资源分享网站。
专注免费分享各大IT培训机构最新培训教学视频,为你的IT学习助力!

!!!回帖受限制请看点击这里!!!
!!!资源失效请在此版块发帖说明!!!

[PS:按 CTRL+D收藏本站网址~]

——“优质IT资源分享社区”管理员专用签名~

本版相似帖子

游客