I am creating a music player application in Android. It works great, but whenever I scroll through the list of songs, it starts crashing and gives this exception.
Process: com.example.lenovo.musicplayer, PID: 31100 java.lang.SecurityException: External path: /storage/emulated/0/Android/data/com.android.providers.media/albumthumbs/1460104607336: Neither user 10294 nor current process has android.permission.WRITE_EXTERNAL_STORAGE. at android.os.Parcel.readException(Parcel.java:1555) at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:190) at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:153) at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:691) at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1170) at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:994) at android.content.ContentResolver.openInputStream(ContentResolver.java:719) at android.provider.MediaStore$Images$Media.getBitmap(MediaStore.java:1110) at com.example.lenovo.musicplayer.Adapter.getView(Adapter.java:119) at android.widget.AbsListView.obtainView(AbsListView.java:2571) at android.widget.ListView.makeAndAddView(ListView.java:1894) at android.widget.ListView.fillDown(ListView.java:710) at android.widget.ListView.fillGap(ListView.java:674) at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5900) at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:5378) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:825) at android.view.Choreographer.doCallbacks(Choreographer.java:619) at android.view.Choreographer.doFrame(Choreographer.java:578) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:811) at android.os.Handler.handleCallback(Handler.java:815) at android.os.Handler.dispatchMessage(Handler.java:104) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:6102) 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:1028) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
This problem disappears when I give write permission to the manifest file, but that I donβt understand why WriteExternalStoragePermission asking when I am not writing anything for any types of storage location. As far as I understand, the music player does not require external storage permissions.
Here is the code for song list activity
public class ActivitySongsList extends AppCompatActivity { public static ArrayList<MusicBean>songsList; ListView listView; Toolbar toolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_songs_list); toolbar= (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); listView= (ListView) findViewById(R.id.lv_songs); songsList=getAudioList(); Adapter adapter=new Adapter(this,songsList); listView.setAdapter(adapter); getSupportActionBar().setTitle("Songs"); toolbar.setTitleTextColor(Color.parseColor("#ffffff")); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent=new Intent(ActivitySongsList.this,ActivityMusicDetails.class); intent.putExtra("song",songsList.get(position)); intent.putExtra("position",String.valueOf(position)); startActivity(intent); } }); } private ArrayList<MusicBean> getAudioList() { ArrayList<MusicBean> musicBeanArrayList=new ArrayList<>(); try { final Cursor mCursor = getContentResolver().query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Audio.Media.DISPLAY_NAME, MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.ALBUM_ID,MediaStore.Audio.Media.ARTIST,MediaStore.Audio.Media.TITLE}, null, null, "LOWER(" + MediaStore.Audio.Media.TITLE + ") ASC"); int count = mCursor.getCount(); int i = 0; if (mCursor.moveToFirst()) { do { String song=mCursor.getString(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE)); String path=mCursor.getString(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)); long album_id=mCursor.getLong(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID)); String artist=mCursor.getString(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST)); Uri sArtworkUri = Uri .parse("content://media/external/audio/albumart"); Uri albumArtUri = ContentUris.withAppendedId(sArtworkUri, album_id); musicBeanArrayList.add(new MusicBean(song,path,albumArtUri.toString(),String.valueOf(album_id),artist)); i++; } while (mCursor.moveToNext()); } mCursor.close(); }catch (Exception e) { e.printStackTrace(); } return musicBeanArrayList; } }
Failure with exception on this line
bitmap = MediaStore.Images.Media.getBitmap(ctx.getContentResolver(), uri);
In this code, I get Album Art for the corresponding mp3 file. But this code is also read from external storage, so it also should not ask for write permission, since I only read the bitmap without writing it.