eu.geopaparazzi.library.camera.AbstractCameraActivity.java Source code

Java tutorial

Introduction

Here is the source code for eu.geopaparazzi.library.camera.AbstractCameraActivity.java

Source

/*
 * 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();
}