Broadcast Recevier 广播接收器是一个专注于接收广播通知信息,并做出对应处理的组件。很多广播是源自于系统代码的──比如,通知时区改变、电池电量低、拍摄了一张照片或者用户改变了语言选项。应用程序也可以进行广播──比如说,通知其它应用程序一些数据下载完成并处于可用状态。 应用程序可以拥有任意数量的广播接收器以对所有它感兴趣的通知信息予以响应。所有的接收器均继承自BroadcastReceiver基类。 广播接收器没有用户界面。然而,它们可以启动一个activity来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。句段摘自Android Broadcast Security

一,API解读

BroadcastReceiver

  • 抽象类,继承自 java.lang.Object ,类的声明为:public abstract class BroadcastReceiver
  • API位置:android.content.BroadcastReceiver
  • 直接子类:AppWidgetProvider, DeviceAdminReceiver, MediaButtonReceiver, RestrictionsReceiver, WakefulBroadcastReceiver

这是接受由sendBroadcast()发送的Intent的代码的基类。
如果broadcast只是在自己应用内发送接收,应该考虑使用 LocalBroadcastManager类,
广播接收器的注册方式有两种

  • 一种在类中动态注册,
  • 一种在AndroidManifest.xml中用 标签注册,
    在动态注册中,如果是在 Activity.onResume() 中实现的注册事件,那就应该在 Activity.onPause(). 取消注册。

可以接收的广播有两种

  • 一种是正常广播, Context.sendBroadcast发送,Normal broadcasts是完全异步的可以同一时间被所有的接收者接收到。消息的传递效率比较高。但缺点是接收者不能讲接收的消息的处理信息传递给下一个接收者也不能停止消息的传播
  • 一种是有序广播,Context.sendOrderedBroadcast发送,根据设置的优先级决定发送广播发送的次序。Ordered broadcasts的接收者按照一定的优先级进行消息的接收。如:A,B,C的优先级依次降低,那么消息先传递给A,在传递给B,最后传递给C。优先级别声明在中,取值为[-1000,1000]数值越大优先级别越高。优先级也可通过filter.setPriority(10)方式设置。 另外Ordered broadcasts的接收者可以通过abortBroadcast()的方式取消广播的传播,也可以通过setResultData和setResultExtras方法将处理的结果存入到Broadcast中,传递给下一个接收者。然后,下一个接收者通过getResultData()和getResultExtras(true)接收高优先级的接收者存入的数据。句段摘自Android开发之BroadcastReceiver详解

注意,尽管广播也是通过intent类发送和接受广播,但是,这种Intent broadcast机制和通过 Context.startActivity()启动Activities 的intent是不同的概念

安全:

通过 Context APIs实现Receivers,会赋予其夸应用的性质。所以必须考虑会有其他程序滥用这些广播接收器:

  • intent命名空间是全局性的,要确保定义的意图动作名称和其他的字符串是自己独有的,防止不经意的与其他应用造成冲突
  • 注册广播时,设置权限决定哪个接收器可以接受它
  • 在AndroidManifest.xml中注册广播时设置了意图过滤器,其他应用也会通过这个意图过滤器发送广播,如果阻止发送,设置 android:exported=”false”
  • 除了可以通过设置广播接收器的权限限制谁可以接受谁的广播外,从 ICE_CREAM_SANDWICH,开始,可以通过调用 Intent.setPackage设置单一某个包接受广播

使用LocalBroadcastManage意图不会在进程之外传递,全无这些问题

接收器生命周期:

BroadcastReceiver 对象仅在调用 onReceive(Context, Intent) 期间有效,一旦此方法中进行return ,系统会认为其结束了并且不再执行.
此方法内不能进行任何异步或耗时的操作,尤其是不能使用BroadcastReceiver显示对话框或绑定服务,对于前者,可以使用NotificationManager API., 对于后者,可以通过调用 Context.startService() 向service发送一个命令.

进程生命周期:

正在执行BroadcastReceiver的进程(也就是说正在执行 onReceive(Context, Intent) 方法),系统会当作其为一个前台进程,并且即使在内存不足的时候也会保持它运行
一旦onReceive()中return,BroadcastReceiver就不会再执行了,其宿主进程的重要程度会变得和其他组件一样,这个性质很重要,因为如果宿主进程仅仅包含一个BroadcastReceiver,如果onReceive()中return,BroadcastReceiver就会结束,进程就是一个空进程,系统会为其他更重要的进程提供内存资源而杀死这个进程
这意味着,对于一些耗时操作,需要使用 Service 搭配 BroadcastReceiver, 保证在操作时间内,进程一直处于有效状态

LocalBroadcastManager

  • 实体类,继承自 java.lang.Object ,类的声明为:public final class LocalBroadcastManager
  • API位置:android.support.v4.content.LocalBroadcastManager

在进程中为本地对象注册并发送广播。这比使用sendBroadcast(Intent)发送的全局性的广播有优点:

  • 你知道你正在广播数据不会离开你的应用程序,因此不必担心泄露隐私数据。
  • 其他应用不可能将这些广播发送到您的应用程序,所以你不必担心有会 有人们可以利用的安全漏洞出现。
  • 它比在系统中发送的全局性的广播更有效率

LocalBroadcastManager可以认为是context版的Broadcast的缩小版 相似方法用法相似

二,代码示例

发出广播:

1,创建启动BroadcastReceiver的intent
2,发送广播

  • 发送普通广播sendBroadcast (Intent intent),或sendBroadcast (Intent intent, String receiverPermission)
  • 发送有序广播sendOrderedBroadcast (Intent intent, String receiverPermission),或sendOrderedBroadcast (Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)
  • 使用LocalBroadcastManager 发送本地广播sendBroadcast (),仅仅本地广播
Intent intent=new Intent();//创建Intent
intent.setAction("android.accessibilityservice.AccessibilityService");//注册广播接收器时包含有意图过滤器时的intent设置
//intent.setClassName(context,"类名");//明确指出发送的接收器的类
//intent.setPackage("包名");//明确指出哪个包的接收器
//intent.setClass(context,class);//明确指出发往的接收器的类
// context.sendBroadcast(intent);//发送全局性质的普通广播
//context.sendUrderedBroadcast(intent,null);//发送全局性质的有序广播
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);//发送本地广播

创建广播接收器:

继承BroadcastReceiver:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;public class MyReceiver extends BroadcastReceiver {public MyReceiver() {}@Overridepublic void onReceive(Context context, Intent intent) {}
}

注册广播:

静态注册:

<serviceandroid:name=".MyReceiver"android:enabled="true"android:exported="true"  //使用LocalBroadcastManager时,设置为falseandroid:permission="android.permission.自定义"><intent-filter><action android:name="android.accessibilityservice.AccessibilityService"/> //自定义</intent-filter>
</service>

动态注册:

MyReceiver receiver=new MyReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction("android.accessibilityservice.AccessibilityService");
//注册receiver
registerReceiver(receiver, filter);
//取消注册receiver
unregisterReceiver(receiver);

此时也可以以new的方式创建广播:

BroadcastReceiver broadcastReceiver=new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {}};

设置有序广播接收器的接收广播的优先级

静态注册时:

<intent-filter android:priority="200"><action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>

动态注册时:

filter.setPriority(200);

三,推荐阅读

基础

Android开发之BroadcastReceiver详解

深入

Broadcast内部机制讲解
Android Broadcast Security

四,完善上次的自定义DeviceAdminReceiver模板

DeviceAdminReceiver.java.ftl

import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Build;/*** 作者:liuyaowei;日期:2016-07-14.* QQ:1054185214* 类作用:设备管理器服务类  手机上的位置:设置--安全与隐私--设备管理器*/
public class ${className} extends DeviceAdminReceiver {public ${className}() {}@Overridepublic DevicePolicyManager getManager(Context context) {return (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);}@Overridepublic ComponentName getWho(Context context) {return new ComponentName(context, ${className}.class);}/**   * 接受其他组件发送来的广播 * @param context* @param intent*/@Overridepublic void onReceive(Context context, Intent intent) {int flags=intent.getFlags();if (!getManager(context).isAdminActive(getWho(context))){// Launch the activity to have the user enable our admin.Intent a = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);a.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, getWho(context));a.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "555555");//说明信息context.startActivity(a);}else {switch (flags){case 0:getManager(context).lockNow();break;//锁屏case 1:getManager(context).wipeData(DevicePolicyManager.WIPE_EXTERNAL_STORAGE);break; //清除存储数据case 2:getManager(context).wipeData(DevicePolicyManager.WIPE_RESET_PROTECTION_DATA);break;  //恢复出厂设置case 3:if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {getManager(context).reboot(getWho(context));}break; //重启case 4:getManager(context).resetPassword("",DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);break; //更改锁屏密码case 5:getManager(context).removeActiveAdmin(getWho(context));break;//取消激活设备管理器default:break; //其他另行}}}/*** 供其他组件调用来发送广播 * @param context* @param flag*/public static void sendBroadcast(Context context,int flag){Intent intent=new Intent();intent.setAction("android.app.action.DEVICE_ADMIN_ENABLED");intent.addFlags(flag);context.sendBroadcast(intent,"android.permission.BIND_DEVICE_ADMIN");}
}

liuyaowei/DeviceAdminReceiver

Broadcast Recevier回顾及自定义DeviceAdminReceiver模板完善相关推荐

  1. 乐乎常用的html源码,点点网关闭自定义html模板代码功能,网易lofter重新映入眼帘...

    点点网大家都熟悉,在之前我也介绍过,很出色的一款轻博客. 但是在我准备正式使用的时候,点点却发生了意想不到的变故,点点不顾广大点友的利益,将唯一独特的吸引我们的功能:自定义html模板代码功能残忍的关 ...

  2. 产品周报第30期|编辑器支持自定义写作模板;MarkDown编辑器接入质量分检测功能;CSDN APP V5.2.0版本发布

    hello,大家好,这里是「CSDN产品周报」第30期.本次更新主要涉及博客.首页和CSDN APP,欢迎大家详细了解和使用. 博客产品体验优化 一.编辑器新增自定义模板创建功能 每个人都有自己的写作 ...

  3. 2BizBox 免费ERP v3.3.0 新版本剧透之二:自定义打印模板

    2BizBox ERP使的可以,但销售单等单据有时不能反应企业风格满足独特需要.对于企业来讲,很多单据特别重要.尤其是传递给往来业务单位的单据,由于其固有的业务格式和双方的特殊业务约定等因素的影响,需 ...

  4. TFS2008自定义过程模板之 Power Tools 工具篇

    上午写了一篇关于自定义过程模板的文章http://www.cnblogs.com/sansi/archive/2010/03/11/1683355.html,是手工直接处理xml文件.刚刚发现原来是有 ...

  5. VSCode 自定义html5模板

    新建html快捷键 当我们想在VSCode中新建html代码时,可以 输入! 然后回车或者Tab即可自动生成一个html文件模板,效果如下: (二)自定义html5模板 但我们每次新建html模板时候 ...

  6. 类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器

     1.第一个最简单的类模板案例 #include "mainwindow.h" #include <QApplication> #include <QPush ...

  7. MyEclipse自定义servlet模板

    每次用MyEclipse默认的servlet的模板创建servlet的时候,里面会生成好多没有用的代码.因此,我们可以自定义servlet模板.步骤如下: 找到com.genuitec.eclipse ...

  8. 用Visual Studio2019自定义项目模板

    项目模板简介 众所周知,在我们使用VS新建项目时,都需要选择一个项目模板,如下图: 我们选择完项目模板进行创建,创建完成之后,可以发现项目中已经包含了一些基础的文件.例如MVC: 可以看到,MVC项目 ...

  9. ASP.NET 自定义项目模板

    前言 在微服务架构盛行的时代,一言不合就新建一个服务,虽然搭建服务并没什么难度,但不可避免的是每个人搭建出来的架子会存在差异,这很合理,因为每个开发者的个人风格.工作经验都不一样,难免认为自己喜欢的才 ...

最新文章

  1. 关于火狐(firefox4)
  2. ACM入门之【差分】
  3. Bootstrap的轮播图
  4. 12864液晶驱动源码,独创中英文混合输出
  5. 13.10 Scala中使用JSON.toJSONString报错:ambiguous reference to overloaded definition
  6. 表的转置 行转列: DECODE(Oracle) 和 CASE WHEN 的异同点
  7. gRPC编码初探(java)
  8. 初中学习计算机基础,初中生计算机基础学习心得
  9. C语言中定义变量位置
  10. 移动端WEB开发之响应式布局(响应式开发原理、bootstrap、阿里百秀案例)
  11. vm怎么装vim_虚拟机中Ubuntu下安装vim及配置文件和插件之菜鸟初体验
  12. sublime text3 python找不到文件路径_如何在sublime3 项目设置中设置 python 解释器的路径?...
  13. Beetlsql自学笔记
  14. 熔断机制什么意思_[财经]熔断机制的由来介绍 熔断机制什么意思 - 南方财富网...
  15. MISF:Multi-level Interactive Siamese Filtering for High-Fidelity Image Inpainting 论文解读与感想
  16. 分众传媒CEO江南春:没钱是这个社会进步最大的动力
  17. 中文化最好的linux,中文化最好的蓝点Linux 2.0下载----红旗甘拜下风!
  18. 学术写作(Scientifi Academic Writing in English)
  19. 易语言调试工具 code by:↖星空·之上↗ Ver:2.0 (2017/5/28更新)
  20. python矩阵、解方程、绘图操作

热门文章

  1. Java面试题目汇总/英文Java面试题(核心知识)
  2. error: ‘CV_LOAD_IMAGE_UNCHANGED’ was not declared in this scope
  3. 三菱系统四轴正反转参数_三菱第四轴参数
  4. 技术美术自学——PBR材质通道基础 常见贴图种类列举(求dalao轻喷)
  5. css英文文本不换行,CSS样式表让英文文本自动换行
  6. CSS中已经定义宽度的样式 英文不执行换行
  7. 卸载CTEX后再安装LaTex时会遇到的问题
  8. 安卓源码AOSP下载使用的正确姿势
  9. 如何将caj格式文件转换成word文档
  10. html椭圆的写法,4.8 把圆变换为椭圆 - HTML5 Canvas 实战