Android中的自助服务terminal模式
我正在评估是否以及如何将CF .NET企业应用程序移植到Android设备上运行。 Windows Mobile手机上的应用程序在Kiosk模式下运行,应用程序在启动后以全屏模式自动启动,用户无法意外或无意地访问手机的任何其他部分。
是否有可能在启动后只有一个应用程序自动启动,并防止用户意外(或自愿)访问Android设备的任何其他部分?
您可以通过侦听BroadcastReceiver中的android.intent.action.BOOT_COMPLETED
意图,在启动时自动启动应用程序,并从那里启动您的Activity。 在活动中,您可以将自己注册为新的默认主屏幕[1]并处理按键。
我认为有些情况下,如果不修改框架,就无法处理(例如,在Home上显示longpress以显示当前活动的应用程序) – 但我也可能会误解。
但是对于一个足够的原型来说。
玩得开心!
[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>
您可以自定义(禁止访问菜单,限制应用程序添加等)来启用信息亭。 http://code.google.com/p/android-launcher-plus/
在新的Android L预览版中,Google已经宣布了“ 任务locking” ,而这正是如此。 它似乎需要root然而。
L Developer Preview引入了一个新的任务lockingAPI,可让您暂时限制用户离开您的应用程序或被通知中断。 例如,如果您正在开发教育应用程序以支持Android上的高风险评估要求,则可以使用此function。 一旦您的应用程序激活此模式,用户将无法看到通知,访问其他应用程序或返回到主屏幕,直到您的应用程序退出该模式。
为了防止未经授权的使用,只有授权的应用程序可以激活任务锁 此外,任务locking授权必须由专门configuration的设备所有者应用通过
android.app.admin.DevicePolicyManager.setLockTaskComponents()
方法授予。要设置设备所有者,请按照下列步骤操作:
- 将运行Android
userdebug
构build的设备附加到您的开发机器上。- 安装设备所有者应用
- 创build一个
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
在应用程序中使用任务lockingAPI之前,请通过调用DevicePolicyManager.isLockTaskPermitted()来validation您的活动是否已获得授权。
要激活任务locking,请从授权活动调用
android.app.Activity.startLockTask()
。当任务locking处于活动状态时,以下行为将生效:
- 状态栏为空,用户通知和状态信息被隐藏。
- Home和Recent Appsbutton被隐藏。
- 其他应用可能不会启动新的活动。
- 目前的应用程序可能会开始新的活动,只要这样做不会创造新的任务。
- 用户保持locking在您的应用程序,直到授权的活动调用
Activity.stopLockTask()
。
找了一段时间后,我想出了一个很好的解决scheme。 这只适用于固定的设备,但我想如果只是为了这个应用程序,然后生根不应该是一个问题。
-
通过添加您的应用程序启动器
<category android:name="android.intent.category.HOME" />
到你的意图filter
-
确保你的应用程序崩溃的工具栏,所以你不能到达通知栏请参阅如何以编程方式禁用android上的状态栏/通知栏? 或http://blog.vogella.com/2011/02/28/android-hidding-the-status-and-title-bar/
-
然后停止任何其他程序打开错误使用Accessibility服务来检查窗口状态改变,比较包白色或黑色列表,并使用ActivityManager.killBackgroundProcesses杀死,如果它不应该运行。
另外请查看http://thebitplague.wordpress.com/2013/04/05/kiosk-mode-on-the-nexus-7/
设置 Android开发者的单一用途设备页面描述了这个事情,你可以很容易地从那里知道更多的东西。
现在很容易将Android 6.0 Marshmallow和更高版本的设备configuration为公司拥有的一次性(COSU)设备。
启动您的应用程序
最好的方法是将你的应用程序设置为启动器
<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>
locking您的应用程序
最可靠的方法是使用棒棒糖或更大的设备,并利用
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! } }
一旦你有一个未configuration的设备,你可以从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(); }
谷歌最近发布了Androidpipe理API ,可以为任何运行Android 5.1或更高版本的Android设备轻松设置Kiosk模式,并设置各种其他策略。
在这个论坛发帖find另一种可能的技术。 引用该post:
使用以下方法可以构build一个应用程序,防止“普通”用户使用除应用程序之外的任何其他应用程序。
该应用程序由两个模块组成。 主要活动和一项服务。 该服务被configuration为在启动时启动。 当服务启动时,它检查活动是否正在运行。 如果未运行,则使用定时器启动主要活动。
当活动暂停时,它会安排服务在一秒钟内启动:代码:
Sub Activity_Pause (UserClosed As Boolean) If kiosk Then StartServiceAt(KioskService, DateTime.Now + 1 * DateTime.TicksPerSecond, false) End Sub
如果用户在主屏幕上按下,则主屏幕将出现几秒钟。 但是,您的应用程序将在几秒钟后返回到前端,用户将无法与任何其他应用程序交互或更改设置。
该服务被设置为前台服务。 这可以防止Android终止我们的服务。 按停止button可以停用信息亭模式。
似乎还有一个示例kiosk模式代码ZIP文件可供下载 。
Xposed框架可以做到这一点。 它需要根,而且有可能不会在所有的平台上工作。 在类android.app.StatusBarManager中查找disable()方法。
在这里Android的源代码
在这里看看如何编写自己的模块: Xposed开发教程
乍一看比你想象的要容易得多。 祝你好运!
除了使用BOOT接收器设置您的应用程序以及防止状态栏扩展的这个答案之外 ,该解决scheme还可以作为完整的自助服务terminal应用程序在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); } } }); }
这将完全隐藏后退button,应用程序和主页button。