plugins icon indicating copy to clipboard operation
plugins copied to clipboard

[@nativescript/imagepicker] Returns `ImageAsset` with `content://` scheme that can't be loaded with `ImageSource.fromAsset`

Open tomups opened this issue 4 years ago • 8 comments

Versions

@nativescript/core: 7.3.0
@nativescript/android: 7.0.1
@nativescript/imagepicker: 1.0.5

Problem

Using @nativescript/imagepicker in Android 10, the returned selected image has the following form when logged to console:

{
  "_observers": {},
   "_options": {
     "keepAspectRatio": true,
     "autoScaleFactor": true
 },
"_android": "content://com.android.providers.media.documents/document/image%3A29"

When trying to load this ImageAsset into an ImageSource with ImageSource.fromAsset I get an Asset 'content://com.android.providers.media.documents/document/image%3A29' cannot be found. error.

Example code

let context = imagepicker.create({
      mode: "single",
      mediaType: ImagePickerMediaType.Image,
    });

    context
      .authorize()
      .then(() => {
        return context.present();
      })
      .then((selection) => {        
        if (selection.length > 0) {
          ImageSource.fromAsset(selection[0])
            .then((imageSource) => {
              console.log("ImageSource loaded:", imageSource);
            })
            .catch((err) => console.error("Error loading ImageSource:", err));
        }
      });

Is this a bug, or is there another way to get an ImageSource from the result of the imagepicker selection?

tomups avatar Jun 29 '21 18:06 tomups

As a heads up the issue looks to be this line: https://github.com/NativeScript/plugins/blob/master/packages/imagepicker/index.android.ts#L198

I'm getting these Uris returned on API Level 30 devices which suggests this line is causing the problem. Manually setting this to true fixed the issue for API Level 30 devices but I can't be sure of the impact.

To workaround the problem in my project I've:

  1. copied UriHelper into my own code as an exported class.
  2. Wrapped my old ImageSource.fromAsset in a try catch
  3. In the catch, if android, call UriHelper._calculateFileUri and try again.

Looks something like this:

      await picker.authorize();
      const result = await picker.present();

      // No images selected then return null
      // Should return here
      if (!result?.length) return null;

      const path = ImagePaths.rawImagePath();
      const asset: ImageAsset = result[0];
      try {
        const image = await ImageSource.fromAsset(asset);
        image.saveToFile(path, IMAGE_FORMAT);
        return path;
      } catch (error) {
        // This the new bit while waiting on #145
        if (isAndroid) {
          const url = asset?.android;
          if (!url) throw error;
          const uri = android.net.Uri.parse(url);

          const rawUrl = UriHelper._calculateFileUri(uri);
          if (!rawUrl) throw error;

          const newAsset = new ImageAsset(rawUrl);
          const image = await ImageSource.fromAsset(newAsset);
          image.saveToFile(path, IMAGE_FORMAT);
          return path;
        }
        throw error;
      }

jamescodesthings avatar Jul 16 '21 12:07 jamescodesthings

I'll run some more tests but this should be working

triniwiz avatar Jul 16 '21 12:07 triniwiz

@triniwiz on a chromebook running API 29 (ASUS Chromebook C202SA), UriHelper seems to throw with:

java.lang.IllegalArgumentException: column '_data' does not exist. Available columns: []

I assume the reason being deprecation https://developer.android.com/reference/android/provider/MediaStore.MediaColumns#DATA

but I am not sure

nikoTM avatar Jul 21 '21 11:07 nikoTM

Anything new about this?

I updated nativescript to version 7 in the hope that things will work better, but there are still problems

Edit: @jamescodesthings you're right,changing the conditions solves the problem. But is it the best solution @triniwiz ?

Siergiej29 avatar Jul 29 '21 10:07 Siergiej29

When can I expect to update and fix the bug?

tka3k avatar Aug 12 '21 06:08 tka3k

Can you which version of core you are using?

triniwiz avatar Aug 13 '21 21:08 triniwiz

I reproduce this bug with this versions :

    "@nativescript/android": "8.0.0",
    "@nativescript/core": "~7.1.0",
    "@nativescript/imagepicker": "^1.0.5",

The workaround of @jamescodesthings works

AntoineBouquet avatar Aug 18 '21 08:08 AntoineBouquet

Same here. I am using @jamescodesthings hack while waiting for a fix

soscler avatar Nov 14 '21 10:11 soscler

ImageSource.fromAsset(selection[0]) .then((imageSource) => { console.log("ImageSource loaded:", imageSource); }) .catch((err) => console.error("Error loading ImageSource:", err));

Hi @jamescodesthings , do you have a working code example of the UriHelper? I am trying to fix an similair issue but not quite managing. Maybe its my lack of skill.. if you do, it would be really helpful for me.

Thank you in advanced!

patrickvandasler avatar Mar 22 '23 10:03 patrickvandasler

In 2.0.0 you can now pass copyToAppFolder: 'myfolder' which should address this issue. You can then either use ImageSource.fromAsset(selected.asset).then((img) => { /// do things }) or ImageSource.fromAsset(selected.path).then((img) => { /// do things })

FYI you can also pass renameFileTo: 'mycoolfile' and it will rename your selection. If you choose multiple it appends the index like mycoolfile-0.png mycoolfile-1.png etc

davecoffin avatar Apr 18 '23 15:04 davecoffin