Permission Handler in Android: hoe het werkt, verwerking van aanvragen en implementatie

Auteur: IT Sectr Gepubliceerd: 2026-05-20 Leestijd: 8 min

Permission Handler is een component van een Android-app die verantwoordelijk is voor het controleren, aanvragen en verwerken van resultaten van runtime-machtigingen. Volgens Android Developer Guide, 2024, centraliseert de machtigingshandler de logica van checkSelfPermission, requestPermissions en shouldShowRequestPermissionRationale in één klasse of ViewModel. Dit vereenvoudigt het onderhoud van de code en verbetert het testen.

Belangrijkste punten

  • Permission Handler — een gespecialiseerde component voor gecentraliseerd beheer van Android runtime-machtigingen.
  • Inkapselt de logica van checkSelfPermission, requestPermissions en shouldShowRequestPermissionRationale.
  • Moderne implementaties zijn gebaseerd op ActivityResultContracts uit androidx.activity.
  • Vereenvoudigt unittesten dankzij inversie van afhankelijkheden en isolatie van platformcode.
  • Best practices omvatten één handler per Activity en hergebruik via een DI-container.

Wat is Permission Handler in Android

Permission Handler — is een architectuurpatroon voor gecentraliseerd beheer van Android runtime-machtigingen. In plaats van verspreide aanroepen van ContextCompat.checkSelfPermission en ActivityCompat.requestPermissions door de hele app-code, wordt alle logica voor aanvragen en resultaatverwerking in één klasse geconcentreerd. Dit vermindert duplicatie, vereenvoudigt onderhoud en maakt de code voorspelbaarder.

De behoefte aan Permission Handler ontstond met de introductie van runtime-machtigingen in Android 6.0. Daarvoor werden alle machtigingen bij installatie aangevraagd en kon de app-code elke API zonder controles gebruiken. Na de overgang naar het runtime-model vereist elk gebruik van een gevaarlijke machtiging een driestapscontrole: checkSelfPermission, requestPermissions, onRequestPermissionsResult. Het verspreiden van deze logica over Activity en Fragment leidt tot inline-duplicatie en fouten. Volgens Google I/O 2019 vermindert centralisatie van machtigingsverwerking het aantal bugs gerelateerd aan Permission Denial met gemiddeld 60 procent.

Een goede Permission Handler biedt een schone interface voor de aanroepende code. Activity of Fragment hoeven de details van de aanvraag niet te kennen — ze roepen een methode aan zoals requestCamera(callback), en de handler beheert zelf de statuscontrole, weergave van rationale, aanroep van het systeemdialoog en het doorgeven van het resultaat aan de callback. Dit implementeert het principe van enkele verantwoordelijkheid en scheidt bedrijfslogica van de platformcode voor machtigingen.

Wanneer is Permission Handler nodig

Permission Handler wordt noodzakelijk wanneer de app 3 of meer gevaarlijke machtigingen gebruikt. Voor eenvoudige apps met één machtiging (bijvoorbeeld camera voor een QR-codescanner) kan men volstaan met een directe aanroep. Maar voor een typische mobiele app met camera, geolocatie, meldingen en opslag — is een gecentraliseerde handler verplicht voor onderhoud.

Architectuur van Permission Handler

Een typische Permission Handler bestaat uit drie niveaus: interface-contract, implementatie met ActivityResultLauncher en een laag voor ViewModel. De interface definieert aanvraagmethoden voor elke machtiging — requestCamera, requestLocation, requestStorage. De implementatie koppelt deze methoden aan de bijbehorende ActivityResultContracts.RequestPermission-contracten.

Belangrijke componenten van de architectuur:

  • PermissionHandlerContract — interface met methoden voor elke machtiging
  • PermissionHandlerImpl — implementatie die verbinding maakt met ActivityResultRegistry
  • PermissionResult — sealed class met statussen GRANTED, DENIED, NEVER_ASK_AGAIN
  • RationaleHandler — component voor het tonen van uitleg voor de aanvraag

Deze architectuur maakt het eenvoudig om de implementatie in tests te vervangen: in plaats van een echte ActivityResultLauncher wordt een mock gebruikt die een vooraf gedefinieerd resultaat retourneert zonder interactie met het systeem. Dit is kritisch voor unittesten van UI-logica, waar het starten van een Activity voor een machtigingsdialoog onmogelijk is.

Levenscyclusbeheer

Permission Handler moet rekening houden met de levenscyclus van Activity en Fragment. Launchers worden geregistreerd in ActivityResultRegistry, dat automatisch de status opslaat en herstelt bij schermrotatie en het opnieuw aanmaken van de Activity. Handler mag geen directe verwijzingen naar Activity of Fragment bewaren — gebruik in plaats daarvan WeakReference of geef de registry door via de constructor. Dit voorkomt geheugenlekken en crashes bij configuratiewijzigingen.

Implementatie van Permission Handler in Kotlin

De basisimplementatie van Permission Handler is gebouwd op ActivityResultContracts.RequestPermission. Handler krijgt ActivityResultRegistry van ComponentActivity of Fragment en registreert launchers voor elke machtiging. Elke launcher accepteert een lambda-callback die wordt aangeroepen na het antwoord van de gebruiker.

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
    }
}

Initialisatie in Activity

Handler wordt geïnitialiseerd in onCreate van Activity via registerForActivityResult, dat toegang geeft tot ActivityResultRegistry. Na initialisatie is de handler klaar om aanvragen te verwerken gedurende de volledige levenscyclus van de Activity. Het is belangrijk om initialize aan te roepen voor de eerste aanvraag, anders wordt de launcher niet geregistreerd.

Permission Handler met ViewModel

Integratie van Permission Handler met ViewModel is de meest geavanceerde benadering. ViewModel beheert de status van aanvragen en Handler voert alleen platformaanroepen uit. ViewModel bevat StateFlow<PermissionUiState>, waarbij UiState beschrijft welke machtiging wordt aangevraagd en welk resultaat is verkregen. Activity abonneert zich op deze StateFlow en delegeert de aanvraag aan 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()
}

In dit model controleert Activity bij het opstarten isPermissionGranted via Handler en ViewModel beheert alleen de status. Als de machtiging niet is verleend — abonneert Activity zich op uiState, roept requestCamera van Handler aan en geeft het resultaat terug aan ViewModel via onPermissionResult. Het scheiden van platformcode en bedrijfslogica maakt het mogelijk ViewModel te testen zonder Android-afhankelijkheden.

Testen van Permission Handler

Unittesten van Permission Handler is mogelijk dankzij de interface PermissionHandler. In tests wordt een FakePermissionHandler gemaakt die verschillende scenario's simuleert: machtiging verleend, geweigerd, Never Ask Again. Elk scenario wordt onafhankelijk getest. Dit is vooral belangrijk voor het testen van UI-logica die correct moet reageren op alle drie de uitkomsten.

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-implementatie maakt het mogelijk ViewModel te testen zonder emulator. Het volstaat om cameraResult op de gewenste waarde in te stellen en te controleren of ViewModel UiState correct bijwerkt. Integratietests controleren de echte PermissionHandler met ActivityScenario, maar meestal zijn er 2-3 van dergelijke tests voor de hele app — de overige scenario's worden gedekt door unittesten met fakes.

Veelvoorkomende patronen en fouten

Typische fouten bij het werken met Permission Handler zijn onder andere: het ontbreken van een checkSelfPermission-controle voor elke API-aanroep, het negeren van shouldShowRequestPermissionRationale, het opnieuw aanroepen van requestPermissions bij Never Ask Again en het bewaren van launchers zonder rekening te houden met de levenscyclus van de Activity. Laten we elk probleem en de oplossing bekijken.

De meest voorkomende fout — het aanroepen van een API zonder de machtigingsstatus te controleren. Ontwikkelaars nemen aan dat als een machtiging eenmaal is verleend, deze voor altijd blijft. De gebruiker kan deze echter op elk moment intrekken via de instellingen. Permission Handler moet altijd isPermissionGranted aanroepen voor het uitvoeren van een gevoelige bewerking. De tweede veelvoorkomende fout — het negeren van shouldShowRequestPermissionRationale en een herhaalde aanvraag die leidt tot onmiddellijke weigering zonder dialoog bij Never Ask Again.

Best practices omvatten: het maken van één Handler-instantie voor de volledige levenscyclus van de Activity, het gebruik van SharedFlow voor het doorgeven van resultaten aan ViewModel, het loggen van alle aanvragen en weigeringen voor analyse, en het tonen van een aangepast rationale-dialoog voor het systeemdialoog bij de eerste weigering. Het volgen van deze regels garandeert stabiele werking met machtigingen op alle Android-versies.

Veelgestelde vragen

Wat is Permission Handler in Android?

Permission Handler — een component voor gecentraliseerd beheer van runtime-machtigingen, die checkSelfPermission, requestPermissions en shouldShowRequestPermissionRationale inkapselt. Het vereenvoudigt codeonderhoud en verbetert testen.

Welke API gebruiken voor Handler in 2024?

ActivityResultContracts.RequestPermission uit de androidx.activity-bibliotheek wordt aanbevolen. Het vervangt de verouderde onRequestPermissionsResult en biedt een schone callback-API met een Boolean-resultaat.

Is een Handler nodig voor één machtiging?

Voor één machtiging is Handler niet verplicht — u kunt direct de RequestPermission-launcher in Activity aanroepen. Handler wordt noodzakelijk bij 3 of meer machtigingen om codeduplicatie te voorkomen.

Hoe test ik Permission Handler?

Maak een PermissionHandler-interface en een fake-implementatie voor unittesten. Fake retourneert vooraf gedefinieerde resultaten zonder systeemaanroepen. Dit maakt het mogelijk ViewModel en UI-logica te testen zonder emulator.

Hoe verwerk ik Never Ask Again in Handler?

Controleer na weigering shouldShowRequestPermissionRationale. Als de methode false retourneert — is de Never Ask Again-modus geactiveerd. Handler moet PermissionResult.DENIED(false) retourneren en de UI moet een knop tonen om naar Instellingen te gaan.

Samenvatting

  • Permission Handler — architectuurcomponent voor gecentraliseerd beheer van Android runtime-machtigingen.
  • Gebaseerd op ActivityResultContracts.RequestPermission uit de androidx.activity-bibliotheek.
  • Interface met methoden voor elke machtiging vereenvoudigt unittesten via fake-implementaties.
  • Integratie met ViewModel via StateFlow scheidt platformcode en bedrijfslogica.
  • Typische fouten: ontbrekende checkSelfPermission, negeren van rationale en Never Ask Again.
  • Best practice — één Handler per Activity met registratie in onCreate.
  • Centralisatie vermindert het aantal Permission Denial-bugs met 60 procent in typische projecten.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook