L'autorizzazione Android non funziona anche se l'ho dichiarata


167

Sto cercando di scrivere il codice per inviare un SMS da un'app Android, ma quando provo a inviare l'SMS mi restituisce l'errore:

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)

Ho controllato ma ho i permessi nel manifest, come segue:

<?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>

Ho cercato su Internet ma tutti gli errori riguardavano la <uses-permission/>sintassi, potresti aiutarmi per favore?


Su quale versione di Android stai testando?
CommonsWare,

Sto testando su Android 6.0
Nathan Loudjani il

1
sicuramente funzionerà su una versione inferiore di Android. C'è una nuova filosofia delle autorizzazioni in Android 6.0
Fakher

Esiste una sintassi speciale per Android 6? Come posso essere sicuro che funzioni con la versione precedente?
Nathan Loudjani,

il mio precedente è targetsdkversionstato 23aggiornato 27dopo che l' READ_SMSautorizzazione di aggiornamento dell'app non funzionava, che è già abilitata. per favore
aiutatemi

Risposte:


238

(quanto segue è estratto da un mio post sul blog a riguardo )

Il motivo principale per cui non si ottiene l'autorizzazione al giorno d'oggi è perché il progetto ha un numero targetSdkVersiondi 23 o superiore e l'autorizzazione richiesta è "pericolosa". In Android 6.0, questo include:

  • 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

Per queste autorizzazioni, non solo la tua targetSdkVersionapp 23+ deve avere gli <uses-permission>elementi, ma devi anche chiedere tali autorizzazioni in fase di esecuzione dall'utente su dispositivi Android 6.0+, usando metodi come checkSelfPermission()e requestPermissions().

Come soluzione temporanea, rilasciare il valore targetSdkVersioninferiore a 23.

Tuttavia, alla fine, avrai qualche motivo per volere che tu targetSdkVersionabbia 23 anni o più. In quel momento, dovrai adattare la tua app per utilizzare il nuovo sistema di autorizzazioni di runtime. La documentazione di Android ha una pagina dedicata a questo argomento .


2
Grazie mille, ho usato i metodi requestPermissions () e ho funzionato bene
Nathan Loudjani

Ok, ho già tentato prima, ma non sono riuscito a ottenere i metodi ContextCompat.checkSelfPermission e ActivityCompat.requestPermissions, mi danno un errore "non trovato" sui nomi dei metodi. Immagino che abbia a che fare con una libreria mancante, sembra essere in un pacchetto v4 ma la mia unica dipendenza gradle è compile 'com.android.support:appcompat-v7:22.2.1'. Devo cambiarlo in v4?
Ozzy,

2
@Ozzy: devi essere su una generazione v23 delle librerie di supporto ( 23.x.y, per i valori correnti di xey), piuttosto che sulla v22 che stai attualmente utilizzando.
Commons War

Grazie, per il futuro immagino. Per ora ho cambiato la destinazione in v22 e anche se la memoria della scheda SD era impostata su 200 MB sull'emulatore, mi ha dato un errore della scheda SD non montata. Ma poi ho collegato il mio telefono in modalità sviluppatore e tutto funziona. Per qualche motivo, la memoria della scheda SD funziona sull'emulatore che esegue v23 ma non v22.
Ozzy,

3
@NathanLoudjani Ti dispiacerebbe condividere il tuo codice che lo implementa? Sono nella stessa identica barca e faccio fatica a metterlo nella mia attività.
dschuett,

29

Al di sopra del livello API 23 ti verrà dato programmaticamente pragmaticamente come:

    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

richiedere l'autorizzazione pragmaticamente (dopo l'API 23)

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
}

"Se l'app dispone dell'autorizzazione, il metodo checkSelfPermission () restituisce PERMISSION_GRANTED e l'app può procedere con l'operazione.

Se l'app non dispone dell'autorizzazione, il metodo restituisce PERMISSION_DENIED e l'app deve richiedere esplicitamente all'utente l'autorizzazione. È necessario richiedere all'utente tale autorizzazione, come mostrato nel codice sopra. Chiamando requestPermissions () viene visualizzata una finestra di dialogo Android standard, che non è possibile personalizzare. "


Dove metteremmo questa linea? ActivityCompat.requestPermissions (this, new String [] {Manifest.permission.SEND_SMS}, 1); e a cosa si riferisce l'1?
LizG


6

quando dichiari permissonin Manifeste non funziona significa che stai eseguendo Task in MarshMallowe per MarshMallowcui hai impostato Permisson su RunTime.

in questo modo

ActivityCompat.requestPermissions();

6

Si prega di passare attraverso il link seguente, https://developer.android.com/guide/topics/permissions/overview.html

Alcuni esempi sono disponibili anche lì per iniziare con le autorizzazioni.

Per rendere Android più sicuro ora gli sviluppatori devono menzionare l'autorizzazione in manifest e dovrebbero anche chiedere all'utente e in fase di esecuzione di fare il lavoro. Sono le autorizzazioni classificate nella sezione autorizzazioni pericolose che sono menzionate di seguito

CALENDARIO

READ_CALENDAR

WRITE_CALENDAR

TELECAMERA

CAMERA

CONTATTI

READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS

POSIZIONE

ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION

MICROFONO

RECORD_AUDIO

TELEFONO

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

SENSORI

BODY_SENSORS

sms

SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS

CONSERVAZIONE

READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

2

Ho aggiunto questo al mio MainActivity, che risolve il mio problema

       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

Se stai utilizzando la versione Android "23" o "23+", l'app ti mostrerà errori quando tenti di accedere a qualsiasi cosa che richieda l'autorizzazione dell'utente. Devi richiedere le autorizzazioni in fase di esecuzione anche se hai dichiarato tali autorizzazioni nel manifest di Android.

Controlla questo: https://developer.android.com/training/permissions/requesting.html

Ma se hai creato la tua intera applicazione e non vuoi cambiare in ogni luogo, sarà sufficiente un piccolo trucco.

Vai al file "Build.gradle" e modifica la versione Sdk di destinazione in meno di 23, come 22, 21.


1

Insieme alla risposta di CommonsWare,

C'è un'impostazione di sicurezza (ho controllato su CM13) per impostare il limite dei messaggi SMS. Se lo si imposta su "Nessuno", il sistema operativo aprirà una finestra di dialogo per ogni SMS, anche dopo aver ottenuto l'autorizzazione SMS_SEND in fase di esecuzione. La cosa migliore è impostare questo al massimo.

Se il massimo non è sufficiente, esistono modi per aumentare la velocità massima su un dispositivo rooted.


0

Puoi usare questo codice per accedere ai tuoi messaggi

Apri una finestra di dialogo usando il codice seguente:

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

Ottieni il risultato dell'attività come di seguito:

@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
    }
}

o modificare il file build.gradlee modificare il numero in targetSdkVersionmeno di 23
E non è più necessario il codice sopra

NOTA
Naturalmente non è così, ed è solo un aspetto educativo


0

Quindi ho dovuto creare un'app per inviare e ricevere messaggi, ma l'azione di invio si è arrestata in modo anomalo ogni volta che ho fatto clic su Invia anche se l'autorizzazione era stata concessa. Avevo richiesto le autorizzazioni di runtime e le ho consentite, tuttavia ho riscontrato un arresto anomalo che il processo non dispone dell'autorizzazione richiesta per inviare SMS. Ho verificato le autorizzazioni concesse da:

adb shell dumpsys package <package-name>

L'ordine della mia richiesta di autorizzazioni era

  1. RECEIVE_SMS
  2. INVIARE SMS

Ho ripristinato l'ordine della richiesta e funziona benissimo. Questo è stato testato con una nuova app completa (disinstallazione-> installa -> test). La risposta può sembrare strana ma provaci.

(Se funziona nel modo indicato in un certo ordine, Android potrebbe avere un bug !!)


0

Spero che anche la soluzione per scrivere su un archivio esterno sia utile

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;
        }
    }

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.