在拒绝并在运行时授予权限后,在 Android 应用程序上获取 FileNotFoundException
Getting FileNotFoundException on Android app after denying and than granting permission at runtime
我正在尝试获取一个应用程序来播放 SD 卡中的 mp3。我正在使用 android sdk 版本 23,在 Windows 8 上使用 Android studio。我正在 运行 在 nexus 5 模拟器上安装它。
我在 运行 时请求权限,如果我拒绝一次权限但在第二次请求时授予权限,我将收到 FileNotFoundException。如果我重新启动应用程序,我可以播放音乐文件,如果我在第一次尝试时接受权限请求,它也可以成功播放音乐而无需重新启动。
我制作了一个简单的程序来重现该问题并将其发布在 github 上。您需要 /Music 目录中的 mp3 文件才能 运行 此应用程序。
这是我请求存储权限的代码:
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);
}
}
这是失败的相关代码片段:
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;
}
这里是堆栈跟踪:
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.access0(FullscreenActivity.java:24)
at gunboat.com.mediaplayererror.FullscreenActivity.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.access0(FullscreenActivity.java:24)
at gunboat.com.mediaplayererror.FullscreenActivity.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)
今天刚处理完。您需要在授予权限后重新启动您的应用程序。我用这样的东西来完成重启:
private static final int REQUEST_CODE_READ_EXTERNAL_STORAGE = 1;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_READ_EXTERNAL_STORAGE:
if (grantResults.length >= 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Schedule start after 1 second
PendingIntent pi = PendingIntent.getActivity(this, 0, getIntent(), PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, pi);
// Stop now
System.exit(0);
} else {
Toast.makeText(this, R.string.error_external_storage_unavailable, Toast.LENGTH_LONG).show();
finish();
}
break;
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
这是我得出这个结论的来源:Application not able to access SD card when WRITE_EXTERNAL_STORAGE permission is granted at run time
重新启动的原因是当授予 READ_EXTERNAL_STORAGE
或 WRITE_EXTERNAL_STORAGE
权限时,您的应用程序的用户帐户被添加到新的安全组。此更改在应用程序仍在 运行.
时不会生效
我正在尝试获取一个应用程序来播放 SD 卡中的 mp3。我正在使用 android sdk 版本 23,在 Windows 8 上使用 Android studio。我正在 运行 在 nexus 5 模拟器上安装它。
我在 运行 时请求权限,如果我拒绝一次权限但在第二次请求时授予权限,我将收到 FileNotFoundException。如果我重新启动应用程序,我可以播放音乐文件,如果我在第一次尝试时接受权限请求,它也可以成功播放音乐而无需重新启动。
我制作了一个简单的程序来重现该问题并将其发布在 github 上。您需要 /Music 目录中的 mp3 文件才能 运行 此应用程序。
这是我请求存储权限的代码:
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);
}
}
这是失败的相关代码片段:
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;
}
这里是堆栈跟踪:
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.access0(FullscreenActivity.java:24) at gunboat.com.mediaplayererror.FullscreenActivity.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.access0(FullscreenActivity.java:24) at gunboat.com.mediaplayererror.FullscreenActivity.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)
今天刚处理完。您需要在授予权限后重新启动您的应用程序。我用这样的东西来完成重启:
private static final int REQUEST_CODE_READ_EXTERNAL_STORAGE = 1;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_READ_EXTERNAL_STORAGE:
if (grantResults.length >= 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Schedule start after 1 second
PendingIntent pi = PendingIntent.getActivity(this, 0, getIntent(), PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, pi);
// Stop now
System.exit(0);
} else {
Toast.makeText(this, R.string.error_external_storage_unavailable, Toast.LENGTH_LONG).show();
finish();
}
break;
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
这是我得出这个结论的来源:Application not able to access SD card when WRITE_EXTERNAL_STORAGE permission is granted at run time
重新启动的原因是当授予 READ_EXTERNAL_STORAGE
或 WRITE_EXTERNAL_STORAGE
权限时,您的应用程序的用户帐户被添加到新的安全组。此更改在应用程序仍在 运行.