2015-09-07 3 views
54

Я пытаюсь получить доступ к медиафайлам (музыке) на устройстве пользователей, чтобы их воспроизвести; легкое приложение «привет мир» - музыкальный плеер.READ_EXTERNAL_STORAGE разрешение для Android

Я следил за некоторыми учебниками, и они в основном дают тот же код. Но это не сработает; он держит сбой и говорил мне:

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

Теперь это мой файл манифеста:

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

Это мой 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()); 
    } 
} 

Я пробовал:

Чтобы поместить это в разные места в файле манифеста:

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

Чтобы добавить андроид: maxSdkVersion на чтения внешнего premission хранения:

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

Чтобы поставить это в манифесте/приложения/активности тэгом:

android:exported=“true” 

Чтобы положить grantUriPremission между URI и cursro в javamethod:

grantUriPermission(null, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); 

Чтобы использовать это, он не будет врезаться, но курсор становится нулевым:

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

Для использования внутреннего содержания Ури, это работает, как ожидалось, но это дает лишь «OS-звуки», такие как заслонке звук , низкий уровень заряда батареи звука, кнопка кнопкой мыши и такие:

uri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI; 

Просьбы помочь, это не должно быть трудной задачей я знаю, но я чувствую себя новичком!

Я прочитал и пытался (или считали их не применимо для моей проблемы):

Стек след:

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

Странно показано, что ошибка, когда вы не дали эту строку в манифесте <использует-разрешение андроида: имя = «android.permission.READ_EXTERNAL_STORAGE» /> Вы пытаетесь прочитать некоторые файлы, которые защищена некоторыми другими приложениями? –

+0

На каком уровне api вы пытаетесь это сделать? –

+0

Вы пробовали очистить проект. ? –

ответ

53

Вы есть два решения для вашей проблемы. Быстрое - это понизить targetApi до 22 (файл build.gradle). Во-вторых, чтобы использовать новый и замечательный попросить обмен на разрешение модели:

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 найти здесь: https://developer.android.com/training/permissions/requesting.html

+1

Да, конечно! Новая модель разрешения Google, представленная с новейшим Android! Спасибо, я проверю это как можно скорее и пометьте его правильно, если он сработает! (и я начал думать, что это было забыто!) –

+0

Запрошенное разрешение должно быть READ_EXTERNAL_STORAGE. Как в [этом ответе] (http://stackoverflow.com/a/35720050/1432239). – maclir

+0

swap! = PackageManager.READ_EXTERNAL_STORAGE для! = PackageManager.PERMISSION_GRANTED – Renascienza

0

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

Попробуйте изменить линию 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); 

общественности статической конечной строки MEDIA_CONTENT_CONTROL

Не для использования сторонних приложений из-за секретности медиа-потребления

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

попытка удалить <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/> первый и попробовать еще раз?

+0

Спасибо, я попробовал ваше предложение, но он разбился на том же месте ... Я использую Mac, может быть, это проблема? –

+0

обновлено, попробуйте удалить '' и попробовать? Это может создать странное поведение, потому что ваш запрос приложения для разрешения не разрешен –

+0

спасибо, я попытался удалить это разрешение, но он сбой в том же месте с той же ошибкой ... –

0

Пожалуйста, проверьте ниже код, используя который Вы можете найти все музыкальные файлы из 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(); 
    } 
} 


} 

Я также добавил следующую строку в файл AndroidManifest.xml, как показано ниже:

<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

Спасибо, я уже пробовал что-то подобное раньше, но я попробовал ваш код, и он сработает на «cursor = managedQuery (allsongsuri, STAR, selection, null, null);», та же ошибка, что и раньше. Кстати; managedQuery устарел, но он по-прежнему падает, если я меняю его на "contentResolver.query", которые имеют одинаковые параметры ввода ... –

+0

Привет Я могу получить все песни sdcadr, используя вышеприведенный код. с устройством Android версии 4.2.2, а также с версией 5.0.2. В котором вы пытаетесь. Какую ошибку вы получили, пожалуйста, опишите с Android-версией –

+0

. Я обновил вопрос с помощью трассировки стека, надеюсь, что это поможет. Что вы подразумеваете под версией Android? (Я использую apk 23) –

2

Ваша проблема урегулирована? Каков ваш целевой SDK? Попробуйте добавить android;maxSDKVersion="21" к <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

+0

Работала для меня с помощью Кордовы, установив только максимальную версию SDK в AndroidManifest.xml на 22 (вместо 23) –

+0

Поддерживает ли ваше приложение работу над Зефиром и выше? –

9

Вы должны попросить разрешения во время выполнения:

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

И обратного вызова ниже вы можете получить доступ к памяти без проблем.

@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

Шаг 1: добавьте разрешение на манифест андроида.XML

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

Шаг2: 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(); 
    } 

Шаг 3: переопределить onRequestPermissionsResult метод, чтобы получить функцию обратного вызова

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

Примечание: readDataExternal() является метод, чтобы получить данные из внешнего запоминающего устройства.

Спасибо.

+0

Я думаю, что вы упустили необходимое разрешение здесь: READ_EXTERNAL_STORAGE. – Renascienza

+0

да, большое спасибо. – sonnv1368

-1

Просто перейдите в «настройки», в разделе «устройство» выберите «приложения», а затем прокрутите до своего MY_APPLICATION и предоставите разрешение «хранилище».

+1

Я думаю, что это не так ... Он должен сделать это в своем проекте, а не в самом смартфоне. – BrunoDM

2

Я также был подобный журнал ошибок, и вот что я did-

  1. В OnCreate методе мы просим Диалоговое окно для проверки разрешений

    ActivityCompat.requestPermissions(MainActivity.this, 
    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1); 
    
  2. метод для проверки результата

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

Официальная документация к Requesting Runtime Permissions

+1

Я использовал его, и он отлично работал, работает ли он на всех устройствах Android? –

+0

да, он работает на всех устройствах –

0

В дополнение ко всем ответам. Вы также можете указать minsdk применять с этой аннотацией

@TargetApi(_apiLevel_) 

я использовал это для того, чтобы принять этот запрос, даже мой minsdk 18. Что она делает то, что метод работает только тогда, когда целевые устройства «_apilevel_» и верхний. Вот мой метод:

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

} 
Смежные вопросы