Android Studio,信息亭模式,单一用途设备,锁定任务模式 [英] Android Studio, Kiosk mode, Single-Purpose Devices, Lock Task mode
问题描述
我正在尝试创建一个单一用途的应用程序. 因此,我创建了一个BaseActivity,我所有的活动都继承自它.
看起来像
public class LockDeviceActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
private void startLock() {
if(mDevicePolicyManager.isLockTaskPermitted(getPackageName())) {
/**
* If lock task is permitted, we can lock the task. We can use an external DPM like
* TestDPC provided by Google to manage lock task list.
*
* If the lock is obtained using TestDPC, features like status bar, home button, recent
* apps, etc is disabled.
*
* To unlock we can programatically call stopLockTask() when users taps a button. But
* in practice this should be done using a separate admin console or Confirm Credential.
*
* For API 23+ you can check if the lock is active by checking if
* activityManager.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_NONE
*/
Log.d(TAG, "startLock() called");
this.startLockTask();
} else {
/**
* The device is not whitelisted.
*/
Toast.makeText(this, "The app is not whitelisted for lock", Toast.LENGTH_SHORT).show();
// Timber.d("The app is not whitelisted for lock task");
/**
* We can still pin the app but it will not be locked.
*
* We can simply unlock by pressing recent and back button together.
*
* Unlocking by calling stopLockTask() on button click can be achieved as well.
*/
// Timber.d("just pinning the app");
this.startLockTask();
}
}
因此,当我第一次进入应用程序时,我可以看到一些固定的消息,我也可以. 问题是,当我从一个活动到另一个包含Fragment的活动进行Intent时,我得到以下图像:
加上我收到了一些系统吐司消息: 该应用未列入锁定白名单"
如何避免这种行为? 谢谢你们 .
1)将设备重置为出厂默认设置
2)跳过帐户注册
3)安装应用程序然后关闭它
4)运行adb shell dpm set-device-owner <app-package-name>/.<AppAdminReceiver>
5)确保获得成功的结果.
6)重新启动应用程序.
必须满足以下条件:
AndroidManifest.xml
<activity
android:name=".AppActivity"
android:label="Locked Activity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<receiver
android:name=".AppAdminReceiver"
android:description="@string/app_name"
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_receiver" />
<intent-filter>
<action android:name="android.intent.action.DEVICE_ADMIN_ENABLED"/>
<action android:name="android.intent.action.PROFILE_PROVISIONING_COMPLETE"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
创建一个名为AppAdminReceiver.java
的新Java类(可以将其保留为空白)
public class AppAdminReceiver extends android.app.admin.DeviceAdminReceiver {
}
在/res/xml
目录中添加device_admin_receiver.xml
<?xml version="1.0" encoding="utf-8"?>
<device-admin>
<uses-policies>
<disable-keyguard-features/>
</uses-policies>
</device-admin>
在AppActivity.java
中调用startLockTask()
和stopLockTask()
private ComponentName mAdminComponentName;
private DevicePolicyManager mDevicePolicyManager;
...
... onCreate(){
// Retrieve Device Policy Manager so that we can check whether we can
// lock to screen later
mAdminComponentName = new ComponentName(this,AppAdminReceiver.class);
mDevicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
if(mDevicePolicyManager.isDeviceOwnerApp(getPackageName())){
// App is whitelisted
setDefaultCosuPolicies(true);
}
else {
// did you provision the app using <adb shell dpm set-device-owner ...> ?
}
}
... onStart(){
// Consider locking your app here or by some other mechanism
// Active Manager is supported on Android M
if(mDevicePolicyManager.isLockTaskPermitted(this.getPackageName())){
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
if (am.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_NONE) {
setDefaultCosuPolicies(true);
startLockTask();
}
}
}
... unlockApp(){
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
if (am.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_LOCKED) {
stopLockTask();
}
setDefaultCosuPolicies(false);
}
private void setDefaultCosuPolicies(boolean active){
// Set user restrictions
setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, active);
setUserRestriction(UserManager.DISALLOW_FACTORY_RESET, active);
setUserRestriction(UserManager.DISALLOW_ADD_USER, active);
setUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, active);
setUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME, active);
// Disable keyguard and status bar
mDevicePolicyManager.setKeyguardDisabled(mAdminComponentName, active);
mDevicePolicyManager.setStatusBarDisabled(mAdminComponentName, active);
// Enable STAY_ON_WHILE_PLUGGED_IN
enableStayOnWhilePluggedIn(active);
// Set system update policy
if (active){
mDevicePolicyManager.setSystemUpdatePolicy(mAdminComponentName,SystemUpdatePolicy.createWindowedInstallPolicy(60, 120));
} else {
mDevicePolicyManager.setSystemUpdatePolicy(mAdminComponentName,null);
}
// set this Activity as a lock task package
mDevicePolicyManager.setLockTaskPackages(mAdminComponentName,active ? new String[]{getPackageName()} : new String[]{});
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MAIN);
intentFilter.addCategory(Intent.CATEGORY_HOME);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
if (active) {
// set Cosu activity as home intent receiver so that it is started
// on reboot
mDevicePolicyManager.addPersistentPreferredActivity(mAdminComponentName, intentFilter, new ComponentName(getPackageName(), AppActivity.class.getName()));
} else {
mDevicePolicyManager.clearPackagePersistentPreferredActivities(mAdminComponentName, getPackageName());
}
}
private void setUserRestriction(String restriction, boolean disallow){
if (disallow) {
mDevicePolicyManager.addUserRestriction(mAdminComponentName,restriction);
} else {
mDevicePolicyManager.clearUserRestriction(mAdminComponentName,restriction);
}
}
private void enableStayOnWhilePluggedIn(boolean enabled){
if (enabled) {
mDevicePolicyManager.setGlobalSetting(mAdminComponentName,Settings.Global.STAY_ON_WHILE_PLUGGED_IN,Integer.toString(BatteryManager.BATTERY_PLUGGED_AC| BatteryManager.BATTERY_PLUGGED_USB| BatteryManager.BATTERY_PLUGGED_WIRELESS));
} else {
mDevicePolicyManager.setGlobalSetting(mAdminComponentName,Settings.Global.STAY_ON_WHILE_PLUGGED_IN,"0");
}
}
}
I'm trying to create a single purpose app. So I have create an BaseActivity that all my activities inherit from it.
it's look like
public class LockDeviceActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
private void startLock() {
if(mDevicePolicyManager.isLockTaskPermitted(getPackageName())) {
/**
* If lock task is permitted, we can lock the task. We can use an external DPM like
* TestDPC provided by Google to manage lock task list.
*
* If the lock is obtained using TestDPC, features like status bar, home button, recent
* apps, etc is disabled.
*
* To unlock we can programatically call stopLockTask() when users taps a button. But
* in practice this should be done using a separate admin console or Confirm Credential.
*
* For API 23+ you can check if the lock is active by checking if
* activityManager.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_NONE
*/
Log.d(TAG, "startLock() called");
this.startLockTask();
} else {
/**
* The device is not whitelisted.
*/
Toast.makeText(this, "The app is not whitelisted for lock", Toast.LENGTH_SHORT).show();
// Timber.d("The app is not whitelisted for lock task");
/**
* We can still pin the app but it will not be locked.
*
* We can simply unlock by pressing recent and back button together.
*
* Unlocking by calling stopLockTask() on button click can be achieved as well.
*/
// Timber.d("just pinning the app");
this.startLockTask();
}
}
so when I first Enter the app, I can see some Pinned message and it's okay by me. The problem is, when I'm doing an Intent from one activity to other Activity which contain Fragment, I'm getting the following image :
plus i'm getting a some system toast message : " the app is not whitelisted for lock "
how can I avoid this kind of behavior ? thank you all .
1) Reset device to factory default
2) Skip Account registration
3) Install the app then close it
4) Run adb shell dpm set-device-owner <app-package-name>/.<AppAdminReceiver>
5) Make sure you get a successful result.
6) Re-launch the app.
The following must be satisfied:
AndroidManifest.xml
inside application
tag
<activity
android:name=".AppActivity"
android:label="Locked Activity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<receiver
android:name=".AppAdminReceiver"
android:description="@string/app_name"
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_receiver" />
<intent-filter>
<action android:name="android.intent.action.DEVICE_ADMIN_ENABLED"/>
<action android:name="android.intent.action.PROFILE_PROVISIONING_COMPLETE"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Create a new Java Class named AppAdminReceiver.java
(it's fine to leave it blank)
public class AppAdminReceiver extends android.app.admin.DeviceAdminReceiver {
}
Add device_admin_receiver.xml
in /res/xml
directory
<?xml version="1.0" encoding="utf-8"?>
<device-admin>
<uses-policies>
<disable-keyguard-features/>
</uses-policies>
</device-admin>
In AppActivity.java
calling startLockTask()
and stopLockTask()
private ComponentName mAdminComponentName;
private DevicePolicyManager mDevicePolicyManager;
...
... onCreate(){
// Retrieve Device Policy Manager so that we can check whether we can
// lock to screen later
mAdminComponentName = new ComponentName(this,AppAdminReceiver.class);
mDevicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
if(mDevicePolicyManager.isDeviceOwnerApp(getPackageName())){
// App is whitelisted
setDefaultCosuPolicies(true);
}
else {
// did you provision the app using <adb shell dpm set-device-owner ...> ?
}
}
... onStart(){
// Consider locking your app here or by some other mechanism
// Active Manager is supported on Android M
if(mDevicePolicyManager.isLockTaskPermitted(this.getPackageName())){
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
if (am.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_NONE) {
setDefaultCosuPolicies(true);
startLockTask();
}
}
}
... unlockApp(){
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
if (am.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_LOCKED) {
stopLockTask();
}
setDefaultCosuPolicies(false);
}
private void setDefaultCosuPolicies(boolean active){
// Set user restrictions
setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, active);
setUserRestriction(UserManager.DISALLOW_FACTORY_RESET, active);
setUserRestriction(UserManager.DISALLOW_ADD_USER, active);
setUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, active);
setUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME, active);
// Disable keyguard and status bar
mDevicePolicyManager.setKeyguardDisabled(mAdminComponentName, active);
mDevicePolicyManager.setStatusBarDisabled(mAdminComponentName, active);
// Enable STAY_ON_WHILE_PLUGGED_IN
enableStayOnWhilePluggedIn(active);
// Set system update policy
if (active){
mDevicePolicyManager.setSystemUpdatePolicy(mAdminComponentName,SystemUpdatePolicy.createWindowedInstallPolicy(60, 120));
} else {
mDevicePolicyManager.setSystemUpdatePolicy(mAdminComponentName,null);
}
// set this Activity as a lock task package
mDevicePolicyManager.setLockTaskPackages(mAdminComponentName,active ? new String[]{getPackageName()} : new String[]{});
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MAIN);
intentFilter.addCategory(Intent.CATEGORY_HOME);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
if (active) {
// set Cosu activity as home intent receiver so that it is started
// on reboot
mDevicePolicyManager.addPersistentPreferredActivity(mAdminComponentName, intentFilter, new ComponentName(getPackageName(), AppActivity.class.getName()));
} else {
mDevicePolicyManager.clearPackagePersistentPreferredActivities(mAdminComponentName, getPackageName());
}
}
private void setUserRestriction(String restriction, boolean disallow){
if (disallow) {
mDevicePolicyManager.addUserRestriction(mAdminComponentName,restriction);
} else {
mDevicePolicyManager.clearUserRestriction(mAdminComponentName,restriction);
}
}
private void enableStayOnWhilePluggedIn(boolean enabled){
if (enabled) {
mDevicePolicyManager.setGlobalSetting(mAdminComponentName,Settings.Global.STAY_ON_WHILE_PLUGGED_IN,Integer.toString(BatteryManager.BATTERY_PLUGGED_AC| BatteryManager.BATTERY_PLUGGED_USB| BatteryManager.BATTERY_PLUGGED_WIRELESS));
} else {
mDevicePolicyManager.setGlobalSetting(mAdminComponentName,Settings.Global.STAY_ON_WHILE_PLUGGED_IN,"0");
}
}
}
Similar tutorial on setting up kiosk mode
这篇关于Android Studio,信息亭模式,单一用途设备,锁定任务模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!