3

我正在尝试让一个应用程序从 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:创建失败:java.io.FileNotFoundException:/storage/emulated/0/Music/108-radiohead-house of cards-pms.mp3:打开失败:libcore.io.IoBridge.open(IoBridge)的 EACCES(权限被拒绝) .java:452) 在 java.io.FileInputStream.(FileInputStream.java:76) 在 android.media.MediaPlayer.setDataSource(MediaPlayer.java:1095) 在 android.media.MediaPlayer.setDataSource(MediaPlayer.java:1074)在 android.media.MediaPlayer.setDataSource(MediaPlayer.java:1028) 在 android.media.MediaPlayer.setDataSource(MediaPlayer.java:973) 在 android.media.MediaPlayer.create(MediaPlayer.java:880) 在 android。 media.MediaPlayer.create(MediaPlayer.java:857) 在 android.media.MediaPlayer.create(MediaPlayer.java:836) 在 gunboat.com.mediaplayererror.FullscreenActivity。playSong(FullscreenActivity.java:190) 在 gunboat.com.mediaplayererror.FullscreenActivity.CheckPermission(FullscreenActivity.java:135) 在 gunboat.com.mediaplayererror.FullscreenActivity.access$300(FullscreenActivity.java:24) 在 gunboat.com.mediaplayererror。 FullscreenActivity$5.onClick(FullscreenActivity.java:113) 在 android.view.View.performClick(View.java:5198) 在 android.view.View$PerformClick.run(View.java:21147) 在 android.os.Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:148) 在 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)在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)引起:android.system.ErrnoException:打开失败:在libcore.io.Posix.open(本机方法)的EACCES(权限被拒绝)在 libcore.io.BlockGuardOs.open(BlockGuardOs.java:186) 在 libcore.io.IoBridge.open(IoBridge.java:438) 在 java.io.FileInputStream.(FileInputStream.java:76) 在 android.media.MediaPlayer.setDataSource(MediaPlayer.java:1028) 在 android.media.MediaPlayer.setDataSource(MediaPlayer.java:1074) 在 android.media.MediaPlayer.setDataSource(MediaPlayer.java:1095) 在 android. media.MediaPlayer.setDataSource(MediaPlayer.java:973) 在 android.media.MediaPlayer.create(MediaPlayer.java:880) 在 android.media.MediaPlayer.create(MediaPlayer.java:857) 在 android.media.MediaPlayer.create(MediaPlayer.java:836) 在 gunboat.com.mediaplayererror.FullscreenActivity.playSong(FullscreenActivity.java:190) 在 gunboat.com.mediaplayererror.FullscreenActivity.CheckPermission(FullscreenActivity.java:135 ) 在 gunboat.com.mediaplayererror.FullscreenActivity.access$300(FullscreenActivity.java:24) 在 gunboat.com.mediaplayererror.FullscreenActivity$5.onClick(FullscreenActivity.java:113) 在 android.view.View.performClick(View.java:5198) 在 android.view.View$PerformClick.run(View.java:21147) 在 android.os.Handler.handleCallback(Handler.java:739) 在android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread.java:5417)5417)5417)5198) 在 android.os.Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.view.View$PerformClick.run(View.java:21147) 在android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread.java:5417)5198) 在 android.os.Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.view.View$PerformClick.run(View.java:21147) 在android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread.java:5417)Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread .java:5417)Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread .java:5417)主要(ActivityThread.java:5417)主要(ActivityThread.java:5417) 

4

1 回答 1

2

今天刚刚处理了这个。授予权限后,您需要重新启动应用程序。我使用这样的东西来完成重启:

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

这是我曾经得出这个结论的一个来源:当在运行时授予 WRITE_EXTERNAL_STORAGE 权限时,应用程序无法访问 SD 卡

重新启动的原因是,当授予READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE权限时,您的应用程序的用户帐户将被添加到新的安全组中。当应用程序进程仍在运行时,此更改不会生效。

于 2016-02-10T23:53:34.983 回答