Die Android-Berechtigung funktioniert nicht, auch wenn ich sie deklariert habe

167

Ich versuche, Code zum Senden einer SMS von einer Android-App zu schreiben, aber wenn ich versuche, die SMS zu senden, wird mir der folgende Fehler zurückgesendet:

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)

Ich habe überprüft, aber ich habe die Berechtigungen im Manifest wie folgt:

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

Ich habe im Internet gesucht, aber alle Fehler betrafen die <uses-permission/>Syntax. Können Sie mir bitte helfen?

Nathan Loudjani
quelle
Auf welcher Android-Version testen Sie?
CommonsWare
Ich
teste
1
sicherlich wird es auf einer unten stehenden Version von Android funktionieren. Es gibt eine neue Philosophie der Berechtigungen in Android 6.0
Fakher
Gibt es eine spezielle Syntax für Android 6? Wie kann ich sicher sein, dass es unter der folgenden Version funktioniert?
Nathan Loudjani
Meine vorherige targetsdkversionwurde 23aktualisiert, 27nachdem die READ_SMSBerechtigung zum Aktualisieren der App nicht funktioniert, was bereits aktiviert ist. Bitte helfen Sie
Sagar

Antworten:

237

(Das Folgende ist aus einem Blog-Beitrag von mir darüber extrahiert )

Der Hauptgrund dafür, dass Sie heutzutage keine Erlaubnis erhalten, ist, dass Ihr Projekt eine Berechtigung targetSdkVersionvon 23 oder höher hat und die von Ihnen angeforderte Erlaubnis "gefährlich" ist. In Android 6.0 umfasst dies:

  • 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

Für diese Berechtigungen muss Ihre targetSdkVersion23+ App nicht nur über die <uses-permission>Elemente verfügen , sondern Sie müssen diese Berechtigungen auch zur Laufzeit vom Benutzer auf Android 6.0+ Geräten mit Methoden wie checkSelfPermission()und anfordern requestPermissions().

Lassen Sie als vorübergehende Problemumgehung Ihre targetSdkVersionunter 23 fallen.

Irgendwann werden Sie jedoch einen Grund haben zu wollen targetSdkVersion, dass Sie 23 oder höher sind. Zu diesem Zeitpunkt müssen Sie Ihre App anpassen, um das neue Laufzeitberechtigungssystem verwenden zu können. Die Android-Dokumentation enthält eine Seite zu diesem Thema .

CommonsWare
quelle
2
Vielen Dank, ich habe die requestPermissions () -Methoden verwendet und gut gearbeitet
Nathan Loudjani
Okay, ich habe dies zuvor versucht, konnte jedoch die Methoden ContextCompat.checkSelfPermission und ActivityCompat.requestPermissions nicht abrufen. Sie geben mir einen Fehler "nicht gefunden" bei den Methodennamen. Ich vermute, es hat mit einer fehlenden Bibliothek zu tun, es scheint in einem v4-Paket zu sein, aber meine einzige Gradle-Abhängigkeit ist compile 'com.android.support:appcompat-v7:22.2.1'. Soll ich das auf v4 ändern?
Ozzy
2
@Ozzy: Sie müssen sich auf einer v23-Generation der Unterstützungsbibliotheken befinden ( 23.x.yfür aktuelle Werte von x und y) und nicht auf der v22, die Sie derzeit verwenden.
CommonsWare
Danke, für die Zukunft, denke ich. Im Moment habe ich das Ziel wieder auf v22 geändert und obwohl der SD-Kartenspeicher im Emulator auf 200 MB eingestellt war, gab es einen Fehler bei der nicht gemounteten SD-Karte. Aber dann habe ich mein Telefon im Entwicklermodus angeschlossen und alles funktioniert. Aus irgendeinem Grund funktioniert der SD-Kartenspeicher auf dem Emulator, auf dem Version 23 ausgeführt wird, jedoch nicht auf Version 22.
Ozzy
3
@ NathanLoudjani Würde es Ihnen etwas ausmachen, Ihren Code zu teilen, der dies implementiert? Ich bin genau im selben Boot und habe Mühe, dies in meine Tätigkeit umzusetzen.
Dschuett
29

Oberhalb von API Level 23 erhalten Sie programmatisch pragmatisch Folgendes:

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

Erlaubnis pragmatisch anfordern (nach 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
}

"Wenn die App über die Berechtigung verfügt, gibt die Methode checkSelfPermission () PERMISSION_GRANTED zurück, und die App kann mit dem Vorgang fortfahren.

Wenn die App nicht über die Berechtigung verfügt, gibt die Methode PERMISSION_DENIED zurück, und die App muss den Benutzer explizit um Erlaubnis bitten. Sie müssen den Benutzer zur Eingabe dieser Berechtigung auffordern, wie im obigen Code gezeigt. Wenn Sie requestPermissions () aufrufen, wird ein Standard-Android-Dialogfeld angezeigt, das Sie nicht anpassen können. "

Dan Alboteanu
quelle
Wo würden wir diese Linie setzen? ActivityCompat.requestPermissions (dies, neuer String [] {Manifest.permission.SEND_SMS}, 1); und worauf bezieht sich die 1?
LizG
6

Wenn Sie SDK 23 oder höher verwenden, müssen Sie die Laufzeitberechtigungen überprüfen.

Dharmendra Pratap
quelle
6

wenn Sie erklären permissonin Manifestund es wird nicht funktionieren Mittel Sie Aufgabe ausführen in MarshMallowund für MarshMallowSie bei permisson gesetzt haben RunTime.

so

ActivityCompat.requestPermissions();
Harshad Pansuriya
quelle
6

Bitte gehen Sie über den unten stehenden Link https://developer.android.com/guide/topics/permissions/overview.html

Dort sind auch einige Beispiele verfügbar, um mit den Berechtigungen zu beginnen.

Um Android jetzt sicherer zu machen, müssen Entwickler die Berechtigung im Manifest erwähnen und den Benutzer zur Laufzeit bitten, die Arbeit zu erledigen. Sie sind Berechtigungen, die im Abschnitt "Gefährliche Berechtigungen" aufgeführt sind und unten aufgeführt sind

KALENDER

READ_CALENDAR

WRITE_CALENDAR

KAMERA

CAMERA

KONTAKTE

READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS

ORT

ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION

MIKROFON

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

SENSOREN

BODY_SENSORS

SMS

SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS

LAGER

READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
Rishabh Saxena
quelle
2

Ich habe dies zu meiner MainActivity hinzugefügt, um mein Problem zu beheben

       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
quelle
2

Wenn Sie die Android-Version "23" oder "23+" verwenden, zeigt die App Fehler an, wenn Sie versuchen, auf etwas zuzugreifen, für das die Erlaubnis des Benutzers erforderlich ist. Sie müssen zur Laufzeit nach Berechtigungen fragen, auch wenn Sie diese Berechtigungen im Android-Manifest deklariert haben.

Überprüfen Sie dies: https://developer.android.com/training/permissions/requesting.html

Wenn Sie jedoch Ihre gesamte Anwendung erstellt haben und nicht an jedem Ort Änderungen vornehmen möchten, ist ein kleiner Cheat ausreichend.

Gehen Sie zur Datei "Build.gradle" und ändern Sie die Sdk-Zielversion auf weniger als 23, z. B. 22, 21.

Zohaib Hassan
quelle
1

Zusammen mit der Antwort von CommonsWare

Es gibt eine Sicherheitseinstellung (ich habe CM13 überprüft), um das SMS-Nachrichtenlimit festzulegen. Wenn Sie dies auf "Keine" setzen, öffnet das Betriebssystem für jede SMS einen Dialog, auch nachdem Sie zur Laufzeit die SMS_SEND-Berechtigung erhalten haben. Am besten setzen Sie dies auf Maximum.

Wenn das Maximum nicht ausreicht, gibt es Möglichkeiten, die maximale Rate auf einem gerooteten Gerät zu erhöhen.

Dumi Jay
quelle
0

Mit diesem Code können Sie auf Ihre Nachrichten zugreifen

Öffnen Sie einen Dialog mit dem folgenden Code:

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

Erhalten Sie das Aktivitätsergebnis wie folgt:

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

oder bearbeiten Sie die Datei build.gradleund die Chanche-Nummer targetSdkVersionkleiner als 23
Und benötigen Sie den obigen Code nicht mehr

HINWEIS
Dies ist natürlich nicht der Fall und nur ein pädagogischer Aspekt

Amirhf
quelle
0

Also musste ich eine App erstellen, um Nachrichten zu senden und zu empfangen, aber die Sendeaktion stürzte ab, wenn ich auf Senden klickte, obwohl die Berechtigung erteilt wurde. Ich hatte Laufzeitberechtigungen angefordert und sie zugelassen, aber ich hatte immer noch einen Absturz, dass der Prozess nicht über die angeforderte Berechtigung zum Senden von SMS verfügt. Ich hatte die erteilten Berechtigungen überprüft von:

adb shell dumpsys package <package-name>

Die Reihenfolge meiner Ersuchen um Erlaubnis war

  1. RECEIVE_SMS
  2. SMS SENDEN

Ich habe die Reihenfolge der Anfrage zurückgesetzt und es funktioniert gut. Dies wurde mit einer komplett neuen App getestet (deinstallieren-> installieren -> testen). Die Antwort mag seltsam erscheinen, aber probieren Sie es einfach aus.

(Wenn es in einer bestimmten Reihenfolge auf die gezeigte Weise funktioniert, hat Android möglicherweise einen Fehler !!)

Partha Sarathi Murmu
quelle
0

Ich hoffe, dass die Lösung zum Schreiben in einen externen Speicher auch nützlich ist

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
quelle