又是用户的需求,实现Kiosk模式,让设备只运行他想要的程序。之前做过一种是自动隐藏底部所有按键,可以看我之前的博客隐藏底部按键

但是这种方式还是有缺陷,虽然也能实现想要的模式,总感觉,很不满意。这次想要实现Android原本就有的Kiosk模式。

在Android中有两种模式对我们非常有用

  1. DeviceAdmin设备管理

  2. 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/><!-- &lt;!&ndash;设置设备全局代理&ndash;&gt;<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 模式相关推荐

  1. android Run模式也会出现Waiting for debugger的解决方法

    android Run模式也会出现"Waiting for debugger"的解决方法 出现"waiting for debugger"窗口是在debug模式 ...

  2. Android MVP模式 简单易懂的介绍方式

    主要学习这位大神的博客:简而易懂 Android MVP模式 简单易懂的介绍方式 https://segmentfault.com/a/1190000003927200 转载于:https://www ...

  3. android eng 模式,android 4.0 编译模式 eng - user 时遇到的有关问题

    android 4.0 编译模式 eng -- > user 时遇到的问题 关键词:android  4.0  user  eng  camera  nand  串口 平台信息: 内核:linu ...

  4. android返回后屏幕旋转了,Android recovery 模式下屏幕显示旋转

    Android recovery 模式下屏幕显示旋转 大家在网上搜索 Android屏幕旋转,成千上万的文章,但是没有几个是写recovery 模式的.难道你们只旋转正常模式下的屏幕方向,不管reco ...

  5. android doze模式源码分析,Android Doze模式启用和恢复详解

    从Android 6.0(API level 23)开始,Android提出了两个延长电池使用时间的省电特性给用户.用户管理可以在没有充电的情况下管理app的行为.当用户一段时间没有使用手机的时候,D ...

  6. Android MVC模式

    Android MVC模式     [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/51172105       前些天看到 ...

  7. windows 10下的kiosk模式

    windows 10下的kiosk模式可以保证windows 10 开机自动运行某个程序,且全屏,除了按alt + del + ctrl组合键退出外,按鼠标.键盘不能见到任何window系统下的任何界 ...

  8. android mvp模式

    越来越多人讨论mvp模式,mvp在android应用开发中获得更多的重视,这里说一下对MVP的简单了解. 什么是 MVP? MVP模式使逻辑从视图层分开,目的是我们在屏幕上怎么表现,和界面如何工作的所 ...

  9. Android MVP模式简单易懂的介绍方式 (一)

    Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 最近正在研究Android的MVP模式 ...

  10. Android夜间模式实践

    前言 由于项目需要,近段时间开发的夜间模式功能.主流的方案如下: 1.通过切换theme实现 2.通过resource id映射实现 3.通过Android Support Library的实现 方案 ...

最新文章

  1. 你真的会写二分查找吗?
  2. eclipse开发项目关于内存是如何分配的
  3. 安装MindStudio
  4. windows下安装TensorFlow(清华镜像)
  5. oracle数据库优化--基本概念
  6. Angular项目构建指南 - 不再为angular构建而犹豫不决(转)
  7. iis负载均衡与文件同步[网摘]
  8. linux c之((void *) - 1)是啥意思
  9. 前端学习(3345):设计模式之工厂模式2
  10. python绘制社会关系网络图_Python networkx 网络图绘制
  11. http协议(十)实体首部字段
  12. 「平衡树splay」学习笔记#1
  13. c语言 桌面下雪程序,用C++写的在桌面上飘雪的特效程序
  14. 晶振封装与频率对照表
  15. Kindle刷安卓双系统的方法
  16. x86 x64 IA64的关系和区别
  17. 小学语文经典好词好句好段
  18. java经典题丨有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总对数为多少?
  19. excel 表格怎么让内容回车换行?
  20. windows不安装虚拟机如何使用Linux系统作为开发工具?

热门文章

  1. MFC——Listcontrol 添加背景颜色
  2. 关于Entity FrameWork获取插入后的自增ID
  3. 新生代公链再攻「不可能三角」
  4. the owning Session was closed
  5. 离散数学学习笔记——命题逻辑
  6. LeetCode 1101. The Earliest Moment When Everyone Become Friends
  7. oracle+归档时间设置,oracle 归档设置
  8. windows 环境下 0x色彩对应表
  9. 国企安逸?我笑了……
  10. 数字IC入门基础(汇总篇)