Android原生应用开发:如何阻止用户切换应用/返回主屏幕?
实现类似闹钟响铃的锁定Activity方案
要实现这种禁止用户切换应用、返回主屏幕的锁定Activity,核心是利用系统窗口标记、全屏意图和辅助服务来拦截系统操作,以下是具体实现步骤:
1. 配置Manifest与主题
首先在AndroidManifest.xml中声明必要权限、配置Activity主题和辅助服务:
<!-- 声明权限 --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" /> <!-- 锁定Activity配置 --> <activity android:name=".LockActivity" android:theme="@style/FullScreenLockTheme" android:excludeFromRecents="true" android:launchMode="singleInstance" /> <!-- 辅助服务注册 --> <service android:name=".LockAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config" /> </service>
在res/values/styles.xml中定义全屏主题:
<style name="FullScreenLockTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <item name="android:windowFullscreen">true</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowShowWallpaper">true</item> <item name="android:windowDisablePreview">true</item> </style>
2. Activity核心逻辑实现
在LockActivity中设置窗口标记、拦截返回键、监听焦点变化并拉回应用:
public class LockActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_lock); // 设置窗口标记:保持屏幕常亮、解锁锁屏、锁屏时显示 Window window = getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON); // 隐藏状态栏和导航栏 hideSystemBars(); // 启动全屏意图通知(增强系统优先级) startFullScreenNotification(); // 检查并请求辅助服务权限 if (!isAccessibilityServiceEnabled()) { requestAccessibilityPermission(); } } // 隐藏系统栏并设置沉浸式模式 private void hideSystemBars() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { getWindow().getInsetsController().hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars()); getWindow().getInsetsController().setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); } else { getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); } } // 启动全屏意图通知,确保Activity在系统层级优先显示 private void startFullScreenNotification() { // Android 8.0+ 创建通知渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel("LOCK_CHANNEL", "锁定通知", NotificationManager.IMPORTANCE_HIGH); NotificationManager manager = getSystemService(NotificationManager.class); manager.createNotificationChannel(channel); } Intent intent = new Intent(this, LockActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); Notification notification = new NotificationCompat.Builder(this, "LOCK_CHANNEL") .setSmallIcon(R.drawable.ic_launcher_foreground) .setContentTitle("应用锁定中") .setContentText("无法切换至其他应用") .setPriority(NotificationCompat.PRIORITY_HIGH) .setFullScreenIntent(pendingIntent, true) .build(); NotificationManagerCompat.from(this).notify(1, notification); } // 拦截返回键 @Override public void onBackPressed() { // 空实现,禁止返回操作 } // 失去焦点时拉回Activity @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (!hasFocus) { moveTaskToFront(getTaskId(), 0); hideSystemBars(); } } // 检查辅助服务是否开启 private boolean isAccessibilityServiceEnabled() { final String service = getPackageName() + "/" + LockAccessibilityService.class.getName(); int accessibilityEnabled = 0; try { accessibilityEnabled = Settings.Secure.getInt(getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED); } catch (Settings.SettingNotFoundException e) { e.printStackTrace(); } TextUtils.SimpleStringSplitter colonSplitter = new TextUtils.SimpleStringSplitter(':'); if (accessibilityEnabled == 1) { String settingValue = Settings.Secure.getString(getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); if (settingValue != null) { colonSplitter.setString(settingValue); while (colonSplitter.hasNext()) { String accessibilityService = colonSplitter.next(); if (accessibilityService.equalsIgnoreCase(service)) { return true; } } } } return false; } // 引导用户开启辅助服务权限 private void requestAccessibilityPermission() { Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS); startActivity(intent); } }
3. 辅助服务拦截系统导航
创建LockAccessibilityService来监听窗口切换事件,强制拉回锁定Activity:
public class LockAccessibilityService extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) { if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { ComponentName currentComponent = new ComponentName(event.getPackageName().toString(), event.getClassName().toString()); // 检查当前显示的是否为锁定Activity,否则强制拉回 if (!currentComponent.getClassName().equals(LockActivity.class.getName())) { Intent intent = new Intent(this, LockActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); } } } @Override public void onInterrupt() {} @Override protected void onServiceConnected() { super.onServiceConnected(); AccessibilityServiceInfo info = new AccessibilityServiceInfo(); info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED; info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; setServiceInfo(info); } }
在res/xml/accessibility_service_config.xml中配置辅助服务参数:
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeWindowStateChanged" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="flagDefault" android:canRetrieveWindowContent="true" android:description="@string/accessibility_desc" />
在res/values/strings.xml中添加辅助服务描述:
<string name="accessibility_desc">用于锁定应用,防止切换至其他应用或系统界面</string>
注意事项
- 辅助服务权限需要用户手动开启,应用无法自动获取,必须引导用户进入设置页面授权。
- 不同Android版本及国产ROM(如MIUI、EMUI)可能存在额外限制,需针对性测试适配。
- 无法完全拦截所有系统操作(如长按电源键强制关机),这是系统安全机制限制。
内容的提问来源于stack exchange,提问作者Layer891203
相关产品推荐
相关产品推荐

