我开发了一个设备所有者应用程序(完整信息亭),并在锁定任务模式下,一旦安装在已配置的设备上,便被指示将其设置在屏幕顶部。
直到一天前,一切都还不错,在某些设备上,固件升级后,出现了问题。
[在设备启动(或重新启动)时,应用会在其上方的PIN屏幕上自行打开,因此它停止了设备启动,因为我无法再插入PIN,并且该屏幕占据了主屏幕(并且仅)活动。
通常,启动顺序为:
但是在这种情况下,只要设备在PIN锁定屏幕上直接启动,应用程序就可以自行打开。
我在manifest.xml
中剩下的唯一接收器(我已删除所有其他接收器,但App仍会自行打开):
<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锁定屏幕,相反,重要的是将其绑定为在发生不良事件(例如,启动,重新引导,默认操作)时处于打开状态,...)
解决方案的实现如下:
我已从AdminController中删除:
intentFilter.addCategory(Intent.CATEGORY_HOME);
与[相关 devicePolicyManager.addPersistentPreferredActivity(•)
(并且还要添加以确保正确重置)
devicePolicyManager.clearPackagePersistentPreferredActivities(
adminComponentName, context.getPackageName());
并且也从我的清单中删除:
<category android:name="android.intent.category.HOME" />
P.S。我发现动作BOOT_COMPLETED并非总是正确地传递(甚至与QUICKBOOT_POWERON一起使用),所以这就是我使用CATEGORY_HOME意图的原因。
我更改了以前的解决方案。
由于BOOT_COMPLETED的事实在Android系统中无法如此经济地触发,同样由于Android安全策略,即使该应用程序处于Device Owner COSU模式(锁定任务),我也必须恢复到CATEGORY_HOME的意图。
因此,为了解决我以前的问题,我发现这是由于该应用在PIN锁定屏幕下处于后台时调用startLockTask
引起的,通常该应用会停留在该屏幕下的活动中。我只需要添加以下检查,以确保仅当屏幕解锁时该应用程序才会被锁定。
KeyguardManager myKM = (KeyguardManager) this.getSystemService(Context.KEYGUARD_SERVICE);
if( !myKM.inKeyguardRestrictedInputMode() && MyApp.getInstance().isAppInForeground() ) {
adminController.lockApp(this);
}