Im using a slightly modified version of the Gluon AndroidPicturesService
(to be able to access the taken / selected picture). While taking or selecting a picture is basically working, sometimes there is no activity result and the app gets new initialized, i.e. there is no FXActivity onRestart
prior to onStart, onResume
, or even worse there is a crash (it seems not to be caused by a specific image or directory).
public class AndroidPictureService {
private static final int TAKE_PICTURE = 1;
private static final int SELECT_PICTURE = 2;
private File imageFile;
private ObjectProperty<Image> image;
public AndroidPictureService() {
}
public ObjectProperty<Image> imageProperty() {
if (image == null) {
image = new SimpleObjectProperty<>();
}
return image;
}
public void takePicture(int width, int height, boolean savePicture) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File sourceFile = createImageFile();
Uri imageUri = Uri.fromFile(sourceFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
FXActivity.getInstance().setOnActivityResultHandler((requestCode, resultCode, data) ->
{
if (requestCode == TAKE_PICTURE) {
if (resultCode == RESULT_OK) {
MediaScannerConnection.scanFile(FXActivity.getInstance(), new String[] { sourceFile.toString() }, null, null);
if (width > 0 && height > 0) {
File tmpFile = new File(FXActivity.getInstance().getFilesDir(), "image_tmp.jpg");
adjustSizeAndStoreImage(sourceFile, tmpFile, width, height);
imageFile = tmpFile;
} else {
imageFile = sourceFile;
}
image.set(new Image(Uri.fromFile(imageFile).toString()));
if (!savePicture) {
sourceFile.delete();
}
}
Platform.runLater(() ->
{
try {
Toolkit.getToolkit().exitNestedEventLoop(imageProperty(), null);
} catch (Exception e) {
System.out.println("GalleryActivity: exitNestedEventLoop failed: " + e);
}
});
}
});
if (intent.resolveActivity(FXActivity.getInstance().getPackageManager()) != null) {
FXActivity.getInstance().startActivityForResult(intent, TAKE_PICTURE);
try {
Toolkit.getToolkit().enterNestedEventLoop(imageProperty());
} catch (Exception e) {
System.out.println("GalleryActivity: enterNestedEventLoop failed: " + e);
}
} else {
System.out.println("GalleryActivity: resolveActivity failed");
}
}
public void retrievePicture(int width, int height) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
FXActivity.getInstance().setOnActivityResultHandler((requestCode, resultCode, data) ->
{
if (requestCode == SELECT_PICTURE && resultCode == RESULT_OK) {
Uri selectedImageUri = data.getData();
String selectedImagePath = FileUtils.getPath(FXActivity.getInstance(), selectedImageUri);
if (selectedImagePath != null && !selectedImagePath.isEmpty()) {
File sourceFile = new File(selectedImagePath);
if (width > 0 && height > 0) {
File tmpFile = new File(FXActivity.getInstance().getFilesDir(), "image_tmp.jpg");
adjustSizeAndStoreImage(sourceFile, tmpFile, width, height);
imageFile = tmpFile;
} else {
imageFile = sourceFile;
}
imageProperty().set(new Image(Uri.fromFile(imageFile).toString()));
}
Platform.runLater(() ->
{
try {
Toolkit.getToolkit().exitNestedEventLoop(imageProperty(), null);
} catch (Exception e) {
System.out.println("GalleryActivity: exitNestedEventLoop failed: " + e);
}
});
}
});
// check for permissions
if (intent.resolveActivity(FXActivity.getInstance().getPackageManager()) != null) {
FXActivity.getInstance().startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURE);
try {
Toolkit.getToolkit().enterNestedEventLoop(imageProperty());
} catch (Exception e) {
System.out.println("GalleryActivity: enterNestedEventLoop failed: " + e);
}
} else {
System.out.println("GalleryActivity: resolveActivity failed");
}
}
@Override
public void adjustSizeAndStoreImage(File sourceFile, File targetFile, int width, int height) {
try (InputStream inForSizeCalculation = new FileInputStream(sourceFile);
InputStream inForBitmapCreation = new FileInputStream(sourceFile);
OutputStream out = new FileOutputStream(targetFile);) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(inForSizeCalculation, null, options);
int scale = calculateInSampleSize(options, width, height);
options.inJustDecodeBounds = false;
options.inSampleSize = scale;
Bitmap bitmap = BitmapFactory.decodeStream(inForBitmapCreation, null, options);
bitmap.compress(CompressFormat.JPEG, 100, out);
} catch (IOException ex) {
LOGGER.error("Failed to adjustSizeAndStoreImage", ex);
}
}
private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
private File createImageFile() {
String timeStamp = DateTimeFormatters.createTimeStamp();
String imageFileName = "IMG_" + timeStamp + ".jpg";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return new File(storageDir, imageFileName);
}
}