package org.commcare.activities.components;
import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
import android.provider.MediaStore.Images.Media;
import android.widget.Toast;
import org.commcare.activities.FormEntryActivity;
import org.commcare.google.services.analytics.GoogleAnalyticsFields;
import org.commcare.google.services.analytics.GoogleAnalyticsUtils;
import org.commcare.utils.FileUtil;
import org.commcare.views.widgets.ImageWidget;
import org.javarosa.core.services.locale.Localization;
import java.io.File;
import java.io.IOException;
public class ImageCaptureProcessing {
/**
* Performs any necessary relocating and scaling of an image coming from either a
* SignatureWidget or ImageWidget (capture or choose)
*
* @param originalImage the image file returned by the image capture or chooser intent
* @param shouldScale if false, indicates that the image is from a signature capture, so should
* not attempt to scale
* @return the image file that should be displayed on the device screen when this question
* widget is in view
*/
private static File moveAndScaleImage(File originalImage, boolean shouldScale,
String instanceFolder,
FormEntryActivity formEntryActivity) throws IOException {
String extension = FileUtil.getExtension(originalImage.getAbsolutePath());
String imageFilename = System.currentTimeMillis() + "." + extension;
String finalFilePath = instanceFolder + imageFilename;
boolean savedScaledImage = false;
if (shouldScale) {
ImageWidget currentWidget = (ImageWidget)formEntryActivity.getPendingWidget();
if (currentWidget != null) {
int maxDimen = currentWidget.getMaxDimen();
if (maxDimen != -1) {
GoogleAnalyticsUtils.reportFeatureUsage(GoogleAnalyticsFields.ACTION_IMAGE_CAPTURE_RESIZED);
savedScaledImage = FileUtil.scaleAndSaveImage(originalImage, finalFilePath, maxDimen);
}
}
}
if (!savedScaledImage) {
// If we didn't create a scaled image and save it to the final path, then relocate the
// original image from the temp filepath to our final path
File finalFile = new File(finalFilePath);
if (!originalImage.renameTo(finalFile)) {
throw new IOException("Failed to rename " + originalImage.getAbsolutePath() +
" to " + finalFile.getAbsolutePath());
} else {
return finalFile;
}
} else {
// Otherwise, relocate the original image to a raw/ folder, so that we still have access
// to the unmodified version
String rawDirPath = instanceFolder + "/raw";
File rawDir = new File(rawDirPath);
if (!rawDir.exists()) {
rawDir.mkdir();
}
File rawImageFile = new File(rawDirPath + "/" + imageFilename);
if (!originalImage.renameTo(rawImageFile)) {
throw new IOException("Failed to rename " + originalImage.getAbsolutePath() +
" to " + rawImageFile.getAbsolutePath());
} else {
return rawImageFile;
}
}
}
/**
* Processes the return from an image capture intent, launched by either an ImageWidget or
* SignatureWidget
*
* @param isImage true if this was from an ImageWidget, false if it was a SignatureWidget
* @return if saving the captured image was successful
*/
public static boolean processCaptureResponse(FormEntryActivity activity,
String instanceFolder,
boolean isImage) {
/* We saved the image to the tempfile_path, but we really want it to be in:
* /sdcard/odk/instances/[current instance]/something.[jpg/png/etc] so we move it there
* before inserting it into the content provider. Once the android image capture bug gets
* fixed, (read, we move on from Android 1.6) we want to handle images the audio and
* video
*/
// The intent is empty, but we know we saved the image to the temp file
File originalImage = ImageWidget.getTempFileForImageCapture();
try {
File unscaledFinalImage = moveAndScaleImage(originalImage, isImage, instanceFolder, activity);
activity.saveImageWidgetAnswer(buildImageFileContentValues(unscaledFinalImage));
return true;
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(activity, Localization.get("image.capture.not.saved"), Toast.LENGTH_LONG).show();
return false;
}
}
public static void processImageChooserResponse(FormEntryActivity activity,
String instanceFolder,
Intent intent) {
/* We have a saved image somewhere, but we really want it to be in:
* /sdcard/odk/instances/[current instance]/something.[jpg/png/etc] so we move it there
* before inserting it into the content provider. Once the android image capture bug gets
* fixed, (read, we move on from Android 1.6) we want to handle images the audio and
* video
*/
// get gp of chosen file
Uri selectedImage = intent.getData();
String imagePath = FileUtil.getPath(activity, selectedImage);
if (imagePath == null) {
Toast.makeText(activity, Localization.get("invalid.image.selection"), Toast.LENGTH_LONG).show();
return;
}
File originalImage = new File(imagePath);
if (originalImage.exists()) {
try {
File unscaledFinalImage = moveAndScaleImage(originalImage, true, instanceFolder, activity);
activity.saveImageWidgetAnswer(buildImageFileContentValues(unscaledFinalImage));
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(activity, Localization.get("image.selection.not.saved"), Toast.LENGTH_LONG).show();
}
} else {
// The user has managed to select a file from the image browser that doesn't actually
// exist on the file system anymore
Toast.makeText(activity, Localization.get("invalid.image.selection"), Toast.LENGTH_LONG).show();
}
}
private static ContentValues buildImageFileContentValues(File unscaledFinalImage) {
// Add the new image to the Media content provider so that the viewing is fast in Android 2.0+
ContentValues values = new ContentValues(6);
values.put(Media.TITLE, unscaledFinalImage.getName());
values.put(Media.DISPLAY_NAME, unscaledFinalImage.getName());
values.put(Media.DATE_TAKEN, System.currentTimeMillis());
values.put(Media.MIME_TYPE, "image/jpeg");
values.put(Media.DATA, unscaledFinalImage.getAbsolutePath());
return values;
}
}