Broadcast Recevier回顾及自定义DeviceAdminReceiver模板完善

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() {
    }
    @Override
    public void onReceive(Context context, Intent intent) {
    }
}

注册广播:

静态注册:

".MyReceiver"
    android:enabled="true"
    android:exported="true"  //使用LocalBroadcastManager时,设置为false
    android:permission="android.permission.自定义">
    
        "android.accessibilityservice.AccessibilityService"/> //自定义
    

动态注册:

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() {
        @Override
        public void onReceive(Context context, Intent intent) {
        }
    };

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

静态注册时:

"200">
    "android.accessibilityservice.AccessibilityService"/>

动态注册时:

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}() {
    }

    @Override
    public DevicePolicyManager getManager(Context context) {
        return (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
    }

    @Override
    public ComponentName getWho(Context context) {
        return new ComponentName(context, ${className}.class);
    }

    /**   
     * 接受其他组件发送来的广播 
     * @param context
     * @param intent
     */
    @Override
    public 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

你可能感兴趣的:(Android,知识)