惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
J
Java Code Geeks
爱范儿
爱范儿
雷峰网
雷峰网
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 三生石上(FineUI控件)
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog RSS Feed
Google DeepMind News
Google DeepMind News
Jina AI
Jina AI
The GitHub Blog
The GitHub Blog
I
InfoQ
月光博客
月光博客
博客园 - 聂微东
博客园 - Franky
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
博客园_首页
G
Google Developers Blog
Blog — PlanetScale
Blog — PlanetScale
L
LangChain Blog
罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Разработка Android Kiosk приложения
Davran Khasa · 2026-05-24 · via DEV Community

Всем привет это моя первая публикация. И первый опыт написания статей по разработке.

Давайте начнем с небольшого знакомства.
Меня зовут Давран, я андройд разработчик с 8 летнем стажем разработки мобильных приложений разного спектра.

Мой опыт работы:

Сегодня я хотел начать свое повествование с темы Android Kiosk.

На первый взгляд kiosk приложение на Android - это что то простое: нужно просто "залочить" пользователя внутри одного экрана.

На практике все оказалось немного сложнее.

В рамках нашего проекта Pai, я занимался разработкой приложения под планшет, а так же написанием лаунчера(как в итоге оказалось не совсем лаунчером)

*Что такое киоск *
Kiosk-приложение - это приложение с ограниченным доступом в котором пользователь не может выйти за пределы одного приложения.

Такие решения используется в терминалах, POS системах инфокиосках и устройствах самообслуживания.

Требования

На старте требования казались простыми, у меня был небольшой опыт написания лаунчера под android, и я думал что этих знаний и каких нибудь pet проектов на гитхабе хватит для решения задачи.
Но у меня было много вопросов которые направили меня на поиск документации для этой области(ссылка)

Итого нам нужно чтобы:

  • Пользователь не смог выйти из приложения
  • Приложение должно запускаться автоматически при включении устройства
  • Нельзя давать доступ к системным настройкам и UI

Реализация

Все что мне потребовалось это немного документации,
пару снипетов кода.

За основу решения были взяты Device Owner и Lock Task Mode.

Ну что же, теперь перейдем непосредственно к коду и реализации...

Kiosk Controller

Первым делом нам предстоит ознакомиться с DevicePolicyManager API
если в двух словах то это API для администратора устройства которое позволяет нам много вещей(управление приложениями, управление настройками девайса и прочие вещи)
но для этого нам нужно одно из двух, либо нужные пермишины либо же админ права(это не есть рут устройства)

Дальше нам предстоит ознакомиться с KeyguardManager API
это API нужно нам для работы с лок скрином девайса а точнее для прослушивание его стейтов.

И так же нам нужно создать DeviceAdminReceiver для получения установленных настроек в наше приложение

1 - Нам нужно создать white list приложений которые можно будет запускать в режиме киоска поэтому мы создадим массив названия пакетов:

private val WHITE_LIST_PACKAGES = arrayOf(
    "your.package.name",
    "dev.firebase.appdistribution",
    "com.android.settings"
)

Enter fullscreen mode Exit fullscreen mode

2 - Мы создаем класс KioskController и создаем ссылки на системные сервисы

 private val dpm = context.getSystemService(DevicePolicyManager::class.java)
    private val keyguard = context.getSystemService(KeyguardManager::class.java)
    private val admin = ComponentName(context, AdminReceiver::class.java)

Enter fullscreen mode Exit fullscreen mode

3 - Основную работу будет делать нам DevicePolicyManager
и первая магическая строчка это

dpm.setLockTaskPackages(admin, arrayOf(WHITE_LIST_PACKAGES))

Enter fullscreen mode Exit fullscreen mode

данная команда отдает системе белый список приложений которые можно будет открыть в режиме киоска

вторая магичечская строчка

dpm.setLockTaskFeatures(
admin,
DevicePolicyManager.LOCK_TASK_FEATURE_NONE
)

Enter fullscreen mode Exit fullscreen mode

данная команда отключает все настраиваемые элементы с UI в режиме киоска(статус бар,навигационный бар, одним словом у вас в киоск режиме отключается весь внешний UI системы)

из минусов я нашел только вновь кривой API, так как флаг
DevicePolicyManager.LOCK_TASK_FEATURE_NONE выключает все
но нет флажка включить все, поэтому придется использовать комбинацию флажков чтобы вернуться с режима киоска

dpm.setLockTaskFeatures(
            admin,
            DevicePolicyManager.LOCK_TASK_FEATURE_HOME or
                DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW or
                DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS or
                DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS
        )

Enter fullscreen mode Exit fullscreen mode

и на выходе у нас получаются две функции

 fun enterAdminMode() {
        if (!isDeviceOwner()) return
        dpm.setLockTaskFeatures(
            admin,
            DevicePolicyManager.LOCK_TASK_FEATURE_HOME or
                DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW or
                DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS or
                DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS
        )
    }

Enter fullscreen mode Exit fullscreen mode

fun exitAdminMode() {
        if (!isDeviceOwner()) return

        dpm.setLockTaskFeatures(admin, DevicePolicyManager.LOCK_TASK_FEATURE_NONE)
    }

Enter fullscreen mode Exit fullscreen mode

есть еще вспомогательные

fun canStartLockTask(): Boolean {
        if (!isDeviceOwner()) return false
        if (!dpm.isLockTaskPermitted(context.packageName)) return false
        return !keyguard.isDeviceLocked
    }

Enter fullscreen mode Exit fullscreen mode

isLockTaskPermitted - это проверка на на наличие прав у приложение переходить в режим киоска.

fun isDeviceOwner(): Boolean = dpm.isDeviceOwnerApp(context.packageName)

Enter fullscreen mode Exit fullscreen mode

Проверка на наличие прав админа устройства

Так же у DevicePolicyManager есть функция addRestriction
которая позволяет выключить ту или иную вещь на девайсе:

  • Сейф бут
  • сброс заводских настроек
  • подключение внешних юсб
  • добавление аккаунтов на устройство
  • настройки блютуза и еще много чего.

переменная admin - это DeviceAdminReceiver
который помогает системе определить куда вести все эти настройки в действие.

*Установка приложения *

На этом создание контролера завершено, далее нам нужно сбросить девайс до заводских настроек, включить USB debugging, разрешить установку через USB и не создавать и не авторизовываться ни под каким аккаунтом на устройстве.

Мы ставим наше приложение на устройство, открываем терминал и выполняем команду

Установка девайс овнера

adb shell dpm set-device-owner "your.package.name/com.example.AdminReceiver

Enter fullscreen mode Exit fullscreen mode

Удаление девайс овнера

adb shell dpm remove-active-admin "your.package.name/com.example.AdminReceiver

Enter fullscreen mode Exit fullscreen mode

и указываем путь до нашего AdminReceiver(это DeviceAdminReceiver который мы создали в KioskController)

class AdminReceiver : DeviceAdminReceiver()

Enter fullscreen mode Exit fullscreen mode

На этом нам осталось лишь установить наше приложение как домашний лаунчер устройства и поздравляю вас, вы теперь админ устройства в режиме киоска.

P.S - я использовал SingleActivity архитектуру для того чтобы добавить скрытую кнопку которая позволит открыть AdminScreen
ввести пин код админа и выйти с режима киоска для конфигурации планшета.

Если хотите могу эту часть тоже описать.