Android Kiosk模式下使用Kotlin实现状态栏图标显示及锁屏状态保留状态栏信息的技术问询
Hey there! Let's tackle this problem step by step—keeping the status bar visible (with battery, Wi-Fi, and time) in your Kiosk-mode Android app, even when the device is locked, using Kotlin.
核心前提
Kiosk mode typically restricts system UI access, but we can tweak permissions, window flags, and system UI settings to carve out an exception for the status bar while maintaining your app's auto-launch and lockscreen behavior.
1. 第一步:更新AndroidManifest.xml
先添加必要权限,并配置启动Activity使其能在锁屏状态下正常显示:
权限配置
在manifest根节点添加以下权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
启动Activity配置
修改主Activity的配置,允许它在锁屏时显示:
<activity android:name=".MainActivity" android:launchMode="singleTask" android:showOnLockScreen="true" android:showWhenLocked="true" android:turnScreenOn="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
2. Kotlin代码控制状态栏可见性
接下来在Activity中实现逻辑,确保状态栏在Kiosk模式下保持可见。我们同时提供现代(Android 11+)和旧版本兼容的API。
现代方案(Android 11+,API 30+)
使用WindowInsetsController实现更简洁的控制:
override fun onResume() { super.onResume() setupPersistentStatusBar() } private fun setupPersistentStatusBar() { window.apply { // 显式显示状态栏 insetsController?.show(WindowInsets.Type.statusBars()) // 确保应用布局不会覆盖状态栏(可根据需求调整) decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // 设置状态栏透明,避免遮挡应用内容 statusBarColor = Color.TRANSPARENT // 锁屏相关标记 addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD) addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) } }
旧版本兼容方案(Android 10及以下)
如果需要支持旧设备,使用传统的SystemUiVisibility API:
private fun setupPersistentStatusBarLegacy() { window.apply { // 保持状态栏可见 decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN statusBarColor = Color.TRANSPARENT // 锁屏相关标记 addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD) addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) } }
3. 调整Kiosk模式策略(若使用DevicePolicyManager)
如果你的Kiosk模式是通过DevicePolicyManager实现的,确保没有设置隐藏状态栏的限制。检查DeviceAdminReceiver的配置,移除相关限制:
val devicePolicyManager = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager val adminComponent = ComponentName(this, YourDeviceAdminReceiver::class.java) if (devicePolicyManager.isAdminActive(adminComponent)) { // 清除任何隐藏状态栏的限制 devicePolicyManager.clearRestrictions(adminComponent, UserManager.DISALLOW_STATUS_BAR) }
4. 确保状态栏图标正常显示
为了让电池、Wi-Fi和时间图标清晰可见,调整应用主题:
- 使用不隐藏状态栏的主题(例如
Theme.MaterialComponents.DayNight.NoActionBar) - 在
styles.xml的主题中添加以下属性:
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <item name="android:statusBarColor">@android:color/transparent</item> <item name="android:windowLightStatusBar">true</item> <!-- 浅色状态栏下显示深色图标 --> </style>
排查技巧
- 如果状态栏仍不显示,检查是否有第三方MDM工具或其他Kiosk软件覆盖了你的设置
- 确认
SYSTEM_ALERT_WINDOW权限已授予(Android 6+需要动态申请) - 在锁屏设备上测试,验证电池、Wi-Fi和时间图标是否正常显示
内容的提问来源于stack exchange,提问作者ahmed cheema




