首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Android: Uri访问从一个活动到另一个活动的生命时间

Android: Uri访问从一个活动到另一个活动的生命时间
EN

Stack Overflow用户
提问于 2022-03-28 10:29:50
回答 2查看 197关注 0票数 2

我有一个选择图像和视频的帮助方法,让我们称之为Activity B

所以,这就是它的工作原理:

代码语言:javascript
运行
复制
// 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的访问就完全消失了。因此,当我稍后尝试上传视频时,它会抛出这个错误。

我尝试了这些解决方案:

  1. 创建视频的本地副本并将该副本传递给Activity A。这是可行的,但却是一个糟糕的解决方案。对于更长的视频,应用程序崩溃时内存溢出。所以这不是一个选择。
  2. 设置前面提到的标志@CommonsWare。代码看起来如下:
代码语言:javascript
运行
复制
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?

EN

回答 2

Stack Overflow用户

发布于 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副本。

票数 1
EN

Stack Overflow用户

发布于 2022-03-28 11:16:10

对于第二种设置标志以获得长生存期的方法,可以尝试添加以下代码,以获得权限,然后启动活动

代码语言:javascript
运行
复制
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)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71645999

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档