Merhaba. Şuan 9.0 versiyonu çıkmış olsa da Android 6.0 (Marshmallow)’da gelen ve birçok uygulamanın hata vermesine sebep olan bir yenilikten bahsedeceğim.
Android 6.0 (Marshmallow) öncesinde, Google Play’ den uygulama indirirken izinler, indirme esnasında toptan kabul ediliyordu ve bunların arasından erişmesini istemediğimiz izinleri iptal etme gibi bir lüksümüz yoktu. Başta kabul edildiğinde artık izinler kaldırılamıyordu.
4.4.2 versiyonlu bir cihazda, indirilmiş bir uygulamanın izinleri:
Versiyonu 6.0 ve üzeri olan cihazlarda ise artık uygulamayı indirirken değil uygulama açıkken, ihtiyaç olduğu sürece izin isteniyor ve dilerseniz izin vermeyebiliyorsunuz.
Mesela indirdiğiniz bir uygulama kameranızı açmak istiyor diyelim. O an bir uyarı penceresi ile uygulamanın kameranıza erişmek istediği söyleniyor. İzin verirseniz kamera açılıyor, vermezseniz açılmıyor. İzin vermediğinizde uygulama tam olarak işlevini görmüyor fakat en azından hangi izne nerede ve niçin erişmek istediğini bilebiliyorsunuz ve tüm izinleri, 6.0’dan önceki gibi peşinen kabul etmemiş oluyorsunuz. 6.0 altındaki cihazlarda ise uygulama içinde izin pencereleri açılmaz. Uygulamayı indirirken verdiğiniz izinler uygulama boyunca kullanılır.
Android 6.0 İzin İşlemi – Örnek
Örnek üzerinde gösterelim. Örneğimizde butona tıklandığında kameranın açılmasını isteyelim. Cihazın API versiyonu 23 ve üzeriyse (Android 6.0’a denk gelir) izin istesin. Değilse, izinsiz doğrudan kamera açsın.
AndroidManifest.xml dosyamıza ilk olarak kamera izni ekleyelim.
1 |
<uses-permission android:name="android.permission.CAMERA" /> |
Daha sonra activity_main.xml layout dosyasına bir buton ekleyelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/btnKameraAc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:text="Kamera Aç" /> </RelativeLayout> |
Şimdi ise bu tasarıma bağlı olan MainActivity.java dosyasına gelerek, butonun click eventini dolduralım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public class MainActivity extends AppCompatActivity { Button btnKameraAc; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnKameraAc = findViewById(R.id.btnKameraAc); btnKameraAc.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Build.VERSION.SDK_INT >= Build.VERSION_CODES.M if (Build.VERSION.SDK_INT >= 23) { String[] KAMERA_IZNI = {Manifest.permission.CAMERA}; if (!izinKontrol(MainActivity.this, KAMERA_IZNI)) { // izin verilmiş mi requestPermissions(KAMERA_IZNI, 100); // verilmediyse, izin isteme penceresi aç } else kameraAc(); // zaten izin verilmişse kamera aç } else kameraAc(); // api 6.0 altındaysa izne bakmadan doğrudan kamera aç } }); } } |
Kamera açan bir uygulamanız var ve butona basıldığında ya da herhangi bir işlemden sonra doğrudan kamera açmak istiyorsunuz. Yukarıdaki gibi kontrol koymanız gerekiyor. Cihazın Android versiyonu 6.0 altında ise doğrudan kamera açılır. 6.0 ve üzeri ise önce izin verilmiş mi bakılır. İzin verilmemişse izin istenir (16.satırdaki ünlem işaretine dikkat!!). Verilmişse yine doğrudan kamera açılır.
Burada izin isterken 100 değeri gönderdik. Aşağıdaki gibi bir izin penceresi açıldı.

Bu izin penceresinde bir seçeneğe tıklayacağız. Tıkladıktan sonra istek gönderirken verdiğimiz 100 değeri ile yanıtımızı handle edeceğiz. Handle yani kontrol etmek için ise onRequestPermissionsResult metodu kullanılır. 100 yerine herhangi bir sayı veya sabit verilebilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case 100: if (grantResults.length > 0) { boolean kameraIzniVerildiMi = grantResults[0] == PackageManager.PERMISSION_GRANTED; if (kameraIzniVerildiMi) { kameraAc(); } else { Toast.makeText(getApplicationContext(), "İzin verilmediği için kamera açılamıyor", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(getApplicationContext(), "İzin verilmediği için kamera açılamıyor", Toast.LENGTH_SHORT).show(); } break; } } |
Pencerede Reddet veya İzin Ver butonlarından birine tıklayınca onRequestPermissionsResult metodu çalışır. Metod içerisinde, önce kamera iznine ait olan 100 değeri switch içerisine yazılır. İzin verildiyse yine kameraAc() metodu çağrılır. Verilmediyse ekrana uyarı mesajları verilir.
ÖNEMLİ!!!
Eğer bir sefer izin verirsek, 2.tıklamada artık requestPermissions() metodu çağrılmayacak doğrudan kamera açılacaktır. Çünkü izin verilmediyse izin isteği gönderiyorduk. İzin verildikten sonra kişi eğer huylanır da cihazın Ayarlar sekmesinden uygulama izinlerini manuel olarak iptal ederse, uygulamaya girip butona tıkladığında tekrar requestPermissions() metodu çağrılır. O yüzden her tıklamada izin verilmiş mi kontrolü yapılmalı yoksa uygulama hata vererek durur.
Aşağıdaki gibi kişinin manuel olarak izinleri kapatma ihtimali vardır.

Dikkat ettiyseniz değinmediğimiz bir metot var. O da izinKontrol() metodu. Bu metot şu işe yarar:
-Bu uygulama için istenilen izinler kullanıcı tarafından verilmiş mi ?
Bu metot, aynı anda birden fazla izin alacağımız durumlarda işimize yarayacaktır. Tek izin için de işimizi görür. Hemen o metodu da yazalım.
1 2 3 4 5 6 7 8 9 |
public static boolean izinKontrol(Context context, String... izinler) { if (context != null && izinler != null) { for (String izin : izinler) { if (ActivityCompat.checkSelfPermission(context, izin) != PackageManager.PERMISSION_GRANTED) return false; } } return true; } |
Aynı Ekranda 2.İzni İsteme
Örneğimizde 1 adet izin istedik. Şimdi ise aynı activity içinde 2.buton ekleyip, bu buton ile de cihazın konumunu alalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/btnKameraAc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:text="Kamera Aç" /> <Button android:id="@+id/btnKonumAl" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/btnKameraAc" android:text="Konum Al" /> </RelativeLayout> |
Manifest dosyamıza izinleri de ekleyelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mkirazli.izinayarlari"> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> |
MainActivity.java dosyasına, konum alma butonu için click eventi oluşturalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
btnKonumAl = findViewById(R.id.btnKonumAl); btnKonumAl.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Build.VERSION.SDK_INT >= Build.VERSION_CODES.M if (Build.VERSION.SDK_INT >= 23) { String[] KONUM_IZNI = {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}; if (!izinKontrol(MainActivity.this, KONUM_IZNI)) { // izin verilmiş mi requestPermissions(KONUM_IZNI, 200); // verilmediyse, izin isteme penceresi aç } else konumAl(); // zaten izin verilmişse konum al } else konumAl(); // api 6.0 altındaysa izne bakmadan doğrudan konum al } }); |
Cihazlarda 2 tür konum olduğu için 2 tür izin istemek zorundayız. İzin isterken bu defa 100 değil 200 değeri gönderdik ve aşağıdaki onRequestPermissionsResult() metodunda da 200 için ayrı bir case oluşturarak, konum izni verildiğinde yapılacakları yazdık.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case 100: if (grantResults.length > 0) { boolean kameraIzniVerildiMi = grantResults[0] == PackageManager.PERMISSION_GRANTED; if (kameraIzniVerildiMi) { kameraAc(); } else { Toast.makeText(getApplicationContext(), "İzin verilmediği için devam edilemiyor", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(getApplicationContext(), "İzin verilmediği için devam edilemiyor", Toast.LENGTH_SHORT).show(); } break; case 200: if (grantResults.length > 0) { boolean konumIzniVerildiMi1 = grantResults[0] == PackageManager.PERMISSION_GRANTED; boolean konumIzniVerildiMi2 = grantResults[1] == PackageManager.PERMISSION_GRANTED; if (konumIzniVerildiMi1 && konumIzniVerildiMi2) { konumAl(); } else { Toast.makeText(getApplicationContext(), "İzin verilmediği için konum alınamıyor", Toast.LENGTH_SHORT).show(); finish(); } } else { Toast.makeText(getApplicationContext(), "İzin verilmediği için konum alınamıyor", Toast.LENGTH_SHORT).show(); finish(); } break; } } |
Buradaki grantResults[0] ve grantResults[1] içerisinde, lokasyon için istediğimiz izinler vardır. İlkinde ACCESS_COARSE_LOCATION, ikincisinde de ACCESS_FINE_LOCATION izni için bilgiler bulunmaktadır. Yani izin verildi mi bilgisi tutulur.
Sonuç olarak eğer izin gerektiren bir işlem yaptırmak istiyorsak, hem cihaz için API 23 kontrolü yapmalıyız hem de izin verilmediyse izin penceresi açarak, seçilen seçeneğe göre aynı işlemleri orada da yapmalıyız. Yani her tıklamada ve izin penceresi açıldığı her durumda…
Son olarak şunu da söyleyelim. Android SDK’sı, tehlikeli bulduğu izinler için bu işlemi yapar. Yani bir internet ve bluetooth açma işlemi için API 23 kontrolüne gerek yoktur. Sadece AndroidManifest.xml dosyasına izin eklenir ve kodda doğrudan işlem yapılır. Dosya okuma yazma, kamera açma, mikrofon açma, konum alma gibi işlemler için kullanıcıdan izin isteme mecburiyeti vardır. Bu yaptıklarımız da tehlikeli olan izinler içindir.
Tehlikeli ve normal izinlerin listesine buradan ulaşabilirsiniz.
Mehmet hocam 3 gündür uüraşıyorum permission.WRITE_SETTINGS iznini +23 ler için veremedim.
En anlaşılır makale sizinki ama sizinkine permission.WRITE_SETTINGS ekliyorum 3. olarak ilk ikidi yani kamera ve konum izin alıyor ama permission.WRITE_SETTINGS izin almıyor
“izin verilmediği için” diye mesaj veriyor.
Yardımcı olursaniz sevinirim
saygılar
Merhaba. 3 izin eklediyseniz 3 defa popup çıkması lazım. Eğer çıkıyor ama WRİTE izni alınmamış görünüyorsa, sebebi şunlar olabilir. Manifeste eklememiş olabilirsiniz, verilen izni handle ettiğiniz yerde (onRequestPermissionsResult metodunda) yanlış id ile kontrol etmeye çalışıyor olabilirsiniz. Verdğiniz 100,200,300 değerlerini kontrol edin. Eğer bunlar da tamamsa o zaman “izin verilmediği için” mesajını yanlış şartta veriyor olabilirsiniz.
Yararlı bir yazı olmuş, ellerinize emeğinize sağlık. Çok teşekkürler.
Merhaba hocam ben android ogrenmek istiyorum java dili’ni biliyorum sizce hangi kitabdan ogrenebilirim ?
Merhaba. Java biliyorsanız android öğrenmeniz kolay olur. Video eğitim setlerinden öğrenebilirsiniz, kitaptan yavaş olur.