Το Dangerous Permission είναι μια κατηγορία αδειών στο Android που απαιτούν ρητή συγκατάθεση του χρήστη μέσω διαλόγου runtime κατά τη λειτουργία της εφαρμογής. Σύμφωνα με τον Android Developer Guide, 2024, οι επικίνδυνες άδειες έχουν ProtectionLevel dangerous και παρέχουν πρόσβαση σε εμπιστευτικά δεδομένα: κάμερα, μικρόφωνο, γεωτοποθεσία και επαφές. Χωρίς ρητή συγκατάθεση του χρήστη, η εφαρμογή δεν μπορεί να χρησιμοποιήσει αυτές τις λειτουργίες.
Κύρια σημεία
Dangerous Permission είναι μια κατηγορία αδειών συστήματος Android που παρέχουν πρόσβαση σε εμπιστευτικά δεδομένα χρήστη. Σε αντίθεση με τις κανονικές άδειες, οι επικίνδυνες άδειες δεν εκδίδονται αυτόματα κατά την εγκατάσταση — η εφαρμογή πρέπει να τις ζητήσει ρητά κατά το χρόνο εκτέλεσης μέσω του μηχανισμού runtime που εισήχθη στο Android 6.0 Marshmallow (API 23).
Η ανάγκη για ρητό αίτημα οφείλεται στη φύση των δεδομένων που προστατεύουν αυτές οι άδειες: γεωτοποθεσία χρήστη, προσωπικές επαφές, περιεχόμενο κάμερας και μικροφώνου, ιστορικό κλήσεων και SMS. Το Android θεωρεί αυτά τα δεδομένα ευαίσθητα και απαιτεί συνειδητή συγκατάθεση του χρήστη. Σύμφωνα με το Android Privacy Sandbox (2024), οι χρήστες απορρίπτουν κατά μέσο όρο περίπου το 30 τοις εκατό των αιτημάτων runtime.
Το βασικό χαρακτηριστικό του Dangerous Permission — η δυνατότητα ανάκλησης ανά πάσα στιγμή. Ο χρήστης μπορεί να πάει στις Ρυθμίσεις — Εφαρμογές — Άδειες και να αλλάξει τον διακόπτη για οποιαδήποτε επικίνδυνη άδεια. Η εφαρμογή πρέπει να είναι προετοιμασμένη ότι η άδεια που έχει χορηγηθεί μπορεί να ανακληθεί ανά πάσα στιγμή χωρίς επανεκκίνηση.
Το επίπεδο προστασίας dangerous ορίζεται στους ορισμούς συστήματος των αδειών σε επίπεδο OS. Όταν η εφαρμογή δηλώνει uses-permission με τέτοιο protectionLevel, το σύστημα επισημαίνει την άδεια ως απαιτούσα αίτημα runtime. Σε αντίθεση με το normal, οι dangerous άδειες εμφανίζονται πάντα στο UI διαχείρισης αδειών του συστήματος και μπορούν να ανακληθούν.
Όλες οι επικίνδυνες άδειες ομαδοποιούνται σε Permission Group βάσει λειτουργικού χαρακτηριστικού. Για παράδειγμα, οι CAMERA και CAMERA2 βρίσκονται στην ομάδα CAMERA, οι ACCESS_FINE_LOCATION και ACCESS_COARSE_LOCATION — στην ομάδα LOCATION. Εάν ο χρήστης έχει χορηγήσει μία άδεια από την ομάδα, οι υπόλοιπες άδειες της ίδιας ομάδας χορηγούνται αυτόματα χωρίς πρόσθετο διάλογο.
Το αίτημα runtime είναι ο μηχανισμός με τον οποίο η εφαρμογή καλεί το API συστήματος για να εμφανίσει ένα διάλογο με αίτημα άδειας. Ο χρήστης βλέπει ένα modal παράθυρο με το όνομα της άδειας και τα κουμπιά Allow και Deny. Μετά την απάντηση, το σύστημα καλεί το callback onRequestPermissionsResult με το αποτέλεσμα.
Ο πλήρης κύκλος περιλαμβάνει τρία βήματα: έλεγχος κατάστασης μέσω checkSelfPermission, κλήση requestPermissions ελλείψει άδειας και επεξεργασία αποτελέσματος στο onRequestPermissionsResult. Ο έλεγχος κατάστασης είναι υποχρεωτικός, επειδή ο χρήστης μπορεί να ανακαλέσει την άδεια ανά πάσα στιγμή μέσω ρυθμίσεων και η κλήση της συνάρτησης χωρίς έλεγχο θα οδηγήσει σε SecurityException.
fun checkAndRequestCameraPermission() {
when {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
openCamera()
}
else -> {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.CAMERA),
REQUEST_CAMERA_CODE
)
}
}
}
Η επεξεργασία του αποτελέσματος γίνεται στο ActivityResultLauncher ή στο onRequestPermissionsResult. Η συνιστώμενη σύγχρονη προσέγγιση — η χρήση του ActivityResultContracts.RequestPermission, που παρέχει καθαρότερο API χωρίς ρητούς κωδικούς αιτήματος. Αυτό το συμβόλαιο επιστρέφει Boolean — εάν η άδεια χορηγήθηκε ή όχι.
Ζητήστε επικίνδυνες άδειες αυστηρά στο πλαίσιο χρήσης της λειτουργίας, όχι κατά την εκκίνηση της εφαρμογής. Εάν ο χρήστης πάτησε το κουμπί της κάμερας — ζητήστε CAMERA. Εάν άνοιξε τον χάρτη — ζητήστε LOCATION. Το συμφραζόμενο αίτημα δίνει διπλάσιες εγκρίσεις από το αίτημα όλων των αδειών κατά την πρώτη εκκίνηση. Επίσης συνιστάται να μην ζητάτε περισσότερες από μία άδειες τη φορά, ώστε ο χρήστης να καταλαβαίνει ποια λειτουργία απαιτεί πρόσβαση.
Το Android ορίζει πολλές ομάδες επικίνδυνων αδειών, καθεμία από τις οποίες περιέχει από μία έως πολλές σταθερές. Η πληρέστερη λίστα παρουσιάζεται στην κλάση Manifest.permission. Παρακάτω παρουσιάζονται οι κύριες ομάδες και άδειες που χρησιμοποιούνται στην ανάπτυξη.
| Ομάδα Permission Group | Άδειες | API πρόσβασης |
|---|---|---|
| CAMERA | CAMERA | Camera API, CameraX |
| LOCATION | ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION | FusedLocationProvider, Geofence |
| MICROPHONE | RECORD_AUDIO | MediaRecorder, AudioRecord |
| PHONE | READ_PHONE_STATE, CALL_PHONE, READ_CALL_LOG | TelephonyManager |
| CONTACTS | READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS | ContactsContract |
| SMS | READ_SMS, SEND_SMS, RECEIVE_SMS | SmsManager |
| STORAGE | READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE | MediaStore, File API |
| CALENDAR | READ_CALENDAR, WRITE_CALENDAR | CalendarContract |
Από το Android 12, η Google αυστηροποίησε τις απαιτήσεις για ορισμένες άδειες. Για παράδειγμα, οι BLUETOOTH_CONNECT και BLUETOOTH_SCAN έγιναν επικίνδυνες και απαιτούν αίτημα runtime. Εμφανίστηκε επίσης η άδεια BODY_SENSORS_BACKGROUND για πρόσβαση παρασκηνίου σε αισθητήρες. Οι προγραμματιστές πρέπει να ενημερώνουν το targetSdkVersion και να δοκιμάζουν τα αιτήματα στις τρέχουσες εκδόσεις OS.
Το Android 13 (API 33) εισήγαγε νέες άδειες για ειδοποιήσεις (POST_NOTIFICATIONS) και για αρχεία πολυμέσων (READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_AUDIO), αντικαθιστώντας τη γενική READ_EXTERNAL_STORAGE. Τώρα η πρόσβαση σε φωτογραφίες, βίντεο και ήχο ζητείται ξεχωριστά μέσω εξειδικευμένων αδειών χωρίς ενιαίο διάλογο.
Οι Dangerous και Normal Permission διαφέρουν θεμελιωδώς ως προς τον τρόπο χορήγησης, τη δυνατότητα ανάκλησης και την UX. Η Normal εκδίδεται αυτόματα κατά την εγκατάσταση, η Dangerous απαιτεί ρητό διάλογο runtime. Η Normal δεν μπορεί να ανακληθεί μέσω ρυθμίσεων, η Dangerous μπορεί να απενεργοποιηθεί ανά πάσα στιγμή. Αυτή η ασυμμετρία δημιουργεί διαφορετικά μοτίβα ανάπτυξης.
Από άποψη κώδικα, οι επικίνδυνες άδειες απαιτούν περισσότερη δουλειά: checkSelfPermission, requestPermissions, χειρισμός άρνησης. Για τις Normal αρκεί μία γραμμή στο AndroidManifest.xml. Ταυτόχρονα, το Dangerous Permission δίνει στον χρήστη έλεγχο, αυξάνοντας την εμπιστοσύνη, ειδικά για ευαίσθητες λειτουργίες όπως κάμερα ή γεωτοποθεσία.
Η επιλογή μεταξύ κατηγοριών δεν βρίσκεται μπροστά στον προγραμματιστή — καθορίζεται από το σύστημα. Ο προγραμματιστής δηλώνει μόνο uses-permission και το σύστημα βάσει protectionLevel καθορίζει την κατηγορία. Ωστόσο, η στρατηγική αιτήματος επικίνδυνων αδειών επηρεάζει την εμπειρία χρήστη: οι συχνοί ή ακατάλληλοι διάλογοι μειώνουν την αξιολόγηση της εφαρμογής.
Ο σύγχρονος τρόπος αιτήματος αδειών σε Kotlin — η χρήση ActivityResultContracts.RequestMultiplePermissions ή RequestPermission. Αυτά τα συμβόλαια αποτελούν μέρος της βιβλιοθήκης androidx.activity και παρέχουν καθαρό API βασισμένο σε λάμδα, χωρίς ανάγκη υπερφόρτωσης του onRequestPermissionsResult.
class CameraActivity : AppCompatActivity() {
private val requestPermissionLauncher =
registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
openCamera()
} else {
showPermissionDeniedMessage()
}
}
fun requestCamera() {
when {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED ->
openCamera()
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.CAMERA
) ->
showRationaleDialog()
else ->
requestPermissionLauncher.launch(
Manifest.permission.CAMERA
)
}
}
}
Όταν η εφαρμογή χρειάζεται πολλές επικίνδυνες άδειες ταυτόχρονα, χρησιμοποιήστε το RequestMultiplePermissions. Το συμβόλαιο επιστρέφει Map<String, Boolean> όπου το κλειδί είναι το όνομα της άδειας και η τιμή είναι το αποτέλεσμα. Αυτό είναι βολικό κατά την πρώτη εκκίνηση όταν χρειάζονται CAMERA και RECORD_AUDIO για εγγραφή βίντεο.
Εάν ο χρήστης απέρριψε το αίτημα, η μέθοδος shouldShowRequestPermissionRationale επιστρέφει true. Αυτό είναι ένα σήμα για εμφάνιση εξήγησης σχετικά με το γιατί χρειάζεται η άδεια. Βέλτιστη πρακτική — εμφάνιση προσαρμοσμένου διαλόγου με εξήγηση και κουμπί Επανάληψης. Εάν ο χρήστης απέρριψε ξανά το αίτημα με το σημάδι Never Ask Again, το shouldShowRequestPermissionRationale θα επιστρέψει false και πρέπει να ανακατευθύνει στις Ρυθμίσεις.
Το Never Ask Again είναι μια σημαία που ο χρήστης μπορεί να ορίσει κατά την εκ νέου απόρριψη του διαλόγου runtime. Μετά από αυτό, το τυπικό παράθυρο διαλόγου δεν εμφανίζεται πλέον για αυτήν την άδεια. Ο μόνος τρόπος παροχής πρόσβασης — η ανακατεύθυνση του χρήστη στις ρυθμίσεις συστήματος εφαρμογών.
Ο προγραμματιστής πρέπει να διακρίνει δύο σενάρια άρνησης: πρώτο — όταν το shouldShowRequestPermissionRationale επιστρέφει true (ο χρήστης απέρριψε αλλά ο διάλογος μπορεί ακόμα να εμφανιστεί) και δεύτερο — όταν η μέθοδος επιστρέφει false (το Never Ask Again είναι ενεργό ή η άδεια είναι αποκλεισμένη από πολιτική). Στη δεύτερη περίπτωση, πρέπει να εμφανιστεί ένα κουμπί Άνοιγμα ρυθμίσεων.
fun handlePermissionDenied(permission: String) {
if (ActivityCompat.shouldShowRequestPermissionRationale(
this, permission
)) {
showRationaleDialog(permission)
} else {
showSettingsRedirectDialog(permission)
}
}
private fun showSettingsRedirectDialog(permission: String) {
AlertDialog.Builder(this)
.setTitle("Απαγορευμένη πρόσβαση")
.setMessage(
"Η άδεια είναι μπλοκαρισμένη. Ανοίξτε τις ρυθμίσεις."
)
.setPositiveButton("Ρυθμίσεις") { _, _ ->
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts(
"package", packageName, null
)
)
startActivity(intent)
}
.show()
}
Είναι σημαντικό να μην ζητάτε ξανά την άδεια εάν το shouldShowRequestPermissionRationale επέστρεψε false. Η επαναλαμβανόμενη κλήση του requestPermissions σε αυτήν την περίπτωση δεν θα εμφανίσει διάλογο — το αποτέλεσμα θα έρθει αμέσως με DENIED χωρίς εξήγηση. Ο χρήστης θα αντιμετωπίσει ακατανόητη συμπεριφορά, η οποία θα επηρεάσει αρνητικά την εμπειρία χρήσης της εφαρμογής.
Συχνές Ερωτήσεις
Στο Dangerous Permission ανήκουν άδειες με ProtectionLevel dangerous: CAMERA, RECORD_AUDIO, ACCESS_FINE_LOCATION, READ_CONTACTS, READ_SMS, READ_CALENDAR και άλλες. Η πλήρης λίστα είναι διαθέσιμη στην κλάση Manifest.permission.
Χρησιμοποιήστε το ContextCompat.checkSelfPermission, μεταδίδοντας το περιβάλλον και το όνομα της άδειας. Η μέθοδος επιστρέφει PERMISSION_GRANTED ή PERMISSION_DENIED. Ο έλεγχος πρέπει να εκτελείται πριν από κάθε κλήση API που απαιτεί επικίνδυνη άδεια.
Permission Group ομαδοποιεί σχετικές επικίνδυνες άδειες. Εάν ο χρήστης έχει χορηγήσει μία άδεια από την ομάδα, οι υπόλοιπες χορηγούνται αυτόματα. Για παράδειγμα, το LOCATION περιλαμβάνει ACCESS_FINE_LOCATION και ACCESS_COARSE_LOCATION.
Ελέγξτε το shouldShowRequestPermissionRationale μετά την άρνηση. Εάν η μέθοδος επέστρεψε false και η άδεια δεν έχει ακόμα χορηγηθεί — το Never Ask Again είναι ενεργό. Ανακατευθύνετε τον χρήστη στις Ρυθμίσεις μέσω Intent με ACTION_APPLICATION_DETAILS_SETTINGS.
Ναι, παραμένουν υποχρεωτικές. Σε Android 13+ ορισμένες άδειες άλλαξαν: η POST_NOTIFICATIONS έγινε ξεχωριστή άδεια runtime και η READ_EXTERNAL_STORAGE αντικαταστάθηκε από READ_MEDIA_IMAGES για ακριβή πρόσβαση σε αρχεία πολυμέσων.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης