Android - 无法打开内容:file:/// storage/emulated/0

Cec*_*oCQ 15 android widget nine-patch

我有一个九个补丁图像背景的小部件.图像保存在/ sdcard/mydir/bgs中.

当我尝试使用setImageViewUri方法加载图像时,我遇到了以下错误:

Unable to open content: file:///storage/emulated/0/sdcard/mydir/bgs
Run Code Online (Sandbox Code Playgroud)

..

然后

...

open failed: EACCES (Permission denied)
Run Code Online (Sandbox Code Playgroud)

这只出现在主屏幕上,只有Nexus 10和Nexus 7(最新的启动器4.4不存在此错误).我的应用程序上也有一些RemoteView,一切正常.

我还在清单中添加了READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE.

我怎么解决?

更新:我检查方法setImageViewUri,我发现它改变了我的文件的路径.

if (value != null) {
            // Resolve any filesystem path before sending remotely
            value = value.getCanonicalUri();
            if (StrictMode.vmFileUriExposureEnabled()) {
                value.checkFileUriExposed("RemoteViews.setUri()");
            }
        }
Run Code Online (Sandbox Code Playgroud)

此方法接收我的值(/ sdcard/mydir/bgs)并将其更改为(storage/emulated/0/sdcard/mydir/bgs).但是这个文件不是通过adb存在于系统中的.

小智 17

从Lollipop开始,Google推出了一种新方法,即明确向应用程序提供您希望它们在您的设备上使用的权限,并禁用您要拒绝该应用程序的权限.如果您注意到,在您的Android监视器中,日志显示

java.io.FileNotFoundException: /storage/emulated/0/advert.mp4: open failed: EACCES (Permission denied)
Run Code Online (Sandbox Code Playgroud)

EACCESS permission denied是java臭名昭着的原因FileNotFoundException.

要解决此问题,只需转到您的App权限并为您的应用启用存储空间即可

在此输入图像描述


Kuf*_*ffs 12

你需要

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Run Code Online (Sandbox Code Playgroud)

在你的清单中.


Gri*_*ace 6

setImageViewUri使用file:// uris 似乎不再安全.

为什么?

Jellybean介绍了READ_EXTERNAL_STORAGE许可.想要从外部存储中读取的应用必须拥有此权限.在KitKat之前,默认情况下不执行此操作.

启动器不拥有此权限.实际上,您不能保证您附加的任何RemoteView都拥有该权限.这使得使用setImageViewUri不安全,因为您不知道远程图像视图是否能够读取给定的uri.

现在怎么办?

选项1:使用setImageViewBitmap.

由于活页夹交易失败,您可能已经远离此选项.这些技巧只是确保您的图像低于1 MB.这并不像听起来那么难.您可以准确计算出图像的大小.例如,如果您使用的是ARGB_8888图像,则意味着每个像素需要4个字节.我们可以通过以下方式计算最大尺寸:

1 Mb = 1048576字节= 262144像素= 512 x 512图像

当然,你可以使用RGB_565来挤出更多的像素.

另请注意,如果您的小部件很小,您可能不需要大图像.您的appwidget可以通过以下方式询问其具体选项:

Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetIds[i]);

int minWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);

int maxWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH);
int maxHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT);
Run Code Online (Sandbox Code Playgroud)

请注意,返回的值是dip而不是像素,因此您需要将它们转换为缩放位图.

选项2:使用内容提供商

如果由于某种原因您仍然不喜欢IPC限制,您始终可以构建自定义内容提供程序.将uri传递给setImageViewUri,你应该好好去.

路径切换怎么样?

路径切换不是真正的问题.它看起来像是一个问题,但仿真实际上工作正常.尝试在里面创建一个文件//storage/emulated/0/sdcard/mydir/bgs,文件创建就好了.

您会注意到,虽然异常是FileNotFoundException,但消息是Permission Denied.