Android API 29媒体存储访问
我的应用程序在android mediastore中创建播放列表。api包括28都很好,但api 29似乎需要额外的权限。 插入新的播放列表名称和id不会出现问题。在插入曲目id和播放顺序时,会引发访问权限异常。 在验证Uri时,我发现API 29的resolver.insert出现异常错误:Android API 29媒体存储访问,android,mediastore,android-10.0,Android,Mediastore,Android 10.0,我的应用程序在android mediastore中创建播放列表。api包括28都很好,但api 29似乎需要额外的权限。 插入新的播放列表名称和id不会出现问题。在插入曲目id和播放顺序时,会引发访问权限异常。 在验证Uri时,我发现API 29的resolver.insert出现异常错误: java.lang.SecurityException: myapp_name has no access to content://media/external_primary/audio/media/
java.lang.SecurityException: myapp_name has no access to content://media/external_primary/audio/media/146
守则:
Uri exturi = MediaStore.Audio.Playlists.Members.getContentUri("external", playlist_id);
// exturi : content://media/external/audio/playlists/227/members
// values : audio_id=146 play_order=0
values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, play_order);
values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, audio_id);
try {
resolver.insert(exturi, values);
} catch (Exception e) {
e.printStackTrace();
}
奇怪的是,虽然在Mediastore中插入新的播放列表有效,但添加曲目(曲目id、播放顺序)会导致访问权限错误
如何解决API 29的此异常错误?
2021年2月更新:
向前迈出了一小步,我非常确定我需要获取原始uri的Documenturi,但仍然会给出访问错误。因此,问题不在于访问曲目,而在于uri本身
doc_uri = MediaStore.getDocumentUri(context,playlist_members_uri);
java.lang.SecurityException: com.flyingdutchman.newplaylistmanager has no access to content://media/external/audio/playlists/130/members
我认为这是安卓10的一个bug,所以我在这里提交了一份报告:(如果你感兴趣的话,包括仿真器测试用例复制它的说明)。请考虑它让Android团队知道它对你有影响。 据我所知,它只影响“外部”存储上的文件,如安装在
/storage/XXXX-XXXX
同时,我的一些用户能够成功应用的唯一修复方法是将他们的音乐文件移动到内部存储(重新启动并等待媒体扫描完成,以确保MediaStore是最新的)。我已经实现了SAF,因此不使用scopedStorage,一旦用户接受,就可以访问。 事实上,我可以插入新的播放列表条目清楚地显示对MediaStore的访问,我也可以删除这些条目。但是,尝试向这些播放列表中添加曲目对api29不起作用。插入/删除新播放列表不涉及位于内部或外部SD卡上的任何文件,因为它只是在添加值 内部和外部SD卡的权限:
2020-07-12 14:39:04.435 11858-11858/com.flyingdutchman.newplaylistmanager E/onCreate:: uriPermission: UriPermission {uri=content://com.android.externalstorage.documents/tree/17F5-240A%3A, modeFlags=3, persistedTime=1594551961263}
2020-07-12 14:39:04.435 11858-11858/com.flyingdutchman.newplaylistmanager E/onCreate:: uriPermission: UriPermission {uri=content://com.android.externalstorage.documents/tree/primary%3A, modeFlags=3, persistedTime=1594551926876}
现在的问题是
如何确保resolver.insert方法能够识别saf权限在将曲目插入/修改到媒体数据库时在进一步研究答案时,我遇到了这个问题 android 11的更新。 值得注意的是,媒体数据库已从
/data/data/com.android.providers.media
到
结构也发生了显著的变化
和
public static final void readExceptionFromParcel(Parcel reply) {
int code = reply.readExceptionCode();
if (code == 0) return;
String msg = reply.readString();
DatabaseUtils.readExceptionFromParcel(reply, msg, code);
}
msg=com.flyingdutchman.newplaylymanager无权访问content://media/external_primary/audio/playlists/206
场景2不会导致权限错误,但不会将曲目添加到音频播放列表映射表中
playlist_uri = MediaStore.Audio.Playlists.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
url=content://media/external_primary/audio/playlists/206/members
不要只使用外部硬编码,请使用卷外部主。尝试使用MediaStore.VOLUME\u EXTERNAL\u PRIMARY(在API@Khoa Nguy上ễn尝试了这个方法,但没有发现同样的问题。我可以从播放列表中删除曲目,但添加时,我在API 29上遇到了相同的异常。您找到解决方案了吗?我很乐意为此提供帮助。@EvanBlack Hi。目前我正在对基于文件的m3u播放列表进行解决。系统会扫描这些曲目并创建播放列表。市长说:ide是指每次重新创建播放列表时ID都会更改。因此,某些使用播放列表的应用程序需要在每次更改时更新。谢谢,我将在内部存储器上尝试音乐Droid 10引入了一个新的存储概念:作用域存储,如果您对作用域存储不满意,请将此标志添加到您的文件中(但不建议这样做,因为它将在下一版本的Android中成为强制性的):@toumir该漏洞也会影响针对API 28或使用requestLegacyExternalStorage=“true”的应用程序,所以这没有帮助。@现在不是bug,但这种行为会影响针对API 29或+、API 28及以下的应用程序,对我来说正常工作。我很好奇看到它。你能共享一个可以工作的项目吗?我也实现了SAF,但当我在contentresolver上调用update时,例如,
contentresolver.update(mediaFileUri,values,null,null)
它仍然抛出一个可恢复安全性异常
您找到了一种方法,我们不需要捕获该异常并单独请求每个文件的权限吗?这就是我现在正在做的事情,但我真的很讨厌它,这真是一个麻烦。@Vince VD,没有任何进一步的进展。令人难以置信的是,似乎没有人信任它在android 10中设置播放列表。与此同时,android11即将推出,越来越多的东西被弃用。放弃创建播放列表似乎对Play Store上的许多mp3播放器应用都有效,但我注意到他们没有在MediaStore中插入新的播放列表。因此我认为他们使用播放列表管理自己的数据库d这似乎是我们目前唯一的选择。我尝试了所有方法,但在API 28以上仍然无法正常工作。我放弃了,只是使用Room with Playlist和Song table创建了自己的数据库。ScopedStorage破坏了一切。我应用了这个建议,但……Uri Uri_to_use=MediaStore.Audio.Playlists.getContentUri(“0F16-2701”)给出:content://media/0F16-2701/audio/playlists,并导致java.lang.IllegalArgumentException:找不到卷0F16-2701我的意思是,您应该在与要添加的歌曲相同的卷上创建播放列表。在您的情况下,您应该在“0F16-2701”上创建播放列表,然后您可以将位于“0F16-2701”中的歌曲添加到
public static final void readExceptionFromParcel(Parcel reply) {
int code = reply.readExceptionCode();
if (code == 0) return;
String msg = reply.readString();
DatabaseUtils.readExceptionFromParcel(reply, msg, code);
}
playlist_uri = MediaStore.Audio.Playlists.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
url=content://media/external_primary/audio/playlists/206/members