Android izni bildirmiş olsam bile çalışmıyor


167

Bir Android uygulamasından SMS göndermek için kod yazmaya çalışıyorum, ancak SMS göndermeye çalıştığımda bana hatayı geri gönderiyor:

09-17 18:37:29.974  12847-12847/**.**.****E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: **.**.****, PID: 12847
java.lang.SecurityException: Sending SMS message: uid 10092 does not have android.permission.SEND_SMS.
        at android.os.Parcel.readException(Parcel.java:1599)
        at android.os.Parcel.readException(Parcel.java:1552)
        at com.android.internal.telephony.ISms$Stub$Proxy.sendTextForSubscriber(ISms.java:768)
        at android.telephony.SmsManager.sendTextMessageInternal(SmsManager.java:310)
        at android.telephony.SmsManager.sendTextMessage(SmsManager.java:293)
        at **.**.****.MainActivity$3.onClick(MainActivity.java:70)
        at android.view.View.performClick(View.java:5198)
        at android.view.View$PerformClick.run(View.java:21147)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Kontrol ettim ama manifest'te aşağıdaki gibi izinlere sahibim:

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-feature android:name="android.hardware.telephony"
    android:required="true"/>

<application
    android:exported="true"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

İnternette arama yaptım ama <uses-permission/>sözdizimiyle ilgili tüm hatalar vardı , lütfen bana yardım eder misiniz?


Hangi Android sürümünü test ediyorsunuz?
CommonsWare

Android 6.0'da test ediyorum
Nathan Loudjani

1
kesinlikle android aşağıdaki sürümü üzerinde çalışacaktır. Android 6.0'da yeni bir izin felsefesi var
Fakher

Android 6 için özel bir sözdizimi var mı? Aşağıdaki sürümde çalıştığından nasıl emin olabilirim?
Nathan Loudjani

önceki targetsdkversionedildi 23güncellendi 27uygulama güncellemesi sonrasında READ_SMSizni zaten etkin olduğu çalışmıyor. lütfen yardım
Sagar

Yanıtlar:


238

(bununla ilgili bir blog yayınımdan aşağıdakiler çıkarılır )

Bugünlerde izninizi almamanın en büyük nedeni, projenizde targetSdkVersion23 veya daha yüksek bir değer bulunması ve talep ettiğiniz iznin "tehlikeli" olmasıdır. Android 6.0'da buna şunlar dahildir:

  • ACCESS_COARSE_LOCATION
  • ACCESS_FINE_LOCATION
  • ADD_VOICEMAIL
  • BODY_SENSORS
  • CALL_PHONE
  • CAMERA
  • GET_ACCOUNTS
  • PROCESS_OUTGOING_CALLS
  • READ_CALENDAR
  • READ_CALL_LOG
  • READ_CELL_BROADCASTS
  • READ_CONTACTS
  • READ_EXTERNAL_STORAGE
  • READ_PHONE_STATE
  • READ_SMS
  • RECEIVE_MMS
  • RECEIVE_SMS
  • RECEIVE_WAP_PUSH
  • RECORD_AUDIO
  • SEND_SMS
  • USE_SIP
  • WRITE_CALENDAR
  • WRITE_CALL_LOG
  • WRITE_CONTACTS
  • WRITE_EXTERNAL_STORAGE

Bu izinler için, yalnızca targetSdkVersion23+ uygulamanızın öğelere sahip olması gerekmez <uses-permission>, aynı zamanda checkSelfPermission()ve benzeri yöntemleri kullanarak Android 6.0+ cihazlarda kullanıcıdan çalışma zamanında bu izinleri istemeniz de gerekir requestPermissions().

Geçici bir çözüm olarak, targetSdkVersion23'ün altına bırakın .

Ancak, sonunda, targetSdkVersion23 veya daha yüksek olmasını istemek için bir nedeniniz olacaktır . O zaman, uygulamanızı yeni çalışma zamanı izin sistemini kullanacak şekilde ayarlamanız gerekecektir. Android belgelerinde bu konuyla ilgili bir sayfa var .


2
Çok teşekkür ederim, requestPermissions () yöntemlerini kullandım ve iyi çalıştım
Nathan Loudjani

Tamam, bunu daha önce denedim ama ContextCompat.checkSelfPermission ve ActivityCompat.requestPermissions yöntemlerini alamadım, bana yöntem adlarında 'bulunamadı' hatası veriyorlar. Eksik bir kütüphane ile ilgili olduğunu tahmin ediyorum, bir v4 paketinde gibi görünüyor ama benim tek dereceli bağımlılığım compile 'com.android.support:appcompat-v7:22.2.1'. Bunu v4 olarak değiştirmeli miyim?
Ozzy

2
@Ozzy: Şu anda kullanmakta olduğunuz v22 yerine, destek kitaplıklarının v23 neslinde 23.x.y(x ve y'nin geçerli değerleri için) olmanız gerekir.
CommonsWare

Teşekkürler, gelecek için sanırım. Şimdilik hedefi v22 olarak değiştirdim ve SD kart depolama emülatörde 200 MB olarak ayarlanmış olsa da, bana SD kart takılı değil hatası verdi. Ama sonra telefonumu geliştirici moduna bağladım ve her şey çalışıyor. Bazı nedenlerden dolayı SD kart depolama, v23 çalıştıran emülatörde çalışır, ancak v22'de çalışmaz.
Ozzy

3
@NathanLoudjani Bunu uygulayan kodunuzu paylaşmak ister misiniz? Ben tamamen aynı gemideyim ve bunu faaliyetime sokmakta zorlanıyorum.
dschuett

29

API seviyesi 23'ün üstünde size programatik olarak pragmatik olarak verilecektir:

    private static final int PERMISSION_REQUEST_CODE = 1;

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {

        if (checkSelfPermission(Manifest.permission.SEND_SMS)
                == PackageManager.PERMISSION_DENIED) {

            Log.d("permission", "permission denied to SEND_SMS - requesting it");
            String[] permissions = {Manifest.permission.SEND_SMS};

            requestPermissions(permissions, PERMISSION_REQUEST_CODE);

        }
    }

7

pragmatik olarak izin isteme (API 23'ten sonra)

if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.SEND_SMS)
    != PackageManager.PERMISSION_GRANTED) {
    // Permission is not granted 
    // Ask for permision
    ActivityCompat.requestPermissions(this,new String[] { Manifest.permission.SEND_SMS}, 1); 
} 
else {
// Permission has already been granted
}

"Uygulamanın izni varsa, checkSelfPermission () yöntemi PERMISSION_GRANTED değerini döndürür ve uygulama işleme devam edebilir.

Uygulama izni yoksa, yöntem PERMISSION_DENIED değerini döndürür ve uygulama kullanıcıdan açıkça izin istemelidir. Yukarıdaki kodda gösterildiği gibi kullanıcıdan bu izni istemeniz gerekir. RequestPermissions () öğesini çağırmak, özelleştiremeyeceğiniz standart bir Android iletişim kutusu açar. "


Bu çizgiyi nereye koyacağız? ActivityCompat.requestPermissions (bu, yeni Dize [] {Manifest.permission.SEND_SMS}, 1); ve 1 ne anlama geliyor?
LizG

6

Sdk 23 veya üstünü kullanıyorsanız, çalışma zamanı izinlerini kontrol etmeniz gerekir.


6

Eğer beyan zaman permissoniçinde Manifestve sen Görevi performans araçları iş değil MarshMallowve için MarshMallowen iznin belirledik RunTime.

bu şekilde beğen

ActivityCompat.requestPermissions();

6

Lütfen aşağıdaki bağlantıyı inceleyin: https://developer.android.com/guide/topics/permissions/overview.html

İzinlere başlamak için bazı örnekler de mevcuttur.

Şimdi android daha güvenli hale getirmek için geliştiriciler manifest izni yanı sıra iş yapmak için çalışma zamanında da kullanıcı sormak zorunda gerekir söz gerekir. Bunlar aşağıda belirtilen tehlikeli izin bölümünde kategorize edilmiş izinlerdir.

TAKVİM

READ_CALENDAR

WRITE_CALENDAR

KAMERA

CAMERA

İLETİŞİM

READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS

YER

ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION

MİKROFON

RECORD_AUDIO

TELEFON

READ_PHONE_STATE
READ_PHONE_NUMBERS
CALL_PHONE
ANSWER_PHONE_CALLS (must request at runtime)
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
ANSWER_PHONE_CALLS

SENSÖRLER

BODY_SENSORS

SMS

SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS

DEPOLAMA

READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

2

Bunu sorunumu çözen MainActivity'ye ekledim

       int MY_PERMISSIONS_REQUEST_READ_CONTACTS=0;
// Here, thisActivity is the current activity
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

                // Show an expanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

            } else {

                // No explanation needed, we can request the permission.

                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        MY_PERMISSIONS_REQUEST_READ_CONTACTS);

                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        }

2

Android sürümü "23" veya "23+" kullanıyorsanız, kullanıcı izni gerektiren herhangi bir şeye erişmeye çalıştığınızda uygulama size hatalar gösterir. Android bildiriminde bu izinleri bildirmiş olsanız bile, çalışma zamanında izin istemeniz gerekir.

Bunu kontrol edin: https://developer.android.com/training/permissions/requesting.html

Ancak tüm başvurunuzu oluşturduysanız ve her yerde değiştirmek istemiyorsanız, biraz hile yeterli olacaktır.

"Build.gradle" dosyasına gidin ve hedef Sdk sürümünü 22, 21 gibi 23'ten daha düşük bir değere değiştirin.


1

CommonsWare yanıtıyla birlikte,

SMS Mesaj Sınırını ayarlamak için bir Güvenlik Ayarı (CM13'te kontrol ettim) var. Bunu "Hiçbiri" olarak ayarlarsanız, işletim sistemi çalışma zamanında SMS_SEND izni aldıktan sonra bile her SMS için bir İletişim Kutusu açar. En iyisi bunu maksimuma çıkarmak.

Maksimum değer yeterli değilse, köklü bir cihazda maksimum hızı artırmanın yolları vardır.


0

Mesajlarınıza erişmek için bu kodu kullanabilirsiniz

Aşağıdaki kodu kullanarak bir İletişim Kutusu açın:

ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    1);

Etkinlik sonucunu aşağıdaki gibi alın:

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case 1: {

          // If request is cancelled, the result arrays are empty.
          if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.          
            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
                Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

veya dosya build.gradleve kanal numarasını targetSdkVersiondaha az düzenleyin 23
Ve artık yukarıdaki koda gerek yok

NOT
Tabii ki durum böyle değil ve bu sadece eğitimsel bir özellik


0

Bu yüzden mesaj göndermek ve almak için bir uygulama oluşturmak zorunda kaldım, ancak izin verildiği halde gönderimi tıkladığımda gönderme eylemi çöktü. Çalışma zamanı izinleri istemiştim ve onlara izin verdim, yine de sürecin SMS göndermek için gerekli izinlere sahip olmadığı bir çökme ile karşı karşıya kaldım. Verilen izinleri kontrol etmiştim:

adb shell dumpsys package <package-name>

İzin isteğimin sırası

  1. RECEIVE_SMS
  2. SEND_SMS

İstek sırasını geri aldım ve iyi çalışıyor. Bu, tamamen yeni bir uygulama ile test edildi (uninstall-> install -> test). Cevap garip gelebilir ama sadece denemek.

(Belirli bir sırayla gösterilen şekilde çalışırsa, Android'in bir hatası olabilir!)


0

Harici depolama alanına yazma çözümünün de faydalı olacağını umuyorum

public  boolean checkPermission() {
        if (Build.VERSION.SDK_INT >= 23) {
            if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    == PackageManager.PERMISSION_GRANTED) {
                Timber.tag(LOG_TAG).e("Permission error. You have permission");
                return true;
            } else {
                Timber.tag(LOG_TAG).e("Permission error. You have asked for permission");
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
                return false;
            }
        }
        else { 
            // for a stuff below api level 23
            Timber.tag(LOG_TAG).e("Permission error. You already have the permission");
            return true;
        }
    }

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.