使用PhoneGap Camera Plugin从Android 4.4(KitKat)上的库中选择时无法加载图像

时间:2013-12-17 16:03:43

标签: cordova phonegap-plugins

我正在尝试根据使用PhoneGap / Cordova相机插件从设备图库中选择的图像在我的应用中设置img标记的来源。

以前在旧版本的Android(3.3)上按预期工作,在iOS上工作正常,但现在无法解析4.4(KitKat)上的图像路径。

返回的图片网址的返回路径如下所示:

content://com.android.providers.media.documents/document/image%3A352

当我使用此路径通过JavaScript设置为图像src时,无法解析URL,因此会产生加载错误。使用相机拍照时没有问题,只有在从画廊中选择现有照片时才会出现这种情况。

我已经尝试过编码到base64并尝试了文档resolveLocalFileSystemURI();中提到的方法,但我对这些没有运气。我也试过删除相机插件并重建应用程序,但没有快乐。

我的猜测是KitKat处理图库的方式发生了变化,PhoneGap / Camera插件尚未更新以适应这种情况。

6 个答案:

答案 0 :(得分:19)

当修复此错误时,一种非常非常脏的解决方法适用于我。在极端必要的情况下使用:)

if (imageURI.substring(0,21)=="content://com.android") {
  photo_split=imageURI.split("%3A");
  imageURI="content://media/external/images/media/"+photo_split[1];
}

答案 1 :(得分:16)

Android 4.4中的某些内容与图像的URI编码有关。

此处针对Cordova提出了一个错误:https://issues.apache.org/jira/browse/CB-5398

getPicture的文档中,在Android Quicks部分下,它讨论了这个问题,并指出了一个带有解决方法的StackOverflow问题(编辑Camera插件java代码以强制它打开Gallery应用程序而不是存储访问框架应用程序。)

您可以做的另一件事是将目的地类型设置为DATA_URL。

答案 2 :(得分:4)

Adob​​e向我保证,这个问题将在3.5.0中修复。它没有在3.4中修复。由于3.5.0计划于5月中旬发布,我只能等到那时。

Adob​​e声称这不是可以在插件级别上进行的更改。这是科尔多瓦代码的一个基本变化。他们花了这么长时间来解决这个问题太糟糕了。

更新:Cordova 3.5.0于5月9日发布。您可以下载bia节点,看看问题是否已经解决。

答案 3 :(得分:4)

以下是此问题的简单修复:

替换这个:

content://com.android.providers.media.documents/document/image%3A352

由此:

content://com.android.providers.media.documents/document/image%253A352

如果您使用的是JavaScript,则可以使用以下代码:

var path = content://com.android.providers.media.documents/document/image%3A352;
path = path.replace("%", "%25");

这种技术迫使uri按原样传递“%3A”,而不将其改为“:”,希望它能为你效用!

答案 4 :(得分:2)

对于像“内容:”这样没有扩展等特殊条件的更多检查,并没有那么强大。此外,由于我需要上传它,我正在检测扩展名,或者如果文件没有扩展名,则创建.jpg扩展名:

// Android 4.4 cordova workarounds ... returns new kind or URL for content from chooser
                //if (imageUrl.substring(0,21)=="content://com.android") {
                if(imageUrl.indexOf('content://') != -1 && imageUrl.indexOf("%3A") != -1){
                    //"PlainFileUrl = content://com.android.providers.media.documents/document/image%3A14",
                    photo_split=imageUrl.split("%3A");
                    imageUrl="content://media/external/images/media/"+photo_split[1];
                }
                // workaround end

                var fileName = imageUrl.substr(imageUrl.lastIndexOf('/') + 1);
                var extension;

                // check for content: protocol to make sure is not
                // a file with no extension
                if (imageUrl.indexOf('content://') != -1) {
                    if(imageUrl.lastIndexOf('.') > imageUrl.lastIndexOf('/')){
                        extension = imageUrl.substr(imageUrl.lastIndexOf('.') + 1);
                    }else{
                        extension = "jpg";
                        fileName = fileName + ".jpg";
                        LogService.log("Created File Extension jpg");
                    }
                } else {
                    if (imageUrl.lastIndexOf('.') == -1 || (imageUrl.lastIndexOf('.') < imageUrl.lastIndexOf('/')) ) {
                        extension = "invalid";
                    } else {
                        extension = imageUrl.substr(imageUrl.lastIndexOf('.') + 1);
                    }
                }

答案 5 :(得分:0)

每当uri传递给<img src="uri" />时,它就会从

隐式解码
  

内容://com.android.providers.media.documents/document/image%3A9888 (1)

  

内容://com.android.providers.media.documents/document/image:9888 (2)

但是,从Intent.ACTION_OPEN_DOCUMENTIntent.ACTION_GET_CONTENT返回后,Android会为您提供(1)的读取权限,而不是(2)。在这种情况下,WebView将期待记录错误:

  

java.lang.SecurityException:Permission Denial:read   com.android.providers.media.MediaDocumentsProvider uri   内容://com.android.providers.media.documents/document/image:9888   从pid = 13163,uid = 10165需要   android.permission.MANAGE_DOCUMENTS或grantUriPermission()

  

无法打开内容网址

代码段

您需要解决的问题是

    String uriToUseInWebView = transformForWebView(uri.toString());

    private String transformForWebView(String uri) {
        for (int i = 0; i < timesDecodingWebView(); i++)
            uri = uri.replace("%", Uri.encode("%"));
        return uri;
    }

    private int timesDecodingWebView() {
        if (Build.VERSION.RELEASE.equals("4.4.2")) {
            return 2;
        } else {
            return 1;
        }
    }
在将uri传递给HTML / JS之前,在您的Java代码中

以确保实际加载(1)

我在4.4.2,4.4.4和5.0上测试了它。有趣的是,Android 4.4.2在内部对uri进行了两次解码。