2015-02-14 2 views
7

Я пытаюсь получить музыкальные файлы в устройстве. Вот что я делаю:Чтение внешней памяти Android дает securityException

public ArrayList<Track> getAllSongsFromSDCARD() 
{ 
    allTracks = new ArrayList<Track>(); 
    String[] STAR = { "*" }; 
    Uri allsongsuri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 
    String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0"; 

    Cursor cursor = mContext.getApplicationContext().getContentResolver().query(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)); 



       String duration = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION)); 
       int[] splitTime = null; 
       String hours, minutes, seconds, formattedTime; 
       try{ 
        splitTime = splitToComponentTimes(BigDecimal.valueOf(Long.valueOf(duration)/1000)); 
        hours = String.valueOf(splitTime[0]); 
        minutes = String.valueOf(splitTime[1]); 
        seconds = String.valueOf(splitTime[2]); 
        if(hours.equals("0")){ 
         formattedTime = minutes + ":" + seconds; 
        }else{ 
         formattedTime = hours + ":" + minutes + ":" + seconds; 
        } 
       }catch (Exception e){ 
        formattedTime = "00:00"; 
       } 

       allTracks.add(new Track(song_name, song_id, fullpath, album_name, album_id, artist_name, artist_id, formattedTime)); 
      } while (cursor.moveToNext()); 

     } 

     sortTracksAlphabetically(allTracks); 
     cursor.close(); 
    } 
    return allTracks; 
} 

И у меня есть следующие разрешения в моем манифесте:

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

Когда я запускаю этот код на устройстве с Android версии 4.3 работает нормально. Но когда я запустить его на устройстве с версией Android 5.0.2 дает

«java.lang.SecurityException: Разрешение Отрицание: чтение com.android.providers.media.MediaProvider URI содержания: // СМИ/внешний/аудио/медиа с PID = 5701, UID = 10054 требует android.permission.READ_EXTERNAL_STORAGE»

Может кто-нибудь сказать мне, почему? Вот полный стек:

02-14 19:25:52.812 5701-5701/com.yrazlik.musicplayer E/AndroidRuntime﹕ FATAL EXCEPTION: main 
Process: com.yrazlik.musicplayer, PID: 5701 
java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=5701, uid=10054 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission() 
     at android.os.Parcel.readException(Parcel.java:1540) 
     at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:185) 
     at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137) 
     at android.content.ContentProviderProxy.query(ContentProviderNative.java:420) 
     at android.content.ContentResolver.query(ContentResolver.java:478) 
     at android.content.ContentResolver.query(ContentResolver.java:422) 
     at com.yrazlik.musicplayer.dialogs.AllSongsDialog.getAllSongsFromSDCARD(AllSongsDialog.java:74) 
     at com.yrazlik.musicplayer.dialogs.AllSongsDialog.onCreate(AllSongsDialog.java:59) 
     at android.app.Dialog.dispatchOnCreate(Dialog.java:373) 
     at android.app.Dialog.show(Dialog.java:274) 
     at com.yrazlik.musicplayer.fragments.PlaylistFragment$1.onClick(PlaylistFragment.java:86) 
     at android.view.View.performClick(View.java:4756) 
     at android.view.View$PerformClick.run(View.java:19749) 
     at android.os.Handler.handleCallback(Handler.java:739) 
     at android.os.Handler.dispatchMessage(Handler.java:95) 
     at android.os.Looper.loop(Looper.java:135) 
     at android.app.ActivityThread.main(ActivityThread.java:5221) 
     at java.lang.reflect.Method.invoke(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:372) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 

Спасибо.

+1

Убедитесь, что элементы '' правильно расположены. Они должны быть непосредственными детьми из '', как сверстники ''. – CommonsWare

+0

@CommonsWare, вы правы, я применил разрешения внутри тега приложения, и теперь я их переместил. Теперь это работает. Но почему не было проблем с моим устройством Android 4.3, но это проблема в устройстве 5.0.2? – yrazlik

ответ

9

И у меня есть следующие разрешения на мой манифест

Часто, если вы получаете ошибки разрешения, несмотря на наличие <uses-permission> элементов в манифесте, это происходит потому, что элементы находятся в неправильном месте в манифесте. Они должны быть непосредственно детьми <manifest>, в качестве сверстников <application>.

Но почему не было проблем с моим устройством Android 4.3, но это проблема в устройстве 5.0.2?

До Android 4.4, READ_EXTERNAL_STORAGE либо не существовало, либо не применялось на обычных устройствах.

+0

Я столкнулся с этой проблемой на android 6, но разрешение в нужном месте – nAkhmedov

+5

@nAkhmedov: Затем вы сталкиваетесь с [проблемами с разрешениями во время выполнения] (https://stackoverflow.com/questions/32635704/cant-get-the-permission), скорее всего. – CommonsWare

+0

Спасибо большое @nAkhmedov, у меня была проблема с сборкой версии 23, и ссылка, которую вы опубликовали, действительно помогла. – M090009

2

очень хороший ответ на «CommonsWare» на другой линии связи

Большая причина не получить разрешение в настоящее время происходит потому, что ваш проект имеет targetSdkVersion от 23 и выше, а также разрешение, которое вы запрашиваете «опасно ». В Android 6.0, это включает в себя:

ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
ADD_VOICEMAIL
BODY_SENSORS
CALL_PHONE
ТЕЛЕКАМЕР
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

Для этих разрешений для вашего приложения targetSdkVersion 23+ необходимо иметь не только элемент (ы) <uses-permission>, но также вы должны запрашивать эти разрешения во время выполнения от пользователя на устройствах Android 6.0+ с помощью таких методов, как checkSelfPermission () и requestPermissions().

В качестве временного решения, забросьте targetSdkVersion ниже 23.

Однако, в конце концов, у вас будет какая-то причина, чтобы хотеть ваш targetSdkVersion быть 23 или выше. В то время вам нужно будет настроить приложение, чтобы использовать новую систему разрешения во время выполнения. Документация предварительного просмотра Android 6.0 содержит страницу, посвященную этой теме.

СЕЙЧАС Я деградировал свою цельSdkVersion с 23 до 21 своей работы, но это временное решение.

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