我正在评估是否可以以及如何将CF .NET企业应用程序移植到Android设备上运行。Windows Mobile手机上的应用程序以信息亭模式运行,在该模式下,应用程序在启动后以全屏模式自动启动,并且用户无法意外或自愿访问手机的任何其他部分。
Android能否在启动后仅自动启动一个应用程序,并防止用户意外(或自愿)访问Android设备的任何其他部分?
我正在评估是否可以以及如何将CF .NET企业应用程序移植到Android设备上运行。Windows Mobile手机上的应用程序以信息亭模式运行,在该模式下,应用程序在启动后以全屏模式自动启动,并且用户无法意外或自愿访问手机的任何其他部分。
Android能否在启动后仅自动启动一个应用程序,并防止用户意外(或自愿)访问Android设备的任何其他部分?
Answers:
您可以在启动时通过侦听android.intent.action.BOOT_COMPLETED
BroadcastReceiver中的意图来自动启动应用程序,然后从那里开始您的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宣布了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()
。
搜索了一段时间后,我提出了一个好的解决方案。虽然这仅适用于有根设备,但我想如果只是针对这个应用程序,则将其生根应该不是问题。
通过添加将您的应用程序启动
<category android:name="android.intent.category.HOME" />
到您的意图过滤器
确保您的应用折叠了工具栏,以使您无法到达通知栏,请参阅如何以编程方式在android上禁用状态栏/通知栏?或http://blog.vogella.com/2011/02/28/android-hidding-the-status-and-title-bar/
然后,要阻止任何其他程序错误地打开,请使用辅助功能服务来检查“窗口状态已更改”,将程序包与白名单或黑名单进行比较,并使用ActivityManager.killBackgroundProcesses杀死不应运行的程序。
还可以通过其他方式查看http://thebitplague.wordpress.com/2013/04/05/kiosk-mode-on-the-nexus-7/
最好的方法是将您的应用设置为启动器
<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();
}
Google最近发布了Android Management API,该API可以轻松为运行Android 5.1或更高版本的所有Android设备设置信息亭模式,还可以设置其他各种策略。
设置单一用途的设备页面 android开发人员已经描述了这些内容,您可以从那里轻松了解更多内容。
现在,可以轻松地将Android 6.0棉花糖和更高版本的设备配置为公司拥有的一次性(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);
}
}
});
}
这将完全隐藏后退按钮,应用程序和主页按钮。