/*
* Geopaparazzi - Digital field mapping on Android based devices
* Copyright (C) 2016 HydroloGIS (www.hydrologis.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.geopaparazzi.library.camera;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import eu.geopaparazzi.library.R;
import eu.geopaparazzi.library.core.ResourcesManager;
import eu.geopaparazzi.library.database.DefaultHelperClasses;
import eu.geopaparazzi.library.database.GPLog;
import eu.geopaparazzi.library.database.IImagesDbHelper;
import eu.geopaparazzi.library.images.ImageUtilities;
import eu.geopaparazzi.library.util.FileUtilities;
import eu.geopaparazzi.library.util.GPDialogs;
import eu.geopaparazzi.library.util.LibraryConstants;
import eu.geopaparazzi.library.util.Utilities;
/**
* <p>Abstract activity for taking pictures, can be subclassed to
* get specialized behaviours
* <p/>
* <p>
* The image is created in a <b>tmp</b> folder inside the
* application folder. If the intent bundle contains a
* {@link LibraryConstants#PREFS_KEY_CAMERA_IMAGESAVEFOLDER}
* value, that one is used as folder.
* </p>
* <p/>
* <p>
* The activity returns the path to the image on "disk"., that can be
* retrieved through the {@link LibraryConstants#PREFS_KEY_PATH} key from
* the bundle.
* </p>
*
* @author Andrea Antonello (www.hydrologis.com)
* @author Cesar Martinez Izquierdo (www.scolab.es)
*/
@SuppressWarnings("nls")
public abstract class AbstractCameraActivity extends Activity {
protected static final int CAMERA_PIC_REQUEST = 1337;
protected String imageFilePath;
protected File imageFile;
protected Date currentDate;
protected int lastImageMediastoreId;
protected void doTakePicture(Bundle icicle) {
Bundle extras = getIntent().getExtras();
File imageSaveFolder = null;
try {
imageSaveFolder = ResourcesManager.getInstance(this).getTempDir();
String imageName;
if (extras != null) {
String imageSaveFolderTmp = extras.getString(LibraryConstants.PREFS_KEY_CAMERA_IMAGESAVEFOLDER);
if (imageSaveFolderTmp != null && new File(imageSaveFolderTmp).exists()) {
imageSaveFolder = new File(imageSaveFolderTmp);
}
imageName = extras.getString(LibraryConstants.PREFS_KEY_CAMERA_IMAGENAME);
} else {
throw new RuntimeException("Not implemented yet...");
}
if (!imageSaveFolder.exists()) {
if (!imageSaveFolder.mkdirs()) {
Runnable runnable = new Runnable() {
public void run() {
finish();
}
};
GPDialogs.warningDialog(this, getString(R.string.cantcreate_img_folder), runnable);
return;
}
}
File mediaFolder = imageSaveFolder;
currentDate = new Date();
if (imageName == null) {
imageName = ImageUtilities.getCameraImageName(currentDate);
}
imageFilePath = mediaFolder.getAbsolutePath() + File.separator + imageName;
File imgFile = new File(imageFilePath);
Uri outputFileUri = Utilities.getFileUriInApplicationFolder(this, imgFile);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
lastImageMediastoreId = getLastImageMediaId();
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
} catch (Exception e) {
GPLog.error(this, null, e);
GPDialogs.errorDialog(this, e, new Runnable() {
@Override
public void run() {
finish();
}
});
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_PIC_REQUEST) {
checkTakenPictureConsistency();
Intent intent = getIntent();
File imageFile = new File(imageFilePath);
if (imageFile.exists()) {
intent.putExtra(LibraryConstants.PREFS_KEY_PATH, imageFilePath);
intent.putExtra(LibraryConstants.OBJECT_EXISTS, true);
doSaveData();
} else {
intent.putExtra(LibraryConstants.OBJECT_EXISTS, false);
}
setResult(Activity.RESULT_OK, intent);
finish();
}
}
protected void checkTakenPictureConsistency() {
try {
/*
* Checking for duplicate images
* This is necessary because some camera implementation not only save where you want them to save but also in their default location.
*/
final String[] projection = {MediaStore.Images.ImageColumns.DATA, MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.SIZE, MediaStore.Images.ImageColumns._ID};
final String imageOrderBy = MediaStore.Images.Media._ID + " DESC";
final String imageWhere = MediaStore.Images.Media._ID + ">?";
final String[] imageArguments = {Integer.toString(lastImageMediastoreId)};
Cursor imageCursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, imageWhere, imageArguments,
imageOrderBy);
List<File> cameraTakenMediaFiles = new ArrayList<>();
if (imageCursor.getCount() > 0) {
while (imageCursor.moveToNext()) {
// int id =
// imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
String path = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
// Long takenTimeStamp =
// imageCursor.getLong(imageCursor.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN));
// Long size =
// imageCursor.getLong(imageCursor.getColumnIndex(MediaStore.Images.Media.SIZE));
cameraTakenMediaFiles.add(new File(path));
}
}
imageCursor.close();
imageFile = new File(imageFilePath);
boolean imageExists = imageFile.exists();
if (GPLog.LOG)
GPLog.addLogEntry("Image file: " + imageFilePath + " exists: " + imageExists);
if (!imageExists && cameraTakenMediaFiles.size() > 0) {
// was not saved where I wanted, but the camera saved one in the media folder
// try to copy over the one saved by the camera and then delete
try {
File cameraDoubleFile = cameraTakenMediaFiles.get(cameraTakenMediaFiles.size() - 1);
FileUtilities.copyFile(cameraDoubleFile, imageFile);
cameraDoubleFile.delete();
} catch (IOException e) {
GPLog.error(this, null, e);
}
}
for (File cameraTakenFile : cameraTakenMediaFiles) {
// delete the one duplicated
cameraTakenFile.delete();
}
} catch (Exception e) {
GPLog.error(this, null, e);
}
}
/**
* Gets the last image id from the media store.
*
* @return the last image id from the media store.
*/
private int getLastImageMediaId() {
final String[] imageColumns = {MediaStore.Images.Media._ID};
final String imageOrderBy = MediaStore.Images.Media._ID + " DESC";
final String imageWhere = null;
final String[] imageArguments = null;
Cursor imageCursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, imageWhere, imageArguments,
imageOrderBy);
if (imageCursor.moveToFirst()) {
int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
imageCursor.close();
return id;
} else {
return 0;
}
}
protected abstract void doSaveData();
}