我正在评估是否以及如何将 CF .NET 企业应用程序移植到 Android 设备上运行。Windows Mobile 手机上的应用程序在 kiosk 模式下运行,其中应用程序在启动后以全屏模式自动启动,用户无法意外或自愿访问手机的任何其他部分。
在 Android 上是否有可能在启动后只有一个应用程序自动启动并防止用户意外(或自愿)访问 Android 设备的任何其他部分?
我正在评估是否以及如何将 CF .NET 企业应用程序移植到 Android 设备上运行。Windows Mobile 手机上的应用程序在 kiosk 模式下运行,其中应用程序在启动后以全屏模式自动启动,用户无法意外或自愿访问手机的任何其他部分。
在 Android 上是否有可能在启动后只有一个应用程序自动启动并防止用户意外(或自愿)访问 Android 设备的任何其他部分?
您可以通过侦听android.intent.action.BOOT_COMPLETED
BroadcastReceiver 中的意图在启动时自动启动应用程序并从那里启动您的 Activity。在 Activity 中,您可以将自己注册为新的默认主屏幕 [1] 并处理按键。
我认为有些情况在不修改框架的情况下是无法处理的(比如在主页上长按以显示当前活动的应用程序)——不过我也可能弄错了。
但是对于一个原型来说就足够了。
玩得开心修补!
[1]:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
在新的 Android L Preview 中,谷歌宣布了Task Locking,它正是这样做的。但是,它似乎确实需要root。
L Developer Preview 引入了一个新的任务锁定 API,可让您暂时限制用户离开您的应用程序或被通知打断。例如,如果您正在开发一个教育应用程序来支持 Android 上的高风险评估要求,则可以使用此方法。一旦您的应用激活此模式,用户将无法查看通知、访问其他应用或返回主屏幕,直到您的应用退出该模式。
为防止未经授权的使用,只有授权的应用程序才能激活任务锁定。此外,任务锁定授权必须由专门配置的设备所有者应用程序通过该
android.app.admin.DevicePolicyManager.setLockTaskComponents()
方法授予。要设置设备所有者,请按以下步骤操作:
- 将运行 Android
userdebug
构建的设备连接到您的开发机器。- 安装您的设备所有者应用程序。
- 创建一个
device_owner.xml
文件并将其保存到/data/system
设备上的目录中。
$ adb root
$ adb shell stop
$ rm /tmp/device_owner.xml
$ echo "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>" >> /tmp/device_owner.xml
$ echo "&device-owner package=\"<your_device_owner_package>\" name=\"*<your_organization_name>\" />" >> /tmp/device_owner.xml
$ adb push /tmp/device_owner.xml /data/system/device_owner.xml
$ adb reboot
在您的应用程序中使用任务锁定 API 之前,请通过调用 DevicePolicyManager.isLockTaskPermitted() 验证您的活动是否已获得授权。
要激活任务锁定,请
android.app.Activity.startLockTask()
从您的授权活动中调用。当任务锁定处于活动状态时,以下行为生效:
- 状态栏为空白,隐藏用户通知和状态信息。
- 主页和最近的应用程序按钮被隐藏。
- 其他应用程序可能不会启动新活动。
- 当前应用程序可能会启动新的活动,只要这样做不会创建新任务。
- 用户在您的应用程序上保持锁定状态,直到授权的活动调用
Activity.stopLockTask()
。
您可以对此进行自定义(禁用对菜单的访问、限制应用程序添加等)以启用信息亭。http://code.google.com/p/android-launcher-plus/
After searching for this for a while I've come up with a good solution. This only works on rooted devices though, but I guess if it's just for this one app then rooting it shouldn't be a problem.
Make your application the launcher by adding
<category android:name="android.intent.category.HOME" />
to your intent-filter
Make sure your app collapses the toolbar so you cannot reach the notification bar see How to disable status bar / notification bar on android programmatically? or http://blog.vogella.com/2011/02/28/android-hidding-the-status-and-title-bar/
Then to stop any other programs from opening by mistake use an Accessibility Service to check for Window State Changed, compare the package to a white or black list and use ActivityManager.killBackgroundProcesses to kill if it shouldn't run.
Also check out http://thebitplague.wordpress.com/2013/04/05/kiosk-mode-on-the-nexus-7/ for another way
谷歌最近发布了Android Management API,它允许为任何运行 Android 5.1 或更高版本的 Android 设备轻松设置信息亭模式,并设置各种其他策略。
实现此目的的最佳方法是将您的应用设置为启动器
<activity ...
android:launchMode="singleInstance"
android:windowActionBar="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
最可靠的方法是使用带有 Lollipop 或更高版本的设备,并使用
startLockTask
首先,您必须将您的应用设置为设备所有者。注意您的设备必须未配置:如果您注册了它,您应该恢复出厂设置并跳过帐户注册。
为了能够注册您的应用程序,您必须首先设置一个 DeviceAdminReceiver 组件:
package com.example.myapp;
public class MyDeviceAdminReceiver extends android.app.admin.DeviceAdminReceiver {
@Override
public void onEnabled(Context context, Intent intent) {
Toast.makeText(context, "Device admin permission received", Toast.LENGTH_SHORT).show();
}
@Override
public CharSequence onDisableRequested(Context context, Intent intent) {
return "are you sure?";
}
@Override
public void onDisabled(Context context, Intent intent) {
Toast.makeText(context, "Device admin permission revoked", Toast.LENGTH_SHORT).show();
}
@Override
public void onLockTaskModeExiting(Context context, Intent intent) {
// here you must re-lock your app. make your activity know of this event and make it call startLockTask again!
}
}
一旦你有一个未配置的设备,你可以从 adb 启动以下命令(不需要 root)
adb shell dpm set-device-owner com.example.myapp/.MyDeviceAdminReceiver
为了避免 android 询问用户权限来固定您的应用程序,您必须调用 setLockTaskPackages
最后!
@Override
public void onResume(){
super.onResume();
DevicePolicyManager mDevicePolicyManager = (DevicePolicyManager) getSystemService(
Context.DEVICE_POLICY_SERVICE);
ComponentName mAdminComponentName = new ComponentName(getApplicationContext(), MyDeviceAdminReceiver.class);
mDevicePolicyManager.setLockTaskPackages(mAdminComponentName, new String[]{getPackageName()});
startLockTask();
}
@Override
public void finish(){
stopLockTask();
super.finish();
}
安卓开发者的设置单一用途设备页面已经描述了这些事情,您可以从那里轻松了解更多事情。
现在可以轻松地将Android 6.0 Marshmallow 及更高版本的设备配置为企业拥有的一次性 (COSU) 设备。
在这个论坛帖子中发现了另一种可能的技术。引用那个帖子:
使用以下方法,您可以构建一个应用程序,该应用程序将阻止“普通”用户使用您的应用程序以外的任何东西。
该应用程序由两个模块组成。主要活动和服务。该服务配置为在引导时启动。当服务启动时,它会检查活动是否正在运行。如果它没有运行,它会使用一个计时器来启动主要活动。
当活动暂停时,它会安排服务在一秒钟内启动:代码:
Sub Activity_Pause (UserClosed As Boolean)
If kiosk Then StartServiceAt(KioskService, DateTime.Now + 1 * DateTime.TicksPerSecond, false)
End Sub
如果用户按下主屏幕,主屏幕将出现几秒钟。但是,您的应用程序将在几秒钟后返回到前面,用户将无法与任何其他应用程序交互或更改设置。
该服务设置为前台服务。这可以防止 Android 杀死我们的服务。按下停止按钮以停用信息亭模式。
似乎也有一个示例信息亭模式代码 ZIP 文件可供下载。
Xposed 框架可以做到这一点。它需要root,并且有可能无法在所有平台上运行。在android.app.StatusBarManager类中查找disable()方法。
看这里如何编写自己的模块: Xposed开发教程
乍一看,这比您想象的要容易得多。祝你好运!
除了使用 BOOT 接收器设置您的应用程序以及防止状态栏扩展的答案外,此解决方案还可以在 4.4 及更高版本上作为完整的信息亭应用程序运行:
放置在您的 onCreate() 中:
final View view = (View) findViewById(android.R.id.content);
if (view != null) {
//"hides" back, home and return button on screen.
view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_IMMERSIVE |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
View.SYSTEM_UI_FLAG_FULLSCREEN);
view.setOnSystemUiVisibilityChangeListener
(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
// Note that system bars will only be "visible" if none of the
// LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set.
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_IMMERSIVE |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
View.SYSTEM_UI_FLAG_FULLSCREEN);
}
}
});
}
这将完全隐藏后退按钮、应用程序和主页按钮。
Kiosk 模式只不过是在您打开 Android 设备时锁定单个或一组应用程序。这可以通过锁定任务模式来实现。当设备在锁定任务模式下运行时,用户通常无法看到通知、访问未列入白名单的应用程序或返回主屏幕。
设备策略控制器 (DPC) 可以将系统处于锁定任务模式时可以运行的应用列入白名单。由于它是用于特定目的的专用设备,因此使用该设备的人无法离开锁定任务模式。Android 5.0 及更高版本的设备可以在锁定任务模式下运行。
• Whitelisting the applications
第一步是通过 DPC 将应用程序列入白名单。DPC可以通过调用将可以在锁定任务模式下使用的应用程序列入白名单
DevicePolicyManager.setLockTaskPackages()
▪ Start lock task mode
完成白名单后,DPC 可以调用以下函数来启动锁定任务。
ActivityOptions.setLockTaskEnabled()
您可以在此处找到有关锁定任务模式的更多详细信息。https://developer.android.com/work/dpc/dedicated-devices/lock-task-mode