Working with Other Components in an Extension

For the first and second errors resulted in by theImageView symbol, it appears the android.view.ImageView class wasn't imported, importing it should get it fixed.
For the second error, i think the imageComponent variable in @Kumaraswamy's code is equivalent to the image variable in your code, renaming imageComponent to image should work.
The fourth error should be resolved by applying the first fix.

2 Likes

Thank you Mohamed, that clears the errors.

Now need to test.

2 Likes

Success!!

image

JAVA
import android.graphics.Bitmap;
import android.graphics.drawable.*;
import android.util.Base64;
import android.widget.*;
import com.google.appinventor.components.annotations.SimpleEvent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.runtime.*;
import java.io.ByteArrayOutputStream;


public class ImageBase64 extends AndroidNonvisibleComponent {

    public ImageBase64(ComponentContainer container) {
      super(container.$form());

    }

    @SimpleFunction(description = "Get Image and returns base64 string")
    public void GetImageAsBase64(Image image ) throws Exception {

      final ImageView imageView = (ImageView) image.getView();
      Bitmap imageBitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();

      String encodedString = bitMapToBase64(imageBitmap);
      AfterImageBase64(encodedString);
    }

    public String bitMapToBase64(Bitmap bitMap) {
      ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
      bitMap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
      byte[] byteArray = byteArrayOutputStream.toByteArray();
      return Base64.encodeToString(byteArray, Base64.DEFAULT);
    }

    @SimpleEvent(description = "Called after the image is converted. The text argument `imageBase64Data` is the base64 string of the image")
    public void AfterImageBase64(String imageBase64Data) {
      EventDispatcher.dispatchEvent(this, "AfterImageBase64", imageBase64Data);
    }
  }

3 Likes

You will be please to here (if not amazed, given my poor showing so far....) that i have been able to successfully do this part myself:

JAVA

@SimpleFunction(description="Set Image component with image from base64 string")
    public void SetImageFromBase64(final Image image, String base64String) {
        final ImageView imageView = (ImageView) image.getView();
        byte[] decodedString = Base64.decode(base64String, Base64.DEFAULT);
        Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
        imageView.setImageBitmap(decodedByte);
    }

BLOCKS
image

SCREENSHOT

A heartfelt thanks to everyone who has participated, I certainly learnt a lot, and hope it has been useful to others too.

5 Likes

I'd suggest not doing this via reflection, to be honest. We make no guarantees about whether private methods will be retained release to release. Only the public methods are expected to remain stable. Secondly, in systems where proguard is applied to the final app, the method may be renamed or inlined so reflection will fail.

1 Like

Could you expand.....perhaps offer alternatives where reflection / private methods have been used ?

1 Like

Or maybe it's better to add base64 method to all components that display images and that save images? I think it would be an easy project and there would be no backward compatibility issues.

Not just images....

There is the soundRecorder and the camCorder too, we could then get carried away and consider the Player and VideoPlayer as well :wink:

Can sounds also base64 encoded? I think if someone encodes a long sound file that is a few MBs, could it be resource consuming?

It can be up to 30% bigger, but as long as the device can cope....

See method here by @Juan_Antonio (& me...)

Maybe but, there should be a method for extensions to work with the Canvas?

Edit: I created a small PR here.

1 Like

@Kumaraswamy

This appears to have stopped working with the last release (n195 or something Google)

My code in extension:

@SimpleFunction(description = "Get Canvas Image and returns base64 string")
  public void GetCanvasImageAsBase64(final Canvas canvas ) throws Exception {
    final View canvasView = (View) canvas.getView();
    final Method method = canvasView.getClass().getDeclaredMethod("buildCache");
    method.setAccessible(true);
    Bitmap imageBitmap = (Bitmap) method.invoke(canvasView);
    String encodedString = bitMapToBase64(imageBitmap);
    AfterCanvasBase64(encodedString);
  }

image

That's why reflection is a bit unstable over time.

@SimpleFunction(description = "Get Canvas Image and returns base64 string")
  public void GetCanvasImageAsBase64(final Canvas canvas ) throws Exception {
    Bitmap imageBitmap = canvas.getBitmap();
    String encodedString = bitMapToBase64(imageBitmap);
    AfterCanvasBase64(encodedString);
  }

Calling .getBitmap() should be enough.

But... since I believe the extension build sources are not yet updated, you should use this code instead:

@SimpleFunction(description = "Get Canvas Image and returns base64 string")
  public void GetCanvasImageAsBase64(final Canvas canvas) throws Exception {
    final Method method = canvas.getClass().getDeclaredMethod("getBitmap");
    Bitmap imageBitmap = (Bitmap) method.invoke(canvas);
    String encodedString = bitMapToBase64(imageBitmap);
    AfterCanvasBase64(encodedString);
  }

This one, I can assure you, will not break in future.

Did you mean to leave out this:

final View canvasView = canvas.getView();

???

1 Like

That's not required anymore, the code I posted will work.

Thanks so much, just testing....

Works just fine, if a bit slow (using companion), but it works which is the main thing.

Many thanks again

:smiley:

1 Like

Seems to make a much much bigger base64 string than expected ?

Do It Result: "iVBORw0KGgoAAAANSUhEUgAAAzkAAARMCAYAAAC6Wl3lAAAAAXNSR0IArs4c6QAAAARzQklUCAgI
CHwIZIgAACAASURBVHic7N13eF33fef5Nyo7wU6J6r1YlmTZsuTYseXe5DJrJy7ZnczmmcxmJ9lx
difzx6wTl0wyG8/GjuXHdR3HdtyLLFmyVahOkZTYSbEDJBpRL+5Fu/cCuPXsHwJpqrMA+N177vt1
HwkCSIkfkXiA8znf3/n96qIoipAkSZKkmKgPHUCSJEmSZpIlR5IkSVKsWHIkSZIkxYolR5IkSVKs
WHIkSZIkxYolR5IkSVKsWHIkSZIkxYolR5IkSVKsWHIkSZIkxYolR5IkSVKsWHIkSZIkxYolR5Ik
SVKsWHIkSZIkxYolR5IkSVKsWHIkSZIkxYolR5IkSVKsWHIkSZIkxYolR5IkSVKsWHIkSZIkxYol
R5IkSVKsWHIkSZIkxYolR5IkSVKsWHIkSZIkxYolR5IkSVKsWHIkSZIkxYolR5IkSVKsWHIkSZIk
xYolR5IkSVKsWHIkSZIkxYolR5IkSVKsWHIkSZIkxYolR5IkSVKsWHIkSZIkxYolR5IkSVKsWHIk
SZIkxUpj6ACSpLkREVGkRIkShel/Ov5+mTIFipSJKFMGIgoUiYDSibel6R9/9m2JMnVABNRN/3g0
/evUUTf9FgoUT3r/2bcNNFA3/Tr54000nvjvRUDD9L24Jhqpo27634P66VcTjUDd9Ht1NFBPI400
0DD99wbqqaOZZhqnf01JUvxZciSpBkTTrxHGmGCSJMNMMEWSESaYZIJJxkiTZZICRQoUGCNNjjxZ
JshTYIJJJpliihxZJslTOPHfL1MmR54pci/4dUcZf0Ge+cxjAfNf8PEWllB/0iKDZppopoklLGIB
81nIApppoolGlrCYFpbQNP3+IhYwj2ZWsIyFLGAVy1k4/e+sYgWrWA5g0ZGkGmDJkaQqExGRp0CR
IiXKTDE1/TZ34m2Z8olJTZ4C5el/HiPDFFOMk2GSHOPT7+fIk2GCHHkKFChRJkOWIiUmmKREafpn
FabLzLM/7/gE5neZSs+ZzLyU8vSk6PmTnClyz5nwPJs/f+LHJpmigQaaaCRNlnEyNFBPE03Mo5l5
NDFIkvnMZymLp2tPE8tooYXFNNJIPfU00zQ94WmijnrmM+/EFGgeTcxn/on3n/05FiNJqiZ1URS9
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



"
---

can't actually add all the characters here due to a 32000 character limit, but it was @ 41000...

for this file:

which is set in a canvas 400x300...

That's since because, it appears that Bitmap we are retrieving dosent seem to be compressed like the last time.

Bitmap bitmap = ...
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 75, baos);
Bitmap compressed = BitmapFactory.decodeStream(new ByteArrayInputStream(baos.toByteArray()));

Or you should try tweaking the compression level that is set to 75 here.
Then use the compressed bitmap.

2 Likes

LIke this ?

@SimpleFunction(description = "Get Canvas Image and returns base64 string")
  public void GetCanvasImageAsBase64(final Canvas canvas ) throws Exception {
    final Method method = canvas.getClass().getDeclaredMethod("getBitmap");
    Bitmap imageBitmap = (Bitmap) method.invoke(canvas);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    imageBitmap.compress(Bitmap.CompressFormat.JPEG, 75, baos);
    Bitmap compressed = BitmapFactory.decodeStream(new ByteArrayInputStream(baos.toByteArray()));
    String encodedString = bitMapToBase64(compressed);
    AfterCanvasBase64(encodedString);
  }

convert to base64:

  public String bitMapToBase64(Bitmap bitMap) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    bitMap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
    byte[] byteArray = byteArrayOutputStream.toByteArray();
    return Base64.encodeToString(byteArray, Base64.DEFAULT);
  }
1 Like