Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

camera.getPicture() with FILE_URI destination returns invalid/unexpected image URI #783

Closed
1 task
wencywww opened this issue Jan 12, 2022 · 14 comments · Fixed by #902
Closed
1 task

camera.getPicture() with FILE_URI destination returns invalid/unexpected image URI #783

wencywww opened this issue Jan 12, 2022 · 14 comments · Fixed by #902

Comments

@wencywww
Copy link

Bug Report

Problem

What is expected to happen?

camera.getPicture() to return a valid file_URI in the form of content://media/external/images/media/2 when Camera.DestinationType = FILE_URI

What does actually happen?

the returned value is something like: file///data/user/0/com.tld.appname/cache/1642011143203.jpg and this seems to be an unreacheable url for the webview (can not render the picture). Moreover, searching through the filesystem i can't see such a file. There is no problems when the Camera.DestinationType = DATA_URL, however it is undesired due to possible memory problems

Information

Command or Code

navigator.camera.getPicture(onSuccess, onFail, { quality: 50, destinationType: Camera.DestinationType.FILE_URI });

Environment, Platform, Device

Developing on Windows 10, the result is with Android 7.0 phone

Version information

[email protected]
[email protected]
[email protected]
Android SDK Platform 11.0 / API Level 30
Gradle 7.3.3

Checklist

  • I searched for existing GitHub issues

  • I updated all Cordova tooling to most recent version

  • I included all the necessary information above

@cmarian5
Copy link

I have the same issue. Did you found some solution?

@wencywww
Copy link
Author

I don't think so :(
Asked within StackOverflow here
https://stackoverflow.com/questions/70693557/camera-getpicture-returns-an-unexpected-file-uri-on-android
but with little success.
One suggested using this:
<preference name="AndroidInsecureFileModeEnabled" value="true" />
but the resulting url is still like file//

I have the same issue. Did you found some solution?

@kirkHawksworth
Copy link

Same issue

@cmarian5
Copy link

cmarian5 commented Feb 18, 2022

For me <preference name="AndroidInsecureFileModeEnabled" value="true" /> worked fine. Meaning I could obtain a valid url of the image to add it in a html img tag.

@kirkHawksworth
Copy link

@cmarian5 do you still receive the image url like: file:///data/user/0/package.name/cache/1645202153127.jpg

I have that preference enabled in my config.xml, added & removed Android etc. and still get the same issue

@cmarian5
Copy link

With that preference in config.xml I get it like this <img onclick="image(this)" class="poze1" src="file:///data/user/0/com.example.hello/cache/1645205836634.jpg">

In this case the image is displayed correctly. Also in your case should work.

@whria78
Copy link

whria78 commented Mar 27, 2022

This issue is related to the scoped storage of Android 11.

(A) use DATA_URL && low targetHeight & targetWidth values (<3000)

The latest entry-level smartphones have large pixels, so an "out of memory" error occurs during conversion to base64.

navigator.camera.getPicture(onSuccess, onFail, { quality: 100,
destinationType: Camera.DestinationType.DATA_URL,
targetHeight:1000,
targetWidth:1000});

(B) Save the image to photoalbum --> read the image

navigator.camera.getPicture(onSuccess, onFail, { quality: 100,
destinationType: Camera.DestinationType.FILE_URI,
saveToPhotoAlbum : true,
correctOrientation:false
});

Although "cordova-pluggin-camera" can not access the 'cache' folder, but it can write it on photoalbum folder.

cf) src/android/CameraLauncher.java

line 226 : getCacheDir() --> FAIL

private String getTempDirectoryPath() {
    File cache = cordova.getActivity().**getCacheDir()**;
    // Create the cache directory if it doesn't exist
    cache.mkdirs();
    return cache.getAbsolutePath();
}

line 532 : galleryUri.toString() --> SUCCESS

    else if (destType == FILE_URI) {
        // If all this is true we shouldn't compress the image.
        if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 &&
                !this.correctOrientation) {

            // If we saved the uncompressed photo to the album, we can just
            // return the URI we already created
            if (this.saveToPhotoAlbum) {
                this.callbackContext.success(**galleryUri.toString()**);

This FILE URI can be read by the following code.

function onSuccess(imageURI)
{
function gotFile(fileEntry) {
fileEntry.file(function(file) {

    var reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onloadend = function(e) {
        var content = this.result;
        console.log(typeof content);  // --> **BASE64 IMAGE**
        };
        reader.readAsText(file);
    });}

window.resolveLocalFileSystemURL(imageURI, gotFile, function () { console.log("resolveLocalFileSystemURL Error"); });
}

@Barry1990
Copy link

if (this.targetHeight == -1 && this.targetWidth == -1 &&
destType == FILE_URI && !this.correctOrientation
&& getMimetypeForEncodingType().equalsIgnoreCase(mimeTypeOfGalleryFile))
{
this.callbackContext.success(finalLocation);
}

&& getMimetypeForEncodingType().equalsIgnoreCase(mimeTypeOfGalleryFile)) 把这个判断去掉 强制走if条件

@anaura
Copy link

anaura commented Oct 3, 2022

Cordova Android 10.0.0 Released! - Apache Cordova
In "cordova-android 10.0.0", WebViewAssetLoader has been added and file:// access is no longer possible.

As described in the Release document, to keep the previous behavior, add the following to config.xml

<preference name="AndroidInsecureFileModeEnabled" value="true" />

URLs must be converted using cordova-plugin-file in order to be accessed correctly by WebViewAssetLoader.

window.resolveLocalFileSystemURL(imageUri, (fileEntry) => {
  const fileEntryURL = fileEntry.toURL();
  appState.imageUri = fileEntryURL;
  document.getElementById("get-picture-result").src = fileEntryURL;
},
(err) => {
  console.error(err);
});

I think you should modify README.md.

@dreamslabmg
Copy link

so I have to call window.resolveLocalFileSystemURL(imageUri, (fileEntry) => {
const fileEntryURL = fileEntry.toURL();
appState.imageUri = fileEntryURL;
document.getElementById("get-picture-result").src = fileEntryURL;
},
(err) => {
console.error(err);
}); every time I have to display a file uri?

@drogerie21
Copy link

same issue here. Need a content URI to get the proper filename. Is there a way

  1. to get a content uri instead of file uri from the camera plugin
  2. if not, is there a way to convert a file uri into a content uri?

@mattocchi
Copy link

mattocchi commented Jan 23, 2024

I'm facing same issue with Android 13 and [email protected] using camera.getPicture with DestinationType.FILE_URI

  1. workaround that seem to work for me is to move on using instead a DestinationType.DATA_URL:
function onPhotoURISuccess(imgUri) {
    console.log(imgUri); // on Android 13 it's a uri without file:// and resolveLocalFileSystemURL will fail.

    // in case of resolveLocalFileSystemURL fail I'll try to manage imgUri as imgData and store Base64 encoded data to a new File.
    window.resolveLocalFileSystemURL(imgUri, function success(fileEntry) {
        console.log(JSON.stringify(fileEntry));
        console.log("got file: " + fileEntry.fullPath);
        return fileEntry;
    }, function (error) {
        console.log(error.code); // on Android 13 it's Error Code 5
        var tmp = createNewFileEntry(imgUri);
        return tmp;
    });
}
  1. root cause

debugging the cordova-plugin-camera at CameraLauncher.java the processResultFromGallery will return finalLocation the "imgUri" that look like /storage/emulated/0/Pictures/IMG_20240123_164955.jpg (it's an example of a selection from an emulator gallery) that it's later not resolvable from resolveLocalFileSystemURL

see also #866

@hirushacooray
Copy link

same issue

@breautek
Copy link
Contributor

With #902 which will streamline the returned data. It should make it's way to the next major 8.x release.

Most common uris will be file:// or content://, it will depend on the underlying source of the image/video.

If using FILE_URI, the returned path will be resolvable by using the file plugin. The FileEntry object can produce a DOM-usable URL via .toURL(). This will require an unreleased file plugin (so stay tuned for that too).

If DATA_URL is used, then a data: path will be returned but that's still on the TODO as of writing this comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.