You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:39:38