我有一个选择图像和视频的帮助方法,让我们称之为Activity B
。
所以,这就是它的工作原理:
// were in Activity A
// user wants to choose a video
startActivityB(callbacks);
------------------------------------
// were in Activity B now
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("video/*");
chooseVideoLauncher.launch(intent);
------------------------------------
// were in chooseVideoLauncher now
Uri videoURI = ...;
callbacks.passVideoURI(videoURI); // this way, Activity A gets the videoURI
// do some more things...
finish(); // so the helper activity B is finished now, as the video is chosen already
------------------------------------
// were in activity A again, but now we have the videoURI
// user clicked a button: "Upload video"
uploadVideo(videoURI);
这是我得到的错误:java.lang.SecurityException: Permission Denial: opening provider com.miui.gallery.provider.GalleryOpenProvider from ProcessRecord{f5899ab 29899:com.xxx} (pid=xxx, uid=xxx) that is not exported from UID xxx
我搜索了这个错误并找到了这样的线程:这里
@CommonsWare在评论中解释了错误,并链接了他的博客文章:Uri访问寿命:比您想象的更短
所以会发生错误,因为助手Activity B
选择了文件,所以访问被绑定到Activity B
。没有其他活动可以访问,一旦Activity B
被销毁(在我的代码中发生了什么),对videoURI
的访问就完全消失了。因此,当我稍后尝试上传视频时,它会抛出这个错误。
我尝试了这些解决方案:
Activity A
。这是可行的,但却是一个糟糕的解决方案。对于更长的视频,应用程序崩溃时内存溢出。所以这不是一个选择。Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("video/*");
intent.setFlags(FLAG_GRANT_READ_URI_PERMISSION);
intent.setFlags(FLAG_GRANT_WRITE_URI_PERMISSION);
chooseVideoLauncher.launch(intent);
但这似乎改变不了什么。错误消息保持不变。我是不是让他们错了?
@CommonsWare表示,使用服务也是一种解决方案。我不希望创建一个纯粹为了修复这个权限错误的服务。如果没有其他解决办法,我当然会的。
但是,是否也没有办法将Activity A
权限授予该Uri?
发布于 2022-03-28 12:11:12
到目前为止,最好的解决方案是将活动A和活动B合并成一个单一的活动。使用片段或可组合用于单独的屏幕。
设置前面提到的标志@CommonsWare。代码看起来如下:
您不会在ACTION_PICK
Intent
上设置标志。相反,活动B需要启动活动A(除了finish()
之外)。您将把Uri
放入Intent
的“数据”方面(例如,通过setData()
),并将标志放在Intent
上。您还需要类似FLAG_ACTIVITY_REORDER_TO_FRONT
之类的东西来避免后台堆栈中有两个Activity副本。
发布于 2022-03-28 11:16:10
对于第二种设置标志以获得长生存期的方法,可以尝试添加以下代码,以获得权限,然后启动活动
val contentResolver = applicationContext.contentResolver
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
// Check for the freshest data.
contentResolver.takePersistableUriPermission(uri, takeFlags)
https://stackoverflow.com/questions/71645999
复制相似问题