Android API 29及以上版本中ContentResolver无法打开插入的音频文件问题求助
各位好,我碰到了一个兼容性难题,想请大家帮忙排查下。我写的这段代码在API 28及以下版本都能正常运行,但到了API 29及以上就出问题了——我想把自定义音频设置为闹钟铃声,现在删除和插入操作看起来都执行成功了,但就是没法打开对应的文件,设置闹钟后也只会播放默认铃声。
先贴一下我的代码:
ContentResolver contentResolver = getContentResolver(); ContentValues values = new ContentValues(); if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { values.put(MediaStore.Audio.Media.DATA, myFile.getAbsolutePath()); } else { values.put(MediaStore.Audio.Media.RELATIVE_PATH, "Alarms/" + myFile.getName()); } values.put(MediaStore.Audio.Media.DISPLAY_NAME, myFile.getName()); values.put(MediaStore.Audio.Media.TITLE, myFile.getName()); if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/mp3"); } else { values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/mpeg"); } values.put(MediaStore.Audio.Media.SIZE, myFile.length()); values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name); values.put(MediaStore.Audio.Media.IS_RINGTONE, false); values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false); values.put(MediaStore.Audio.Media.IS_ALARM, true); values.put(MediaStore.Audio.Media.IS_MUSIC, false); Uri uri = MediaStore.Audio.Media.getContentUriForPath(myFile.getAbsolutePath()); int cnt = contentResolver.delete(uri, MediaStore.Audio.Media.DISPLAY_NAME + " = ?", new String[]{myFile.getName()}); Uri newUri = contentResolver.insert(uri, values); //contentResolver.openFileDescriptor(newUri, "r"); RingtoneManager.setActualDefaultRingtoneUri(getApplicationContext(), TYPE_ALARM, newUri);
我的文件绝对路径是:/storage/emulated/0/Android/data/some.package/files/Alarms/myFile.mp3
目前的情况是,delete和insert操作看起来都完成得很顺利,newUri.toString()的结果类似content://media/external_primary/audio/media/39。但之后只要尝试打开文件或者文件描述符(比如注释掉的那行代码),就会抛出这个异常:
java.io.FileNotFoundException: open failed: ENOENT (No such file or directory)
另外,尝试设置这个文件为闹钟时,日志里会输出这些警告:
W Failed to open directly; attempting failover: java.io.FileNotFoundException: open failed: ENOENT (No such file or directory)
W Failed to cache ringtone: java.io.IOException: java.lang.SecurityException: Uri is not ringtone, alarm, or notification: content://0@media/external_primary/audio/media/39
奇怪的是,操作并没有完全失败——闹钟应用里能看到我的文件名,但播放的却是默认的闹钟声音,看起来ContentResolver里确实插入了记录,但文件的引用好像是无效的。
有没有大佬知道我该怎么调整这段代码,才能让它在API 29及以上版本正常工作呢?
备注:内容来源于stack exchange,提问作者awa993

