shouldShowRequestPermissionRationale — är en Android API-metod som talar om för utvecklaren om en förklaring ska visas för användaren innan en farlig behörighet begärs. Enligt Android Developer Reference, 2024, metoden rational returnerar true om användaren tidigare avvisade begäran men inte ställde in flaggan Never Ask Again. Det är ett viktigt verktyg för att bygga en artig UX vid arbete med runtime-behörigheter.
Huvudpunkter
shouldShowRequestPermissionRationale — är en metod i klasserna Activity och Fragment i Android, tillgänglig via ActivityCompat för kompatibilitet. Den tar emot behörighetens namn och returnerar en Boolean som anger om en ytterligare förklaring ska visas för användaren innan en upprepad begäran. Metoden introducerades i Android 6.0 Marshmallow tillsammans med runtime-behörighetsmodellen.
Rationale-mekanismen bygger på att spåra användarens interaktionshistorik med behörighetsdialogrutor. Systemet kommer ihåg om användaren tidigare avvisade begäran. Om avvisandet skedde utan att ställa in flaggan Never Ask Again returnerar shouldShowRequestPermissionRationale true. Detta är en signal till utvecklaren: användaren förstår inte varför behörigheten behövs och en ytterligare förklaring krävs. Enligt Google Material Design Guidelines ökar visning av rationale-dialogrutan efter första avvisandet sannolikheten för att behörigheten beviljas igen med 35 procent.
Det är viktigt att förstå semantiken i de returnerade värdena: true innebär att det är meningsfullt att visa dialogrutan, false — dialogrutan är antingen inte nödvändig (behörigheten är redan beviljad eller har aldrig begärts) eller är värdelös (Never Ask Again är aktiv). Metoden är ingen garanti för att dialogrutan kommer att visas — den ger bara en rekommendation. Utvecklaren bestämmer själv vilket UI som ska visas som svar.
shouldShowRequestPermissionRationale introducerades i API Level 23 tillsammans med en grupp metoder för runtime-behörigheter. Före Android 6.0 begärdes alla behörigheter vid installation och en förklaringsmekanism behövdes inte — användaren accepterade eller avvisade hela listan på en gång. Runtime-modellen gjorde det möjligt att användaren avvisar begäran utan att förstå sammanhanget och det är just därför rationale behövs.
Metodens logik är som följer. Vid första anropet av requestPermissions för en specifik behörighet returnerar shouldShowRequestPermissionRationale false — användaren har ännu inte stött på dialogrutan. Om användaren avvisade begäran (tryckte på Deny) börjar metoden returnera true. Efter upprepat avvisande med flaggan Never Ask Again returnerar metoden false.
Fullständig tabell över tillstånd:
| Tillstånd | shouldShowRationale | checkSelfPermission | Utvecklarens åtgärd |
|---|---|---|---|
| Ej begärt | false | DENIED | Visa systemdialogruta |
| Beviljad | false | GRANTED | Utför funktionen |
| Avvisad första gången | true | DENIED | Visa rationale, sedan systemdialogruta |
| Never Ask Again | false | DENIED | Omdirigera till Inställningar |
Kombinationen shouldShowRequestPermissionRationale = false och checkSelfPermission = DENIED — är det svåraste fallet att bearbeta. Det betyder att behörigheten antingen aldrig har begärts eller att Never Ask Again har ställts in. Utvecklaren måste skilja dessa två tillstånd åt. Det enda sättet — att lagra flaggan firstRequest i SharedPreferences eller använda SavedStateHandle. Vid första begäran, ställ in flaggan, och om shouldShowRationale returnerade false och flaggan redan är true — betyder det Never Ask Again.
shouldShowRequestPermissionRationale återställs om användaren tar bort och installerar om applikationen, rensar applikationsdata eller återställer behörighetsinställningar. Efter ominstallation kommer metoden att returnera false igen för den första begäran. Systemuppdateringar och ändring av Android-version återställer inte historiken — den lagras i applikationens data.
Korrekt implementering av rationale innefattar tre komponenter: kontroll av shouldShowRequestPermissionRationale efter avvisande, visning av en anpassad dialogruta med förklaring och återanrop av requestPermissions efter användarens positiva svar. Dialogrutan bör vara koncis, specifik och förklara varför applikationen behöver just denna behörighet.
private fun requestLocationWithRationale() {
val permission = Manifest.permission.ACCESS_FINE_LOCATION
when {
ContextCompat.checkSelfPermission(
this, permission
) == PackageManager.PERMISSION_GRANTED -> {
startLocationTracking()
}
ActivityCompat.shouldShowRequestPermissionRationale(
this, permission
) -> {
showRationaleDialog(permission)
}
else -> {
requestPermissionLauncher.launch(permission)
}
}
}
private fun showRationaleDialog(
permission: String
) {
AlertDialog.Builder(this)
.setTitle("Varför behövs åtkomst till geoplats")
.setMessage(
"Applikationen använder geoplats för att markera platser på kartan" +
". Utan denna behörighet" +
" kommer funktionen inte att fungera."
)
.setPositiveButton("Tillåt") { _, _ ->
requestPermissionLauncher.launch(permission)
}
.setNegativeButton("Avbryt", null)
.show()
}
Material Designs bästa praxis rekommenderar att använda en bottom sheet eller inline-banner istället för en modal dialogruta för rationale. En bottom sheet är mindre påträngande och ger användaren sammanhang. Ett inline-element på skärmen (till exempel ett kort med en förklaring och knappen Tillåt) visar att funktionen inte är tillgänglig utan behörighet, men blockerar inte resten av gränssnittet.
Rationale-texten bör vara lokaliserad och anpassad till den specifika funktionen. Använd inte allmänna fraser som „Detta krävs för att applikationen ska fungera”. Ange konkret: „För att visa vädret nära dig” eller „För att spara foton i galleriet”. Enligt Google UX Research ökar konkreta förklaringar sannolikheten för att behörigheten beviljas med 50 procent.
Skillnaden mellan shouldShowRequestPermissionRationale = true (första avvisandet) och false vid DENIED (Never Ask Again) — är den viktigaste punkten vid hantering av behörigheter. I det första fallet tvekade användaren och en ytterligare förklaring kan övertyga honom att bevilja åtkomst. I det andra — användaren har fattat ett slutgiltigt beslut och en upprepad systemdialogruta kommer bara att orsaka irritation.
Algoritmen för bearbetning efter avvisande bör se ut så här:
Det är viktigt att inte blanda ihop ordningen: kontrollera först shouldShowRequestPermissionRationale, inte checkSelfPermission. checkSelfPermission kommer ändå returnera DENIED i båda fallen. Endast shouldShowRequestPermissionRationale skiljer första avvisandet från Never Ask Again. Använd SavedStateHandle eller SharedPreferences för att lagra flaggan „första begäran har gjorts” — detta är det enda tillförlitliga sättet att skilja „ej begärt” från „blockerad”.
Visa rationale endast en gång. Om användaren avvisade begäran igen efter rationale — visa inte någon mer förklaring. Gå direkt över till förslaget att öppna inställningar. Upprepad visning av rationale uppfattas som påträngande och sänker applikationens betyg. Optimalt scenario: begäran — avvisande — rationale — upprepad begäran — avvisande — Inställningar.
Visa inte rationale före den första begäran. Vissa utvecklare visar felaktigt en förklaring före den första dialogrutan med argumentet att „användaren måste förstå”. Detta försämrar UX: användaren ser två dialogrutor i rad istället för en. Google rekommenderar att visa systemdialogrutan omedelbart och rationale endast efter avvisande.
Använd kontextuellt rationale, kopplat till ögonblicket när funktionen verkligen behövs. Begär inte alla behörigheter vid applikationsstart — detta är den lägsta beviljandegraden. Begär CAMERA när användaren tryckte på knappen „Ta foto” och LOCATION när han öppnade kartan. Kontextuell begäran i kombination med rationale ökar beviljandet till 80 procent jämfört med 30 procent vid den initiala begäran.
Testa shouldShowRequestPermissionRationale kräver kontroll av fyra tillstånd i tabellen: ej begärt, beviljat, avvisat, Never Ask Again. I enhetstester används FakePermissionHandler med konfigurerbart shouldShowRationale-beteende. I instrumentella tester — UiAutomator eller Espresso med emulering av svar på systemdialogrutor.
class RationaleViewModelTest {
private val handler = FakePermissionHandler()
private val viewModel = PermissionsViewModel(handler)
fun testFirstDenial_shouldShowRationale() {
handler.shouldShowRationale = true
handler.cameraResult =
PermissionResult.DENIED(true)
viewModel.onCameraRequested()
assertEquals(
PermissionUiState.Denied(true),
viewModel.uiState.value
)
}
fun testNeverAskAgain_redirectToSettings() {
handler.shouldShowRationale = false
handler.cameraResult =
PermissionResult.DENIED(false)
viewModel.onCameraRequested()
assertEquals(
PermissionUiState.RedirectToSettings,
viewModel.uiState.value
)
}
}
Det viktigaste scenariot för instrumentella tester — kontrollera att rationale-dialogrutan verkligen visas efter första avvisandet. Använd Espresso med idling resources för att vänta på systemdialogrutan, tryck sedan på Deny, kontrollera att den anpassade dialogrutan med förklaringstexten visas och tryck på Allow — kontrollera beviljandet. UIAutomator möjliggör interaktion med systemdialogrutan via knapptexten, vilket gör testet stabilare.
Det är också värt att testa scenariot med avvisande inuti rationale-dialogrutan. Om användaren tryckte på Deny i den anpassade förklaringen bör shouldShowRequestPermissionRationale returnera true igen eftersom Never Ask Again ännu inte har aktiverats. Bästa praxis — efter två på varandra följande avvisanden, omdirigera direkt till Inställningar för att inte irritera användaren med upprepade förklaringar och sänka applikationens betyg.
Vanliga frågor
true — om begäran tidigare avvisats och Never Ask Again inte har ställts in. false — om behörigheten inte har begärts, har beviljats eller är permanent blockerad. Kombinationen false + DENIED kräver kontroll via en extra flagga.
Visa rationale endast efter användarens första avvisande, när shouldShowRequestPermissionRationale returnerade true. Före den första begäran är rationale inte nödvändigt — detta försämrar UX och skapar onödiga dialogrutor.
Lagra flaggan isFirstRequest i SharedPreferences eller SavedStateHandle. Om shouldShowRationale = false, checkSelfPermission = DENIED och flaggan = true — betyder det att Never Ask Again har aktiverats. Om flaggan = false — är detta den första begäran.
Visa en dialogruta med knappen „Öppna inställningar” som omdirigerar användaren till ACTION_APPLICATION_DETAILS_SETTINGS. Anropa inte requestPermissions igen — dialogrutan visas inte och resultatet kommer med DENIED utan meddelande.
I enhetstester, använd FakePermissionHandler med det konfigurerbara fältet shouldShowRationale. I instrumentella tester — Espresso eller UIAutomator med emulering av systemdialogrutan. Kontrollera alla 4 tillstånd i tabellen.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också