I have created a separate Activity for kiosk mode
The main idea is to deliver this task from other activities and keep the lock task always in the root of stack
View.post(...)
and similar with magic delay is not working for me
onResume()
method with checking isFinishing()
works fine, but be careful with clear task flag
<style name="AppTheme.Transparent" parent="android:style/Theme.Translucent.NoTitleBar.Fullscreen">
<item name="android:colorPrimary">@color/colorPrimary</item>
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="android:colorAccent">@color/colorAccent</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
class LockActivity : Activity() {
private lateinit var adminManager: AdminManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
adminManager = AdminManager(applicationContext)
}
override fun onStart() {
super.onStart()
when (activityManager.lockTaskModeState) {
ActivityManager.LOCK_TASK_MODE_NONE -> {
if (true/*IT IS NEEDED*/) {
if (adminManager.setKioskMode(true)) {
// need startLockTask on resume
return
} else {
//toast("HAVE NO OWNER RIGHTS")
}
}
launchActivity()
finish()
}
ActivityManager.LOCK_TASK_MODE_LOCKED -> {
if (false/*IT IS NOT NEEDED*/) {
if (adminManager.setKioskMode(false)) {
stopLockTask()
launchActivity()
finish()
return
} else {
//toast("HAVE NO OWNER RIGHTS")
}
}
launchActivity()
}
else -> finishAffinity()
}
}
override fun onResume() {
super.onResume()
if (!isFinishing) {
if (activityManager.lockTaskModeState == ActivityManager.LOCK_TASK_MODE_NONE) {
startLockTask()
launchActivity()
}
}
}
private fun launchActivity() {
// todo startActivity depending on business logic
}
override fun onBackPressed() {}
}
class AdminManager(context: Context) {
private val adminComponent = ComponentName(context, AdminReceiver::class.java)
private val deviceManager = context.devicePolicyManager
private val packageName = context.packageName
@Suppress("unused")
val isAdmin: Boolean
get() = deviceManager.isAdminActive(adminComponent)
val isDeviceOwner: Boolean
get() = deviceManager.isDeviceOwnerApp(packageName)
fun setKioskMode(enable: Boolean): Boolean {
if (isDeviceOwner) {
setRestrictions(enable)
deviceManager.setKeyguardDisabled(adminComponent, enable)
setLockTask(enable)
return true
}
return false
}
/**
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
private fun setRestrictions(enable: Boolean) {
arrayOf(
UserManager.DISALLOW_FACTORY_RESET,
UserManager.DISALLOW_SAFE_BOOT,
UserManager.DISALLOW_ADD_USER
).forEach {
if (enable) {
deviceManager.addUserRestriction(adminComponent, it)
} else {
deviceManager.clearUserRestriction(adminComponent, it)
}
}
}
/**
* @throws SecurityException if {@code admin} is not the device owner, the profile owner of an
* affiliated user or profile, or the profile owner when no device owner is set.
*/
private fun setLockTask(enable: Boolean) {
if (enable) {
deviceManager.setLockTaskPackages(adminComponent, arrayOf(packageName))
} else {
deviceManager.setLockTaskPackages(adminComponent, arrayOf())
}
}
}