I'm trying to to get an app to play an mp3 from the sd card. I'm using the android sdk version 23, with Android studio on Windows 8. I'm running this on the nexus 5 emulator.
I'm requesting permission at runtime and I'm getting a FileNotFoundException if I deny the permission once but than grant the permission on the second request. If I restart the app, I'm able to play the music file and if I accept the permission request on the first try it also successfully plays the music without requiring a restart.
I've made a simple program that replicates the problem and posted it on github. You need an mp3 file in the /Music dir to run this app.
Here's the code where I ask for storage permission:
private void CheckPermission() {
int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
playSong();
} else {
// we don't have permission, request it
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_EXTERNAL_STORAGE_PERMISSION);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_EXTERNAL_STORAGE_PERMISSION:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission Granted
Toast.makeText(getApplicationContext(), "Storage access granted, touch screen to start music", Toast.LENGTH_SHORT)
.show();
} else {
// Permission Denied
Toast.makeText(getApplicationContext(), "Storage access denied, can't load music", Toast.LENGTH_SHORT)
.show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Here's the relevant code snippet that's failing:
Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String projection[] =
{android.provider.MediaStore.Audio.Media.DATA, android.provider.MediaStore.Audio.Media.TITLE};
Cursor cursor = this.getContentResolver().query(uri, projection, null, null, null);
String songURI = new String();
String title = new String();
while (cursor.moveToNext()) {
String data = cursor.getString(0);
title = cursor.getString(1);
// Note: Look for music folder in root drive.
if (data.matches("^/storage/emulated/0/Music/.*")) {
songURI = data;
break;
}
}
if (cursor != null) {
cursor.close();
}
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
mediaPlayer = MediaPlayer.create(getApplicationContext(), Uri.parse(songURI));
try
{
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.start();
Toast toast = Toast.makeText(getApplicationContext(), title, Toast.LENGTH_SHORT);
toast.show();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return;
}
And here's stacktrace:
MediaPlayer: create failed: java.io.FileNotFoundException: /storage/emulated/0/Music/108-radiohead-house of cards-pms.mp3: open failed: EACCES (Permission denied) at libcore.io.IoBridge.open(IoBridge.java:452) at java.io.FileInputStream.(FileInputStream.java:76) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1095) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1074) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1028) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:973) at android.media.MediaPlayer.create(MediaPlayer.java:880) at android.media.MediaPlayer.create(MediaPlayer.java:857) at android.media.MediaPlayer.create(MediaPlayer.java:836) at gunboat.com.mediaplayererror.FullscreenActivity.playSong(FullscreenActivity.java:190) at gunboat.com.mediaplayererror.FullscreenActivity.CheckPermission(FullscreenActivity.java:135) at gunboat.com.mediaplayererror.FullscreenActivity.access$300(FullscreenActivity.java:24) at gunboat.com.mediaplayererror.FullscreenActivity$5.onClick(FullscreenActivity.java:113) 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: android.system.ErrnoException: open failed: EACCES (Permission denied) at libcore.io.Posix.open(Native Method) at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186) at libcore.io.IoBridge.open(IoBridge.java:438) at java.io.FileInputStream.(FileInputStream.java:76) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1095) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1074) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1028) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:973) at android.media.MediaPlayer.create(MediaPlayer.java:880) at android.media.MediaPlayer.create(MediaPlayer.java:857) at android.media.MediaPlayer.create(MediaPlayer.java:836) at gunboat.com.mediaplayererror.FullscreenActivity.playSong(FullscreenActivity.java:190) at gunboat.com.mediaplayererror.FullscreenActivity.CheckPermission(FullscreenActivity.java:135) at gunboat.com.mediaplayererror.FullscreenActivity.access$300(FullscreenActivity.java:24) at gunboat.com.mediaplayererror.FullscreenActivity$5.onClick(FullscreenActivity.java:113) 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)