Estoy intentando acceder a archivos multimedia (música) en el dispositivo del usuario para reproducirlos; una sencilla aplicación de reproductor de música "hola mundo".
He seguido algunos tutoriales y básicamente dan el mismo código. Pero no funcionará; sigue chocando y diciéndome:
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()
....
Ahora, este es mi archivo de manifiesto:
<?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>
Este es mi método Java:
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());
}
}
Yo he tratado:
Para poner esto en diferentes lugares del archivo de manifiesto:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE”/>
Para agregar android: maxSdkVersion en Leer premisión de almacenamiento externo:
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="21" />
Para poner esto en el manifiesto / aplicación / etiqueta de actividad:
android:exported=“true”
Para poner grantUriPremission entre uri y cursro en el método java:
grantUriPermission(null, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
Para usar esto, no se bloqueará, pero el cursor se vuelve nulo:
uri = MediaStore.Audio.Media.getContentUri("EXTERNAL_CONTENT_URI”);
Para usar la URL de contenido INTERNO, esto funciona como se esperaba, pero solo proporciona "sonidos del sistema operativo", como el sonido del obturador, el sonido de batería baja, el clic del botón y demás:
uri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI;
Por favor, ayuda, esto no debería ser un problema difícil, lo sé, ¡pero me siento como un principiante!
He leído y probado (o considero que no son aplicables para mi problema):
- El permiso READ_EXTERNAL_STORAGE de Android no funciona
- Requiere permiso solo para versiones anteriores de Android: ¿maxSdkVersion no funciona?
- Obtenga el nombre de archivo y la ruta de URI de mediastore
- SecurityException de Android KitKat al intentar leer desde MediaStore
- Android: java.lang.SecurityException: Permission Denial: start Intent
Seguimiento de pila:
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
Respuestas:
Tienes dos soluciones para tu problema. La más rápida es reducir targetApi a 22 (archivo build.gradle). El segundo es utilizar un nuevo y maravilloso modelo de solicitud de permiso:
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 encontrado aquí: https://developer.android.com/training/permissions/requesting.html
Soluciones 2: Si no funciona, intente esto:
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;
}
y luego en devolución de llamada
@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. } } }
eso es de los comentarios. Gracias
fuente
READ_EXTERNAL_STORAGE
. Como en esta respuesta .Tienes que pedir el permiso en tiempo de ejecución:
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; }
Y en la devolución de llamada a continuación, puede acceder al almacenamiento sin problemas.
@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. } } }
fuente
Paso 1: agregue permiso en android manifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Paso 2: método onCreate ()
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(); }
Paso 3: anule el método onRequestPermissionsResult para obtener la devolución de llamada
@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 () es un método para obtener datos del almacenamiento externo.
Gracias.
fuente
También tuve un registro de errores similar y esto es lo que hice:
En el método onCreate solicitamos un cuadro de diálogo para verificar los permisos
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1);
Método para verificar el resultado
@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 documentación oficial para solicitar permisos en tiempo de ejecución
fuente
¿Se ha resuelto tu problema? ¿Cuál es su SDK de destino? Intenta agregar
android;maxSDKVersion="21"
a<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
fuente
http://developer.android.com/reference/android/provider/MediaStore.Audio.AudioColumns.html
Intenta cambiar la línea
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);
http://developer.android.com/reference/android/Manifest.permission.html#MEDIA_CONTENT_CONTROL
intente eliminar el
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
primero y vuelva a intentarlo?fuente
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
y probar? Puede crear un comportamiento extraño porque la solicitud de su aplicación para un permiso no está permitidaPor favor, verifique el código a continuación que al usarlo puede encontrar todos los archivos de música de 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(); } } }
También agregué la siguiente línea en el archivo AndroidManifest.xml de la siguiente manera:
<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" />
fuente
Además de todas las respuestas. También puede especificar los minsdk para aplicar con esta anotación
@TargetApi(_apiLevel_)
Usé esto para aceptar esta solicitud, incluso mi minsdk es 18. Lo que hace es que el método solo se ejecuta cuando el dispositivo apunta a "_apilevel_" y superior. Este es mi método:
@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; } }
fuente