我们的云帆机器人(上面运行的安卓程序)有一个线下场景是商场,由于商场人多,总会遇到一些用户在我们的app里乱点,然后会跳出程序进入到系统设置的一些界面,这样很不友好。

比如程序中有一些需要输入文字的地方,弹出了输入法,有的用户就去故意点输入法的设置,结果就能进入到安卓的系统设置,商场的用户用的是我们机器人程序而不是手机,并且机器人上本来就屏蔽了多任务和返回等虚拟按键,结果无法返回原来的程序。

一种解决方式是自己在程序里去实现一个中文的输入法,但这代价也太大了。

另外一种方式就是使用安卓的Kiosk模式。这个模式直译的话是贩售亭,但实际上的意思是屏幕固定功能,也就是我们想要将用户看到的屏幕固定到我们的app中的意思。

介绍url https://www.sureshjoshi.com/mobile/android-kiosk-mode-without-root/

源码展示区:https://github.com/sureshjoshi/android-kiosk-example

中文介绍 https://juejin.im/entry/578f873dd342d30058e99c51

只看代码可能不太明白,于是我对着代码自己重新写了一个demo。其中遇到的问题如下:

1.写好了后运行代码,并不能锁住,主要原因是没有admin的权限,这个需要到设置--系统安全--设备管理 中找到这个程序并选中才可以。

2.另外就是有了admin权限后还是不能锁定,debug后发现是判断isDeviceOwnerApp的时候为false,这个是因为一个系统只能有一个OwnerApp,需要使用adb命令设置对应的recevier。命令是:

adb shell dpm set-device-owner com.honghe.screenlocktest/.AdminReceiver

3.注意这个功能只能安卓5.1之后可用

代码如下

MainActivity

 package com.honghe.screenlocktest;

 import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View; import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader; @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getName();
private DevicePolicyManager dpm;
private boolean inKioskMode;
private ComponentName deviceAdmin;
private Process process = null;
private DataOutputStream os = null; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
lockScreen();
}
});
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dislockScreen();
}
});
} private boolean doLockScreen() {
if (dpm.isLockTaskPermitted(this.getPackageName())) {
Log.i("yunji.HotelAPP", "start lock screen");
startLockTask();
inKioskMode = true;
Log.i("yunji.HotelAPP", "lock screen success");
return true;
}
Log.w("yunji.HotelAPP", "cannot lock screen");
return false;
} private void lockScreen() {
try {
if (!inKioskMode) {
dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
deviceAdmin = new ComponentName(this, AdminReceiver.class);
Log.e(TAG, "isAdminActive: " + dpm.isAdminActive(deviceAdmin) + "\tisDeviceOwnerApp: " + dpm.isDeviceOwnerApp(getPackageName()));
if (dpm.isDeviceOwnerApp(getPackageName())) {
//如果这里失效,请使用adb shell命令设置deviceOwnerAPP为当前app $ adb shell dpm set-device-owner com.honghe.screenlocktest/.AdminReceiver
//参考 https://juejin.im/entry/578f873dd342d30058e99c51
dpm.setLockTaskPackages(deviceAdmin,
new String[]{getPackageName()});
Log.e(TAG, "setLockTaskPackages: ");
}
doLockScreen();
}
} catch (Exception e) {
Log.e("yunji.HotelAPP", "Exception: " + e);
}
} private void dislockScreen() { try {
if (inKioskMode) {
stopLockTask();
inKioskMode = false;
}
} catch (Exception e) {
Log.e("yunji.HotelAPP", "Exception: " + e);
}
}
}

activity_main.xml

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> <Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="锁定" /> <Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="解锁" /> <EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name" /> </LinearLayout>

AdminReceiver.java

 package com.honghe.screenlocktest;
import android.app.admin.DeviceAdminReceiver;
import android.content.Context;
import android.content.Intent; /**
* Created by zkzhou on 7/15/16.
*/
public class AdminReceiver extends DeviceAdminReceiver {
@Override
public void onEnabled(Context context, Intent intent) {
} @Override
public CharSequence onDisableRequested(Context context, Intent intent) {
return "Warning: Device Admin is going to be disabled.";
} @Override
public void onDisabled(Context context, Intent intent) {
} @Override
public void onLockTaskModeEntering(Context context, Intent intent,
String pkg) {
} @Override
public void onLockTaskModeExiting(Context context, Intent intent) {
}
}

androidManifest.xml

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.honghe.screenlocktest"> <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".AdminReceiver"
android:label="@string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin" /> <intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
</application> </manifest>

xml/device_admin.xml

 <device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<force-lock/>
<watch-login/>
<disable-camera/>
<disable-keyguard-features/>
<encrypted-storage/>
<expire-password/>
<limit-password/>
<reset-password/>
<set-global-proxy/>
<wipe-data/>
</uses-policies>
</device-admin>

在Android上启用Kiosk模式的更多相关文章

  1. Android上实现MVP模式的途径

    今天我想分享我在Android上实现MVP(Model-View-Presenter)模式的方法.如果你对MVP模式还不熟悉,或者不了解为什么要在Android应用中使用MVP模式,推荐你先阅读这篇维 ...

  2. [手机取证] 绕过屏幕锁定启用调试模式-For Android 4.4.2

    Google在Android 4.x中引入了调试信任机制,类似于iOS,在设备有屏幕密码的情况下首次连接(或未记住计算机)的情况下, 需要首先打开屏幕锁定后才可进行调试启用操作. 在Android 4 ...

  3. Android真机测试、乐视手机启用开发者模式

    一.乐视手机启用开发者模式 1.进入 设置>关于手机,连续按5次,进入开发者模式 显示结果如下: 2.启用开发者模式,并且要启用USB调试 3.在VS中部署或调试Android引用,使用真机测试 ...

  4. 如何调试 Android 上 HTTP(S) 流量

    http://greenrobot.me/devpost/how-to-debug-http-and-https-traffic-on-android/ 如何调试 Android 上 HTTP(S) ...

  5. 在Android上使用qemu-user运行可执行文件

    在Android上使用qemu-user运行可执行文件 作者:寻禹@阿里聚安全 前言 QEMU简要介绍: QEMU可以解释执行可执行程序.既然QEMU可以解释执行可执行程序,那么QEMU就能够知道执行 ...

  6. 《C#微信开发系列(1)-启用开发者模式》

    1.0启用开发者模式 ①填写服务器配置 启用开发模式需要先成为开发者,而且编辑模式和开发模式只能选择一个(进入微信公众平台=>开发=>基本配置)就可以看到以下的界面: 点击修改配置,会出现 ...

  7. Android上的MVP:如何组织显示层的内容

    MVP(Model View Presenter)模式是著名的MVC(Model View Controller)模式的一个演化版本,目前它在Android应用开发中越来越重要了,大家也都在讨论关于M ...

  8. ZT 理解 Android 上的安全性

    理解 Android 上的安全性 http://www.ibm.com/developerworks/cn/xml/x-androidsecurity/ 利用沙箱.应用程序签名和权限增强应用程序安全性 ...

  9. 【转】Android 当打开“开发者模式”中的“不保留活动”后,程序应当怎么保持正常运行

    当打开这个设置以后,程序的Activity会自动销毁,每次返回的时候就会不断重oncreate,此时伴随的问题多多. 参考文档:http://www.bubuko.com/infodetail-960 ...

随机推荐

  1. POJ 1742 Coins 【多重背包DP】

    题意:有n种面额的硬币.面额.个数分别为A_i.C_i,求最多能搭配出几种不超过m的金额? 思路:dp[j]就是总数为j的价值是否已经有了这种方法,如果现在没有,那么我们就一个个硬币去尝试直到有,这种 ...

  2. python全栈开发day50-jquery之ajax、XmlHttpRquest

    一.昨日内容回顾 1.jquery位置信息 width() ..,innetWidth() .outWidth() offset().top left scrollTop 2.事件流 DOM2级 (1 ...

  3. python全栈开发day17-常用模块collections,random,time,os,sys,序列化(json pickle shelve)

    1.昨日内容回顾 1.正则表达式     # 正则表达式 —— str           # 检测字符串是否符合要求     # 从大段的文字中找到符合要求的内容 1).元字符 #. # 匹配除换行 ...

  4. Codeforces 460D Little Victor and Set(看题解)

    Little Victor and Set 其他都很好求, 只有k == 3的时候很难受.. 我们找到第一个不大于l的 t, 答案为 l, 3 * t, (3 * t) ^ l 感觉好像是对的, 感觉 ...

  5. Codeforces Round #317 (div 2)

    Problem A Arrays 思路:水一水. #include<bits/stdc++.h> using namespace std; ; int n1,n2,k,m,a[N],b[N ...

  6. 关于tomcat性能优化

    前言 关于 Tomcat 性能调优,一直以来就是运维面试的一个重要话题.今天我们就简单聊聊 Tomcat 如何进行性能优化? 首先声明,我不会去说 Tomcat 是什么,内部结构,原理什么的.我不懂. ...

  7. BZOJ2325 [ZJOI2011]道馆之战 树链剖分 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2325 题意概括 给你一棵N个点的树,树上的每个节点有A,B两块区域,且每种区域有两种状态:可以走的 ...

  8. poj3259 Wormholes (判负环)【spfa】(模板)

    <题目链接> 题目大意: John的农场里N块地,M条路连接两块地,W个虫洞,虫洞是一条单向路,会在你离开之前把你传送到目的地,就是当你过去的时候时间会倒退Ts.我们的任务是知道会不会在从 ...

  9. python的os模块总结

    python的os模块总结 目录 常用方法和属性总结 文件操作 目录操作 常用方法和属性总结 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir(&quo ...

  10. ESLint + lint-staged 禁用老项目中的es6

    前言 ESLint作为插件化的javascript代码检测工具,为我们的平时的开发保驾护航,好处就不多说了详情查看官网. 问题 有这么一个五年前开发的老项目,机缘巧合到了我们这边来维护. 项目是zep ...