• 在Android上启用Kiosk模式


    我们的云帆机器人(上面运行的安卓程序)有一个线下场景是商场,由于商场人多,总会遇到一些用户在我们的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

     1 package com.honghe.screenlocktest;
     2 
     3 import android.app.admin.DevicePolicyManager;
     4 import android.content.ComponentName;
     5 import android.content.Context;
     6 import android.os.Build;
     7 import android.support.annotation.RequiresApi;
     8 import android.support.v7.app.AppCompatActivity;
     9 import android.os.Bundle;
    10 import android.util.Log;
    11 import android.view.View;
    12 
    13 import java.io.BufferedReader;
    14 import java.io.DataOutputStream;
    15 import java.io.InputStream;
    16 import java.io.InputStreamReader;
    17 
    18 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    19 public class MainActivity extends AppCompatActivity {
    20     private static final String TAG = MainActivity.class.getName();
    21     private DevicePolicyManager dpm;
    22     private boolean inKioskMode;
    23     private ComponentName deviceAdmin;
    24     private Process process = null;
    25     private DataOutputStream os = null;
    26 
    27     @Override
    28     protected void onCreate(Bundle savedInstanceState) {
    29         super.onCreate(savedInstanceState);
    30         setContentView(R.layout.activity_main);
    31         findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
    32             @Override
    33             public void onClick(View v) {
    34                 lockScreen();
    35             }
    36         });
    37         findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
    38             @Override
    39             public void onClick(View v) {
    40                 dislockScreen();
    41             }
    42         });
    43     }
    44 
    45 
    46     private boolean doLockScreen() {
    47         if (dpm.isLockTaskPermitted(this.getPackageName())) {
    48             Log.i("yunji.HotelAPP", "start lock screen");
    49             startLockTask();
    50             inKioskMode = true;
    51             Log.i("yunji.HotelAPP", "lock screen success");
    52             return true;
    53         }
    54         Log.w("yunji.HotelAPP", "cannot lock screen");
    55         return false;
    56     }
    57 
    58     private void lockScreen() {
    59         try {
    60             if (!inKioskMode) {
    61                 dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
    62                 deviceAdmin = new ComponentName(this, AdminReceiver.class);
    63                 Log.e(TAG, "isAdminActive: " + dpm.isAdminActive(deviceAdmin) + "	isDeviceOwnerApp: " + dpm.isDeviceOwnerApp(getPackageName()));
    64                 if (dpm.isDeviceOwnerApp(getPackageName())) {
    65                     //如果这里失效,请使用adb shell命令设置deviceOwnerAPP为当前app $ adb shell dpm set-device-owner com.honghe.screenlocktest/.AdminReceiver
    66                     //参考 https://juejin.im/entry/578f873dd342d30058e99c51
    67                     dpm.setLockTaskPackages(deviceAdmin,
    68                             new String[]{getPackageName()});
    69                     Log.e(TAG, "setLockTaskPackages: ");
    70                 }
    71                 doLockScreen();
    72             }
    73         } catch (Exception e) {
    74             Log.e("yunji.HotelAPP", "Exception: " + e);
    75         }
    76     }
    77 
    78     private void dislockScreen() {
    79 
    80         try {
    81             if (inKioskMode) {
    82                 stopLockTask();
    83                 inKioskMode = false;
    84             }
    85         } catch (Exception e) {
    86             Log.e("yunji.HotelAPP", "Exception: " + e);
    87         }
    88     }
    89 }

    activity_main.xml

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     xmlns:app="http://schemas.android.com/apk/res-auto"
     4     xmlns:tools="http://schemas.android.com/tools"
     5     android:layout_width="match_parent"
     6     android:layout_height="match_parent"
     7     android:orientation="vertical"
     8     tools:context=".MainActivity">
     9 
    10     <TextView
    11         android:layout_width="wrap_content"
    12         android:layout_height="wrap_content"
    13         android:text="Hello World!"
    14         app:layout_constraintBottom_toBottomOf="parent"
    15         app:layout_constraintLeft_toLeftOf="parent"
    16         app:layout_constraintRight_toRightOf="parent"
    17         app:layout_constraintTop_toTopOf="parent" />
    18 
    19     <Button
    20         android:id="@+id/button"
    21         android:layout_width="wrap_content"
    22         android:layout_height="wrap_content"
    23         android:text="锁定" />
    24 
    25     <Button
    26         android:id="@+id/button2"
    27         android:layout_width="wrap_content"
    28         android:layout_height="wrap_content"
    29         android:text="解锁" />
    30 
    31     <EditText
    32         android:id="@+id/editText"
    33         android:layout_width="match_parent"
    34         android:layout_height="wrap_content"
    35         android:ems="10"
    36         android:inputType="textPersonName"
    37         android:text="Name" />
    38 
    39 </LinearLayout>

    AdminReceiver.java

     1 package com.honghe.screenlocktest;
     2 import android.app.admin.DeviceAdminReceiver;
     3 import android.content.Context;
     4 import android.content.Intent;
     5 
     6 
     7 /**
     8  * Created by zkzhou on 7/15/16.
     9  */
    10 public class AdminReceiver extends DeviceAdminReceiver {
    11     @Override
    12     public void onEnabled(Context context, Intent intent) {
    13     }
    14 
    15     @Override
    16     public CharSequence onDisableRequested(Context context, Intent intent) {
    17         return "Warning: Device Admin is going to be disabled.";
    18     }
    19 
    20     @Override
    21     public void onDisabled(Context context, Intent intent) {
    22     }
    23 
    24     @Override
    25     public void onLockTaskModeEntering(Context context, Intent intent,
    26                                        String pkg) {
    27     }
    28 
    29     @Override
    30     public void onLockTaskModeExiting(Context context, Intent intent) {
    31     }
    32 }

    androidManifest.xml

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     3     package="com.honghe.screenlocktest">
     4 
     5     <application
     6         android:allowBackup="true"
     7         android:icon="@mipmap/ic_launcher"
     8         android:label="@string/app_name"
     9         android:roundIcon="@mipmap/ic_launcher_round"
    10         android:supportsRtl="true"
    11         android:theme="@style/AppTheme">
    12         <activity android:name=".MainActivity">
    13             <intent-filter>
    14                 <action android:name="android.intent.action.MAIN" />
    15 
    16                 <category android:name="android.intent.category.LAUNCHER" />
    17             </intent-filter>
    18         </activity>
    19         <receiver
    20             android:name=".AdminReceiver"
    21             android:label="@string/app_name"
    22             android:permission="android.permission.BIND_DEVICE_ADMIN">
    23             <meta-data
    24                 android:name="android.app.device_admin"
    25                 android:resource="@xml/device_admin" />
    26 
    27             <intent-filter>
    28                 <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
    29             </intent-filter>
    30         </receiver>
    31     </application>
    32 
    33 
    34 </manifest>

    xml/device_admin.xml

     1 <device-admin xmlns:android="http://schemas.android.com/apk/res/android">
     2     <uses-policies>
     3         <force-lock/>
     4         <watch-login/>
     5         <disable-camera/>
     6         <disable-keyguard-features/>
     7         <encrypted-storage/>
     8         <expire-password/>
     9         <limit-password/>
    10         <reset-password/>
    11         <set-global-proxy/>
    12         <wipe-data/>
    13     </uses-policies>
    14 </device-admin>
  • 相关阅读:
    zookeeper配置
    redis前端启动和后台启动的区别
    SpringMVC接受JSON参数详解及常见错误总结我改
    SpringMVC @RequestBody接收Json对象字符串
    spring MVC 如何接收前台传入的JSON对象数组
    springMVC 接收json字符串参数
    mysql数据库user表host字段的%问题
    mysql.user表中Host为%的含义
    开店攻略: 零售店铺经营的三大原则
    开店攻略: 如何巧妙接近顾客
  • 原文地址:https://www.cnblogs.com/dongweiq/p/10250180.html
Copyright © 2020-2023  润新知