Cordova 使用PhoneGap摄像头插件从Android 4.4(KitKat)上的图库中选择时无法加载图像

Cordova 使用PhoneGap摄像头插件从Android 4.4(KitKat)上的图库中选择时无法加载图像,cordova,phonegap-plugins,Cordova,Phonegap Plugins,我正在尝试使用PhoneGap/Cordova摄像头插件,根据从设备图像库中选择的图像,在我的应用程序中设置img标签的来源 它以前在旧版本的Android(3.3)上可以正常工作,在iOS上也可以正常工作,但现在无法在4.4(KitKat)上解析图像路径 返回的图像url的返回路径如下所示: content://com.android.providers.media.documents/document/image%3A352 当我使用此路径通过JavaScript设置为图像src时,URL

我正在尝试使用PhoneGap/Cordova摄像头插件,根据从设备图像库中选择的图像,在我的应用程序中设置img标签的来源

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

返回的图像url的返回路径如下所示:

content://com.android.providers.media.documents/document/image%3A352
当我使用此路径通过JavaScript设置为图像src时,URL无法解析,因此产生加载错误。使用相机拍照时没有问题,似乎只有在从“多媒体资料”中选择现有图片时才会出现问题

我尝试了编码到base64,也尝试了docs
resolveLocalFileSystemURI()中提到的方法但是我在这些方面运气不好。我也尝试删除摄像头插件并重新构建应用程序,但没有乐趣


我的猜测是KitKat处理多媒体资料的方式发生了一些变化,PhoneGap/Camera插件尚未更新以适应这种情况。

Android 4.4中的图像URI编码出现了一些问题

Cordova的一个缺陷已在此处存档:

在的文档中,在Android Quicks部分下,它讨论了这个问题,并指出了一个带有解决方法的StackOverflow问题(编辑相机插件java代码,强制它打开Gallery应用程序,而不是Storage Access Framework应用程序)


似乎您可以做的另一件事是将目标类型设置为DATA\u URL。

在修复此错误时,一种非常肮脏的解决方法对我有效。在极端需要的情况下使用:)


没有更多的健壮性,只是对“内容:”等特殊条件进行了一些检查,没有扩展等等。另外,由于我需要上传它,我正在检测扩展名,或者如果文件没有扩展名,则创建一个.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);
                    }
                }
//Android 4.4 cordova解决方案。。。从选择器返回内容的新种类或URL
//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/“+照片分割[1];
}
//变通端
var fileName=imageUrl.substr(imageUrl.lastIndexOf('/')+1);
var扩展;
//检查内容:协议以确保不存在
//没有扩展名的文件
if(imageUrl.indexOf('content://')!=-1){
if(imageUrl.lastIndexOf('.')>imageUrl.lastIndexOf('/')){
扩展名=imageUrl.substr(imageUrl.lastIndexOf('.')+1);
}否则{
extension=“jpg”;
fileName=fileName+“.jpg”;
log(“创建的文件扩展名jpg”);
}
}否则{
if(imageUrl.lastIndexOf('.')==-1 | | |(imageUrl.lastIndexOf('.'))
Adobe向我保证,这个问题将在3.5.0中得到解决。3.4中没有解决。由于3.5.0计划在5月中旬发布,我将一直等到那时

Adobe声称这不是插件级别的更改。这是cordova代码中的一个基本更改。遗憾的是,他们花了这么长时间才想出这个修复方案


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

每当一些
uri被传递到
中时,它就被隐式解码

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

进入

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

但是,从
Intent.ACTION\u OPEN\u DOCUMENT
Intent.ACTION\u GET\u CONTENT
返回后,Android为您提供了(1)的读取权限,而不是(2)。在这种情况下,
WebView
将预期记录一个错误:

java.lang.SecurityException:权限拒绝:读取 com.android.providers.media.mediaDocumentsProviderURI content://com.android.providers.media.documents/document/image:9888 从pid=13163,uid=10165需要 android.permission.MANAGE_文档,或grantUriPermission()

无法打开内容URL

代码片段

您需要解决的问题是

    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;
        }
    }
String uritoseinwebview=transformForWebView(uri.toString());
私有字符串transformForWebView(字符串uri){
对于(int i=0;i
在将
uri
传递到HTML/JS之前,请先在Java代码中输入,以确保实际加载(1)


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

这里有一个简单的解决方案:

替换此项:

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”,而不将其更改为“:”,
var path = content://com.android.providers.media.documents/document/image%3A352;
path = path.replace("%", "%25");