Permission Handler v Androidu: jak funguje, zpracování požadavků a implementace

Autor: IT Sectr Publikováno: 2026-05-20 Doba čtení: 8 min

Permission Handler je komponenta aplikace pro Android odpovědná za kontrolu, žádání a zpracování výsledků runtime oprávnění. Podle Android Developer Guide, 2024, obsluha oprávnění centralizuje logiku checkSelfPermission, requestPermissions a shouldShowRequestPermissionRationale do jediné třídy nebo ViewModelu. To zjednodušuje údržbu kódu a zlepšuje testování.

Hlavní body

  • Permission Handler — specializovaná komponenta pro centralizovanou správu runtime oprávnění Androidu.
  • Zapouzdřuje logiku checkSelfPermission, requestPermissions a shouldShowRequestPermissionRationale.
  • Moderní implementace jsou založeny na ActivityResultContracts z androidx.activity.
  • Zjednodušuje unit testování díky inverzi závislostí a izolaci platformního kódu.
  • Nejlepší postupy zahrnují jedinou obsluhu na Activity a opětovné použití prostřednictvím DI kontejneru.

Co je Permission Handler v Androidu

Permission Handler — je architektonický vzor pro centralizovanou správu runtime oprávnění Androidu. Namísto roztroušených volání ContextCompat.checkSelfPermission a ActivityCompat.requestPermissions v celém kódu aplikace je veškerá logika žádostí a zpracování výsledků soustředěna do jedné třídy. To snižuje duplicitu, zjednodušuje údržbu a činí kód předvídatelnějším.

Potřeba Permission Handleru vznikla se zavedením runtime oprávnění v Androidu 6.0. Předtím byla všechna oprávnění vyžadována při instalaci a kód aplikace mohl používat jakékoli API bez kontrol. Po přechodu na runtime model vyžaduje každé použití nebezpečného oprávnění třífázovou kontrolu: checkSelfPermission, requestPermissions, onRequestPermissionsResult. Rozptýlení této logiky mezi Activity a Fragment vede k inline duplicitě a chybám. Podle údajů Google I/O 2019 centralizace zpracování oprávnění snižuje počet chyb souvisejících s Permission Denial v průměru o 60 procent.

Dobrý Permission Handler poskytuje čisté rozhraní pro volající kód. Activity nebo Fragment nemusí znát podrobnosti požadavku — volají metodu typu requestCamera(callback) a handler sám spravuje kontrolu stavu, zobrazení rationale, volání systémového dialogu a předání výsledku do callbacku. To implementuje princip jediné odpovědnosti a odděluje business logiku od platformního kódu oprávnění.

Kdy je Permission Handler potřeba

Permission Handler se stává nezbytným, když aplikace používá 3 nebo více nebezpečných oprávnění. Pro jednoduché aplikace s jedním oprávněním (například kamera pro skener QR kódů) vystačíte s přímým voláním. Ale pro typickou mobilní aplikaci s kamerou, geolokací, notifikacemi a úložištěm — centralizovaný handler je pro údržbu povinný.

Architektura Permission Handleru

Typický Permission Handler se skládá ze tří úrovní: rozhraní-kontrakt, implementace s ActivityResultLauncherem a vrstva pro ViewModel. Rozhraní definuje metody žádostí pro každé oprávnění — requestCamera, requestLocation, requestStorage. Implementace propojuje tyto metody s odpovídajícími kontrakty ActivityResultContracts.RequestPermission.

Klíčové komponenty architektury:

  • PermissionHandlerContract — rozhraní s metodami pro každé oprávnění
  • PermissionHandlerImpl — implementace komunikující s ActivityResultRegistry
  • PermissionResult — sealed class se stavy GRANTED, DENIED, NEVER_ASK_AGAIN
  • RationaleHandler — komponenta pro zobrazení vysvětlení před žádostí

Tato architektura umožňuje snadno nahradit implementaci v testech: místo skutečného ActivityResultLauncheru se používá mock, který vrací předdefinovaný výsledek bez interakce se systémem. To je kritické pro unit testování UI logiky, kde spuštění Activity pro dialog oprávnění není možné.

Správa životního cyklu

Permission Handler musí brát v úvahu životní cyklus Activity a Fragmentu. Launcherové jsou registrováni v ActivityResultRegistry, který automaticky ukládá a obnovuje stav při otočení obrazovky a obnovení Activity. Handler by neměl uchovávat přímé reference na Activity nebo Fragment — místo toho použijte WeakReference nebo předejte registry přes konstruktor. To zabraňuje únikům paměti a pádům při změnách konfigurace.

Implementace Permission Handleru v Kotlinu

Základní implementace Permission Handleru je postavena na ActivityResultContracts.RequestPermission. Handler získává ActivityResultRegistry z ComponentActivity nebo Fragmentu a registruje launcherové pro každé oprávnění. Každý launcherov přijímá lambda-callback, který je volán po odpovědi uživatele.

kotlin
sealed class PermissionResult {
    object GRANTED : PermissionResult()
    data class DENIED(
        val shouldShowRationale: Boolean
    ) : PermissionResult()
}

interface PermissionHandler {
    fun requestCamera(
        callback: (PermissionResult) -> Unit
    )
    fun requestLocation(
        callback: (PermissionResult) -> Unit
    )
    fun isPermissionGranted(
        permission: String
    ): Boolean
}

class AndroidPermissionHandler(
    private val registry: ActivityResultRegistry,
    private val context: Context
) : PermissionHandler {

    private var cameraLauncher: ActivityResultLauncher<String>? = null

    fun initialize() {
        cameraLauncher = registry.register(
            "camera_permission",
            ActivityResultContracts.RequestPermission()
        ) { isGranted ->
            if (isGranted) {
                pendingCameraCallback?.invoke(
                    PermissionResult.GRANTED
                )
            } else {
                val rationale = ActivityCompat.shouldShowRequestPermissionRationale(
                    context as Activity,
                    Manifest.permission.CAMERA
                )
                pendingCameraCallback?.invoke(
                    PermissionResult.DENIED(rationale)
                )
            }
        }
    }

    private var pendingCameraCallback:
        ((PermissionResult) -> Unit)? = null

    override fun requestCamera(
        callback: (PermissionResult) -> Unit
    ) {
        if (isPermissionGranted(
                Manifest.permission.CAMERA
        )) {
            callback.invoke(PermissionResult.GRANTED)
            return
        }
        pendingCameraCallback = callback
        cameraLauncher?.launch(
            Manifest.permission.CAMERA
        )
    }

    override fun isPermissionGranted(
        permission: String
    ): Boolean {
        return ContextCompat.checkSelfPermission(
            context, permission
        ) == PackageManager.PERMISSION_GRANTED
    }
}

Inicializace v Activity

Handler je inicializován v onCreate Activity prostřednictvím registerForActivityResult, který poskytuje přístup k ActivityResultRegistry. Po inicializaci je handler připraven zpracovávat požadavky po celý životní cyklus Activity. Je důležité zavolat initialize před prvním požadavkem, jinak nebude launcherov registrován.

Permission Handler s ViewModelem

Integrace Permission Handleru s ViewModelem je nejpokročilejší přístup. ViewModel spravuje stav požadavků a Handler provádí pouze platformní volání. ViewModel obsahuje StateFlow<PermissionUiState>, kde UiState popisuje, které oprávnění je požadováno a jaký výsledek byl získán. Activity se přihlásí k odběru tohoto StateFlow a deleguje požadavek na Handler.

kotlin
class PermissionsViewModel : ViewModel() {

    private val _uiState =
        MutableStateFlow<PermissionUiState>(
            PermissionUiState.Idle
        )
    val uiState: StateFlow<PermissionUiState> = _uiState.asStateFlow()

    fun onCameraRequested() {
        _uiState.value = PermissionUiState.RequestingCamera
    }

    fun onPermissionResult(
        permission: String,
        result: PermissionResult
    ) {
        when (result) {
            PermissionResult.GRANTED -> {
                _uiState.value = PermissionUiState.Granted(permission)
            }
            is PermissionResult.DENIED -> {
                _uiState.value = PermissionUiState.Denied(
                    permission,
                    result.shouldShowRationale
                )
            }
        }
    }
}

sealed class PermissionUiState {
    object Idle : PermissionUiState()
    object RequestingCamera : PermissionUiState()
    data class Granted(val permission: String) : PermissionUiState()
    data class Denied(
        val permission: String,
        val shouldShowRationale: Boolean
    ) : PermissionUiState()
}

V tomto modelu Activity při startu kontroluje isPermissionGranted přes Handler, zatímco ViewModel spravuje pouze stav. Pokud oprávnění nebylo uděleno — Activity se přihlásí k odběru uiState, zavolá requestCamera z Handleru a předá výsledek zpět do ViewModelu přes onPermissionResult. Oddělení platformního kódu a business logiky umožňuje testovat ViewModel bez Android závislostí.

Testování Permission Handleru

Unit testování Permission Handleru je možné díky rozhraní PermissionHandler. V testech se vytváří FakePermissionHandler, který simuluje různé scénáře: oprávnění uděleno, zamítnuto, Never Ask Again. Každý scénář je testován nezávisle. To je obzvláště důležité pro testování UI logiky, která musí správně reagovat na všechny tři výsledky.

kotlin
class FakePermissionHandler : PermissionHandler {

    var cameraResult: PermissionResult =
        PermissionResult.GRANTED
    var grantedPermissions: Set<String> =
        setOf(Manifest.permission.CAMERA)

    override fun requestCamera(
        callback: (PermissionResult) -> Unit
    ) {
        callback.invoke(cameraResult)
    }

    override fun isPermissionGranted(
        permission: String
    ): Boolean {
        return permission in grantedPermissions
    }
}

Fake implementace umožňuje testovat ViewModel bez emulátoru. Stačí nastavit cameraResult na požadovanou hodnotu a zkontrolovat, že ViewModel správně aktualizuje UiState. Integrační testy kontrolují skutečný PermissionHandler s ActivityScenario, ale obvykle jsou 2-3 takové testy pro celou aplikaci — ostatní scénáře jsou pokryty unit testy s fake implementacemi.

Běžné vzory a chyby

Typické chyby při práci s Permission Handlerem zahrnují: chybějící kontrolu checkSelfPermission před každým API voláním, ignorování shouldShowRequestPermissionRationale, opakované volání requestPermissions při Never Ask Again a uchovávání launcherovů bez ohledu na životní cyklus Activity. Podívejme se na každý problém a jeho řešení.

Nejčastější chyba — volání API bez kontroly stavu oprávnění. Vývojáři předpokládají, že pokud bylo oprávnění jednou uděleno, zůstane navždy. Uživatel jej však může kdykoli odvolat v nastavení. Permission Handler musí vždy volat isPermissionGranted před provedením citlivé operace. Druhou častou chybou je ignorování shouldShowRequestPermissionRationale a opakovaný požadavek, který vede k okamžitému zamítnutí bez dialogu při Never Ask Again.

Nejlepší postupy zahrnují: vytvoření jedné instance Handleru pro celý životní cyklus Activity, použití SharedFlow pro předávání výsledků do ViewModelu, logování všech požadavků a zamítnutí pro analytiku, a také zobrazení vlastního rationale dialogu před systémovým při prvním zamítnutí. Dodržování těchto pravidel zaručuje stabilní práci s oprávněními na všech verzích Androidu.

Často kladené otázky

Co je Permission Handler v Androidu?

Permission Handler — komponenta pro centralizovanou správu runtime oprávnění, zapouzdřující checkSelfPermission, requestPermissions a shouldShowRequestPermissionRationale. Zjednodušuje údržbu kódu a zlepšuje testování.

Jaké API použít pro Handler v roce 2024?

Doporučuje se ActivityResultContracts.RequestPermission z knihovny androidx.activity. Nahrazuje zastaralý onRequestPermissionsResult a poskytuje čisté callback API s výsledkem Boolean.

Je Handler potřebný pro jedno oprávnění?

Pro jedno oprávnění Handler není povinný — můžete použít přímé volání RequestPermission laucherovu v Activity. Handler se stává nezbytným při 3 a více oprávněních, aby se předešlo duplicitě kódu.

Jak testovat Permission Handler?

Vytvořte rozhraní PermissionHandler a jeho fake implementaci pro unit testy. Fake vrací předdefinované výsledky bez systémových volání. To umožňuje testovat ViewModel a UI logiku bez emulátoru.

Jak zpracovat Never Ask Again v Handleru?

Po zamítnutí zkontrolujte shouldShowRequestPermissionRationale. Pokud metoda vrátila false — je aktivován režim Never Ask Again. Handler by měl vrátit PermissionResult.DENIED(false) a UI by mělo zobrazit tlačítko pro přechod do Nastavení.

Shrnutí

  • Permission Handler — architektonická komponenta pro centralizovanou správu runtime oprávnění Androidu.
  • Založen na ActivityResultContracts.RequestPermission z knihovny androidx.activity.
  • Rozhraní s metodami pro každé oprávnění zjednodušuje unit testování prostřednictvím fake implementací.
  • Integrace s ViewModelem přes StateFlow odděluje platformní kód a business logiku.
  • Typické chyby: chybějící checkSelfPermission, ignorování rationale a Never Ask Again.
  • Nejlepší praxe — jeden Handler na Activity s registrací v onCreate.
  • Centralizace snižuje počet Permission Denial chyb o 60 procent v typických projektech.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také