显示带有声音的通知时出现FileUriExposedException

asc*_*sco 8 android android-notifications android-file

我的应用程序的用户可以选择在我的应用程序中收到通知时应播放的铃声。

我显示一个铃声选择对话框:

    Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
    intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false);
    intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
    intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION);

    startActivityForResult(intent, REQUEST_CODE);
Run Code Online (Sandbox Code Playgroud)

并保存结果:

    Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
    PreferenceManager.getDefaultSharedPreferences(this).edit().putString(RINGTONE_SP_KEY, uri.toString()).apply();
Run Code Online (Sandbox Code Playgroud)

显示通知时,我使用用户选择的铃声或默认铃声:

private void showNotification() {
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
    builder.setSound(getRingtone());
    builder.setContentText("MyContentText");
    builder.setSmallIcon(R.drawable.test);

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, builder.build());
}

private Uri getRingtone() {

    String ringtoneUriFromSp = PreferenceManager.getDefaultSharedPreferences(this).getString(RINGTONE_SP_KEY, null);

    if (ringtoneUriFromSp == null) {
        return RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    } else {
        return Uri.parse(ringtoneUriFromSp);
    }
}
Run Code Online (Sandbox Code Playgroud)

默认和自定义选定的铃声Uri通常都看起来像这样:

content://media/internal/audio/media/16
Run Code Online (Sandbox Code Playgroud)

一切都很好。

我确实(很少)通过Crashlytics 收到以下异常

致命异常:android.os.FileUriExposedException file:///storage/emulated/0/MIUI/ringtone/CloudMagic_3.ogg通过Notification.sound在应用程序之外公开

适用于某些设备(例如Xiaomi Mi Max 2,Galaxy Tab A 10.1)。

例外文档说,从这个茎Uri被暴露通过 file:// Uri(错误的方式),而不是 content:// Uri(正确的方法),我不能对我的任何设备的再现; 默认铃声和用户选择的铃声Uri都通过来content:// Uri

我不知道这种情况是否会通过

RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Run Code Online (Sandbox Code Playgroud)

或用户选择的铃声。

是否有人遇到过同样的问题,或者知道这里可能存在什么问题?