作者:白璐
日期:2020/2/23
Android应用程序是由下列4个组件构成,分别是:
活动程序(Activity) 服务程序(Service) 广播接收器(Broadcast Receiver) 内容提供器(Content Provider) 广播接收器(Broadcast Receiver) Broadcast Receiver简介BroadCastReceiver是Android的四大组件之一,主要功能就是发送消息,监听消息,然后根据业务进行逻辑处理,可以在应用内部,也可以是应用之间使用。从应用内部的消息,数据传递这个功能来说,现如今有很多开源的框架可以实现,比如EventBus 或者使用观察者模式自定义封装一个消息发送机制,也都挺好用的。
Broadcast Receiver的注册 一. 静态注册 写一个广播集成BroadcastReceiverpublic class MyReceiver1 extends BroadcastReceiver {
public static final String ACTION1="com.example.liukang.mybroadcastprojrct.test";
@Override
public void onReceive(Context context, Intent intent) {
if (intent!=null){
String r1 = intent.getStringExtra("MyReceiver1");
Toast.makeText(context,"我接收到了"+r1,Toast.LENGTH_LONG).show();
Log.e("TAG",r1);
//abortBroadcast(); 有序广播时候,优先级高的可以接收,进行判断处理是否往下传递
}
}
}
在清单文件中注册一下:
//是否能接收其他APP发送的消息
//有序广播优先级使用,越大越高
发送广播:
Intent intent = new Intent();
intent.setAction("ACTION_RECEIVER"); //一定对应
intent.addCategory("category"); //不写即是默认 可以匹配;但是写了,那么清单文件MyReceiver1注册的必须得有,否则不通过
intent.setComponent(new ComponentName("com.example.liukang.mybroadcastprojrct",
"com.example.liukang.mybroadcastprojrct.MyReceiver1")); // Android 8.0之后必须指定包名,以及包名.类名
intent.putExtra("MyReceiver1", "MyReceiver1广播");
sendBroadcast(intent);
//sendOrderedBroadcast(intent,null); 发送有序广播
二. 动态注册
写一个类继承
public class MyMainReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
String main = intent.getStringExtra("main");
Toast.makeText(MainActivity.this, "这是MyMainReceiver广播接收的数据:" + main, Toast.LENGTH_LONG).show();
}
}
}
动态注册
MyMainReceiver myMainReceiver = new MyMainReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("MyMainReceiver");
registerReceiver(myMainReceiver, filter);
发送广播:
//发送Main广播
Intent intent =new Intent();
intent.setAction("MyMainReceiver");
intent.putExtra("main","123456");
sendBroadcast(intent);
取消注册
unregisterReceiver(myMainReceiver );
三. 本地广播
只是APP内部使用,保证信息传递的安全。
自定义广播public class MyFirstActiivtyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
if (intent!=null){
String r2 = intent.getStringExtra("r2");
Toast.makeText(context,r2,Toast.LENGTH_LONG).show();
Log.e("TAG",r2);
}
}
}
本地动态注册
receiver=new MyFirstActiivtyReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction("ACTION_TEST");
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.registerReceiver(receiver,filter);
本地发送:
Intent intent =new Intent();
intent.setAction("ACTION_TEST");
intent.putExtra("r2","123456");
localBroadcastManager.sendBroadcast(intent);
取消注册
localBroadcastManager.unregisterReceiver(receiver);
发送Broadcast Receiver
广播的三种发送方式
无序广播
//无序广播
Intent intent = new Intent();
intent.setAction("android.bawei.action.customer");
Bundle bundle = new Bundle();
bundle.putString("msg","我是猪头");
intent.putExtras(bundle);
sendBroadcast(intent);
有序广播
//有序广播
//有序广播要在注册时给intentFilter对象设置一个优先级
intentFilter.setPriority(1000);
//在发送消息时
sendOrderedBroadcast(intent,null);
粘性广播
//粘性广播
//要注意的是 粘性广播已经过时在android8.0以后已经无法使用
//粘性广播最大的特点就是可以先发送消息 再注册 缺点是很消耗内存
sendStickyBroadcast(intent);
静态广播接收的处理器是由PackageManagerService负责,当手机启动或者新安装了应用的时候,PackageManagerService会扫描手机中所有已安装的APP应用,将AndroidManifest.xml中有关注册广播的信息解析出来,存储至一个全局静态变量当中。
动态广播接收的处理器是由ActivityManagerService负责,当APP的服务或者进程起来之后,执行了注册广播接收的代码逻辑,即进行加载,最后会存储在一个另外的全局静态变量中。需要注意的是:
广播发出的时候,广播接收者接收的顺序如下:1.当广播为普通广播时,有如下的接收顺序:
无视优先级
动态优先于静态
同优先级的动态广播接收器,先注册的大于后注册的
同优先级的静态广播接收器,先扫描的大于后扫描的
2.如果广播为有序广播,那么会将动态广播处理器和静态广播处理器合并在一起处理广播的消息,最终确定广播接收的顺序:
优先级高的先接收
同优先级的动静态广播接收器,动态优先于静态
同优先级的动态广播接收器,先注册的大于后注册的
同优先级的静态广播接收器,先扫描的大于后扫描的 常用的系统广播的action 和permission
系统操作 | Action | permission |
---|---|---|
开机启动 | android.intent.action.BOOT_COMPLETED | android.permission.RECEIVE_BOOT_COMPLETED |
网络状态 | android.net.conn.CONNECTIVITY_CHANGE | android.permission.ACCESS_NETWORK_STATE |
电量变化 | android.intent.action.BATTERY_CHANGED | |
SD卡状态 | android.intent.action.MEDIA_MOUNTED android.intent.action.MEDIA_UNMOUNTED android.intent.action.MEDIA_REMOVED |
|
监听应用的安装、卸载、更新 | android.intent.action.PACKAGE_ADDED android.intent.action.PACKAGE_REPLACED android.intent.action.PACKAGE_REMOVED |
自定义权限时必须同时指定 protectionLevel 属性值,系统根据该属性值确定自定义权限的使用方式
属性值 | 限定方式 |
---|---|
normal | 默认值。较低风险的权限,对其他应用,系统和用户来说风险最小。系统在安装应用时会自动批准授予应用该类型的权限,不要求用户明确批准(虽然用户在安装之前总是可以选择查看这些权限) |
dangerous | 较高风险的权限,请求该类型权限的应用程序会访问用户私有数据或对设备进行控制,从而可能对用户造成负面影响。因为这种类型的许可引入了潜在风险,所以系统可能不会自动将其授予请求的应用。例如,系统可以向用户显示由应用请求的任何危险许可,并且在继续之前需要确认,或者可以采取一些其他方法来避免用户自动允许 |
signature | 只有在请求该权限的应用与声明权限的应用使用相同的证书签名时,系统才会授予权限。如果证书匹配,系统会自动授予权限而不通知用户或要求用户的明确批准 |
signatureOrSystem | 系统仅授予Android系统映像中与声明权限的应用使用相同的证书签名的应用。请避免使用此选项,“signature”级别足以满足大多数需求,“signatureOrSystem”权限用于某些特殊情况 |
作者:白露未晞