L'autorisation Android ne fonctionne pas même si je l'ai déclarée

167

J'essaie d'écrire du code pour envoyer un SMS à partir d'une application Android, mais lorsque j'essaie d'envoyer le SMS, cela me renvoie l'erreur:

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)

J'ai vérifié mais j'ai les autorisations dans le manifeste, comme suit:

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

J'ai cherché sur Internet mais toutes les erreurs concernaient la <uses-permission/>syntaxe, pourriez-vous m'aider s'il vous plaît?

Nathan Loudjani
la source
Sur quelle version d'Android testez-vous?
CommonsWare
Je teste sur Android 6.0
Nathan Loudjani
1
cela fonctionnera sûrement sur une version ci-dessous d'Android. Il y a une nouvelle philosophie des autorisations dans Android 6.0
Fakher
Existe-t-il une syntaxe spéciale pour Android 6? Comment puis-je être sûr que cela fonctionne sur la version ci-dessous?
Nathan Loudjani
mon précédent a targetsdkversionété 23mis à jour 27après que l' READ_SMSautorisation de mise à jour de l' application ne fonctionne pas, ce qui est déjà activé. s'il vous plaît aider
Sagar

Réponses:

238

(ce qui suit est extrait d' un article de mon blog à ce sujet )

La principale raison pour laquelle vous n'obtenez pas votre permission de nos jours est que votre projet a une valeur targetSdkVersionde 23 ou plus et que la permission que vous demandez est "dangereuse". Dans Android 6.0, cela comprend:

  • 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

Pour ces autorisations, non seulement votre targetSdkVersionapplication 23+ doit avoir le ou les <uses-permission>éléments, mais vous devez également demander ces autorisations au moment de l'exécution à l'utilisateur sur les appareils Android 6.0+, en utilisant des méthodes telles que checkSelfPermission()et requestPermissions().

En guise de solution temporaire, déposez votre targetSdkVersionsous 23.

Cependant, vous aurez éventuellement des raisons de vouloir targetSdkVersionavoir 23 ans ou plus. À ce moment-là, vous devrez ajuster votre application pour utiliser le nouveau système d'autorisation d'exécution. La documentation Android a une page dédiée à ce sujet .

CommonsWare
la source
2
Merci beaucoup, j'ai utilisé les méthodes requestPermissions () et j'ai bien travaillé
Nathan Loudjani
D'accord, j'ai essayé cela avant mais je n'ai pas pu obtenir les méthodes ContextCompat.checkSelfPermission et ActivityCompat.requestPermissions, elles me donnent une erreur `` introuvable '' sur les noms des méthodes. Je suppose que cela a à voir avec une bibliothèque manquante, cela semble être dans un package v4 mais ma seule dépendance gradle est compile 'com.android.support:appcompat-v7:22.2.1'. Dois-je changer cela en v4?
Ozzy
2
@Ozzy: Vous devez être sur une génération v23 des bibliothèques de support ( 23.x.y, pour les valeurs actuelles de x et y), plutôt que sur la v22 que vous utilisez actuellement.
CommonsWare
Merci, pour l'avenir je suppose. Pour l'instant, j'ai changé la cible en v22 et même si le stockage de la carte SD était réglé sur 200 Mo sur l'émulateur, cela m'a donné une erreur de carte SD non montée. Mais ensuite, j'ai connecté mon téléphone en mode développeur et tout fonctionne. Pour une raison quelconque, le stockage sur carte SD fonctionne sur l'émulateur exécutant v23 mais pas v22.
Ozzy
3
@NathanLoudjani Pourriez-vous partager votre code qui implémente cela? Je suis exactement dans le même bateau et j'ai du mal à intégrer cela dans mon activité.
dschuett
29

Au-dessus du niveau 23 de l'API, vous recevrez de manière pragmatique comme:

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

        }
    }
user7176550
la source
7

demander l'autorisation de manière pragmatique (après 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
}

"Si l'application dispose de l'autorisation, la méthode checkSelfPermission () renvoie PERMISSION_GRANTED, et l'application peut poursuivre l'opération.

Si l'application n'a pas l'autorisation, la méthode retourne PERMISSION_DENIED et l'application doit explicitement demander l'autorisation à l'utilisateur. Vous devez demander à l'utilisateur cette autorisation, comme indiqué dans le code ci-dessus. L'appel de requestPermissions () ouvre une boîte de dialogue Android standard, que vous ne pouvez pas personnaliser. "

Dan Alboteanu
la source
Où placerions-nous cette ligne? ActivityCompat.requestPermissions (this, new String [] {Manifest.permission.SEND_SMS}, 1); et à quoi fait référence le 1?
LizG
6

Si vous utilisez sdk 23 ou supérieur, vous devez vérifier les autorisations d'exécution.

Dharmendra Pratap
la source
6

lorsque vous déclarez permissondans Manifestet son travail ne signifie que vous effectuez des tâches dans MarshMallowet MarshMallowvous avez mis permisson à RunTime.

comme ça

ActivityCompat.requestPermissions();
Harshad Pansuriya
la source
6

Veuillez suivre le lien ci-dessous, https://developer.android.com/guide/topics/permissions/overview.html

Quelques exemples y sont également disponibles pour commencer avec les permissions.

Pour rendre Android plus sécurisé, les développeurs doivent maintenant mentionner l'autorisation dans le manifeste et doivent également demander à l'utilisateur au moment de l'exécution de faire le travail. Ils sont des autorisations classées dans la section des autorisations dangereuses qui sont mentionnées ci-dessous

CALENDRIER

READ_CALENDAR

WRITE_CALENDAR

CAMÉRA

CAMERA

CONTACTS

READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS

EMPLACEMENT

ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION

MICROPHONE

RECORD_AUDIO

TÉLÉPHONE

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

CAPTEURS

BODY_SENSORS

SMS

SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS

ESPACE DE RANGEMENT

READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
Rishabh Saxena
la source
2

J'ai ajouté ceci à ma MainActivity, qui résout mon problème

       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.
            }
        }
Masquitos
la source
2

Si vous utilisez la version Android "23" ou "23+", l'application vous montrera des erreurs lorsque vous essayez d'accéder à tout ce qui nécessite l'autorisation de l'utilisateur. Vous devez demander des autorisations au moment de l'exécution même si vous avez déclaré ces autorisations dans le manifeste Android.

Vérifiez ceci: https://developer.android.com/training/permissions/requesting.html

Mais si vous avez créé toute votre application et que vous ne voulez pas changer à chaque endroit, une petite astuce sera suffisante.

Allez dans le fichier "Build.gradle" et changez la version Sdk cible en moins de 23, comme 22, 21.

Zohaib Hassan
la source
1

Avec la réponse de CommonsWare,

Il existe un paramètre de sécurité (j'ai vérifié sur CM13) pour définir la limite de message SMS. Si vous définissez ceci sur "Aucun", le système d'exploitation affichera une boîte de dialogue pour chaque SMS, même après avoir obtenu l'autorisation SMS_SEND dans le runtime. La meilleure chose à faire est de régler ce paramètre au maximum.

Si le maximum ne suffit pas, il existe des moyens d'augmenter le débit maximum sur un appareil enraciné.

Dumi Jay
la source
0

Vous pouvez utiliser ce code pour accéder à vos messages

Ouvrez une boîte de dialogue en utilisant le code ci-dessous:

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

Obtenez le résultat de l'activité comme ci-dessous:

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

ou éditez le fichier build.gradleet le numéro de changement targetSdkVersioninférieur à 23
Et vous n'avez plus besoin du code ci-dessus

NOTE
Bien sûr, ce n'est pas le cas, et c'est juste un aspect éducatif

Amirhf
la source
0

J'ai donc dû créer une application pour envoyer et recevoir des messages, mais l'action d'envoi plantait chaque fois que je cliquais sur envoyer même si l'autorisation était accordée. J'avais demandé des autorisations d'exécution et je les ai autorisées, mais j'ai toujours fait face à un plantage que le processus n'a pas l'autorisation requise pour envoyer des SMS. J'avais vérifié les autorisations accordées à partir de:

adb shell dumpsys package <package-name>

L'ordre de ma demande d'autorisation était

  1. RECEIVE_SMS
  2. ENVOYER UN SMS

J'ai inversé l'ordre de la demande et cela fonctionne très bien. Cela a été testé avec une nouvelle application complète (désinstallation-> installation -> test). La réponse peut sembler étrange, mais essayez-la.

(Si cela fonctionne de la manière indiquée dans un certain ordre, alors Android pourrait avoir un bogue !!)

Partha Sarathi Murmu
la source
0

J'espère que la solution pour écrire sur un stockage externe sera également 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;
        }
    }
SergeyUr
la source