shouldShowRequestPermissionRationale — bu Android API metodudur ki, tərtibatçıya təhlükəli icazə tələb etməzdən əvvəl istifadəçiyə izah göstərməyin lazım olub-olmadığını bildirir. Android Developer Reference, 2024 məlumatına görə, rational metodu əgər istifadəçi əvvəllər sorğunu rədd edibsə, lakin Never Ask Again bayrağını təyin etməyibsə, true qaytarır. Bu, runtime icazələri ilə işləyərkən nəzakətli UX qurmaq üçün əsas alətdir.
Əasası
shouldShowRequestPermissionRationale — Android’də Activity və Fragment siniflərinin metodudur, uyğunluq üçün ActivityCompat vasitəsilə əldə edilir. O, icazə adını qəbul edir və təkrari sorğudan əvvəl istifadəçiyə əlavə izah göstərməyin lazım olub-olmadığını göstərən Boolean qaytarır. Metod Android 6.0 Marshmallow ilə birlikdə runtime icazə modeli ilə təqdim edilmişdir.
Rationale mexanizmi istifadəçinin icazə dialoqları ilə qarşılıqlı əlaqə tarixçəsinin izlənilməsi üzərində qurulub. Sistem istifadəçinin sorğunu əvvəllər rədd edib-etmədiyini xatırlayır. Əgər rədd Never Ask Again bayrağı təyin edilmədən baş veribsə, shouldShowRequestPermissionRationale true qaytarır. Bu, tərtibatçıya siqnaldır: istifadəçi icazənin nəyə lazım olduğunu anlamır və əlavə izah tələb olunur. Google Material Design Guidelines məlumatına görə, ilk rəddən sonra rationale dialoqunun göstərilməsi icazənin yenidən verilmə ehtimalını 35 faiz artırır.
Qaytarılan dəyərlərin semantikasını başa düşmək vacibdir: true o deməkdir ki, dialoqu göstərməyin mənası var, false — dialoq ya lazım deyil (icazə artıq verilib və ya heç vaxt tələb olunmayıb), ya da faydasızdır (Never Ask Again aktivdir). Metod dialoqun göstəriləcəyinə zəmanət vermir — o, yalnız tövsiyə verir. Tərtibatçı cavab olaraq hansı UI göstərəcəyinə özü qərar verir.
shouldShowRequestPermissionRationale API Level 23-də runtime icazə metodları qrupu ilə birlikdə təqdim edilmişdir. Android 6.0-dan əvvəl bütün icazələr quraşdırma zamanı tələb olunurdu və izah mexanizmi tələb olunmurdu — istifadəçi bütün siyahını qəbul və ya rədd edirdi. Runtime modeli istifadəçinin konteksti anlamadan sorğunu rədd etdiyi vəziyyəti mümkün etdi və məhz buna görə rationale lazımdır.
Metodun məntiqi belədir. Müəyyən bir icazə üçün requestPermissions ilk dəfə çağırıldıqda shouldShowRequestPermissionRationale false qaytarır — istifadəçi hələ dialoqla qarşılaşmayıb. Əgər istifadəçi sorğunu rədd edibsə (Deny düyməsini basıbsa), metod true qaytarmağa başlayır. Never Ask Again bayrağı ilə təkrari rədddən sonra metod false qaytarır.
Vəziyyətlərin tam cədvəli:
| Vəziyyət | shouldShowRationale | checkSelfPermission | Tərtibatçının hərəkəti |
|---|---|---|---|
| Tələb olunmayıb | false | DENIED | Sistem dialoqunu göstər |
| Verilib | false | GRANTED | Funksiyanı icra et |
| İlk dəfə rədd edilib | true | DENIED | Rationale göstər, sonra sistem dialoqu |
| Never Ask Again | false | DENIED | Parametrlərə yönləndir |
shouldShowRequestPermissionRationale = false və checkSelfPermission = DENIED kombinasiyası — emal edilməsi ən çətin haldır. Bu, ya icazənin heç vaxt tələb olunmadığını, ya da Never Ask Again-in təyin edildiyini bildirir. Tərtibatçı bu iki vəziyyəti fərqləndirməlidir. Yeganə yol — SharedPreferences və ya SavedStateHandle-də firstRequest bayrağını saxlamaqdır. İlk sorğuda bayrağı təyin edin və əgər shouldShowRationale false qaytarıbsa və bayraq artıq true-dirsə — bu Never Ask Again deməkdir.
shouldShowRequestPermissionRationale, istifadəçi proqramı silib yenidən quraşdırdıqda, proqram məlumatlarını təmizlədikdə və ya icazə parametrlərini sıfırladıqda sıfırlanır. Yenidən quraşdırmadan sonra metod ilk sorğu üçün yenə false qaytaracaq. Sistem yeniləmələri və Android versiyasının dəyişməsi tarixçəni sıfırlamır — o, proqram məlumatlarında saxlanılır.
Düzgün tətbiq üç komponenti əhatə edir: rədddən sonra shouldShowRequestPermissionRationale’i yoxlamaq, izah ilə fərdi dialoq göstərmək və istifadəçinin müsbət cavabından sonra requestPermissions-i təkrari çağırmaq. Dialoq qısa, konkret olmalı və proqramın məhz bu icazəyə niyə ehtiyacı olduğunu izah etməlidir.
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("Geolokasiyaya giriş nəyə lazımdır")
.setMessage(
"Proqram xəritədə yerləri qeyd etmək üçün geolokasiyadan istifadə edir" +
". Bu icazə olmadan" +
" funksiya işləməyəcək."
)
.setPositiveButton("İcazə ver") { _, _ ->
requestPermissionLauncher.launch(permission)
}
.setNegativeButton("Ləğv et", null)
.show()
}
Material Design ən yaxşı təcrübələri rationale üçün modal dialoq əvəzinə bottom sheet və ya inline-banner istifadə etməyi tövsiyə edir. Bottom sheet daha az müdaxiləlidir və istifadəçiyə kontekst verir. Ekrandakı inline element (məsələn, izah və İcazə Ver düyməsi olan kart) funksiyanın icazə olmadan əlçatan olmadığını göstərir, lakin qalan interfeysi bloklamır.
Rationale mətni lokallaşdırılmalı və konkret funksiyaya uyğunlaşdırılmalıdır. “Bu, proqramın işləməsi üçün lazımdır” kimi ümumi ifadələrdən istifadə etməyin. Konkret olaraq qeyd edin: “Yaxınlığınızdakı hava proqnozunu göstərmək üçün” və ya “Şəkilləri qalereyaya yadda saxlamaq üçün”. Google UX Research məlumatına görə, konkret izahlar icazənin verilmə ehtimalını 50 faiz artırır.
shouldShowRequestPermissionRationale = true (ilk rədd) ilə DENIED olduqda false (Never Ask Again) arasındakı fərq — icazələrin emalında əsas məqamdır. Birinci halda istifadəçi tərəddüd edirdi və əlavə izah onu giriş verməyə inandıra bilər. İkinci halda — istifadəçi son qərarını verib və təkrari sistem dialoqu yalnız qıcıq yaradacaq.
Rədddən sonra emal alqoritmi belə olmalıdır:
Sıralamanı qarışdırmamaq vacibdir: əvvəlcə shouldShowRequestPermissionRationale’i yoxlayın, checkSelfPermission’i yox. checkSelfPermission hər iki halda DENIED qaytaracaq. Yalnız shouldShowRequestPermissionRationale ilk rəddi Never Ask Again-dən fərqləndirir. SavedStateHandle və ya SharedPreferences istifadə edərək “ilk sorğu oldu” bayrağını saxlayın — bu, “tələb olunmayıb” ilə “bloklanıb” arasında fərq qoymağın yeganə etibarlı yoludur.
Rationale’i yalnız bir dəfə göstərin. Əgər istifadəçi rationaledən sonra sorğunu yenidən rədd edibsə — bir daha izah göstərməyin. Birbaşa parametrlərin açılması təklifinə keçin. Rationale’in təkrari göstərilməsi narahatlıq kimi qəbul edilir və proqramın reytinqini aşağı salır. Optimal ssenari: sorğu — rədd — rationale — təkrari sorğu — rədd — Parametrlər.
İlk sorğudan əvvəl rationale göstərməyin. Bəzi tərtibatçılar “istifadəçi başa düşməlidir” deyərək ilk dialoqdan əvvəl izah göstərmək səhvini edirlər. Bu, UX-i pisləşdirir: istifadəçi bir əvəzinə ardıcıl iki dialoq görür. Google tövsiyə edir sistem dialoqunu dərhal göstərməyi, rationale isə yalnız rədddən sonra göstərməyi.
Funksiyanın həqiqətən lazım olduğu ana bağlı kontekstual rationaledən istifadə edin. Proqramın başlanğıcında bütün icazələri tələb etməyin — bu, ən aşağı verilmə göstəricisidir. İstifadəçi “Şəkil çək” düyməsini basdıqda CAMERA, xəritəni açdıqda LOCATION tələb edin. Rationale ilə birlikdə kontekstual sorğu verilməni başlanğıc sorğusunda 30 faizə qarşı 80 faizə qədər artırır.
shouldShowRequestPermissionRationale’in test edilməsi cədvəlin dörd vəziyyətinin yoxlanmasını tələb edir: tələb olunmayıb, verilib, rədd edilib, Never Ask Again. Vahid testlərdə konfiqurasiya olunan shouldShowRationale davranışı olan FakePermissionHandler istifadə olunur. Instrumental testlərdə — sistem dialoqlarına cavabların emulyasiyası ilə UiAutomator və ya Espresso.
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
)
}
}
Instrumental test üçün əsas ssenari — rationale dialoqunun ilk rədddən sonra həqiqətən göründüyünü yoxlamaqdır. Sistem dialoqunu gözləmək üçün idling resources ilə Espresso istifadə edin, sonra Deny basın, izah mətni ilə fərdi dialoqun göründüyünü yoxlayın və Allow basın — verilməni yoxlayın. UIAutomator düymə mətni ilə sistem dialoqu ilə qarşılıqlı əlaqəyə imkan verir ki, bu da testi daha sabit edir.
Həmçinin rationale dialoqu daxilində rədd ssenarisini test etməyə dəyər. Əgər istifadəçi fərdi izahda Deny basıbsa, shouldShowRequestPermissionRationale yenidən true qaytarmalıdır, çünki Never Ask Again hələ aktivləşdirilməyib. Ən yaxşı təcrübə — ardıcıl iki rədddən sonra istifadəçini təkrari izahlarla qıcıqlandırmamaq və proqram reytinqini aşağı salmamaq üçün birbaşa Parametrlərə yönləndirməkdir.
Tez-tez verilən suallar
true — əgər sorğu əvvəllər rədd edilibsə və Never Ask Again təyin edilməyibsə. false — əgər icazə tələb olunmayıbsa, verilibsə və ya əbədi bloklanıbsa. false + DENIED kombinasiyası əlavə bayraq vasitəsilə yoxlama tələb edir.
Rationale’i yalnız istifadəçinin ilk rəddindən sonra, shouldShowRequestPermissionRationale true qaytardıqda göstərin. İlk sorğudan əvvəl rationale lazım deyil — bu, UX-i pisləşdirir və lazımsız dialoqlar yaradır.
SharedPreferences və ya SavedStateHandle-də isFirstRequest bayrağını saxlayın. Əgər shouldShowRationale = false, checkSelfPermission = DENIED və bayraq = true — bu, Never Ask Again’in aktivləşdirildiyi deməkdir. Əgər bayraq = false — bu ilk sorğudur.
İstifadəçini ACTION_APPLICATION_DETAILS_SETTINGSə yönləndirən “Parametrləri aç” düyməsi ilə dialoq göstərin. requestPermissions’i təkrari çağırmayın — dialoq görünməyəcək və nəticə mesaj olmadan DENIED gələcək.
Vahid testlərdə konfiqurasiya olunan shouldShowRationale sahəsi ilə FakePermissionHandler istifadə edin. Instrumental testlərdə — sistem dialoqunun emulyasiyası ilə Espresso və ya UIAutomator. Cədvəldən bütün 4 vəziyyyəti yoxlayın.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun