AndroidManifest Permissions jsou deklarace oprávnění v souboru AndroidManifest.xml, které určují, k jakým systémovým prostředkům a datům má aplikace přístup. Android vyžaduje, aby každé oprávnění bylo uvedeno v manifestu před použitím odpovídajícího API: od kamery a geolokace po odesílání SMS a přístup ke kontaktům. Podle Android Developer Documentation se každé oprávnění dělí do jedné ze čtyř úrovní ochrany: normal, dangerous, signature a special.
Hlavní body
AndroidManifest Permissions je bezpečnostní mechanismus Androidu, který řídí přístup aplikací k chráněným datům a systémovým funkcím. Každá aplikace musí deklarovat požadovaná oprávnění v souboru AndroidManifest.xml pomocí elementu <uses-permission>. Bez deklarace volání odpovídajícího API selže s bezpečnostní chybou SecurityException.
Model oprávnění Androidu prošel několika fázemi vývoje. Před Androidem 6.0 (API 23) byla všechna oprávnění udělována při instalaci — uživatel viděl úplný seznam a souhlasil nebo odmítl instalaci aplikace. Od Androidu 6.0 jsou oprávnění úrovně dangerous vyžadována za běhu (Runtime Permissions), což uživateli poskytuje flexibilnější kontrolu.
Oprávnění se dělí do čtyř úrovní ochrany: normal (automaticky udělena při instalaci), dangerous (vyžadují žádost za běhu), signature (dostupná pouze aplikacím podepsaným stejným certifikátem) a special (vyžadují samostatné povolení v nastavení). Každá úroveň má svůj vlastní mechanismus udělování a odvolání.
Podle Google I/O 2024 je v Androidu 15 plánováno zavedení podrobnějších oprávnění — uživatel bude moci poskytnout přístup pouze k určitým souborům v mediální knihovně, nikoli k celé knihovně. To pokračuje v trendu Androidu minimalizovat objem poskytovaných dat ve výchozím nastavení.
Na rozdíl od iOS, kde jsou všechna oprávnění vyžadována za běhu (runtime), Android dělí oprávnění na instalační (install-time) a běhová (runtime). Úroveň normal je udělena automaticky při instalaci bez upozornění uživatele. Úroveň dangerous vyžaduje explicitní dialog, stejně jako v iOS.
Další rozdíl: v Androidu jsou oprávnění sdružena do skupin (permission groups). Pokud uživatel souhlasí s přístupem ke kameře, aplikace automaticky získá přístup k mikrofonu — jsou ve stejné skupině MICROPHONE. V iOS je každé oprávnění vyžadováno samostatně, nezávisle na skupině.
| Verze Androidu | Změna v modelu oprávnění |
|---|---|
| Android 1.0–5.x | Všechna oprávnění udělována při instalaci (install-time) |
| Android 6.0 (API 23) | Zavedení Runtime Permissions pro úroveň dangerous |
| Android 10 (API 29) | Scoped Storage — omezený přístup k souborovému systému |
| Android 11 (API 30) | Automatický reset oprávnění — nepoužívaná oprávnění se resetují |
| Android 14 (API 34) | Runtime oprávnění pro přístup k médiím (foto, video, audio) |
Android definuje čtyři úrovně ochrany (protection levels) pro oprávnění, každá s vlastními pravidly udělování. Pojďme každou úroveň podrobně prozkoumat.
Normal oprávnění jsou automaticky udělena při instalaci aplikace bez upozornění nebo žádosti uživatele. Pokrývají přístup k funkcím s nízkým rizikem, které neohrožují soukromí uživatele: INTERNET, ACCESS_NETWORK_STATE, VIBRATE, BLUETOOTH. Uživatel nevidí dialog souhlasu — oprávnění je považováno za udělené samotnou instalací.
Vývojář nemusí v kódu zpracovávat žádost pro normal oprávnění — stačí je deklarovat v manifestu. V Androidu 12+ však při instalaci z Google Play uživatel vidí kartu „Oprávnění” se seznamem všech normal oprávnění, což zvyšuje transparentnost. Podle Statista (2024) více než 90 % aplikací v Google Play používá INTERNET jako nejběžnější normal oprávnění.
Dangerous oprávnění pokrývají přístup k datům a funkcím, které mohou narušit soukromí: kamera, mikrofon, geolokace, kontakty, SMS, telefon, kalendář, tělesné senzory. Tato oprávnění vyžadují dvoufázový mechanismus: deklaraci v manifestu + žádost za běhu prostřednictvím ActivityCompat.requestPermissions().
Uživatel může odmítnout udělení dangerous oprávnění a aplikace musí tento scénář správně zpracovat. V Androidu 11+, pokud uživatel dvakrát odmítl, následné žádosti nezobrazují systémový dialog — systém automaticky vrací DENIED. V tomto případě je třeba uživatele nasměrovat do nastavení.
Úroveň signature — oprávnění je automaticky uděleno, pokud je aplikace podepsána stejným certifikátem jako systém nebo jiná aplikace, která oprávnění definovala. Používá se pro systémové a podnikové aplikace. Příklad: BIND_ACCESSIBILITY_SERVICE — dostupné pouze systémovým aplikacím.
Úroveň special (SYSTEM_ALERT_WINDOW, WRITE_SETTINGS, REQUEST_INSTALL_PACKAGES, MANAGE_EXTERNAL_STORAGE) — vyžaduje samostatnou akci uživatele prostřednictvím systémového nastavení. Aplikace může otevřít stránku nastavení pomocí Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION). Google Play omezuje použití special oprávnění a vyžaduje odůvodnění ve formuláři při publikování.
Od Androidu 6.0 vyžadují všechna dangerous oprávnění žádost za běhu. Pojďme prozkoumat celý cyklus práce s runtime permissions v Kotlinu.
Před voláním API, které vyžaduje dangerous oprávnění, vždy zkontrolujte aktuální stav pomocí ContextCompat.checkSelfPermission(). Pokud je stav PERMISSION_GRANTED — API lze zavolat. Pokud je PERMISSION_DENIED — je třeba oprávnění vyžádat prostřednictvím ActivityResultContract RequestPermission (AndroidX) nebo zastaralého requestPermissions().
Doporučuje se používat ActivityResultContracts.RequestMultiplePermissions pro současné vyžádání více oprávnění. Google doporučuje seskupovat související oprávnění (např. kamera + mikrofon pro nahrávání videa) do jednoho dialogu, aby uživatel viděl úplný kontext žádosti.
import android.Manifest
import android.content.pm.PackageManager
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
class CameraActivity : AppCompatActivity() {
private val requestPermissionLauncher =
registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
openCamera()
} else {
explainWhyPermissionNeeded()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
checkCameraPermission()
}
private fun checkCameraPermission() {
when {
ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
openCamera()
}
shouldShowRequestPermissionRationale(
Manifest.permission.CAMERA
) -> {
showRationale()
}
else -> {
requestPermissionLauncher.launch(
Manifest.permission.CAMERA
)
}
}
}
}
Pokud uživatel dvakrát odmítl oprávnění, Android převede žádost do stavu „Never ask again”. V tomto případě shouldShowRequestPermissionRationale() vrací false a systémový dialog se nezobrazí. Aplikace musí uživatele nasměrovat do systémového nastavení pomocí Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).
Důležité: nezobrazujte dialog s návrhem otevřít nastavení ihned po prvním odmítnutí — to je vnímáno jako agresivní chování. Použijte shouldShowRequestPermissionRationale() k určení, zda je třeba zobrazit vysvětlení. Material Design Guidelines doporučují zobrazit obrazovku s vysvětlením hodnoty přístupu, ne pouze tlačítko „Otevřít nastavení”.
private fun openAppSettings() {
Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", packageName, null)
).also { intent ->
startActivity(intent)
}
}
private fun showPermissionSettings() {
AlertDialog.Builder(this)
.setTitle("Přístup kameře")
.setMessage("Povolte přístup kameře v Nastavení, "
+ "pro pořízení profilové fotky")
.setPositiveButton("Otevřít nastavení") { _, _ ->
openAppSettings()
}
.setNegativeButton("Zrušit", null)
.show()
}
Soubor AndroidManifest.xml obsahuje element <uses-permission> pro každé oprávnění, které aplikace používá. Oprávnění se deklarují na úrovni <manifest> před elementem <application>.
Každé oprávnění je deklarováno jako samostatný element <uses-permission> s atributem android:name, který udává úplný název oprávnění. Pro oprávnění, která se objevila v určitých verzích Androidu, použijte atribut maxSdkVersion k omezení deklarace pouze na potřebné verze — to zlepšuje kompatibilitu.
Například oprávnění WRITE_EXTERNAL_STORAGE není potřeba na Androidu 10+ (Scoped Storage), proto uveďte maxSdkVersion=„28” (Android 9). To zabraňuje zbytečným otázkám od uživatelů na novějších verzích. Android Studio varuje o doporučených maxSdkVersion prostřednictvím Lint.
<!-- AndroidManifest.xml -->
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Normal permissions (install-time) -->
<uses-permission
android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Dangerous permissions (runtime) -->
<uses-permission
android:name="android.permission.CAMERA" />
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- Legacy storage permission limited to API 28 and below -->
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<application>
<!-- ... -->
</application>
</manifest>
Element <uses-feature> určuje, že aplikace vyžaduje určitý hardware (kameru, GPS, NFC). Atribut android:required=„false” umožňuje instalaci aplikace na zařízení bez tohoto hardwaru — kontrola dostupnosti se provádí v kódu. Pokud je required=„true”, Google Play aplikaci filtruje a stává se nedostupnou pro nevhodná zařízení.
Doporučuje se pro všechny hardwarové funkce nastavit required=„false” a kontrolovat dostupnost programově pomocí PackageManager.hasSystemFeature(). To rozšiřuje publikum vaší aplikace. Jedinou výjimkou je, když je funkce kritická pro provoz aplikace (aplikace pro objednání taxi bez GPS nemá smysl).
Správná práce s oprávněními je klíčovým aspektem kvality aplikace pro Android. Pojďme prozkoumat hlavní doporučení a typické chyby.
Požadujte pouze oprávnění, která jsou skutečně nezbytná pro provoz aplikace. Každé další oprávnění snižuje konverzi instalací a zvyšuje počet odmítnutí. Google Play Console ukazuje, kolik uživatelů upustilo od instalace kvůli sadě oprávnění. Podle AppBrain (2024) mají aplikace s 10+ dangerous oprávněními o 35 % méně instalací.
Pravidelně revidujte seznam oprávnění. Odstraňte nepoužívaná, zejména při přechodu na novější verze Androidu, kde se některá oprávnění stala volitelnými. Například s příchodem výběru fotografií (ActivityResultContracts.PickVisualMedia) v Androidu 13+ lze přístup k mediální knihovně získat bez dangerous oprávnění READ_MEDIA_IMAGES.
Před vyžádáním dangerous oprávnění zobrazte uživateli obrazovku s vysvětlením, proč je toto oprávnění potřeba a jakou hodnotu poskytuje. Material Design doporučuje použít bottom sheet nebo dialog s ikonou, krátkým textem a tlačítkem „Pokračovat”. Rationale zvyšuje souhlas o 20–30 % ve srovnání s přímou žádostí.
Zkontrolujte shouldShowRequestPermissionRationale() před voláním launch(). Pokud je true — zobrazte rationale. Pokud je false — buď je oprávnění již uděleno, nebo uživatel natrvalo odmítl (never ask again). V druhém případě zobrazte tlačítko „Otevřít nastavení”, neopakujte žádost.
Otestujte všechny možné scénáře: udělení oprávnění, odmítnutí, trvalé odmítnutí, odvolání oprávnění v nastavení, reset oprávnění (Android 11+ auto-reset). Každý scénář musí být zpracován bez pádu a bez ztráty dat. Android Testing Guide doporučuje používat knihovnu TestPermission pro automatizaci testování.
Zvláštní pozornost věnujte scénáři, kdy uživatel odvolá oprávnění během provozu aplikace (minimalizovaná aplikace → Nastavení → odvolání). Při návratu do aplikace znovu zkontrolujte všechna oprávnění pomocí onResume(). Nespoléhejte na ukládání stavu oprávnění do mezipaměti — uživatel je může kdykoli změnit.
Často kladené otázky
Ano, pokud SDK zahrnuje oprávnění ve svém manifestu, při sestavení se sloučí s manifestem aplikace. Nežádoucí oprávnění SDK můžete zakázat pomocí tools:node=„remove” v AndroidManifest.xml.
Volání API bez oprávnění způsobí SecurityException, což povede k pádu aplikace. Vždy kontrolujte stav oprávnění před použitím odpovídajícího API a správně zpracujte odmítnutí.
V nastavení zařízení: Nastavení → Aplikace → [vaše aplikace] → Oprávnění. Pro resetování všech oprávnění použijte příkaz adb: adb shell pm reset-permissions.
Ano, pomocí ActivityResultLauncher ve Fragment nebo Service. Dialog žádosti však vždy vyžaduje kontext UI Activity. Pro Service můžete zobrazit Notification s Intent, který otevře Activity s žádostí.
Například WRITE_EXTERNAL_STORAGE není potřeba na Androidu 10+ (Scoped Storage). Uvedením android:maxSdkVersion=„28” vyloučíte deklaraci oprávnění na novějších verzích, což zlepšuje kompatibilitu a snižuje seznam požadovaných oprávnění.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také