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

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

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

Unable to open content: file:///storage/emulated/0/sdcard/mydir/bgs 

..

然后

 open failed: EACCES (Permission denied) 

这只出现在主屏幕上,只有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()"); } } 

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

Related of "Android – 无法打开内容:file:/// storage / emulated / 0"

似乎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); 

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

选项2:使用内容提供商

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

路径切换怎么样?

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

您会注意到,虽然exception是FileNotFoundException,但消息是Permission Denied。

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

 java.io.FileNotFoundException: /storage/emulated/0/advert.mp4: open failed: EACCES (Permission denied) 

EACCESS permission denied是java臭名昭着的FileNotFoundException

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

在此处输入图像描述

你需要

  

在你的清单中。

我想你手动输入SD卡路径。 而不是手动输入SD卡路径,你应该得到这样的存储路径:

 File extStore = Environment.getExternalStorageDirectory(); String mPath = extStore.getAbsolutePath() + "/mydir/bgs";