Unable to load image when selected from the gallery on Android 4.4 (KitKat) using PhoneGap Camera Plugin

后端 未结 6 427
小蘑菇
小蘑菇 2020-12-01 06:15

I\'m trying to set the source of an img tag in my app based on the image chosen from the device image gallery using the PhoneGap/Cordova Camera Plugin.

It has worked

相关标签:
6条回答
  • 2020-12-01 06:49

    Something broke in Android 4.4 with the URI encoding of images.

    A bug has been filed against Cordova here: https://issues.apache.org/jira/browse/CB-5398

    In the docs for getPicture, under the Android Quicks section, it discusses this problem and points to a StackOverflow question with a workaround (edit the Camera plugin java code to force it to open the Gallery app instead of the Storage Access Framework app.)

    It seems another thing you could do is set the destination type to DATA_URL.

    0 讨论(0)
  • 2020-12-01 06:52

    A kind of really-very-dirty workaround works for me while this bug is fixed. Use in case of extreme necessity :)

    if (imageURI.substring(0,21)=="content://com.android") {
      photo_split=imageURI.split("%3A");
      imageURI="content://media/external/images/media/"+photo_split[1];
    }
    
    0 讨论(0)
  • 2020-12-01 06:54

    Adobe assures me that that this problem will be fixed in 3.5.0. It is not fixed in 3.4. As 3.5.0 is scheduled to be release in mid-May, I'm just going to wait until then.

    Adobe claims that this was not a change that could be made on the plugin level. It was a basic change in the cordova code. It's too bad it took so long for them to come up with this fix.

    UPDATE: Cordova 3.5.0 was released on May 9. You can download it bia node and see if the problems are in fact solved.

    0 讨论(0)
  • 2020-12-01 07:03

    Here is a simple fix to this problem:

    replace this:

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

    by this:

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

    if you are using JavaScript you can use this code:

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

    this technique force the uri to let pass "%3A" as it is, without changing it to ":", hope it will work for you !

    0 讨论(0)
  • 2020-12-01 07:03

    Not much more robust just a few more checks for special conditions like "content:" with no extensions and so. Also, since I need to upload it, I am detecting the extension, or create a .jpg extension if the file does not have one:

    // 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);
                        }
                    }
    
    0 讨论(0)
  • 2020-12-01 07:07

    Whenever some uri is passed into <img src="uri" /> it's implicitly decoded from

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

    into

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

    However, after returning from Intent.ACTION_OPEN_DOCUMENT or Intent.ACTION_GET_CONTENT Android provides you with the read permission for (1), not (2). In this case WebView will expectantly log an error:

    java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaDocumentsProvider uri content://com.android.providers.media.documents/document/image:9888 from pid=13163, uid=10165 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()

    or

    Unable to open content URL

    Code snippet

    All you need to resolve the issue is

        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;
            }
        }
    

    in your Java code before passing uri into HTML/JS to ensure that (1) will be actually loaded.

    I've tested that on 4.4.2, 4.4.4 and 5.0. The funny part is that Android 4.4.2 decodes the uri internally twice.

    0 讨论(0)
提交回复
热议问题