To help expand my java coding skills, I took on what should be a simple project to take a picture with the camera, and return the thumbnail generated to an image component.
With help and advice from others, I followed code from Android Developers Training:
and came up with the following java file below. I have no errors in my IDE (IntelliJ). This builds an aix using RUSH. However, on testing in companion (2.61u) on Android 10 and 11, it generates an error on load:
Error from Companion: java.lang.Class is not accessible from java.lang.Class
(I do not have mismatched companion, and have reloaded after installing extension etc., tested on multiple devices)
and if I run the TakePicture block it generates this error:
invoke: no method named `TakePicture' in class java.lang.Boolean
I can compile an apk, but on first run it just crashes.
Not really sure what is wrong or what is missing, and would welcome some help. If more information is needed then please say.
JAVA
package uk.co.metricrat.simplecamera;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.MediaStore;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.runtime.ActivityResultListener;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.runtime.errors.YailRuntimeError;
import android.widget.ImageView;
import com.google.appinventor.components.runtime.Image;
class SimpleCamera extends AndroidNonvisibleComponent implements ActivityResultListener {
final Activity activity;
static final int REQUEST_IMAGE_CAPTURE = 1;
private ImageView imageView;
public SimpleCamera(ComponentContainer container) {
super(container.$form());
this.activity = container.$context();
}
@SimpleFunction(description = "Takes Thumbnail Picture with Camera and return")
public void TakePicture(Image image) {
imageView = (ImageView) image.getView();
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
try {
this.activity.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
} catch (ActivityNotFoundException e) {
throw new YailRuntimeError(e.getMessage(), "Cannot start activity");
}
}
@Override
public void resultReturned(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
imageView.setImageBitmap(imageBitmap);
}
}
}
You should make your extension's class public to outer packages.
public SimpleCamera extends AndroidNonvisibleComponent
It's because AppInventor is trying to create an instance of your extension class and fails to finds it since it's not public. While creating the class, an error has occurred, so you couldn't access any methods since the component is not sucessfully created.
Thank you @vknow360. Your code returns a file, I am seeking to avoid that, but to directly display the bitmap in the image component (or other view component...)
OK, added this to the @SimpleFunction before calling the intent, changing the 0 to 1,
and changed the variable setting to static int REQUEST_IMAGE_CAPTURE = 1;
(there was a final there too, but this was bring up an error in IntelliJ...)
On first run this produces an image (:D), but will not generate an image on subsequent clicks of the button. I am guessing that REQUEST_IMAGE_CAPTURE is for some reason not being reset to 1 ? or should I just set it 0?
JAVA now...
public class SimpleCamera extends AndroidNonvisibleComponent implements ActivityResultListener {
final Activity activity;
static int REQUEST_IMAGE_CAPTURE = 1;
private ImageView imageView;
public SimpleCamera(ComponentContainer container) {
super(container.$form());
this.activity = container.$context();
}
@SimpleFunction(description = "Takes Thumbnail Picture with Camera and return")
public void TakePicture(Image image) {
imageView = (ImageView) image.getView();
if (REQUEST_IMAGE_CAPTURE == 1) {
REQUEST_IMAGE_CAPTURE = form.registerForActivityResult(this);
}
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
try {
this.activity.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
} catch (ActivityNotFoundException e) {
throw new YailRuntimeError(e.getMessage(), "Cannot start activity");
}
}
@Override
public void resultReturned(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
imageView.setImageBitmap(imageBitmap);
}
}
For what it is worth, the thumbnail images are OK for viewing at around half screen width (landscape) and below on a normal phone. If that is all you need then it could be a way....
Final Java
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.MediaStore;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.runtime.ActivityResultListener;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.runtime.errors.YailRuntimeError;
import android.widget.ImageView;
import com.google.appinventor.components.runtime.Image;
public class SimpleCamera extends AndroidNonvisibleComponent implements ActivityResultListener {
final Activity activity;
private final int REQUEST_IMAGE_CAPTURE;
private ImageView imageView;
public SimpleCamera(ComponentContainer container) {
super(container.$form());
this.activity = container.$context();
REQUEST_IMAGE_CAPTURE = form.registerForActivityResult(this);
}
@SimpleFunction(description = "Takes Thumbnail Picture with Camera and return")
public void TakePicture(Image image) {
imageView = (ImageView) image.getView();
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
try {
this.activity.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
} catch (ActivityNotFoundException e) {
throw new YailRuntimeError(e.getMessage(), "Cannot start activity");
}
}
@Override
public void resultReturned(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
imageView.setImageBitmap(imageBitmap);
}
}
}