Android知识梳理之BroadcastReceiver整理

PS.不知不觉间发现自己已经做了很久很久的Android开发了,过去对知识块的梳理总是放在云笔记里面.主要的原因还是自己的笔记太杂乱,没有脉络.本着开源的精神,也趁着这段时间有空将之前云笔记里面的文章梳理下.同时将一些知识点整理出来和大家共同分享.

转载请注明出处:http://blog.csdn.net/unreliable_narrator?viewmode=contents

android 的广播接收者主要分为两个方面:一个方面是广播发送者另一个方面是广播接受者.广播发送者可以自定义广播进行发送.而广播接收者则是对广播进行接收并且做出相应的事件逻辑.广播接收者的主要作用就是Android组件间的通信不同进程间的通信.

    一.广播发送者:

广播发送者就是通过发送广播消息,让注册了该广播事件的广播接收者接收相关数据.它的主要的作用就是发送广播消息.广播的发送是通过Intent的方式来进行的,当然通过intent我们也可以携带一些相关的数据进行传递.由于需要对事件进行过滤.在使用intent发送广播的时候我们显然是不能通过显示的方式来进行的,这里就需要使用到隐式的intent来发送广播.

广播发送者按不同的用法大致可以分为三种:  普通广播有序广播.异步广播

     1.普通广播:普通广播就是直接使用sendbroadcast()发送出去的广播,并且正是由于这种广播的接收者的接收顺序没有相关的规律.因此这种发送广播的方式效率极高,当然使用这种方式也是有弊端的,

就是无法对这种广播进行拦截和终止.这种方式发送的广播在BroadcastReceiver无法使用setResult系列,getResult系列及abort系列API对广播进行相关的处理 .

  1. Intent intent = new Intent();
  2. intent.setAction("test");
  3. sendBroadcast(intent);

   2. 有序广播:

(1.)使用有序广播是可以通过设置广播接收者的优先级,从而达到优先接收到广播事件的目的.在使用的时候首先要提前对广播接收者对象设置优先级,优先级高的接收者先收到广播消息,优先级低的接收者后收到广播

消息,具有相同优先级的广播接收者接收到广播消息的顺序是随机的(一般是先注册的先收到);这样,按照广播接收者的优先级顺序接收的广播就是有序广播;优先级别在配置文件AndroidManifest.xml中的标签<intent-

filter android:priority="xxx">的属性priority中配置,其数值范围是[-1000,+1000],值越大,优先级就越高;有序广播可以终止后续的继续转播,接收者可以修改广播的内容;有序广播消息是通过函

数:Context.sendOrderedBroadcast(Intent,Permission)发送的;第二个参数是需要一个权限参数,如果为null则表示不要求接收者声明指定的权限,如果不为null,则表示接收者若要接收此广播,需声明指定权

限。这样做是从安全角度考虑的,例如系统的短信就是有序广播的形式,一个应用可能是具有拦截垃圾短信的功能,当短信到来时它可以先接受到短信广播,必要时终止广播传递,这样的软件就必须声明接收短信的

权限。比如,有3个广播接收者A、B、C,优先级顺序是A>B>C,则,A最先收到广播消息,当A收到广播消息之后,可以向广播消息中添加一些数据,然后再传递给下一个广播接收者(Intent.putExtra()),或者是终止广播消

息(Context.abortBroadcast());

  1. Intent intent = new Intent();
  2. intent.setAction("com.dapeng");
  3. sendOrderedBroadcast(intent, null);
  1. <receiver
  2. android:name=".MyReciverTwo"
  3. android:priority="1000">
  4. <intent-filter>
  5. <action android:name="com.dapeng"/>
  6. </intent-filter>
  7. </receiver>
  8. <receiver
  9. android:name=".MyReciver">
  10. <intent-filter android:priority="300">
  11. <action android:name="com.dapeng"/>
  12. </intent-filter>
  13. </receiver>

(2.)终止有序广播的传递:调用abortbroadcast()方法就可以直接将有序广播事件终止掉并且不再向下传递。

  1. public class ReciverTwo extends BroadcastReceiver {
  2. @Override
  3. public void onReceive(Context context, Intent intent) {
  4. abortBroadcast();
  5. Log.d("--", "ReciverTwo被执行了");
  6. }
  7. }

(3.)对有序广播里面的内容进行修改.例如recivertwo的优先级大于reciverone的优先级我们就可以在recivertwo里面对广播数据进行修改.

  1. public class ReciverTwo extends BroadcastReceiver {
  2. @Override
  3. public void onReceive(Context context, Intent intent) {
  4. Bundle bundle = new Bundle();
  5. bundle.putString("add", "新加的数据");
  6. setResultExtras(bundle);
  7. Log.d("--", "ReciverTwo被执行了");
  8. }
  9. }
  1. public class ReciverOne extends BroadcastReceiver {
  2. @Override
  3. public void onReceive(Context context, Intent intent) {
  4. Bundle resultExtras = getResultExtras(true);
  5. String add = resultExtras.getString("add");
  6. Log.d("--", "ReciverOne被执行了");
  7. Log.d("--", "ReciverOne_add==" + add);
  8. }

     3.异步广播:

又叫做黏性广播.这个的概念并不好解释.但是通过一个例子就可以让我们明白它的意义.ActivityA发送广播到ActivityB,但BroadcastReceiver是在ActivityB中用代码进行注册的,ActivityA发送出去的广播ActivityB

是接收不到的,如果遇到这种情况该怎么办呢?使用sendStickyBroadcast方法就很好的解决了。sendStickyBroadcast()开启的广播并不会马上消失.后面等开启了界面还是可以收到异步的广播.在使用这个广播的时

候要加上相对应的权限才能够正常的使用android.permission.BROADCAST_STICKYbut,这个方法有安全性的问题so.在api21中将这个方法遗弃了.使用的时候会报过时方法.

  1. public class MainActivity extends AppCompatActivity {
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(R.layout.activity_main);
  6. findViewById(R.id.btnOne).setOnClickListener(new View.OnClickListener() {
  7. @Override
  8. public void onClick(View v) {
  9. Intent intent = new Intent();
  10. intent.setAction("com.test");
  11. sendStickyBroadcast(intent);
  12. }
  13. });
  14. findViewById(R.id.btnTwo).setOnClickListener(new View.OnClickListener() {
  15. @Override
  16. public void onClick(View v) {
  17. startActivity(new Intent(MainActivity.this, SecondActivity.class));
  18. }
  19. });
  20. }
  21. }
  1. public class SecondActivity extends AppCompatActivity {
  2. private MyReciver mMyReciver;
  3. private IntentFilter mIntentFilter;
  4. @Override
  5. protected void onCreate(Bundle savedInstanceState) {
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.activity_second);
  8. //注册广播事件
  9. mMyReciver = new MyReciver();
  10. mIntentFilter = new IntentFilter();
  11. mIntentFilter.addAction("com.test");
  12. registerReceiver(mMyReciver, mIntentFilter);
  13. }
  14. public class MyReciver extends BroadcastReceiver {
  15. @Override
  16. public void onReceive(Context context, Intent intent) {
  17. Log.d("--", "我接收到了异步广播");
  18. }
  19. }
  20. @Override
  21. protected void onDestroy() {
  22. unregisterReceiver(mMyReciver);
  23. super.onDestroy();
  24. }
  25. }
  1. <uses-permission android:name="android.permission.BROADCAST_STICKY"/>

二.广播接收者.

广播接收者同属于四大组件之一,其主要的作用就是用来接收广播,并且根据这些广播做出相应的事件处理. 这些广播可以是系统发出来的广播,也可以是自己自已定义的广播事件的广播事件.使用它的时候有两种

方式可以进行注册,一种是静态注册,也就是在清单文件中配置设置过滤.另外的一种就是动态去注册广播事件.在代码中去进行注册 广播的事件.需要注意的一点就是动态注册的广播接收者的优先级始终是高于静态注

册的广播接收者

   1.静态注册广播:

(1.)编写一个类继承自broadcastreciver  .

  1. public class ReciverOne extends BroadcastReceiver {
  2. @Override
  3. public void onReceive(Context context, Intent intent) {
  4. Log.d("--", "ReciverOne被执行了");
  5. }
  6. }

(2.) 然后在清单文件中进行配置.action需要和发送者的action进行正确的匹配才能够正确的使用.

  1. <receiver android:name=".ReciverOne">
  2. <intent-filter android:priority="100">
  3. <action android:name="com.test"/>
  4. </intent-filter>
  5. </receiver>

 需要注意的是:从3.1开始静态注册的app如果处于退出的状态,将无法收到广播事件.主要是发送广播的时候增加了addflags()函数所致.

FLAG_INCLUDE_STOPPED_PACKAGES:包含已经停止的应用(停止:即应用所在的进程已经退出)

FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已经停止的应用

系统发送的广播都是采用的不包含已经停止的包.但是我们自己发送的广播事件确可以加上相应的flag,这样一来即使app处于退出的状态,仍然是可以接收到广播事件的.

  1. Intent intent = new Intent();
  2. intent.setAction("com.test");
  3. intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
  4. intent.putExtra("name", "dapeng");
  5. sendBroadcast(intent);

            2. 动态注册: 

(2.)动态注册的时候要在宿主activity销毁的时候对广播接收者进行解除注册.

  1. public class SecondActivity extends AppCompatActivity {
  2. private MyReciver mMyReciver;
  3. private IntentFilter mIntentFilter;
  4. @Override
  5. protected void onCreate(Bundle savedInstanceState) {
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.activity_second);
  8. //注册广播事件
  9. mMyReciver = new MyReciver();
  10. mIntentFilter = new IntentFilter();
  11. mIntentFilter.addAction("com.test");
  12. registerReceiver(mMyReciver, mIntentFilter);
  13. }
  14. public class MyReciver extends BroadcastReceiver {
  15. @Override
  16. public void onReceive(Context context, Intent intent) {
  17. //TODO do your work
  18. }
  19. }
  20. @Override
  21. protected void onDestroy() {
  22. unregisterReceiver(mMyReciver);
  23. super.onDestroy();
  24. }
  25. }

     3.补充:

我们知道:Android中的广播可以跨进程甚至跨App直接通信,且intent-filter的情况下属性exported的默认值是true,由此将可能出现安全隐患如下:

(1.)如果当前App intent-filter匹配了其他应用发出的广播,会导致当前App不断接收到广播并处理;

解决的方式是:将清单文件中广播接收者的exported属性人为设置成false,使得非本App内部发出的此广播不被接收;

  1. <receiver
  2. android:name=".Myreciver"
  3. android:exported="false">
  4. <intent-filter>
  5. <action android:name="com.test"/>
  6. </intent-filter>
  7. </receiver>

(2)其他App可以通过注册与当前App一致的intent-filter用于接收广播,获取广播具体信息。

解决的方式是:.发送广播时,指定特定广播接收器所在的包名,具体是通过intent.setPackage(packageName)指定在,这样此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。

  1. Intent intent = new Intent();
  2. intent.setAction("com.test");
  3. intent.setPackage(getPackageName());
  4. sendOrderedBroadcast(intent, null);
时间: 2024-08-14 08:44:31

Android知识梳理之BroadcastReceiver整理的相关文章

Android知识梳理之自定义View

虽然android本身给我们提供了形形色色的控件,基本能够满足日常开发的需求,但是面对日益同质化的app界面,和不同的业务需求.我们可能就需要自定义一些View来获得比较好的效果.自定义View是android开发者走向高级开发工程师必须要走的一关. 转载请标明出处:http://blog.csdn.net/unreliable_narrator/article/details/51274264 一,构造函数: 当我们创建一个类去继承View的时候,会要求我们至少去实现一个构造函数. publi

Android知识梳理之屏幕适配全攻略

 引言: 我相信Android碎片化问题是让所有的Android开发者都比较头疼的问题.尤其是屏幕适配这一块儿.想要自己的app在不同的设备上面都有一个比较好的显示效果.就必须做好相应的屏幕适配.本文是结合网上的相关知识总结.官方文档结合自己的一些理解来进行阐述的.如有不恰当的地方,欢迎斧正.共同学习. 转载请标明出处:http://blog.csdn.net/unreliable_narrator/article/details/51315776 我们先来了解两个概念:屏幕尺寸和屏幕的分辨率:

Android 知识梳理

**** Google工程师解析Android系统架构 http://www.oschina.net/question/12_13318 Android并不是传统的Linux风格的一个规范或分发版本,也不是一系列可重用的组件集成,Android是一个用于连接设备的软件块. Dalvik虚拟机只执行.dex APK是压缩文件夹 Android Manifest——介于App和Android System的接口 &&&& 1-Android 线程模型和 AsyncTask ht

Android四大组件之BroadcastReceiver详细解析

什么是BroadcastReceiver? BroadcastReceiver作为Android四大组件之一,在实际开发中也发挥着重要的作用,广播机制在Android程序通信中至关重要,广播其实与我们现实生活中的电台很相似,电台在某个频道上发送它的内容,那么只要有在收听这个频道的人都会收到这些内容.在Android中,广播也同样分为两个角色:广播发送者.广播接收者. BroadcastReceiver的应用场景 1.在一个应用中,我们的Activity与Service的通信就需要用到广播来作为中

[SQL] SQL 基础知识梳理(一)- 数据库与 SQL

SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 序 目录 What's 数据库 数据库结构 SQL 概要 创建表 删除和更新表 1-1 What's 数据库 1.数据库(Database,DB):将大量数据保存起来,通过计算机加工而成的可以进行高效访问的数据集合.如:大型-银行存储的信息,小型-电话簿. 2.数据库管理系统(Batabase Management Syste

[SQL] SQL 基础知识梳理(四) - 数据更新

SQL 基础知识梳理(四) - 数据更新 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5929786.html 目录 一.插入数据 1.INSERT 语句的基本语法 --语法: --INSERT INTO <表名>(列1, 列2, ...) VALUES (值1, 值2, ...) INSERT INTO dbo.Shohin ( shohin_id , shohin_mei , shohin_bunrui , hanbai_tanka , s

[SQL] SQL 基础知识梳理(三)- 聚合和排序

SQL 基础知识梳理(三)- 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 目录 一.对表进行聚合查询 1.聚合函数 (1)5 个常用函数: ①COUNT:计算表中的记录(行)数. ②SUM:计算表中数值列的数据合计值. ③AVG:计算表中数值列的数据平均值. ④MAX:求出表中任意列中数据的最大值. ⑤MIN:求出表中任意列中数据的最小值. (2)聚合:将多行汇总成一行. 图1-1 Shohin 表 2.计算

指针知识梳理7- 函数指针

一.函数的地址 前面讲 程序运行起来以后,在内存中有代码区,程序运行每一条指令,是从内存中读出来这条指令,然后再运行. 所谓函数的地址是指函数的入口地址,这个函数的从这个地址開始进入运行,也就是从这个地址处取指令运行. 那么在代码层面,函数的地址用 函数指针变量 来存储. 二.基本使用 1.函数指针定义 函数指针的定义,在语法看起来略微有点怪,仅仅须要记住形式 返回值 (*指针变量名)(形參类型): 比方,下面4个函数 void func1(void) { } int func2(void) {

基础知识:Promise(整理)

基础知识:Promise(整理) (来自牛客网)下面关于promise的说法中,错误的是(D) A. resolve和reject都是直接生成一个进入相应状态的promise对象,其参数就是进入相应状态时传递过去的参数,可以在完成回调的参数中得到 B. Promise.resolve(value),Promise.reject(reason)是Promise构造器上还直接提供了一组静态方法 C. 在调用then方法或者catch方法时都是异步进行的,但是执行速度比较快 D. Promise构造器