READ_EXTERNAL_STORAGE Berechtigung für Android

84

Ich versuche, auf Mediendateien (Musik) auf dem Gerät des Benutzers zuzugreifen, um sie abzuspielen. eine einfache "Hallo Welt" -Musik-Player-App.

Ich habe einige Tutorials befolgt und sie geben im Grunde den gleichen Code. Aber es wird nicht funktionieren; es stürzt immer wieder ab und sagt mir:

error.....
Caused by: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=27696, uid=10059 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
....

Dies ist meine Manifestdatei:

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="slimsimapps.troff" >

    <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


<application
    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" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

Dies ist meine Java-Methode:

public void initialize() {
    ContentResolver contentResolver = getContentResolver();
    Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    Cursor cursor = contentResolver.query(uri, null, null, null, null);
    if (cursor == null) {
        // query failed, handle error.
    } else if (!cursor.moveToFirst()) {
        // no media on the device
    } else {
        do {
            addSongToXML(cursor);
        } while (cursor.moveToNext());
    }
}

Ich habe versucht:

So legen Sie dies an verschiedenen Stellen in der Manifestdatei ab:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE”/>

So fügen Sie Android hinzu: maxSdkVersion at Read external storage premission:

<uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE"
    android:maxSdkVersion="21" />

So fügen Sie dies in das Manifest / application / activity-tag ein:

android:exported=“true

So setzen Sie grantUriPremission zwischen uri und cursro in die javamethod:

grantUriPermission(null, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

Um dies zu verwenden, stürzt es nicht ab, aber der Cursor wird null:

uri = MediaStore.Audio.Media.getContentUri("EXTERNAL_CONTENT_URI”);

Um INTERNAL Content Uri zu verwenden, funktioniert dies wie erwartet, es werden jedoch nur "OS-Sounds" wie Shutter-Sound, Low-Battery-Sound, Button-Click und dergleichen ausgegeben:

uri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI;

Bitte helfen Sie, das sollte kein schweres Problem sein, das ich kenne, aber ich fühle mich wie ein Anfänger!

Ich habe gelesen und versucht (oder sie als für mein Problem nicht zutreffend angesehen):

Stapelspur:

09-08 06:59:36.619    2009-2009/slimsimapps.troff D/AndroidRuntime﹕ Shutting down VM
    --------- beginning of crash
09-08 06:59:36.619    2009-2009/slimsimapps.troff E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: slimsimapps.troff, PID: 2009
    java.lang.IllegalStateException: Could not execute method for android:onClick
            at android.view.View$DeclaredOnClickListener.onClick(View.java:4452)
            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)
     Caused by: java.lang.reflect.InvocationTargetException
            at java.lang.reflect.Method.invoke(Native Method)
            at android.view.View$DeclaredOnClickListener.onClick(View.java:4447)
            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)
     Caused by: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=2009, uid=10059 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
            at android.os.Parcel.readException(Parcel.java:1599)
            at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
            at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
            at android.content.ContentProviderProxy.query(ContentProviderNative.java:421)
            at android.content.ContentResolver.query(ContentResolver.java:491)
            at android.content.ContentResolver.query(ContentResolver.java:434)
            at slimsimapps.troff.MainActivity.initialize(MainActivity.java:106)
            at slimsimapps.troff.MainActivity.InitializeExternal(MainActivity.java:80)
            at java.lang.reflect.Method.invoke(Native Method)
            at android.view.View$DeclaredOnClickListener.onClick(View.java:4447)
            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)
    --------- beginning of system
Schlanker Sim
quelle
Seltsam, dass dieser Fehler angezeigt wird, wenn Sie diese Zeile nicht im Manifest angegeben haben.
Sunil Sunny
Auf welcher API-Ebene versuchst du das?
Sharp Edge
Haben Sie versucht, das Projekt zu reinigen? ?
Sunil Sunny
@sunilsunny Ich versuche nicht, einige geschützte Dateien zu lesen, von denen ich sowieso nichts weiß, nur einen einfachen Mediaplayer. Ja, ich habe versucht, es zu bereinigen, ich habe versucht, den Computer neu zu starten, ich habe versucht, eine signierte APK zu generieren und sie in Google Play zu veröffentlichen und als Tester darauf zuzugreifen, ohne Glück ...
Slim Sim
@Scharfe Kante ; Meine AVD ist das Standard-Nexus 5, API 23. Mein Modul Gradle hat: compileSdkVersion 23 buildToolsVersion "23.0.0" minSdkVersion 14 targetSdkVersion 23 Also würde ich sagen 23.
Slim Sim

Antworten:

90

Sie haben zwei Lösungen für Ihr Problem. Am schnellsten ist es, targetApi auf 22 zu senken (build.gradle-Datei). Zweitens ist es, ein neues und wunderbares Modell für die Erlaubnis zu verwenden:

if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (shouldShowRequestPermissionRationale(
            Manifest.permission.READ_EXTERNAL_STORAGE)) {
        // Explain to the user why we need to read the contacts
    }

    requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);

    // MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is an
    // app-defined int constant that should be quite unique

    return;
}

Sniplet finden Sie hier: https://developer.android.com/training/permissions/requesting.html

Lösungen 2: Wenn es nicht funktioniert, versuchen Sie Folgendes:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
    && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
        REQUEST_PERMISSION);

return;

}}

und dann im Rückruf

@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION) {
    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // Permission granted.
    } else {
        // User refused to grant permission.
    }
}
}

das ist aus Kommentaren. Vielen Dank

piotrpo
quelle
1
Ja natürlich! Das neue Berechtigungsmodell, das Google mit dem neuesten Android eingeführt hat! Vielen Dank, ich werde dies so schnell wie möglich testen und es als korrekt markieren, wenn es funktioniert! (und ich fing an zu denken, dass dies vergessen wurde!)
Slim Sim
1
Die angeforderte Erlaubnis sollte sein READ_EXTERNAL_STORAGE. Wie in dieser Antwort .
Maclir
Swap! = PackageManager.READ_EXTERNAL_STORAGE für! = PackageManager.PERMISSION_GRANTED
Renascienza
1
@ Renascienza, ja du hast recht. Jemand hat diese Antwort falsch bearbeitet.
Piotrpo
2
Was ist MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE?
Solo
17

Sie müssen zur Laufzeit um Erlaubnis bitten:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
        && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            REQUEST_PERMISSION);
    dialog.dismiss();
    return;
}

Im folgenden Rückruf können Sie problemlos auf den Speicher zugreifen.

@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Permission granted.
        } else {
            // User refused to grant permission.
        }
    }
}
Maclir
quelle
Das hat funktioniert. danke
MindRoasterMir
7

Schritt 1: Fügen Sie die Berechtigung für android manifest.xml hinzu

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Schritt 2: onCreate () -Methode

int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_MEDIA);
    } else {
        readDataExternal();
    }

Schritt 3: Überschreiben Sie die onRequestPermissionsResult-Methode, um einen Rückruf zu erhalten

 @Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_MEDIA:
            if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                readDataExternal();
            }
            break;

        default:
            break;
    }
}

Hinweis: readDataExternal () ist eine Methode zum Abrufen von Daten aus einem externen Speicher.

Vielen Dank.

sonnv1368
quelle
1
Ich denke, Sie haben die erforderliche Berechtigung hier verlegt: ist READ_EXTERNAL_STORAGE.
Renascienza
4

Ich hatte auch ein ähnliches Fehlerprotokoll und hier ist, was ich getan habe:

  1. In der onCreate-Methode fordern wir ein Dialogfeld zum Überprüfen der Berechtigungen an

    ActivityCompat.requestPermissions(MainActivity.this,
    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1);
    
  2. Methode zur Überprüfung des Ergebnisses

    @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 granted and now can proceed
             mymethod(); //a sample method called
    
            } 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;
        }
        // add other cases for more permissions
        }
    }
    

Die offizielle Dokumentation zum Anfordern von Laufzeitberechtigungen


quelle
1
Ich habe es benutzt und es hat perfekt funktioniert. Funktioniert es auf allen Android-Geräten?
Mahdi Hraybi
1

Wurde Ihr Problem behoben? Was ist Ihr Ziel-SDK? Versuchen Sie es android;maxSDKVersion="21"mit<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Jerry Ejonavi
quelle
Arbeitete für mich mit Cordova, indem ich nur die maximale SDK-Version in AndroidManifest.xml auf 22 (statt 23) setzte
George Kagan
0

http://developer.android.com/reference/android/provider/MediaStore.Audio.AudioColumns.html

Versuchen Sie, die Zeile zu ändern contentResolver.query

//change it to the columns you need
String[] columns = new String[]{MediaStore.Audio.AudioColumns.DATA}; 
Cursor cursor = contentResolver.query(uri, columns, null, null, null);

public static final String MEDIA_CONTENT_CONTROL

Aufgrund der Vertraulichkeit des Medienkonsums nicht für Anwendungen von Drittanbietern geeignet

http://developer.android.com/reference/android/Manifest.permission.html#MEDIA_CONTENT_CONTROL

versuchen Sie das <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>erste zu entfernen und versuchen Sie es erneut?

Derek Fung
quelle
Danke, ich habe Ihren Vorschlag ausprobiert, aber er ist an derselben Stelle abgestürzt. Ich verwende einen Mac. Kann das ein Problem sein?
Slim Sim
aktualisiert, versuchen zu entfernen <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>und versuchen? Es kann seltsames Verhalten verursachen, weil Ihre App-Anfrage für eine Erlaubnis nicht erlaubt ist
Derek Fung
danke, ich habe versucht, diese Erlaubnis zu entfernen, aber es stürzt an der gleichen Stelle mit dem gleichen Fehler ab ...
Slim Sim
0

Bitte überprüfen Sie den folgenden Code, mit dem Sie alle Musikdateien von SD-Karte finden können:

public class MainActivity extends Activity{

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_animations);
    getAllSongsFromSDCARD();

}

public void getAllSongsFromSDCARD() {
    String[] STAR = { "*" };
    Cursor cursor;
    Uri allsongsuri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";

    cursor = managedQuery(allsongsuri, STAR, selection, null, null);

    if (cursor != null) {
        if (cursor.moveToFirst()) {
            do {
                String song_name = cursor
                        .getString(cursor
                                .getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
                int song_id = cursor.getInt(cursor
                        .getColumnIndex(MediaStore.Audio.Media._ID));

                String fullpath = cursor.getString(cursor
                        .getColumnIndex(MediaStore.Audio.Media.DATA));

                String album_name = cursor.getString(cursor
                        .getColumnIndex(MediaStore.Audio.Media.ALBUM));
                int album_id = cursor.getInt(cursor
                        .getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));

                String artist_name = cursor.getString(cursor
                        .getColumnIndex(MediaStore.Audio.Media.ARTIST));
                int artist_id = cursor.getInt(cursor
                        .getColumnIndex(MediaStore.Audio.Media.ARTIST_ID));
                System.out.println("sonng name"+fullpath);
            } while (cursor.moveToNext());

        }
        cursor.close();
    }
}


}

Ich habe auch die folgende Zeile in der Datei AndroidManifest.xml wie folgt hinzugefügt:

<uses-sdk
    android:minSdkVersion="16"
    android:targetSdkVersion="17" />

<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Rajan Bhavsar
quelle
Danke, ich habe schon etwas Ähnliches versucht, aber ich habe Ihren Code ausprobiert und er stürzt ab bei "cursor = manageQuery (allsongsuri, STAR, selection, null, null);", der gleiche Fehler wie zuvor. Apropos; ManagedQuery ist veraltet, aber es stürzt immer noch ab, wenn ich es in "contentResolver.query" ändere, die die gleichen Eingabeparameter haben ...
Slim Sim
Hallo, ich kann alle SDCADR-Songs mit dem obigen Code erhalten. mit Android Version 4.2.2 Gerät und auch mit Version 5.0.2. In dem du es versuchst. Welchen Fehler Sie haben, beschreiben Sie bitte mit Android-Version
Rajan Bhavsar
Ich habe die Frage mit dem Stack-Trace aktualisiert, hoffe das hilft. Was meinst du mit Android Version? (Ich benutze apk 23)
Slim Sim
Ok, lassen Sie mich den vollständigen Quellcode geben und das noch einmal überprüfen.
Rajan Bhavsar
Wenn Sie selbst testen möchten, laden Sie die Zip- Datei hier herunter: drive.google.com/open?id=0B2AV8VRk9HUeVzFXSWVRZU9TRUk Drücken Sie beim Ausführen die linke Initialisierungstaste, um den Crach zu generieren.
Slim Sim
0

Neben allen Antworten. Sie können auch das minsdk angeben, das mit dieser Anmerkung angewendet werden soll

@TargetApi(_apiLevel_)

Ich habe dies verwendet, um diese Anfrage zu akzeptieren, auch wenn mein minsdk 18 ist. Die Methode wird nur ausgeführt, wenn das Gerät auf "_apilevel_" und höher abzielt. Hier ist meine Methode:

    @TargetApi(23)
void solicitarPermisos(){

    if (ContextCompat.checkSelfPermission(this,permiso)
            != PackageManager.PERMISSION_GRANTED) {

        // Should we show an explanation?
        if (shouldShowRequestPermissionRationale(
                Manifest.permission.READ_EXTERNAL_STORAGE)) {
            // Explain to the user why we need to read the contacts
        }

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

        // MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is an
        // app-defined int constant that should be quite unique

        return;
    }

}
jan4co
quelle