欢迎光临散文网 会员登陆 & 注册

第六章 组件通讯与广播消息( 普通广播、有序广播、粘性广播、本地广播

2018-11-09 23:34 作者:swiss126  | 我要投稿

参考资料:

《Android应用程序开发》ISBN 9787302283164

参考软件:

Android Studio、Eclipse+ADT、Android SDK、JDK

普通广播

普通广播是完全异步执行的广播。该广播没有任何的顺序可言,因此效率比较高。也意味着它无法被截断。广播的工作流程如下: 

 

广播之间不能传递数据,不能终止广播

这是一种不需要考虑接收者接收顺序的广播,比如说有3个接收机,都关注custom.action.mybroadcast这种广播,无所谓谁先收到谁后收到。接收机不能阻止其它接收机获取到这条广播。

(1)、我们创建一个名为GostBroadcast的类继承BroadcastReceiver,实现一个自定义的广播。

 

  public class GostBroadcast extends BroadcastReceiver {  

      @Override  

      public void onReceive(Context context, Intent intent) {  

          String data = intent.getStringExtra("data");  

          Toast.makeText(context, data + "/cast", Toast.LENGTH_LONG).show();  

      }  

  }  

(2)、注册广播,我们注册一个应用程序级别的广播,在manifest文件中进行注册。注意在注册广播的时候需要指定该广播的action

  <receiver android:name="com.dsw.servicedemo.GostBroadcast"  

              android:exported="false">  

              <intent-filter>  

                  <action android:name="com.dsw.send"/>  

              </intent-filter>  

  </receiver>  

(3)、发送广播,通过Intent进行广播的启动发送。

  Intent intent = new Intent();  

  intent.setAction("com.dsw.send");  

  intent.putExtra("data""data");  

  sendBroadcast(intent);  

通过这样一个流程,我们就完成了一个广播从创建、发送、接收处理的整个过程。最后在页面弹出Toast展示我们传递的数据。

有序广播

有序广播是同步执行的,广播可以被中断。  

有序广播是用sendOrderedBroadcast来发送。高优先级的接收者会先接收到广播,然后它可以决定是否继续转发,让低优先级的接收者接收到,或者终止广播。高优先级的接收者可以通过setResult把一些信息传给下一个接收者,下一个接收者则通过getResult获取上一个接收者传过来的信息。这个优先级也是用android:priority来设置,范围是-1000到1000。

这是一种需要考虑接收者接收顺序的广播,比如说有3个接收机,都关注custom.action.mybroadcast这种广播,那么安卓系统将根据这3个接收机声明的优先级进行广播的投递。

而且有序广播是可以被阻截的。

比如,一个广播按照顺序传递给3个接收机-A B C,但是B将广播拦截了,因此C将不会收到这个广播。

1 发送

Intent i = new Intent("custom.action.mybroadcast");

sendOrderedBroadcast(i, null);

2 接收

接收的时候,需要给intent-filter标签设置android:priority属性,表示这个接收机的优先级。优先级从-1000到1000,数值越大,优先级越高。

<receiver

   android:name=".MyReceiver"

   android:enabled="true"

   android:exported="true">

   <intent-filterandroid:priority="1000">

       <actionandroid:name="custom.action.mybroadcast"/>

       <categoryandroid:name="android.intent.category.DEFAULT" />

   </intent-filter>

</receiver>

接收到广播以后,Broadcast Receiver可以将广播拦截,禁止它往下传播,

publicclassMyReceiverextendsBroadcastReceiver {

   publicMyReceiver() {

   }

   //实现onReceive接口

   @Override

   publicvoidonReceive(Context context, Intent intent) {

       //禁止往下传播

       abortBroadcast();

   }

}

如果接收机1在onReceive()中,希望把数据传递给下个接收机2,

接收机1可以使用setResultExtras()方法,

publicclassMyReceiver1extendsBroadcastReceiver {

    publicMyReceiver() {

    }

    @Override

    publicvoidonReceive(Context context, Intent intent) {

        Bundle b = new Bundle();

        b.putString("data", "this data from MyReceiver");

        setResultExtras(b);

    }

}

接收机2中,

publicclassMyReceiver2extendsBroadcastReceiver {

    publicMyReceiver2() {

    }

    @Override

    publicvoidonReceive(Context context, Intent intent) {

        Bundle b = getResultExtras(true);

        if(b!=null)

        {

            //data就是前一个接收机1传来的-this data from MyReceiver

            String data = b.getString("data");

        }

    }

}

假如希望将数据放到onReceive()传入的Intent当中,是不会传递成功的,

@Override

publicvoidonReceive(Context context, Intent intent) {

    //这是不会成功的

    intent.putExtra("data", "this data from MyReceiver");

}

传递数据,一定要通过BroadcastReceiver提供的setResultExtras()方法。

粘性广播

在Android系统粘性广播一般用来确保重要的状态改变后的信息被持久保存,并且能随时广播给新的广播接收器,比如电源的改变,因为耗电需要一个过程,前一个过程必须提前得到,否则可能遇到下次刚好接收到的广播后系统自动关机了,随之而来的是kill行为,所以对某些未处理完的任务来说,后果很严重。

发送粘性广播需要权限(这里的权限是保存信息的权限和由系统发送未处理的广播的权限)

<uses-permission android:name="android.permission.BROADCAST_STICKY" />

对于粘性广播的发送,和普通广播的发送方式是一致的。为了测试粘性广播的正确使用方式,我们需要定义一个SenderActivity来发送stick Broadcast

public class SenderActivity{@Overrideprotected void onCreate(Bundle saveInstance) {    super.onCreate(saveInstance);    setContentView(R.layout.stcik_test_layout);    getWindow().setBackgroundDrawableResource(R.drawable.avatar11);}@Overrideprotected void onResume() {    super.onResume();getWindow().getDecorView().postDelayed(new Runnable() {    @Override        public void run() {     sendStickyBroadcast();      }    }, 3*1000);}private void sendStickyBroadcast(){    Intent i = new Intent();    i.setAction(StickyBroadcastReceiver.Action);    i.putExtra("info", "sticky broadcast has been receiver");    sendStickyBroadcast(i);    Log.i("Other","sticky broadcast send ok!");}}

需要知道的是粘性广播是普通广播的一种,因此也可以使用普通广播接收器来接收,当然粘性广播还有另一种常用的接收方式。

1.使用普通广播接收器,注意,必须在Manifiest或者发送之前接收(这和定义有点违背,因为这种方式不是正确的接收方式)

public class StickyBroadcastReceiver extends BroadcastReceiver {    public static final String Action = "com.sample.test.sticky.broadcast.receiver";    public static final String PERMISSION = "com.sample.test.permission.sticky.receiver";    @Override    public void onReceive(Context context, Intent intent)    {        int checkCallingOrSelfPermission = context.checkCallingOrSelfPermission(PERMISSION);        if(PackageManager.PERMISSION_GRANTED == checkCallingOrSelfPermission) //权限判断        {            Toast.makeText(context, "授权成功", Toast.LENGTH_SHORT).show();        }else{            Toast.makeText(context, "授权失败", Toast.LENGTH_SHORT).show();            throw new RuntimeException("permission denied");        }        if(intent!=null&&Action.equals(intent.getAction()))        {            Toast.makeText(context, intent.getStringExtra("info"), Toast.LENGTH_SHORT).show();        }    }}

Mainifest.xml

<!--自定义权限--><permission android:name="com.sample.test.permission.sticky.receiver" android:protectionLevel="normal" /><!--使用自定义权限--><uses-permission android:name="com.sample.test.permission.sticky.receiver"/><!--使用粘性广播发送权限--><uses-permission android:name="android.permission.BROADCAST_STICKY" /><!--省略一部分--><receiver android:name="test.view.weitop.home.StickyBroadcastReceiver"    android:permission="com.sample.test.permission.sticky.receiver" >    <!--android:permission 其他应用使用时,需要检测的权限-->    <intent-filter >         <action android:name="com.sample.test.sticky.broadcast.receiver"/>    </intent-filter></receiver>

2.使用正确的方式接收(推荐)

正确的接收方式不应该使用BroadcastReceiver就可以接收到

只需要将SenderActivity的onResume稍作修改即可

@Overrideprotected void onResume() {    super.onResume();//3秒后发送 getWindow().getDecorView().postDelayed(new Runnable() {    @Override        public void run()         {         sendStickyBroadcast();      }    }, 3*1000);//15秒后就收getWindow().getDecorView().postDelayed(new Runnable() {    @Override    public void run()    {        IntentFilter intentFilter = new IntentFilter(StickyBroadcastReceiver.Action);        Intent data = registerReceiver(null, intentFilter);        if(data!=null&&StickyBroadcastReceiver.Action.equals(data.getAction()))        {            Toast.makeText(this, data.getStringExtra("info"), Toast.LENGTH_SHORT).show();        }    }    }, 15*1000);}

在这样一个相差10秒左右的时间段 【先发送,后接收】,说明了粘性广播的已经将信息完全保存起来了,只要我们去使用如下方式,即可获取到,而且无限次获取。

 Intent data = registerReceiver(null, intentFilter); //注意,不需要接收器,否则可能无法接收到

附注:这种广播也可以被移除 ,我们可以接收到 广播后调用 removeStickyBroadcast(intent);

本地广播

    前面所发送和接收的所用广播都属于系统的全局广播,我们发出的这些广播可以给系统中任何应用程序接收到,当然我们也可以接受其他应用程序的广播。但是,只用本地广播机制发出的广播只能在本应用程序中接收到。这样的话安全性得到了提升。本地广播机制主要是用LocalBroadcastManager来管理,它提供了发送广播的方法sendBroadcast()和sendBroadcastSync()(这也方法好像用的不多,我暂时没有深究,等以后真正用到可以查一下),注册接收者的方法registerReceiver(localReceiver, localIntentTilter),需要两个参数,取消注册的方法localBroadcastManager.unregisterReceiver(localReceiver);

下面看一下本地广播机制的工作流程:
1.发送本地广播

 //发送本地广播localBroadcastManager = LocalBroadcastManager.getInstance(this); //获取本地广播管理实例localCastBtn = (Button) findViewById(R.id.local_btn);localCastBtn.setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View v) {        //发送本地广播        Intent intent = new Intent("com.zwf.broadcastdemo.LOCAL_BROADCAST");        localBroadcastManager.sendBroadcast(intent);    }});

2.注册广播接收者

//注册本地广播监听localIntentTilter = new IntentFilter("com.zwf.broadcastdemo.LOCAL_BROADCAST");localReceiver = new LocalReceiver();localBroadcastManager.registerReceiver(localReceiver, localIntentTilter);

3.取消注册

//取消本地广播监听localBroadcastManager.unregisterReceiver(localReceiver);

使用本地广播的优势 
1. 可以明确地知道正在发送的广播不会离开本程序,因此不需要担心机密数据泄漏的问题。 
2. 其他程序无法将广播发送到本程序的内部,因此不需要担心会有安全漏洞的隐患。 
3. 发送本地广播比起发送系统全局广播将会更加高效。

 


第六章 组件通讯与广播消息( 普通广播、有序广播、粘性广播、本地广播的评论 (共 条)

分享到微博请遵守国家法律