7

I am trying to get the music files in the device. here is what i do:

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

And i have the following permissions in my manifest:

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

When i run that code on a device with Android version 4.3 it works fine. But when i run it on a device with Android version 5.0.2 it gives

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

Can anyone tell me why? Here is the full stacktrace:

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)

Thanks.

yrazlik
  • 10,411
  • 33
  • 99
  • 165
  • 1
    Make sure that your `` elements are properly positioned. They need to be immediate children of ``, as peers of ``. – CommonsWare Feb 14 '15 at 17:40
  • @CommonsWare oh you are right, i had put the permissions inside application tag and now i moved them. Now it works. But why there was no problem with my android 4.3 device but it is a problem in 5.0.2 device? – yrazlik Feb 14 '15 at 17:43

2 Answers2

9

And i have the following permissions in my manifest

Frequently, if you get permission errors despite having <uses-permission> elements in the manifest, it is because the elements are in the wrong place in the manifest. They need to be immediate children of <manifest>, as peers of <application>.

But why there was no problem with my android 4.3 device but it is a problem in 5.0.2 device?

Prior to Android 4.4, READ_EXTERNAL_STORAGE either did not exist or was not enforced on ordinary devices.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I have faced this issue on android 6 but the permission is right place – nAkhmedov Oct 23 '15 at 10:54
  • 5
    @nAkhmedov: Then you are running into [issues with runtime permissions](https://stackoverflow.com/questions/32635704/cant-get-the-permission), most likely. – CommonsWare Oct 23 '15 at 10:55
  • Thanks a lot @nAkhmedov, i had a problem with the build version 23 and the link you posted really helped. – M090009 Nov 09 '15 at 14:26
  • @CommonsWare This is actually happening in your Leanback/VideoBrowse sample when running on Android 23 emulator. – IgorGanapolsky Dec 11 '15 at 04:48
  • @IgorGanapolsky: `Leanback/VideoBrowse` properly requests `READ_EXTERNAL_STORAGE`, as you can see in [its manifest](https://github.com/commonsguy/cw-omnibus/blob/master/Leanback/VideoBrowse/AndroidManifest.xml). – CommonsWare Dec 12 '15 at 22:54
  • @CommonsWare manifest permissions have nothing to do with runtime permissions on Marshmallow. Run your sample on a Marshmallow device to see what I mean. – IgorGanapolsky Dec 13 '15 at 18:11
  • 2
    @IgorGanapolsky: "manifest permissions have nothing to do with runtime permissions on Marshmallow" -- of course they do. Runtime permissions start with having the permissions in the manifest. Beyond that, this sample's `targetSdkVersion` of that project is below 23, so the runtime permission system is not used on any version of Android. Android 6.0 devices treat legacy apps like this the same as older devices did, with respect to permissions (all granted up front). – CommonsWare Dec 13 '15 at 22:52
  • @CommonsWare thanks bro u are a genius . i was giving permission in menifesttag instead of tag – Varun Chaudhary Feb 23 '17 at 07:42
2

A very Good Answer by "CommonsWare" on other link

The big reason for not getting your permission nowadays is because your project has a targetSdkVersion of 23 or higher, and the permission that you are requesting is "dangerous". In Android 6.0, this includes:

ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
ADD_VOICEMAIL
BODY_SENSORS
CALL_PHONE
CAMERA
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

For these permissions, not only does your targetSdkVersion 23+ app need to have the <uses-permission> element(s), but you also have to ask for those permissions at runtime from the user on Android 6.0+ devices, using methods like checkSelfPermission() and requestPermissions().

As a temporary workaround, drop your targetSdkVersion below 23.

However, eventually, you will have some reason to want your targetSdkVersion to be 23 or higher. At that time, you will need to adjust your app to use the new runtime permission system. The Android 6.0 preview documentation has a page dedicated to this topic.

For NOW I degraded my targetSdkVersion from 23 to 21 its work but its a temporary solution.

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Sophia
  • 1,046
  • 1
  • 12
  • 15