2015-09-07 26 views
54

Sto provando ad accedere ai file multimediali (musica) sul dispositivo dell'utente per riprodurli; un facile "ciao mondo" -music player app.Autorizzazione READ_EXTERNAL_STORAGE per Android

Ho seguito alcuni tutorial e in pratica danno lo stesso codice. Ma non funzionerà; si blocca e mi dice:

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() 
.... 

Ora, questo è il mio file manifesto:

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

Questo è il mio Java-metodo:

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

ho provato:

Per inserire questo in diversi punti nel file manifest:

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

Per aggiungere Android: maxSdkVersion a Leggi premission archiviazione esterna:

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

di mettere questo nel manifesto/application/attività-tag:

android:exported=“true” 

Per mettere grantUriPremission tra uri e cursro in javamethod:

grantUriPermission(null, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); 

Per utilizzare questo, non collasserà, ma il cursore diventa nullo:

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

di utilizzare il contenuto URI interna, questo funziona come previsto, ma dà solo "OS-suoni" come otturatore-sound , basso-batteria-suono, il pulsante del mouse e quali:

uri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI; 

Motivi aiuto, questo non dovrebbe essere un problema difficile lo so, ma mi sento come una principiante!

Ho letto e provato (o ritenuto non applicabile per il mio problema):

Stack trace:

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 
+0

Strano che l'errore viene visualizzato quando non hai dato questa linea in palese Stai cercando di leggere alcuni file che è protetto da alcune altre app? –

+0

Su quale livello di API stai provando questo? –

+0

Hai provato a pulire il progetto. ? –

risposta

53

È hai due soluzioni per il tuo problema. Quello veloce è di abbassare targetApi a 22 (file build.gradle). In secondo luogo è quello di utilizzare di nuovo e meraviglioso chiedere-per-il permesso il modello:

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 trovato qui: https://developer.android.com/training/permissions/requesting.html

+1

Sì, certo! Il nuovo modello di autorizzazione introdotto da Google con l'ultimo Android! Grazie, lo metterò alla prova il prima possibile e segnalo correttamente se funziona! (e stavo cominciando a pensare che fosse dimenticato!) –

+0

L'autorizzazione richiesta è "READ_EXTERNAL_STORAGE". Come in [questa risposta] (http://stackoverflow.com/a/35720050/1432239). – maclir

+0

swap! = PackageManager.READ_EXTERNAL_STORAGE per! = PackageManager.PERMISSION_GRANTED – Renascienza

0

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

provare a cambiare la linea 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

Non per l'uso da applicazioni di terze parti a causa di privacy di consumo dei media

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

tenta di rimuovere il primo <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/> e riprovare?

+0

Grazie, ho provato il tuo suggerimento ma si è schiantato nello stesso punto ... Sto usando un Mac, può essere un problema? –

+0

aggiornato, prova a rimuovere '' e prova? Può creare strani comportamenti perché la tua richiesta di app per un'autorizzazione non è consentita –

+0

grazie, ho provato a rimuovere tale autorizzazione, ma si blocca nello stesso punto con lo stesso errore ... –

0

Controlli prego sotto il codice che usando che potete trovare tutti i file musicali da sdcard:

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


} 

Ho anche aggiunto seguente riga nella AndroidManifest.xml file come di seguito:

<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" /> 
+0

Grazie, ho provato qualcosa di simile prima, ma io provato il tuo codice e si blocca su "cursor = managedQuery (allsongsuri, STAR, selection, null, null);", lo stesso errore di prima. A proposito; managedQuery è deprecato, ma si blocca ancora se lo cambio in "contentResolver.query", che ha gli stessi parametri di input ... –

+0

Ciao, sono in grado di ottenere tutti i brani sdcadr utilizzando il codice sopra. con dispositivo Android versione 4.2.2 e anche in grado di con la versione 5.0.2. In cui stai provando Che errore hai riscontrato per favore descrivi con la versione Android –

+0

Ho aggiornato la domanda con lo stack-trace, spero che sia d'aiuto. Cosa intendi con la versione Android? (Sto usando l'apk 23) –

2

ha il tuo problema è stato risolto? Qual è il tuo SDK di destinazione? Prova ad aggiungere android;maxSDKVersion="21"-<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

+0

Ha funzionato per me utilizzando Cordova, impostando solo la versione max SDK in AndroidManifest.xml su 22 (anziché su 23) –

+0

La tua app funziona ancora su Marshmallow e versioni successive? –

9

Devi chiedere il permesso in fase di esecuzione:

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

E nella richiamata qui sotto potete accedere alla memoria senza un problema.

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

Passaggio 1: aggiungere autorizzazione su Android manifest.XML

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

Fase 2: onCreate() metodo

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

Fase 3: sostituire onRequestPermissionsResult metodo per ottenere callback

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

Nota: readDataExternal() è il metodo per ottenere i dati dalla memoria esterna.

Grazie.

+0

Penso che tu abbia sbagliato l'autorizzazione necessaria qui: READ_EXTERNAL_STORAGE. – Renascienza

+0

sì, grazie mille. – sonnv1368

-1

Basta andare alle "impostazioni", sotto "dispositivo" selezionare "app" e quindi scorrere fino a MY_APPLICATION e concedere l'autorizzazione "archiviazione".

+1

Penso che non sia il caso ... Deve farlo nel suo progetto, non nello smartphone stesso. – BrunoDM

2

Ho anche avuto un simile registro errori e qui è quello che ho did-

  1. Nel metodo onCreate chiediamo una finestra di dialogo per le autorizzazioni di controllo

    ActivityCompat.requestPermissions(MainActivity.this, 
    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1); 
    
  2. Metodo per verificare il risultato

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

La documentazione ufficiale a Requesting Runtime Permissions

+1

l'ho usato e ha funzionato perfettamente funziona su tutti i dispositivi Android? –

+0

sì, funziona su tutti i dispositivi –

0

In aggiunta a tutte le risposte. È anche possibile specificare il minsdk da applicare con questa annotazione

@TargetApi(_apiLevel_) 

ho usato questo per accettare questa richiesta anche la mia minsdk è 18. Quello che fa è che il metodo funziona solo quando gli obiettivi di dispositivi "_apilevel_" e superiore. Ecco il mio metodo:

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

}