Android Kiosk 模式
又是用户的需求,实现Kiosk模式,让设备只运行他想要的程序。之前做过一种是自动隐藏底部所有按键,可以看我之前的博客隐藏底部按键
但是这种方式还是有缺陷,虽然也能实现想要的模式,总感觉,很不满意。这次想要实现Android原本就有的Kiosk模式。
在Android中有两种模式对我们非常有用
DeviceAdmin设备管理
- DeviceOwner设备所有者
当然还有一种模式ProfileOwner(配置文件所有者),这种模式看了一下资料说国内不好用,暂时不管,因为今天讲的也用不上。
先说设备管理模式
Android 2.2通过提供Android设备管理API引入了对企业应用程序的支持。设备管理API提供了系统级的设备管理功能。这些api允许您创建安全感知的应用程序,这些应用程序在企业设置中非常有用,在企业设置中,IT专业人员需要对员工设备进行丰富的控制。例如,内置的Android电子邮件应用程序利用了新的api来改进Exchange支持。通过电子邮件应用程序,Exchange管理员可以跨设备强制执行密码策略——包括字母数字密码或数字pin。管理员还可以远程擦除(即恢复出厂默认值)丢失或被盗的手机。Exchange用户可以同步他们的电子邮件和日历数据。 ——来自有道翻译官方Android文档。哈哈哈哈哈哈哈
代码实现如下
在AndroidManifest.xml文件中添加<receiverandroid:name=".AdminReceiver"android:label="@string/app_name"android:permission="android.permission.BIND_DEVICE_ADMIN"><meta-dataandroid:name="android.app.device_admin"android:resource="@xml/device_admin" /><intent-filter><action android:name="android.app.action.DEVICE_ADMIN_ENABLED" /></intent-filter></receiver>
上面的receiver的name就是我们要创建的类名
public class AdminReceiver extends DeviceAdminReceiver {@Overridepublic void onReceive(Context context, Intent intent) {super.onReceive(context, intent);LogUtil.d("设备管理=onReceive");}@Overridepublic CharSequence onDisableRequested(Context context, Intent intent) {LogUtil.d("设备管理=onDisableRequested");return super.onDisableRequested(context, intent);}@Overridepublic void onDisabled(Context context, Intent intent) {super.onDisabled(context, intent);LogUtil.d("设备管理=onDisabled");}@Overridepublic void onEnabled(Context context, Intent intent) {super.onEnabled(context, intent);LogUtil.d("设备管理=onEnabled");//可以在此处进行跳转,但是不好处理其他的逻辑,暂时保留,后面会说其他跳转Intent itn = new Intent(context,MainActivity.class);itn.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(itn);}
}
其中还有一个xml文件,声明元数据中使用的安全策略。元数据提供特定于设备管理员的附加信息,由DeviceAdminInfo类解析
device_admin示例:
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android"><!-- 指定设备超级管理员所拥有的权限 --><uses-policies><!--停用相机--><disable-camera/><!--锁屏时禁用某些功能--><disable-keyguard-features/><!--设置存储设备加密--><encrypted-storage/><!--设置锁定屏幕密码的有效期--><expire-password/><!--锁定屏幕--><force-lock/><!--设置密码规则--><limit-password/><!--更改屏幕解锁密码--><reset-password/><!-- <!–设置设备全局代理–><set-global-proxy/>--><!--监控屏幕解锁尝试次数--><watch-login/><!--恢复出厂设置--><wipe-data/></uses-policies>
</device-admin>
当然你也可以创建一个空的<device-admin>文件。不需要设置管理的权限
好了,需要的文件已经准备好了,现在是开始触发该模式的方式了
先通过代码判断我们的包名app是否已经处在设备管理者模式状态下
private DevicePolicyManager dpm;private ComponentName componentName;dpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); componentName = new ComponentName(context, AdminReceiver.class);dpm.isAdminActive(componentName);//判断是否已经是设备管理者模式了,返回boolean。
当我们进入闪屏页时,进行判断。
if(isAdminActive()){startMain();//跳转主页面的逻辑 }else {satrtOpenDevicer();//主动询问设备管理者权限的逻辑 }
public void satrtOpenDevicer() {ComponentName componentName = new ComponentName(this, AdminReceiver.class);Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "请求设备管理权限...");/** 不能直接startActivity 因为可能在激活的时候用户点击了取消,这时候CheckBox状态是勾选的,但是实际是没激活的,*/startActivityForResult(intent, DEVICECOMPONENTCODE);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);Log.e("jsb_kiosk","结果"+requestCode);if(requestCode == DEVICECOMPONENTCODE){startMain();}}
这个时候当我们处于没有设备管理权限时进入app都会进行询问权限,界面如下:
好了处于设备模式后,就该处理DeviceOwner设备所有者
在这里查看大神写的比较完整的介绍
Android 提供了比较完善的设备所有者api,但是我发现调用的那些api效果完全没有作用,
ComponentName deviceAdmin = new ComponentName(this, AdminReceiver.class);
mDpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
if (!mDpm.isAdminActive(deviceAdmin)) {Toast.makeText(this, "没有设备管理权限", Toast.LENGTH_SHORT).show();}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {if (mDpm.isDeviceOwnerApp(getPackageName())) {mDpm.setLockTaskPackages(deviceAdmin, new String[]{getPackageName()});} else {Log.i("jsb_","没有专属模式");}}
上面代码没有效果。我们通过mDpm.isDeviceOwnerApp去判断当前是否处于设备所有者的是没有效果的。
但是通过adb shell处理设备确实可以进入Kiosk模式,
命令adb shell dpm set-device-owner 包名/包名.
AdminReceiver (跟你创建的AdminReceiver地址一样)设置DeviceOwner;
命令adb shell dpm remove-active-admin 包名/包名.
AdminReceiver 退出DeviceOwner;
那么我们只要通过代码实现该操作命令就可以了
private void execShell(String cmd){try{java.lang.Process p = Runtime.getRuntime().exec("sh");OutputStream outputStream = p.getOutputStream();DataOutputStream dataOutputStream=new DataOutputStream(outputStream);dataOutputStream.writeBytes(cmd);dataOutputStream.flush();dataOutputStream.close();outputStream.close();} catch(Throwable t) {t.printStackTrace();}}
调用:
execShell("adb shell dpm set-device-owner "+getPackageName()+"/"+AdminReceiver.class.getName());
至于在什么时候调用该命令,就看个人需要,我是在闪屏页获取设备管理者后直接调用的
@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);Log.e("jsb_kiosk","结果"+requestCode);if(requestCode == DEVICECOMPONENTCODE){execShell("adb shell dpm set-device-owner "+getPackageName()+"/"+AdminReceiver.class.getName());startMain();}}
好了通过上面的操作,我们已经完全进入DeviceOwner设备所有者模式了
但是并没有完事,还差最后一步,真正的完成Kiosk模式
调用下面方法
private void enableKioskMode(boolean enabled) {try {if (enabled) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {if (mDpm.isLockTaskPermitted(this.getPackageName())) {startLockTask();mIsKioskEnabled = true;} else {//没有进入该模式,没有权限}}} else {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {stopLockTask();}mIsKioskEnabled = false;}} catch (Exception e) {// TODO: Log and handle appropriately}}
最后看效果吧
点击进入改模式
ok,感觉很不错~~今天就到这里了,有空我上传一下demo,下班了。
Android Kiosk 模式相关推荐
- android Run模式也会出现Waiting for debugger的解决方法
android Run模式也会出现"Waiting for debugger"的解决方法 出现"waiting for debugger"窗口是在debug模式 ...
- Android MVP模式 简单易懂的介绍方式
主要学习这位大神的博客:简而易懂 Android MVP模式 简单易懂的介绍方式 https://segmentfault.com/a/1190000003927200 转载于:https://www ...
- android eng 模式,android 4.0 编译模式 eng - user 时遇到的有关问题
android 4.0 编译模式 eng -- > user 时遇到的问题 关键词:android 4.0 user eng camera nand 串口 平台信息: 内核:linu ...
- android返回后屏幕旋转了,Android recovery 模式下屏幕显示旋转
Android recovery 模式下屏幕显示旋转 大家在网上搜索 Android屏幕旋转,成千上万的文章,但是没有几个是写recovery 模式的.难道你们只旋转正常模式下的屏幕方向,不管reco ...
- android doze模式源码分析,Android Doze模式启用和恢复详解
从Android 6.0(API level 23)开始,Android提出了两个延长电池使用时间的省电特性给用户.用户管理可以在没有充电的情况下管理app的行为.当用户一段时间没有使用手机的时候,D ...
- Android MVC模式
Android MVC模式 [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/51172105 前些天看到 ...
- windows 10下的kiosk模式
windows 10下的kiosk模式可以保证windows 10 开机自动运行某个程序,且全屏,除了按alt + del + ctrl组合键退出外,按鼠标.键盘不能见到任何window系统下的任何界 ...
- android mvp模式
越来越多人讨论mvp模式,mvp在android应用开发中获得更多的重视,这里说一下对MVP的简单了解. 什么是 MVP? MVP模式使逻辑从视图层分开,目的是我们在屏幕上怎么表现,和界面如何工作的所 ...
- Android MVP模式简单易懂的介绍方式 (一)
Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 最近正在研究Android的MVP模式 ...
- Android夜间模式实践
前言 由于项目需要,近段时间开发的夜间模式功能.主流的方案如下: 1.通过切换theme实现 2.通过resource id映射实现 3.通过Android Support Library的实现 方案 ...
最新文章
- 你真的会写二分查找吗?
- eclipse开发项目关于内存是如何分配的
- 安装MindStudio
- windows下安装TensorFlow(清华镜像)
- oracle数据库优化--基本概念
- Angular项目构建指南 - 不再为angular构建而犹豫不决(转)
- iis负载均衡与文件同步[网摘]
- linux c之((void *) - 1)是啥意思
- 前端学习(3345):设计模式之工厂模式2
- python绘制社会关系网络图_Python networkx 网络图绘制
- http协议(十)实体首部字段
- 「平衡树splay」学习笔记#1
- c语言 桌面下雪程序,用C++写的在桌面上飘雪的特效程序
- 晶振封装与频率对照表
- Kindle刷安卓双系统的方法
- x86 x64 IA64的关系和区别
- 小学语文经典好词好句好段
- java经典题丨有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总对数为多少?
- excel 表格怎么让内容回车换行?
- windows不安装虚拟机如何使用Linux系统作为开发工具?