AndroidManifest Permissions су декларације дозвола у датотеци AndroidManifest.xml које одређују којим системским ресурсима и подацима апликација има приступ. Android захтева да се свака дозвола наведе у манифесту пре коришћења одговарајућег API-ја: од камере и геолокације до слања SMS-а и приступа контактима. Према Android Developer Documentation, свака дозвола се дели на један од четири нивоа заштите: normal, dangerous, signature и special.
Главне тачке
AndroidManifest Permissions је безбедносни механизам Android-а који контролише приступ апликација заштићеним подацима и системским функцијама. Свака апликација мора да декларише потребне дозволе у датотеци AndroidManifest.xml помоћу елемента <uses-permission>. Без декларације, позивање одговарајућег API-ја ће се завршити безбедносном грешком SecurityException.
Модел дозвола Android-а је прошао кроз неколико фаза еволуције. Пре Android 6.0 (API 23), све дозволе су се одобравале приликом инсталације — корисник је видео комплетну листу и прихватао или одбијао инсталацију апликације. Почевши од Android 6.0, дозволе нивоа dangerous се захтевају у време извршавања (Runtime Permissions), што даје кориснику флексибилнију контролу.
Дозволе се деле на четири нивоа заштите: normal (аутоматски се одобравају при инсталацији), dangerous (захтевају захтев у време извршавања), signature (доступне само апликацијама потписаним истим сертификатом) и special (захтевају посебно укључивање у подешавањима). Сваки ниво има свој механизам одобравања и опозива.
Према Google I/O 2024, у Android 15 се планира увођење грануларнијих дозвола — корисник ће моћи да одобри приступ само одређеним датотекама у медијатеци, а не целој библиотеци. Ово наставља тренд Android-а ка минимизацији обима података који се подразумевано дају.
За разлику од iOS-а, где се све дозволе захтевају у време извршавања (runtime), Android дели дозволе на инсталационе (install-time) и извршне (runtime). Ниво normal се аутоматски одобрава при инсталацији без обавештавања корисника. Ниво dangerous захтева експлицитан дијалог, као у iOS-у.
Још једна разлика: у Android-у су дозволе обједињене у групе (permission groups). Ако је корисник прихватио приступ камери, апликација аутоматски добија приступ микрофону — оне су у истој групи MICROPHONE. У iOS-у се свака дозвола захтева одвојено, независно од групе.
| Верзија Android-а | Промена у моделу дозвола |
|---|---|
| Android 1.0–5.x | Све дозволе се одобравају при инсталацији (install-time) |
| Android 6.0 (API 23) | Увођење Runtime Permissions за dangerous ниво |
| Android 10 (API 29) | Scoped Storage — ограничен приступ систему датотека |
| Android 11 (API 30) | Ауто-ресет дозвола — некоришћене дозволе се ресетују |
| Android 14 (API 34) | Runtime дозволе за медијски приступ (фото, видео, аудио) |
Android дефинише четири нивоа заштите (protection levels) за дозволе, сваки са сопственим правилима одобравања. Размотримо сваки ниво детаљно.
Normal дозволе се аутоматски одобравају при инсталацији апликације без обавештавања или захтева од корисника. Оне покривају приступ функцијама ниског ризика које не угрожавају приватност корисника: INTERNET, ACCESS_NETWORK_STATE, VIBRATE, BLUETOOTH. Корисник не види дијалог сагласности — дозвола се сматра одобреном чињеницом инсталације.
Програмер не мора да обрађује захтев у коду за normal дозволе — довољно је да их декларише у манифесту. Међутим, у Android 12+ при инсталацији из Google Play-а, корисник види картицу „Дозволе” са списком свих normal дозвола, што повећава транспарентност. Према Statista (2024), преко 90% апликација у Google Play-у користи INTERNET као најчешћу normal дозволу.
Dangerous дозволе покривају приступ подацима и функцијама које могу нарушити приватност: камера, микрофон, геолокација, контакти, SMS, телефон, календар, телесни сензори. Ове дозволе захтевају двостепени механизам: декларацију у манифесту + захтев у време извршавања путем ActivityCompat.requestPermissions().
Корисник може одбити давање dangerous дозволе, а апликација мора правилно да обради овај сценарио. У Android 11+, ако је корисник два пута одбио, накнадни захтеви не приказују системски дијалог — систем аутоматски враћа DENIED. У овом случају, потребно је усмерити корисника у подешавања.
Ниво signature — дозвола се аутоматски одобрава ако је апликација потписана истим сертификатом као систем или друга апликација која је дефинисала дозволу. Користи се за системске и корпоративне апликације. Пример: BIND_ACCESSIBILITY_SERVICE — доступно само системским апликацијама.
Ниво special (SYSTEM_ALERT_WINDOW, WRITE_SETTINGS, REQUEST_INSTALL_PACKAGES, MANAGE_EXTERNAL_STORAGE) — захтева одвојену радњу корисника кроз системска подешавања. Апликација може отворити страницу подешавања помоћу Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION). Google Play ограничава коришћење special дозвола и захтева оправдање у формулару при објављивању.
Од Android 6.0, све dangerous дозволе захтевају захтев у време извршавања. Размотримо комплетан циклус рада са runtime permissions у Kotlin-у.
Пре позивања API-ја који захтева dangerous дозволу, увек проверавајте тренутни статус путем ContextCompat.checkSelfPermission(). Ако је статус PERMISSION_GRANTED — можете позвати API. Ако је PERMISSION_DENIED — потребно је затражити дозволу путем ActivityResultContract RequestPermission (AndroidX) или застарелог requestPermissions().
Препоручује се коришћење ActivityResultContracts.RequestMultiplePermissions за захтев више дозвола истовремено. Google препоручује груписање повезаних дозвола (нпр. камера + микрофон за видео снимање) у један дијалог, како би корисник видео пун контекст захтева.
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
)
}
}
}
}
Ако је корисник два пута одбио дозволу, Android преводи захтев у стање \u201eNever ask again’. У овом случају shouldShowRequestPermissionRationale() враћа false, а системски дијалог неће бити приказан. Апликација мора да усмери корисника у системска подешавања путем Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).
Важно: не приказујте дијалог са предлогом отварања подешавања одмах након првог одбијања — то се доживљава као агресивно понашање. Користите shouldShowRequestPermissionRationale() за утврђивање да ли је потребно приказати објашњење. Material Design Guidelines препоручују приказ екрана са објашњењем вредности приступа, а не само дугме \u201eОтвори подешавања’.
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("Приступ камери")
.setMessage("Дозволите приступ камери у Подешавањима, "
+ "да бисте сликали фотографију за профил")
.setPositiveButton("Отвори подешавања") { _, _ ->
openAppSettings()
}
.setNegativeButton("Откажи", null)
.show()
}
Датотека AndroidManifest.xml садржи елемент <uses-permission> за сваку дозволу коју апликација користи. Дозволе се декларишу на нивоу <manifest> пре елемента <application>.
Свака дозвола се декларише засебним елементом <uses-permission> са атрибутом android:name који указује пуно име дозволе. За дозволе које су се појавиле у одређеним верзијама Android-а, користите атрибут maxSdkVersion да ограничите декларацију само на потребне верзије — ово побољшава компатибилност.
На пример, дозвола WRITE_EXTERNAL_STORAGE није потребна на Android 10+ (Scoped Storage), зато наведите maxSdkVersion=„28” (Android 9). Ово спречава непотребна питања од корисника на новијим верзијама. Android Studio упозорава о препорученим maxSdkVersion путем 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>
Елемент <uses-feature> наводи да апликација захтева одређени хардвер (камеру, GPS, NFC). Атрибут android:required=„false” омогућава инсталацију апликације на уређајима без тог хардвера — провера доступности се врши у коду. Ако је required=„true”, Google Play филтрира апликацију и она постаје недоступна за неодговарајуће уређаје.
Препоручује се да за све хардверске функције наведете required=„false” и проверавате доступност програмски путем PackageManager.hasSystemFeature(). Ово проширује публику ваше апликације. Једини изузетак је када је функција критична за рад апликације (апликација за наручивање таксија без GPS-а нема смисла).
Правилан рад са дозволама је кључни аспект квалитета Android апликације. Размотримо главне препоруке и типичне грешке.
Захтевајте само оне дозволе које су заиста неопходне за рад апликације. Свака додатна дозвола смањује конверзију инсталација и повећава број одбијања. Google Play Console показује колико корисника је одустало од инсталације због скупа дозвола. Према AppBrain (2024), апликације са 10+ dangerous дозвола имају 35% мање инсталација.
Редовно преиспитујте листу дозвола. Уклањајте некоришћене, посебно при преласку на новије верзије Android-а где су неке дозволе постале опционе. На пример, са појавом бирача фотографија (ActivityResultContracts.PickVisualMedia) у Android 13+, приступ медијатеци се може добити без dangerous дозволе READ_MEDIA_IMAGES.
Пре захтева за dangerous дозволу, прикажите кориснику екран са објашњењем зашто је ова дозвола потребна и какву вредност пружа. Material Design препоручује коришћење bottom sheet-а или дијалога са иконом, кратким текстом и дугметом \u201eНастави’. Rationale повећава сагласност за 20–30% у поређењу са директним захтевом.
Проверавајте shouldShowRequestPermissionRationale() пре позивања launch(). Ако је true — прикажите rationale. Ако је false — или је дозвола већ дата или је корисник заувек одбио (never ask again). У последњем случају прикажите дугме \u201eОтвори подешавања’, а не понављајте захтев.
Тестирајте све могуће сценарије: одобравање дозволе, одбијање, заувек одбијање, опозив дозволе у подешавањима, ресетовање дозвола (Android 11+ auto-reset). Сваки сценарио мора бити обрађен без crash-а и без губитка података. Android Testing Guide препоручује коришћење библиотеке TestPermission за аутоматизацију тестирања.
Посебну пажњу посветите сценарију када корисник опозове дозволу током рада апликације (смањена апликација → Подешавања → опозив). При повратку у апликацију проверите све дозволе поново путем onResume(). Не ослањајте се на кеширање статуса дозвола — корисник их може променити у било ком тренутку.
Често постављана питања
Да, ако SDK укључује дозволу у свој манифест, она се спаја са манифестом апликације приликом изградње. Можете онемогућити непотребну дозволу SDK-а помоћу tools:node=„remove” у AndroidManifest.xml.
Позивање API-ја без дозволе ће изазвати SecurityException, што ће довести до crash-а апликације. Увек проверавајте статус дозволе пре коришћења одговарајућег API-ја и правилно обрађујте одбијање.
У подешавањима уређаја: Подешавања → Апликације → [ваша апликација] → Дозволе. За ресетовање свих дозвола користите adb команду: adb shell pm reset-permissions.
Да, помоћу ActivityResultLauncher у Fragment-у или Service-у. Међутим, дијалог захтева увек захтева UI контекст Activity. За Service можете приказати Notification са Intent-ом који отвара Activity са захтевом.
На пример, WRITE_EXTERNAL_STORAGE није потребан на Android 10+ (Scoped Storage). Навођењем android:maxSdkVersion=„28”, искључујете декларацију дозволе на новијим верзијама, што побољшава компатибилност и смањује листу захтеваних дозвола.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође