AndroidManifest Permissions, AndroidManifest.xml dosyasında, bir uygulamanın hangi sistem kaynaklarına ve verilere erişebileceğini belirleyen izin bildirimleridir. Android, ilgili API'yi kullanmadan önce her iznin manifestoda bildirilmesini gerektirir: kameradan ve coğrafi konumdan SMS göndermeye ve kişilere erişmeye kadar. Android Geliştirici Dokümantasyonu'na göre, her izin dört koruma seviyesinden birine ayrılır: normal, dangerous, signature ve special.
Önemli Noktalar
AndroidManifest Permissions, uygulamaların korunan verilere ve sistem işlevlerine erişimini kontrol eden Android güvenlik mekanizmasıdır. Her uygulama,
Android izin modeli birkaç evrim aşamasından geçmiştir. Android 6.0'dan (API 23) önce, tüm izinler kurulum sırasında verilirdi — kullanıcı tam listeyi görür ve uygulama kurulumunu kabul eder veya reddederdi. Android 6.0'dan itibaren, dangerous seviyesindeki izinler çalışma zamanında (Runtime Permissions) talep edilir ve kullanıcıya daha esnek kontrol sağlar.
İzinler dört koruma seviyesine ayrılır: normal (kurulumda otomatik olarak verilir), dangerous (çalışma zamanı talebi gerektirir), signature (yalnızca aynı sertifikayla imzalanmış uygulamalar için kullanılabilir) ve special (ayarlarda ayrı etkinleştirme gerektirir). Her seviyenin kendi verme ve iptal mekanizması vardır.
Google I/O 2024'e göre, Android 15 daha ayrıntılı izinler sunmayı planlıyor — kullanıcı, medya kitaplığının tamamına değil, yalnızca belirli dosyalara erişim izni verebilecek. Bu, Android'in varsayılan olarak sağlanan veri miktarını en aza indirme eğilimini sürdürmektedir.
Tüm izinlerin çalışma zamanında talep edildiği iOS'un aksine, Android izinleri kurulum zamanı (install-time) ve çalışma zamanı (runtime) olarak ikiye ayırır. Normal seviye, kullanıcıya bildirim yapılmadan kurulumda otomatik olarak verilir. Dangerous seviyesi, iOS'ta olduğu gibi açık bir diyalog gerektirir.
Başka bir fark: Android'de izinler izin grupları halinde gruplandırılmıştır. Kullanıcı kameraya erişime izin verirse, uygulama otomatik olarak mikrofona erişim kazanır — aynı MICROPHONE grubundadırlar. iOS'ta her izin, gruplardan bağımsız olarak ayrı ayrı talep edilir.
| Android Sürümü | İzin Modelindeki Değişiklik |
|---|---|
| Android 1.0–5.x | Tüm izinler kurulumda verilir |
| Android 6.0 (API 23) | Dangerous seviyesi için Runtime Permissions'ın tanıtımı |
| Android 10 (API 29) | Scoped Storage — dosya sistemine sınırlı erişim |
| Android 11 (API 30) | Otomatik izin sıfırlama — kullanılmayan izinler sıfırlanır |
| Android 14 (API 34) | Medya erişimi (fotoğraf, video, ses) için çalışma zamanı izinleri |
Android, her biri kendi verme kurallarına sahip dört koruma seviyesi tanımlar. Her seviyeyi ayrıntılı olarak inceleyelim.
Normal izinler, kullanıcıya bildirim veya talep olmadan uygulama kurulumunda otomatik olarak verilir. Kullanıcının gizliliğini tehdit etmeyen düşük riskli işlevleri kapsarlar: INTERNET, ACCESS_NETWORK_STATE, VIBRATE, BLUETOOTH. Kullanıcı herhangi bir onay diyaloğu görmez — izin kurulumla birlikte verilmiş sayılır.
Geliştiricinin normal izinler için kodda talep işlemesi gerekmez — manifestoda bildirmek yeterlidir. Ancak, Android 12+'da Google Play'den kurulum yaparken, kullanıcı tüm normal izinleri listeleyen bir “İzinler” sekmesi görür, bu da şeffaflığı artırır. Statista (2024)'ye göre, Google Play'deki uygulamaların %90'ından fazlası en yaygın normal izin olarak INTERNET'i kullanır.
Dangerous izinler, gizliliği tehlikeye atabilecek verilere ve işlevlere erişimi kapsar: kamera, mikrofon, coğrafi konum, kişiler, SMS, telefon, takvim, vücut sensörleri. Bu izinler iki aşamalı bir mekanizma gerektirir: manifestoda bildirim + ActivityCompat.requestPermissions() ile çalışma zamanı talebi.
Kullanıcı dangerous bir izni reddedebilir ve uygulama bu senaryoyu doğru şekilde ele almalıdır. Android 11+'da, kullanıcı iki kez reddederse, sonraki talepler sistem diyaloğunu göstermez — sistem otomatik olarak DENIED döndürür. Bu durumda, uygulama kullanıcıyı ayarlara yönlendirmelidir.
Signature seviyesi — izin, uygulamanın sistem veya izni tanımlayan başka bir uygulamayla aynı sertifikayla imzalanması durumunda otomatik olarak verilir. Sistem ve kurumsal uygulamalar için kullanılır. Örnek: BIND_ACCESSIBILITY_SERVICE — yalnızca sistem uygulamaları için kullanılabilir.
Special seviyesi (SYSTEM_ALERT_WINDOW, WRITE_SETTINGS, REQUEST_INSTALL_PACKAGES, MANAGE_EXTERNAL_STORAGE) — sistem ayarları aracılığıyla kullanıcının açık eylemini gerektirir. Uygulama, Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION) ile ayarlar sayfasını açabilir. Google Play, special izinlerin kullanımını kısıtlar ve yayınlama sırasında formda gerekçe belirtilmesini ister.
Android 6.0'dan itibaren, tüm dangerous izinleri çalışma zamanında talep gerektirir. Kotlin'de runtime permissions ile tam çalışma döngüsünü inceleyelim.
Dangerous izin gerektiren bir API'yi çağırmadan önce, ContextCompat.checkSelfPermission() ile mevcut durumu her zaman kontrol edin. Durum PERMISSION_GRANTED ise API'yi çağırabilirsiniz. PERMISSION_DENIED ise, ActivityResultContract RequestPermission (AndroidX) veya eski requestPermissions() aracılığıyla izin talep etmeniz gerekir.
Aynı anda birden fazla izin talep etmek için ActivityResultContracts.RequestMultiplePermissions kullanılması önerilir. Google, ilgili izinlerin (örneğin, video kaydı için kamera + mikrofon) tek bir diyalogda gruplandırılmasını önerir, böylece kullanıcı talebin tam bağlamını görür.
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
)
}
}
}
}
Kullanıcı iki kez reddederse, Android talebi “Never ask again” durumuna geçirir. Bu durumda, shouldShowRequestPermissionRationale() false döndürür ve sistem diyaloğu gösterilmez. Uygulama, Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) aracılığıyla kullanıcıyı sistem ayarlarına yönlendirmelidir.
Önemli: İlk reddin hemen ardından ayarları açmayı öneren bir diyalog göstermeyin — bu saldırgan davranış olarak algılanır. Bir açıklama gösterilmesi gerekip gerekmediğini belirlemek için shouldShowRequestPermissionRationale() kullanın. Material Design Yönergeleri, yalnızca “Ayarları aç” düğmesi yerine erişimin değerini açıklayan bir ekran gösterilmesini önerir.
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("Kamera erişimi")
.setMessage("Ayarlar'da kamera erişimine izin ver, "
+ "profil fotoğrafı çekmek için")
.setPositiveButton("Ayarları aç") { _, _ ->
openAppSettings()
}
.setNegativeButton("İptal", null)
.show()
}
AndroidManifest.xml dosyası, uygulamanın kullandığı her izin için
Her izin, android:name niteliğini kullanarak tam izin adını belirten ayrı bir
Örneğin, WRITE_EXTERNAL_STORAGE izni Android 10+'da (Scoped Storage) gerekli değildir, bu nedenle maxSdkVersion="28" (Android 9) belirtin. Bu, yeni sürümlerde kullanıcılardan gereksiz soruları önler. Android Studio, Lint aracılığıyla önerilen maxSdkVersion hakkında uyarır.
<!-- 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>
Tüm donanım özellikleri için required="false" ayarlanması ve PackageManager.hasSystemFeature() ile programatik olarak kullanılabilirliğin kontrol edilmesi önerilir. Bu, uygulamanızın kitlesini genişletir. Tek istisna, özelliğin uygulamanın çalışması için kritik olmasıdır (GPS'siz bir taksi çağırma uygulaması anlamsızdır).
İzinlerin doğru yönetimi, bir Android uygulamasının kalitesinin önemli bir yönüdür. Başlıca önerileri ve tipik hataları inceleyelim.
Yalnızca uygulamanın çalışması için gerçekten gerekli olan izinleri talep edin. Her ekstra izin, kurulum dönüşüm oranını düşürür ve reddetme sayısını artırır. Google Play Console, izin seti nedeniyle kurulumu reddeden kullanıcı sayısını gösterir. AppBrain (2024)'e göre, 10+ dangerous iznine sahip uygulamaların kurulum sayısı %35 daha azdır.
İzin listenizi düzenli olarak gözden geçirin. Özellikle bazı izinlerin isteğe bağlı hale geldiği daha yeni Android sürümlerine geçerken kullanılmayan izinleri kaldırın. Örneğin, Android 13+'teki fotoğraf seçici (ActivityResultContracts.PickVisualMedia) ile medya kitaplığına dangerous READ_MEDIA_IMAGES izni olmadan erişilebilir.
Dangerous bir izin talep etmeden önce, kullanıcıya bu iznin neden gerekli olduğunu ve ne gibi değer sağladığını açıklayan bir ekran gösterin. Material Design, bir simge, kısa metin ve “Devam” düğmesi içeren bir alt sayfa veya diyalog kullanılmasını önerir. Gerekçe gösterme, doğrudan talebe kıyasla onayı %20–30 artırır.
launch()'ı çağırmadan önce shouldShowRequestPermissionRationale()'ı kontrol edin. true ise, gerekçeyi gösterin. false ise, izin ya zaten verilmiştir ya da kullanıcı kalıcı olarak reddetmiştir (tekrar sorma). İkinci durumda, talebi tekrarlamak yerine “Ayarları aç” düğmesi gösterin.
Tüm olası senaryoları test edin: izin verme, reddetme, kalıcı reddetme, ayarlarda izni iptal etme, izin sıfırlama (Android 11+ otomatik sıfırlama). Her senaryo çökme veya veri kaybı olmadan ele alınmalıdır. Android Test Kılavuzu, testleri otomatikleştirmek için TestPermission kitaplığının kullanılmasını önerir.
Kullanıcının uygulama çalışırken bir izni iptal ettiği senaryoya (uygulama simge durumuna küçültülmüş → Ayarlar → iptal) özellikle dikkat edin. Uygulamaya döndüğünüzde, onResume() içinde tüm izinleri yeniden kontrol edin. İzin durumunu önbelleğe almaya güvenmeyin — kullanıcı bunları istediği zaman değiştirebilir.
Sıkça Sorulan Sorular
Evet, bir SDK kendi manifestosunda bir izin içeriyorsa, derleme sırasında uygulama manifestosuyla birleşir. AndroidManifest.xml'de tools:node="remove" kullanarak gereksiz bir SDK iznini kaldırabilirsiniz.
İzin olmadan API çağırmak SecurityException oluşturarak uygulamanın çökmesine neden olur. İlgili API'yi kullanmadan önce her zaman izin durumunu kontrol edin ve reddetmeyi doğru şekilde ele alın.
Cihaz ayarlarında: Ayarlar → Uygulamalar → [uygulamanız] → İzinler. Tüm izinleri sıfırlamak için adb komutunu kullanın: adb shell pm reset-permissions.
Evet, bir Fragment veya Service'te ActivityResultLauncher kullanarak. Ancak, talep diyaloğu her zaman bir Activity UI bağlamı gerektirir. Bir Service için, talep Activity'sini açan bir Intent ile Bildirim gösterebilirsiniz.
Örneğin, WRITE_EXTERNAL_STORAGE Android 10+'da (Scoped Storage) gerekli değildir. android:maxSdkVersion="28" belirterek, izin bildirimini yeni sürümlerde hariç tutar, uyumluluğu artırır ve talep edilen izin listesini azaltırsınız.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun