Lollipop DevicePolicyManager学习下届

Android 5.0(lollipop)发布之后,看特性文档增加了不少有趣的东西。

最近花了一些时间,研究了下其中Managed Profile的概念,简称MP,记录下来作为一些经验,有需要的同学请参考。

简介

Managed Profile,简称被管理者账户。这个概念并不是什么新东西,因为早在4.2版本中,Android就引入了多用户机制来解决平板使用上的问题。而如今5.0新加入的这个被管理者账户功能,可以理解成为是为了解决用户本人对于应用进行分类的需求问题而做的细化吧。

存在于被管理者账户中的应用受制于主账户,也就是仍然处于机主本人的控制之下。但这些应用的存储空间,以及应用的userID和PID都不同于主账户的同名应用。

这些在被管理者账户中的应用可以由机主进行各方面的限制,比如说控制这些应用不能访问摄像头——所有涉及到拍照部分的功能都开启不了,再比如说控制某些特定应用的功能——比如说让chrome的历史记录功能禁止使用。而所有的这些应用都与主账户中的应用隔离,这就意味着原本可能会被无故唤起的某些应用放到这里之后,它也再也不会被另一些流氓应用给后台唤醒了。

前提条件

首先,你需要一台安装Android5.0及以上版本的手机,亲儿子系列最好,因为不知道第三方ROM是否会将“加密”功能给阉割了。

开启手机加密的方法为:

设置——安全——加密手机

一般来说,手机出厂设置是不默认加密的,需要用户自己启动才行。当然,也可以通过代码来启动该功能,具体如下:

  

  private voidregisterPovisionManagerProfile() {
        if (null== this) {
           return;
        }
        Intentintent = new Intent(ACTION_PROVISION_MANAGED_PROFILE);
       intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
               this.getApplicationContext().getPackageName());
        if(intent.resolveActivity(this.getPackageManager()) != null) {
           startActivityForResult(intent, REQUEST_PROVISION_MANAGED_PROFILE);
           this.finish();
        } else {
           Toast.makeText(this, "Device provisioning is not enabled.Stopping.",
                   Toast.LENGTH_SHORT).show();
        }
}

    @Override
    public voidonActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode == REQUEST_PROVISION_MANAGED_PROFILE) {
            if(resultCode == Activity.RESULT_OK) {
               Toast.makeText(getApplicationContext(), "Provisioning done.",Toast.LENGTH_SHORT).show();
            }else {
               Toast.makeText(getApplicationContext(), "Provisioningfailed.", Toast.LENGTH_SHORT).show();
            }
           return;
        }
       super.onActivityResult(requestCode, resultCode, data);
    }

之后根据引导窗口则可以完成加密手机并设置Managed Profile的流程。

具体模块设计相关

对手机加密完成,并生成Managed Profile账户之后,我考虑了以下几个问题。

1.      启动MP账户的流程

在google给出的官方样例中,启动一个ManagedProfile已经有了一套成熟的方案。

具体如下:

a)        判断当前应用是否已经注册为当前账户的账户所有者(profile owner)——可以理解是拥有某些高级权限,类似admin用户。

b)        如果不是,则参考加密的流程,发一个系统的intent启动加密流程。

c)        如果是,那么恭喜你,你已经处于一个MP中,并且拥有这个MP下的类管理者权限了。

参考google的官方样例BasicManagedProfile即可。

为了方便后续描述,当前应用我简称为AdminApp好了。

2.      如何添加现有应用至MP账户中。

一般来说,查询当前系统中安装的应用状态Android已经有了非常方便的方式,通过PackageManager可以查到系统中安装的各个包的信息总合,也可以指定特定的包名来查询对应信息。

但是,这个在MP账户中是做不到的。

比如常见的getInstalledPackages(intflag)方法,虽然平时调用时仅使用参数flags。但从源码来看,真实的被调用者其实是被隐藏的方法getInstalledPackages(int flags,int userId),暴露给我们的方法中,userId已经固定为当前的用户ID。

再看一下PackageManager服务进程就能知道,真正在查询安装包信息时,该方法需要将userID作为校验条件之一。通常一个Profile下对应的所有应用都有一个相同的userID,所以跨了Profile后就无法查询主账户下的应用信息了。

所以在默认的MP账户中操作getInstalledPackages(),如果指明返回非系统应用,则只会返回当前应用本身,其他的三方应用是无法找到的。同样,查找系统应用也只能查找到在MP账户中注册的系统应用,没有注册的同样也找不到。

因此,如果要添加相关应用至MP账户中,无法通过轮询当前被管理者账户下所有的应用名称来一一添加。目前可行的有两种方法,一种是用包名字串来激活,另一种是从主账户AP来获取包名激活。

其中,谷歌的官方demo BasicManagedProfile使用的第一种方法,这里先进行介绍这种方法。如何从主账户来获取留在后面介绍。

还是以Chrome应用为例。

Chrome的包名是:com.android.chrome

通过isApplicationEnabled方法可以判断当前这个应用并没有在MP账户中。具体的原理就是刚才所说的userID隔离后的查询的结果。

    /**
     * Checks if the application is availablein this profile.
     *
     * @param packageName The package name
     * @return True if the application isavailable in this profile.
     */
private boolean isApplicationEnabled(String packageName) {
…
}

Android对已知包名的系统应用,提供了将其重新安装到被管理者账户中的方法供AdminApp来调用。即public void enableSystemApp (ComponentName admin, StringpackageName)。

具体的使用流程可以参考demo中的代码段:

     /**
    * Enables or disables the specified app in this profile.
    *
    * @param packageName The package name of the target app.
    * @param enabled     Pass true toenable the app.
    */
private voidsetAppEnabled(String packageName, boolean enabled) {
}

需要注明的一点是,这个方法只针对拥有INSTALL_PACKAGES权限的系统应用有效,如果你传入的第三方应用包名,那么肯定会抛出IllegalArgumentException:Only system apps canbe enabled this way异常。

即使通过反射直接调用PackageManager服务的installExistingPackageAsUser(packageName,userID)方法,也会因为权限的问题而失败。

所以,手动添加第三方应用到MP中目前我是没有找到更好的方法,只能在建立MP之后重新安装指定的第三方应用,此时,MP中会同样安装一份拷贝版本。

通过AdminApp调用enableSystemApp使能的系统应用会出现在被管理者账户中,作为快捷方式显示出来:

同样,如果不希望该应用显示在MP中,可以用AdminApp调用publicboolean setApplicationHidden (ComponentName admin, String packageName, booleanhidden)来隐藏。

时间: 2024-08-09 09:06:14

Lollipop DevicePolicyManager学习下届的相关文章

Lollipop DevicePolicyManager学习(下)

3.      如何在主账户与被管理者账户之间做数据通信. a)        什么是userID 刚才提到,Lollipop用来区分主账户与被管理账户的其实是一个int型数值userID. 从UserHandler.class可以看到,这个userID是通过对uid作整除得到的: public static final int PER_USER_RANGE =100000; /** *Returns the user id for a given uid. *@hide */ public s

Google官方提供的有用的Android范例程序,值得学习的新技术

原文,Google官方blog. http://android-developers.blogspot.sg/2015/04/new-android-code-samples.html 这里有一些例子,涵盖了Android穿戴,NFC ,截屏 ,都已经提交到Google样列仓库的Github上. https://github.com/googlesamples 这有些代码列子. XYZTouristAttractions https://github.com/googlesamples/andr

学习心得——day1

今天是参加讲授的第一天.上午主要学习了一部分的DP选讲和线段树的运用,下午是练习测试.这里将今天所学的知识点做一个清理和总结消化. 上午 - DP选讲 Part 1 酱神寻宝(CDOJ1141) 题意: 酱神来到了一座小岛,岛上有n个箱子. 一共有3中不同的钥匙,金钥匙.银钥匙和万能钥匙.酱神一开始有a把金钥匙.b把银钥匙和c把万能钥匙. 第i个箱子上有xi把金锁,yi把银锁.金钥匙只能打开金锁,银钥匙只能打开银锁,万能钥匙两种锁都能打开.用于打开锁的钥匙会立刻损坏,酱神会丢掉损坏的钥匙.箱子里

Android应用程序UI硬件加速渲染技术简要介绍和学习计划

Android系统的流畅性一直被拿来与iOS比较,并且认为不如后者.这一方面与Android设备硬件质量参差不齐有关,另一方面也与Android系统的实现有关.例如在3.0前,Android应用程序UI绘制不支持硬件加速.不过从4.0开始,Android系统一直以"run fast, smooth, and responsively"为目标对UI进行优化.本文对这些优化进行简要介绍和制定学习计划. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!

Vue.js学习笔记:属性绑定 v-bind

v-bind  主要用于属性绑定,Vue官方提供了一个简写方式 :bind,例如: <!-- 完整语法 --> <a v-bind:href="url"></a> <!-- 缩写 --> <a :href="url"></a> 绑定HTML Class 一.对象语法: 我们可以给v-bind:class 一个对象,以动态地切换class.注意:v-bind:class指令可以与普通的class特

Java多线程学习(吐血超详细总结)

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线程状态转换 五线程调度 六常用函数说明 使用方式 为什么要用join方法 七常见线程名词解释 八线程同步 九线程数据传递 本文主要讲了java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用法.概述等. 首先讲一下进程和线程

微信小程序学习总结(2)------- 之for循环,绑定点击事件

最近公司有小程序的项目,本人有幸参与其中,一个项目做下来感觉受益匪浅,与大家做下分享,欢迎沟通交流互相学习. 先说一下此次项目本人体会较深的几个关键点:微信地图.用户静默授权.用户弹窗授权.微信充值等等. 言归正传,今天分享我遇到的关于wx:for循环绑定数据的一个tips:  1. 想必大家的都知道wx:for,如下就不用我啰嗦了: <view class="myNew" wx:for="{{list}}">{{item.title}}<view

【安全牛学习笔记】

弱点扫描 ╋━━━━━━━━━━━━━━━━━━━━╋ ┃发现弱点                                ┃ ┃发现漏洞                                ┃ ┃  基于端口五福扫描结果版本信息(速度慢)┃ ┃  搜索已公开的漏洞数据库(数量大)      ┃ ┃  使用弱点扫描器实现漏洞管理            ┃ ╋━━━━━━━━━━━━━━━━━━━━╋ [email protected]:~# searchsploit Usage:

winform学习日志(二十三)---------------socket(TCP)发送文件

一:由于在上一个随笔的基础之上拓展的所以直接上代码,客户端: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using Sys