shouldShowRequestPermissionRationale — είναι μια μέθοδος Android API που υποδεικνύει στον προγραμματιστή αν πρέπει να δείξει μια εξήγηση στον χρήστη πριν ζητήσει μια επικίνδυνη άδεια. Σύμφωνα με το Android Developer Reference, 2024, η rational μέθοδος επιστρέφει true αν ο χρήστης έχει απορρίψει προηγουμένως το αίτημα, αλλά δεν έχει ορίσει τη σημαία Never Ask Again. Είναι ένα βασικό εργαλείο για την οικοδόμηση ευγενικής UX κατά την εργασία με άδειες χρόνου εκτέλεσης.
Κύρια σημεία
shouldShowRequestPermissionRationale — είναι μια μέθοδος των κλάσεων Activity και Fragment στο Android, διαθέσιμη μέσω ActivityCompat για συμβατότητα. Δέχεται το όνομα της άδειας και επιστρέφει Boolean που υποδεικνύει αν πρέπει να εμφανιστεί μια επιπλέον εξήγηση στον χρήστη πριν από επαναληπτικό αίτημα. Η μέθοδος εμφανίστηκε στο Android 6.0 Marshmallow μαζί με το μοντέλο αδειών χρόνου εκτέλεσης.
Ο μηχανισμός rationale βασίζεται στην παρακολούθηση του ιστορικού αλληλεπίδρασης του χρήστη με τα παράθυρα αδειών. Το σύστημα θυμάται αν ο χρήστης απέρριψε το αίτημα προηγουμένως. Αν η απόρριψη συνέβη χωρίς τον ορισμό της σημαίας Never Ask Again, η shouldShowRequestPermissionRationale επιστρέφει true. Αυτό είναι ένα σήμα για τον προγραμματιστή: ο χρήστης δεν καταλαβαίνει γιατί χρειάζεται η άδεια και απαιτείται επιπλέον εξήγηση. Σύμφωνα με τις Google Material Design Guidelines, η εμφάνιση του παραθύρου rationale μετά την πρώτη άρνηση αυξάνει την πιθανότητα εκ νέου χορήγησης της άδειας κατά 35 ποσοστό.
Είναι σημαντικό να κατανοήσετε τη σημασιολογία των επιστρεφόμενων τιμών: true σημαίνει ότι έχει νόημα να εμφανιστεί το παράθυρο, false — το παράθυρο είτε δεν χρειάζεται (η άδεια έχει ήδη χορηγηθεί ή δεν έχει ζητηθεί ποτέ) είτε είναι άχρηστο (το Never Ask Again είναι ενεργό). Η μέθοδος δεν είναι εγγύηση ότι το παράθυρο θα εμφανιστεί — δίνει απλώς μια σύσταση. Ο προγραμματιστής αποφασίζει μόνος του ποιο UI θα εμφανίσει ως απάντηση.
Η shouldShowRequestPermissionRationale εισήχθη στο API Level 23 μαζί με μια ομάδα μεθόδων για άδειες χρόνου εκτέλεσης. Πριν από το Android 6.0, όλες οι άδειες ζητούνταν κατά την εγκατάσταση και δεν απαιτούνταν μηχανισμός εξήγησης — ο χρήστης αποδεχόταν ή απέρριπτε ολόκληρη τη λίστα μονομιάς. Το μοντέλο χρόνου εκτέλεσης κατέστησε δυνατή την κατάσταση όπου ο χρήστης απορρίπτει το αίτημα χωρίς να κατανοεί το πλαίσιο και ακριβώς γι' αυτό χρειάζεται το rationale.
Η λογική της μεθόδου είναι η εξής. Κατά την πρώτη κλήση της requestPermissions για μια συγκεκριμένη άδεια, η shouldShowRequestPermissionRationale επιστρέφει false — ο χρήστης δεν έχει ακόμα συναντήσει το παράθυρο. Αν ο χρήστης απέρριψε το αίτημα (πάτησε Deny), η μέθοδος αρχίζει να επιστρέφει true. Μετά από επαναληπτική απόρριψη με τη σημαία Never Ask Again, η μέθοδος επιστρέφει false.
Πλήρης πίνακας καταστάσεων:
| Κατάσταση | shouldShowRationale | checkSelfPermission | Ενέργεια προγραμματιστή |
|---|---|---|---|
| Δεν έχει ζητηθεί | false | DENIED | Εμφάνιση συστήματος παραθύρου |
| Έχει χορηγηθεί | false | GRANTED | Εκτέλεση λειτουργίας |
| Απορρίφθηκε πρώτη φορά | true | DENIED | Εμφάνιση rationale, μετά σύστημα παραθύρου |
| Never Ask Again | false | DENIED | Ανακατεύθυνση στις Ρυθμίσεις |
Ο συνδυασμός shouldShowRequestPermissionRationale = false και checkSelfPermission = DENIED — είναι η πιο δύσκολη περίπτωση για επεξεργασία. Σημαίνει ότι είτε η άδεια δεν έχει ζητηθεί ποτέ, είτε το Never Ask Again έχει οριστεί. Ο προγραμματιστής πρέπει να διακρίνει αυτές τις δύο καταστάσεις. Ο μόνος τρόπος — η αποθήκευση της σημαίας firstRequest στο SharedPreferences ή η χρήση SavedStateHandle. Κατά το πρώτο αίτημα, ορίστε τη σημαία και αν η shouldShowRationale επέστρεψε false και η σημαία είναι ήδη true — σημαίνει Never Ask Again.
Η shouldShowRequestPermissionRationale επαναφέρεται αν ο χρήστης διαγράψει και επανεγκαταστήσει την εφαρμογή, καθαρίσει τα δεδομένα της εφαρμογής ή επαναφέρει τις ρυθμίσεις αδειών. Μετά από επανεγκατάσταση, η μέθοδος θα επιστρέψει ξανά false για το πρώτο αίτημα. Οι ενημερώσεις συστήματος και η αλλαγή έκδοσης Android δεν επαναφέρουν το ιστορικό — αποθηκεύεται στα δεδομένα της εφαρμογής.
Η σωστή υλοποίηση του rationale περιλαμβάνει τρία συστατικά: έλεγχο της shouldShowRequestPermissionRationale μετά από άρνηση, εμφάνιση προσαρμοσμένου παραθύρου με εξήγηση και επαναληπτική κλήση της requestPermissions μετά από θετική απάντηση του χρήστη. Το παράθυρο πρέπει να είναι σύντομο, συγκεκριμένο και να εξηγεί γιατί η εφαρμογή χρειάζεται ακριβώς αυτήν την άδεια.
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("Γιατί χρειάζεται πρόσβαση στη γεωτοποθεσία")
.setMessage(
"Η εφαρμογή χρησιμοποιεί γεωτοποθεσία για σημείωση τοποθεσιών στο χάρτη" +
". Χωρίς αυτήν την άδεια" +
" η λειτουργία δεν θα λειτουργεί."
)
.setPositiveButton("Επιτρέπω") { _, _ ->
requestPermissionLauncher.launch(permission)
}
.setNegativeButton("Άκυρο", null)
.show()
}
Οι βέλτιστες πρακτικές Material Design συνιστούν τη χρήση bottom sheet ή inline banner αντί για modal παράθυρο για το rationale. Το bottom sheet είναι λιγότερο ενοχλητικό και δίνει πλαίσιο στον χρήστη. Το ενσωματωμένο στοιχείο στην οθόνη (για παράδειγμα, μια κάρτα με εξήγηση και κουμπί Επιτρέπω) δείχνει ότι η λειτουργία δεν είναι διαθέσιμη χωρίς άδεια, αλλά δεν μπλοκάρει την υπόλοιπη διεπαφή.
Το κείμενο του rationale πρέπει να είναι μεταφρασμένο και προσαρμοσμένο στη συγκεκριμένη λειτουργία. Μην χρησιμοποιείτε γενικές φράσεις όπως “Αυτό χρειάζεται για τη λειτουργία της εφαρμογής”. Αναφέρετε συγκεκριμένα: “Για την εμφάνιση του καιρού κοντά σας” ή “Για την αποθήκευση φωτογραφιών στη συλλογή”. Σύμφωνα με την Google UX Research, οι συγκεκριμένες εξηγήσεις αυξάνουν την πιθανότητα χορήγησης της άδειας κατά 50 ποσοστό.
Η διαφορά μεταξύ shouldShowRequestPermissionRationale = true (πρώτη άρνηση) και false με DENIED (Never Ask Again) — είναι το κλειδί σημείο στην επεξεργασία αδειών. Στην πρώτη περίπτωση, ο χρήστης δίσταζε και μια επιπλέον εξήγηση μπορεί να τον πείσει να παραχωρήσει πρόσβαση. Στη δεύτερη — ο χρήστης πήρε τελική απόφαση και ένα επαναληπτικό σύστημα παράθυρο θα προκαλέσει μόνο εκνευρισμό.
Ο αλγόριθμος επεξεργασίας μετά από άρνηση πρέπει να είναι ως εξής:
Είναι σημαντικό να μην μπερδεύετε τη σειρά: πρώτα ελέγξτε την shouldShowRequestPermissionRationale, όχι την checkSelfPermission. Η checkSelfPermission θα επιστρέψει DENIED και στις δύο περιπτώσεις. Μόνο η shouldShowRequestPermissionRationale διακρίνει την πρώτη άρνηση από το Never Ask Again. Χρησιμοποιήστε SavedStateHandle ή SharedPreferences για την αποθήκευση της σημαίας “το πρώτο αίτημα έγινε” — αυτός είναι ο μόνος αξιόπιστος τρόπος να διακρίνετε το “δεν έχει ζητηθεί” από το “αποκλείστηκε”.
Εμφανίστε το rationale μόνο μία φορά. Αν ο χρήστης απέρριψε ξανά το αίτημα μετά το rationale — μην εμφανίσετε άλλη εξήγηση. Μεταβείτε απευθείας στην πρόταση να ανοίξετε τις ρυθμίσεις. Η επαναλαμβανόμενη εμφάνιση του rationale γίνεται αντιληπτή ως ενοχλητική και μειώνει την αξιολόγηση της εφαρμογής. Βέλτιστο σενάριο: αίτημα — άρνηση — rationale — επαναληπτικό αίτημα — άρνηση — Ρυθμίσεις.
Μην εμφανίζετε το rationale πριν από το πρώτο αίτημα. Μερικοί προγραμματιστές λανθασμένα εμφανίζουν εξήγηση πριν από το πρώτο παράθυρο, υποστηρίζοντας ότι “ο χρήστης πρέπει να καταλάβει”. Αυτό χειροτερεύει την UX: ο χρήστης βλέπει δύο διαδοχικά παράθυρα αντί για ένα. Η Google συνιστά να εμφανίζετε το σύστημα παράθυρο αμέσως και το rationale μόνο μετά από άρνηση.
Χρησιμοποιήστε συγκειμενικό rationale, συνδεδεμένο με τη στιγμή που η λειτουργία είναι πραγματικά απαραίτητη. Μην ζητάτε όλες τις άδειες κατά την εκκίνηση της εφαρμογής — αυτό είναι το χαμηλότερο ποσοστό χορήγησης. Ζητήστε CAMERA όταν ο χρήστης πάτησε το κουμπί “Λήψη Φωτογραφίας” και LOCATION όταν άνοιξε τον χάρτη. Το συγκειμενικό αίτημα σε συνδυασμό με το rationale αυξάνει τη χορήγηση σε 80 ποσοστό έναντι 30 ποσοστό στο αρχικό αίτημα.
Η δοκιμή της shouldShowRequestPermissionRationale απαιτεί τον έλεγχο τεσσάρων καταστάσεων από τον πίνακα: δεν έχει ζητηθεί, έχει χορηγηθεί, έχει απορριφθεί, Never Ask Again. Στις μοναδιαίες δοκιμές χρησιμοποιείται FakePermissionHandler με ρυθμιζόμενη συμπεριφορά shouldShowRationale. Στις οργανικές δοκιμές — UiAutomator ή 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
)
}
}
Το βασικό σενάριο για την οργανική δοκιμή — έλεγχος ότι το παράθυρο rationale εμφανίζεται πράγματι μετά την πρώτη άρνηση. Χρησιμοποιήστε Espresso με idling resources για να περιμένετε το σύστημα παράθυρο, στη συνέχεια πατήστε Deny, ελέγξτε την εμφάνιση του προσαρμοσμένου παραθύρου με το κείμενο εξήγησης και πατήστε Allow — ελέγξτε τη χορήγηση. Το UIAutomator επιτρέπει την αλληλεπίδραση με το σύστημα παράθυρο μέσω του κειμένου του κουμπιού, κάνοντας τη δοκιμή πιο σταθερή.
Επίσης αξίζει να δοκιμάσετε το σενάριο άρνησης μέσα στο παράθυρο rationale. Αν ο χρήστης πάτησε Deny στην προσαρμοσμένη εξήγηση, η shouldShowRequestPermissionRationale πρέπει να επιστρέψει ξανά true, επειδή το Never Ask Again δεν έχει ακόμα ενεργοποιηθεί. Βέλτιστη πρακτική — μετά από δύο διαδοχικές αρνήσεις να ανακατευθύνετε απευθείας στις Ρυθμίσεις για να μην ενοχλείτε τον χρήστη με επαναλαμβανόμενες εξηγήσεις και να μην μειώνετε την αξιολόγηση της εφαρμογής.
Συχνές ερωτήσεις
true — αν το αίτημα απορρίφθηκε προηγουμένως και το Never Ask Again δεν έχει οριστεί. false — αν η άδεια δεν έχει ζητηθεί, έχει χορηγηθεί ή είναι μόνιμα αποκλεισμένη. Ο συνδυασμός false + DENIED απαιτεί έλεγχο μέσω επιπλέον σημαίας.
Εμφανίστε το rationale μόνο μετά την πρώτη άρνηση του χρήστη, όταν η shouldShowRequestPermissionRationale επέστρεψε true. Πριν από το πρώτο αίτημα, το rationale δεν χρειάζεται — αυτό χειροτερεύει την UX και δημιουργεί περιττά παράθυρα.
Αποθηκεύστε τη σημαία isFirstRequest στο SharedPreferences ή SavedStateHandle. Αν shouldShowRationale = false, checkSelfPermission = DENIED και η σημαία = true — σημαίνει ότι το Never Ask Again έχει ενεργοποιηθεί. Αν η σημαία = false — αυτό είναι το πρώτο αίτημα.
Εμφανίστε ένα παράθυρο με κουμπί “Άνοιγμα Ρυθμίσεων” που ανακατευθύνει τον χρήστη στο ACTION_APPLICATION_DETAILS_SETTINGS. Μην καλέσετε ξανά την requestPermissions — το παράθυρο δεν θα εμφανιστεί και το αποτέλεσμα θα έρθει με DENIED χωρίς μήνυμα.
Στις μοναδιαίες δοκιμές, χρησιμοποιήστε FakePermissionHandler με ρυθμιζόμενο πεδίο shouldShowRationale. Στις οργανικές δοκιμές — Espresso ή UIAutomator με προσομοίωση του συστήματος παραθύρου. Ελέγξτε και τις 4 καταστάσεις από τον πίνακα.
Περίληψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης