Runtime Permission — mechanizm żądania uprawnień w czasie wykonywania aplikacji, wprowadzony w Android 6.0 (API 23). W przeciwieństwie do ustawiania uprawnień podczas instalacji, runtime permissions pozwalają użytkownikowi udzielać lub cofać dostęp do poufnych danych (kamera, geolokalizacja, kontakty) w dowolnym momencie. Według danych Android Developers (2026), ponad 85% aplikacji w Google Play używa co najmniej jednego runtime permission.
Najważniejsze
Runtime Permission (uprawnienie czasu wykonania) — to model bezpieczeństwa Android, w którym aplikacja żąda dostępu do poufnych danych w momencie, gdy ta funkcjonalność jest rzeczywiście potrzebna użytkownikowi. Przed Android 6.0 wszystkie uprawnienia były udzielane podczas instalacji aplikacji, a użytkownik nie mógł ich cofnąć bez całkowitego usunięcia aplikacji.
Przed Android 6.0 użytkownik widział listę wszystkich uprawnień podczas instalacji i mógł albo zaakceptować wszystkie, albo zrezygnować z instalacji. Badanie z 2015 roku wykazało, że 87% użytkowników nie czyta listy uprawnień podczas instalacji. Android 6.0 wprowadził runtime permissions, dzieląc uprawnienia na normal (automatyczne) i dangerous (z żądaniem). Android 11 dodał one-time permissions — automatyczne cofanie po zamknięciu aplikacji. Android 13 wprowadził Photo Picker i powiadomienia push jako osobne runtime permissions.
iOS używa podobnego modelu od wersji iOS 10, gdzie dostęp do kamery, mikrofonu i geolokalizacji jest żądany przy pierwszym użyciu. Jednak iOS nie ma pojęcia „normal permissions“ — każde uprawnienie jest żądane jawnie, a odmowa jest zapisywana do czasu ponownego żądania przez programistę poprzez ustawienia systemowe.
Runtime Permission działa przez systemowe okno dialogowe wywoływane metodą requestPermissions() (AndroidX — ActivityResultLauncher). System wyświetla standardowe okno dialogowe z wyjaśnieniem, a użytkownik wybiera „Zezwól“ lub „Zabroń“. Po odpowiedzi wywoływane jest callback wyniku, w którym aplikacja obsługuje decyzję użytkownika.
private lateinit var requestPermissionLauncher: ActivityResultLauncher<String>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
startCamera()
} else {
showPermissionDeniedDialog()
}
}
}
private fun checkCameraPermission() {
when {
ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED -> {
startCamera()
}
ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA) -> {
showRationaleDialog { requestPermissionLauncher.launch(Manifest.permission.CAMERA) }
}
else -> {
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
}
}
}
Metoda shouldShowRequestPermissionRationale zwraca true, jeśli użytkownik już raz odrzucił żądanie. W tym przypadku zaleca się pokazanie okna dialogowego z wyjaśnieniem, dlaczego aplikacja potrzebuje uprawnienia, a dopiero potem ponowne żądanie. Zwiększa to prawdopodobieństwo zgody użytkownika o 30–40% (dane Google I/O 2024).
Android klasyfikuje wszystkie uprawnienia na kilka poziomów ochrony: normal, dangerous, signature i special. Normal permissions są udzielane automatycznie podczas instalacji. Dangerous permissions wymagają żądania runtime. Signature permissions są dostępne tylko dla aplikacji podpisanych tym samym certyfikatem.
| Grupa | Uprawnienia | API Level |
|---|---|---|
| CAMERA | CAMERA | API 23+ |
| LOCATION | ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, ACCESS_BACKGROUND_LOCATION | API 23+ (background — API 29+) |
| STORAGE | READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, READ_MEDIA_IMAGES (API 33+) | API 23+ (zmiany w API 33) |
| PHONE | READ_PHONE_STATE, CALL_PHONE, READ_CALL_LOG | API 23+ |
| MICROPHONE | RECORD_AUDIO | API 23+ |
| CONTACTS | READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS | API 23+ |
| NOTIFICATIONS | POST_NOTIFICATIONS | API 33+ |
Special permissions (SYSTEM_ALERT_WINDOW, WRITE_SETTINGS, MANAGE_EXTERNAL_STORAGE) wymagają dodatkowego przejścia do ustawień systemowych przez Settings.ACTION_MANAGE_OVERLAY_PERMISSION. Te uprawnienia nie mogą być żądane standardowym oknem dialogowym i wymagają wyraźnego przejścia użytkownika do ekranu ustawień.
Android 12 wprowadził znaczące zmiany w modelu runtime permissions. One-time permissions pozwalają udzielić dostępu do kamery, mikrofonu lub geolokalizacji tylko na jedną sesję. Gdy użytkownik zamknie aplikację, uprawnienie jest automatycznie cofane. Privacy indicators — zielone wskaźniki na pasku stanu pokazujące, kiedy aplikacja używa kamery lub mikrofonu.
// Android 12+ — obsługa jednorazowego uprawnienia geolokalizacji
private fun checkLocationPermission() {
val permissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
val fineLocationGranted = permissions[Manifest.permission.ACCESS_FINE_LOCATION]
val coarseLocationGranted = permissions[Manifest.permission.ACCESS_COARSE_LOCATION]
if (fineLocationGranted == true) {
showUserLocation()
} else {
showLocationDisabledDialog()
}
}
permissionLauncher.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
)
}
// Sprawdzenie, czy uprawnienie zostało cofnięte przez system (Android 12+)
class PermissionReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Intent.ACTION_PERMISSION_REVOCATION) {
handleRevokedPermission(intent.getStringExtra(Intent.EXTRA_REVOKED_PERMISSION))
}
}
}
Android 13 dodał uprawnienie POST_NOTIFICATIONS do grupy dangerous, wymagając wyraźnego żądania wysyłania powiadomień push. Android 14 wprowadził ograniczenia dotyczące geolokalizacji w tle: aplikacja musi uzyskać wyraźną zgodę użytkownika za każdym razem przy żądaniu background location. Photo Picker (API 33+) zastąpił potrzebę READ_EXTERNAL_STORAGE do wyboru obrazów.
Odmowa użytkownika udzielenia uprawnienia — to normalna sytuacja, którą należy poprawnie obsłużyć. Istnieją dwa typy odmowy: jednorazowa (użytkownik kliknął „Zabroń“) i stała (użytkownik wybrał „Nie pytaj więcej“). W drugim przypadku systemowe okno dialogowe nie będzie już wyświetlane, a aplikacja musi przekierować użytkownika do ustawień systemowych.
Po pierwszej odmowie aplikacja powinna pokazać rationale dialog — własne wyjaśnienie, dlaczego uprawnienie jest konieczne. Jeśli użytkownik ponownie odmówi, należy przekierować go do ekranu ustawień aplikacji przez Settings.ACTION_APPLICATION_DETAILS_SETTINGS. Material 3 zaleca używanie PermissionRequestBottomSheet dla bardziej naturalnego UX.
Ważne, aby nie blokować całkowicie funkcjonalności aplikacji przy odmowie. Na przykład, jeśli użytkownik odrzucił geolokalizację, aplikacja powinna zaproponować ręczne wprowadzenie adresu. Dla kamery — umożliwić załadowanie obrazu z galerii. Google zaleca zawsze zapewniać mechanizm fallback dla wszystkich runtime permissions.
Runtime permissions — to nie tylko mechanizm techniczny, ale także element zaufania użytkownika do aplikacji. Źądanie uprawnienia w nieodpowiednim momencie (na przykład przy pierwszym uruchomieniu) znacząco zmniejsza prawdopodobieństwo zgody. Google Play Store analizuje częstotliwość i kontekst żądań uprawnień: aplikacje z agresywnymi żądaniami otrzymują niższe pozycje w wyszukiwaniu.
Kontekst — żądaj uprawnienia bezpośrednio przed wykonaniem działania, które go wymaga. Minimum — żądaj tylko tych uprawnień, które są rzeczywiście niezbędne do działania funkcji. Przejrzystość — wyjaśnij użytkownikowi, dlaczego uprawnienie jest potrzebne, przed systemowym oknem dialogowym. Cofnięcie — subskrybuj ACTION_PERMISSION_REVOCATION do poprawnej obsługi cofnięcia uprawnienia w czasie wykonania.
Do testowania runtime permissions używaj poleceń adb: adb shell pm revoke <package> android.permission.CAMERA pozwala symulować cofnięcie uprawnienia bez ponownej instalacji aplikacji. Espresso i UiAutomator obsługują testowanie okien dialogowych uprawnień przez GrantPermissionRule. Integracja tych narzędzi w pipeline CI/CD jest obowiązkowa dla aplikacji z runtime permissions.
Google Play Console udostępnia sekcję Permission auditing (audyt uprawnień), gdzie programista widzi, jak często żądane są uprawnienia, jaki procent użytkowników udziela dostępu i które uprawnienia zostały cofnięte. Analiza tych danych pomaga zidentyfikować nieefektywne żądania i zoptymalizować UX. Na przykład, jeśli mniej niż 40% użytkowników udziela geolokalizacji, warto przeanalizować timing żądania i dodać bardziej przekonujące uzasadnienie.
Używanie Android Vitals do monitorowania permission-related ANR (Application Not Responding) jest również kluczowe. Jeśli żądanie uprawnienia wykonuje się na głównym wątku lub systemowe okno dialogowe blokuje UI, może to spowodować ANR na wolnych urządzeniach. Przenieś sprawdzanie i żądanie uprawnień do osobnego wątku lub użyj korutyn Kotlin do asynchronicznego przetwarzania, aby uniknąć blokowania interfejsu użytkownika.
Często zadawane pytania
shouldShowRequestPermissionRationale zwraca false przy stałej odmowie (gdy użytkownik wybrał „Nie pytaj więcej“). Metoda zwraca true przy jednorazowej odmowie, pozwalając pokazać rationale dialog. Jeśli metoda zwróciła false, jedynym wyjściem jest przekierowanie użytkownika do ustawień systemowych aplikacji.
Tak, ActivityResultContracts.RequestMultiplePermissions pozwala żądać tablicy uprawnień w jednym wywołaniu. System wyświetli kolejno okna dialogowe dla każdego uprawnienia. Zaleca się grupowanie logicznie powiązanych uprawnień (na przykład CAMERA i RECORD_AUDIO do nagrywania wideo), ale nie żądać więcej niż 2–3 na raz.
Android TV używa tego samego modelu runtime permissions z wyświetlaniem okien dialogowych na ekranie telewizora. Wear OS w wersji 3+ obsługuje runtime permissions, ale okna dialogowe wyświetlane są na zegarku. Dla Android Auto wszystkie uprawnienia są żądane na telefonie, a system samochodowy otrzymuje już zatwierdzone uprawnienia przez połączenie bridge.
Według wstępnych informacji Android 16 wprowadza „permission expiration“ dla uprawnień jednorazowych z automatycznym cofnięciem po 24 godzinach. Oczekuje się również zaostrzenia wymagań dotyczących background location i rozszerzenia listy dangerous permissions o nowe kategorie (czujniki otoczenia, skanowanie Wi-Fi). Dokładne szczegóły pojawią się w Q3 2027.
iOS nie obsługuje „normal permissions“ — każde uprawnienie jest żądane jawnie przez systemowe okno dialogowe. Użytkownik może cofnąć uprawnienie w dowolnym momencie przez ustawienia. Główna różnica — iOS nie sprawdza wstępnie statusu uprawnienia przez analog checkSelfPermission: system automatycznie wyświetla okno dialogowe przy pierwszym użyciu chronionego API.
Podsumowanie
POST_NOTIFICATIONS jako runtime permission, Android 14 zaostrzył wymagania dotyczące geolokalizacji w tle.READ_EXTERNAL_STORAGE do wyboru obrazów.Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również