设备所有者"Kiosk"应用程序在BOOT_COMPLETED之前启动,锁定任务将替换 PIN 密码的用户锁定屏幕



我开发了一个设备所有者应用程序(完整展台(,在锁定任务模式下,一旦安装在预配的设备上,就会指示它将自己设置在屏幕顶部。

一切都很好,直到一天前,在某些设备上,在固件升级后,出现了问题。

  • 设备: 黑景 BV6000
  • 安卓: 8 奥利奥 (API l. 26(

在设备启动(或重新启动(时,应用程序会在 PIN 屏幕上自行打开,因此它会停止设备启动,因为我无法再插入我的 PIN,并且它占据屏幕作为主要(也是唯一的(活动。

通常,引导顺序为:

  • LOCK_BOOT_COMPLETED
  • BOOT_COMPLETED
  • 应用启动

但在这种情况下,一旦设备直接在 PIN 锁定屏幕上启动,该应用程序在任何情况下都会自行打开。

我留在manifest.xml中的唯一接收器(我已经删除了所有其他接收器,但应用程序仍然会自行打开(:

<receiver
android:name=".receivers.AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="AlarmReceiver" />
</intent-filter>
</receiver>

在我看来,这是由于以下事实引起的:作为警报,它在通常的情况下总是等待交付,一旦设备启动,我的应用程序就会收到警报意图,因此它会唤醒警报接收器,这样做,它肯定会唤醒整个应用程序,它将被设置为设备所有者并处于lock task模式,所以我得到的是我的应用程序进入前台在我实际做任何事情并强迫我使用它之前,在 PIN 锁定屏幕上。

此外,该应用程序通过以下行设置为启动器:

IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MAIN);
intentFilter.addCategory(Intent.CATEGORY_HOME);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
devicePolicyManager.addPersistentPreferredActivity(
adminComponentName, intentFilter, new ComponentName(
context.getPackageName(), MyActivity.class.getName()));

另外,我通过以下方式禁用键盘锁:

devicePolicyManager.setKeyguardDisabled(adminComponentName, true);

我的问题是:如何防止应用程序在 PIN 锁定屏幕上进入前台?我想让我的应用程序在锁定屏幕后打开(在真实BOOT_COMPLETE上(,但我不知道如何在应用程序获得警报意图后阻止它启动。

经过一番调查,我找到了问题的根源。

解决方案是不要将应用程序作为 HOME 应用程序打开,以便它会覆盖某些设备上的 PIN 锁定屏幕,相反,重要的是将其绑定为在预定事件(即启动、重新启动、默认操作等(上打开

解决方案的实现如下:

我从我的管理控制器中删除了:

intentFilter.addCategory(Intent.CATEGORY_HOME);

devicePolicyManager.addPersistentPreferredActivity(•)相关

(并添加以确保正确重置(

devicePolicyManager.clearPackagePersistentPreferredActivities(
adminComponentName, context.getPackageName());

并且还从我的清单中删除:

<category android:name="android.intent.category.HOME" />

附言我发现该操作BOOT_COMPLETED并不总是正确传递(即使将其与QUICKBOOT_POWERON一起使用(,因此这就是我使用CATEGORY_HOME意图的原因。

我更改了以前的解决方案。

由于BOOT_COMPLETED在Android系统中不会如此经济地触发,也是由于Android安全策略,即使应用程序处于设备所有者COSU模式(锁定任务(,我也必须恢复到CATEGORY_HOME意图。

因此,为了解决我之前的问题,我发现这是由于当应用程序在PIN锁定屏幕下的后台运行时调用startLockTask引起的,并且通常它会停留在屏幕下方的活动上。我只需要添加如下检查,以确保只有在屏幕解锁时才会锁定应用程序。

KeyguardManager myKM = (KeyguardManager) this.getSystemService(Context.KEYGUARD_SERVICE);
if( !myKM.inKeyguardRestrictedInputMode() && MyApp.getInstance().isAppInForeground() ) {
adminController.lockApp(this);
}

相关内容

最新更新