Как создать Android Locker на Kotlin: можно ли написать

Многие разработчики, впервые задумываясь о создании приложения для блокировки экрана, задаются вопросом: возможно ли создать android locker на языке kotlin? Короткий ответ — да, но с важными ограничениями. Полноценный системный локер, который полностью заменяет встроенный экран блокировки Android, без root-прав или системных привилегий не сделать. Однако создать кастомный экран с PIN-кодом, графическим ключом или биометрией для защиты самого приложения или его отдельных функций — задача вполне выполнимая. В этой статье мы разберём оба подхода и напишем работающий пример.


Два типа локеров: что действительно можно сделать

Прежде чем погружаться в код, важно разграничить понятия. Под термином «Android Locker» могут скрываться два принципиально разных продукта: app locker и screen locker. Первый защищает доступ к выбранным приложениям, второй пытается заменить системный экран блокировки. Разница между ними определяет и требования к разрешениям, и саму возможность размещения в Google Play.

Характеристика App Locker (блокировщик приложений) Screen Locker (кастомный экран блокировки)
Как работает Отслеживает запуск выбранных приложений через UsageStats API или foreground service и показывает свой экран с запросом пароля Пытается отключить системный Keyguard и показать собственную Activity поверх локскрина
Системные разрешения PACKAGE_USAGE_STATS, FOREGROUND_SERVICE, SYSTEM_ALERT_WINDOW (опционально) Требует DevicePolicyManager или root-доступа для полного контроля
Допустим ли в Google Play Да, при корректной реализации Строго ограничен: Google пропускает только приложения с обоснованной необходимостью (например, корпоративные)
Сложность реализации Средняя Высокая, с риском блокировки аккаунта разработчика

Поэтому, когда мы говорим возможно ли создать android locker на языке kotlin, практический ответ такой: app locker — да, screen locker — только для корпоративного использования или экспериментальных проектов вне Google Play.


App Locker: создаём блокировщик приложений

App Locker — наиболее реалистичный сценарий для начинающего разработчика. Принцип работы сводится к трём шагам: получить список установленных приложений, отследить запуск выбранного приложения и показать экран с запросом кода. Для хранения пароля используется Room, для проверки — BiometricPrompt API или собственный PIN-экран.


Необходимые разрешения и зависимости

В AndroidManifest.xml нужно прописать два ключевых разрешения: PACKAGE_USAGE_STATS для доступа к статистике запуска приложений и FOREGROUND_SERVICE для работы фонового сервиса. Также добавьте разрешение на использование биометрии, если планируете разблокировку по отпечатку пальца.

<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />

В build.gradle.kts модуля app добавьте Room для хранения паролей и Biometric для fingerprint-аутентификации. Jetpack Compose для интерфейса ускорит разработку в разы.

dependencies {
    implementation("androidx.room:room-runtime:2.6.1")
    ksp("androidx.room:room-compiler:2.6.1")
    implementation("androidx.biometric:biometric:1.4.0")
    implementation("androidx.lifecycle:lifecycle-service:2.5.1")
}

Отслеживание запуска приложений

Сердце любого app locker — фоновый сервис, который периодически опрашивает UsageStatsManager и проверяет, не запущено ли сейчас заблокированное приложение. Частоту опроса стоит выбирать с умом: слишком частая проверка сажает батарею, слишком редкая — позволяет увидеть содержимое приложения до появления блокировки.

class LockerService : Service() {
    private lateinit var usageStatsManager: UsageStatsManager

    override fun onCreate() {
        super.onCreate()
        usageStatsManager = getSystemService(USAGE_STATS_SERVICE) as UsageStatsManager
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        checkForegroundApp()
        return START_STICKY
    }

    private fun checkForegroundApp() {
        val currentTime = System.currentTimeMillis()
        val stats = usageStatsManager.queryUsageStats(
            UsageStatsManager.INTERVAL_DAILY, currentTime - 1000, currentTime
        )
        val foregroundPackage = stats.maxByOrNull { it.lastTimeUsed }?.packageName
        // проверить, заблокировано ли это приложение, и показать LockScreenActivity
    }
}

Биометрическая аутентификация

Для современного локера пароль — не единственный способ защиты. BiometricPrompt API позволяет разблокировать приложение по отпечатку пальца или распознаванию лица. В Kotlin это реализуется лаконично:

val biometricPrompt = BiometricPrompt(
    this,
    ContextCompat.getMainExecutor(this),
    object : BiometricPrompt.AuthenticationCallback() {
        override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
            // разблокировать приложение
            finish()
        }
        override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
            // показать fallback на PIN
        }
    }
)

val promptInfo = BiometricPrompt.PromptInfo.Builder()
    .setTitle("Разблокировка")
    .setSubtitle("Подтвердите личность")
    .setNegativeButtonText("PIN")
    .build()

biometricPrompt.authenticate(promptInfo)

Screen Locker: почему это сложно

Создание кастомного экрана блокировки, который полностью заменяет системный, сопряжено с фундаментальными ограничениями Android. Начиная с API 15, метод KeyguardManager.KeyguardLock.disableKeyguard() объявлен устаревшим, а его использование на современных версиях Android может приводить к непредсказуемому поведению. Официальная документация рекомендует использовать вместо него Activity.setShowWhenLocked(true) в сочетании с флагом окна FLAG_SHOW_WHEN_LOCKED.

Этот подход позволяет вашему Activity отображаться поверх системного локскрина, но не отключает системную блокировку полностью. Для корпоративных устройств существует DevicePolicyManager с методом setKeyguardDisabled(), но он требует прав администратора устройства и не предназначен для массового распространения через Play Store.


Jetpack Compose для экрана блокировки

Современный способ создания UI для локера — Jetpack Compose. Он позволяет за несколько десятков строк написать стильный экран с анимациями ввода PIN-кода. Открытый проект ComposeLockScreen на GitHub демонстрирует именно такой подход: Material 3, тёмная и светлая темы, анимации при вводе и проверке кода. Вот минимальный пример PIN-экрана на Compose:

@Composable
fun PinLockScreen(onSuccess: () -> Unit) {
    var pin by remember { mutableStateOf("") }
    val maxLength = 4

    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Text("Введите PIN", style = MaterialTheme.typography.headlineMedium)
        Spacer(modifier = Modifier.height(24.dp))
        // индикатор введённых цифр
        Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
            repeat(maxLength) { index ->
                val filled = index < pin.length
                Box(
                    modifier = Modifier
                        .size(16.dp)
                        .background(
                            if (filled) MaterialTheme.colorScheme.primary
                            else Color.Gray,
                            shape = CircleShape
                        )
                )
            }
        }
        Spacer(modifier = Modifier.height(32.dp))
        // сетка цифровых кнопок
        val keys = listOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "⌫")
        LazyVerticalGrid(columns = GridCells.Fixed(3)) {
            items(keys) { key ->
                if (key.isNotEmpty()) {
                    Button(onClick = {
                        if (key == "⌫") pin = pin.dropLast(1)
                        else if (pin.length < maxLength) pin += key
                        if (pin.length == maxLength) onSuccess()
                    }) {
                        Text(key, fontSize = 20.sp)
                    }
                }
            }
        }
    }
}

На языке Kotlin или Java: что выбрать

До 2019 года этот вопрос был предметом споров, но сегодня ответ однозначен. Google официально перевела Android-разработку на Kotlin-first, и все современные библиотеки — Jetpack Compose, Room, WorkManager — в первую очередь тестируются на Kotlin. Для создания локера преимущества Kotlin особенно заметны в работе с асинхронщиной, биометрией и Compose. Ответ с площадки Ответы Mail.ru подтверждает: «С недавних пор Kotlin предпочтительный язык для андроида, сам гугл рекомендует на нем писать».


Советы начинающему разработчику

Первое и главное правило: не пытайтесь сразу написать идеальный локер, который заменит системный. Начните с простого app blocker для одного-двух приложений, используя Compose и Room. Следующие шаги помогут выстроить процесс:

  • Сначала реализуйте UI. Напишите экран ввода PIN-кода на Jetpack Compose и протестируйте на реальном устройстве. Убедитесь, что анимации плавные и кнопки отзывчивые.
  • Затем добавьте Room. Сохраняйте PIN не в открытом виде, а в виде хэша. Для этого подойдёт SHA-256, реализованный парой строк на Kotlin.
  • Подключите UsageStatsManager. Реализуйте foreground service и проверьте, что при открытии заблокированного приложения появляется ваш lock screen.
  • Добавьте биометрию. BiometricPrompt API повысит удобство и безопасность.
  • Оптимизируйте потребление батареи. Не опрашивайте UsageStatsManager каждую секунду — интервала в 500 миллисекунд достаточно для быстрой реакции.

Коротко о главном

Итак, возможно ли создать android locker на языке kotlin? Да, app locker с PIN-кодом, графическим ключом и биометрией создаётся штатными средствами Android и публикуется в Google Play. Полноценный системный screen locker — задача принципиально иного уровня, с ограничениями платформы и политикой модерации. Начните с малого: напишите экран блокировки на Compose, добавьте Room для хранения паролей и foreground service для отслеживания запуска приложений. Полученный опыт станет отличной базой для более сложных проектов в сфере мобильной безопасности.