havidarou.com.appgestosfoto.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for havidarou.com.appgestosfoto.MainActivity.java

Source

/**
 *
 *  Copyright (C) 2016  Javier Castro Fernndez
 *
 *    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.
 *
 *  See <http://www.gnu.org/licenses/>.
 *
 */

package havidarou.com.appgestosfoto;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.camera2.*;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Environment;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.TextView;
import android.content.Intent;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

// Photo related
// Code inspired in http://www.experts-exchange.com/questions/27789218/Eclipse-Android-Take-Image-and-set-flash-without-user-interaction.html
// Some advice from http://stackoverflow.com/questions/6825129/android-cam-setpreviewdisplayholder-running-into-ioerror too

// Gesture related
// Code inspired in https://github.com/AdriMedina/Deteccion-Gestos-Android

public class MainActivity extends AppCompatActivity {

    // Data output tags
    private static final String DEBUG_TAG = "EventOutput";
    private static final String COORD_TAG = "Coordenates";

    private TextView helper;
    private ImageView a1, a2, a3, b1, b2, b3, c1, c2, c3;
    private int p1[] = new int[2];
    private int p2[] = new int[2];
    private int p3[] = new int[2];
    private int p4[] = new int[2];
    private int p5[] = new int[2];
    private int p6[] = new int[2];
    private int p7[] = new int[2];
    private int p8[] = new int[2];
    private int p9[] = new int[2];

    // Gesture checking
    float initialX, initialY, currentX, currentY;
    boolean rightPattern = true;

    private Camera camera; // Camera object
    private TextView textTimeLeft; // Time left field

    // This is the movement done by the user
    List<Integer> movement = new ArrayList<>();

    // These are the movements allowed by the app
    List<Integer> zMovement = new ArrayList<>();
    List<Integer> lMovement = new ArrayList<>();
    List<Integer> mMovement = new ArrayList<>();
    List<Integer> nMovement = new ArrayList<>();
    List<Integer> vMovement = new ArrayList<>();

    // This is needed in order to take the photo, will hold the preview (althought it will not show it on screen)
    private SurfaceView view;

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        camera.getParameters();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Associate the textView
        helper = (TextView) findViewById(R.id.textHelper);

        // Associate the imageViews
        a1 = (ImageView) findViewById(R.id.imageView);
        a2 = (ImageView) findViewById(R.id.imageView2);
        a3 = (ImageView) findViewById(R.id.imageView3);
        b1 = (ImageView) findViewById(R.id.imageView4);
        b2 = (ImageView) findViewById(R.id.imageView5);
        b3 = (ImageView) findViewById(R.id.imageView6);
        c1 = (ImageView) findViewById(R.id.imageView7);
        c2 = (ImageView) findViewById(R.id.imageView8);
        c3 = (ImageView) findViewById(R.id.imageView9);

        // Adding the movement patterns
        movement.add(0);

        zMovement.add(0);
        zMovement.add(1);
        zMovement.add(2);
        zMovement.add(3);
        zMovement.add(5);
        zMovement.add(7);
        zMovement.add(8);
        zMovement.add(9);

        lMovement.add(0);
        lMovement.add(1);
        lMovement.add(4);
        lMovement.add(7);
        lMovement.add(8);
        lMovement.add(9);

        mMovement.add(0);
        mMovement.add(7);
        mMovement.add(4);
        mMovement.add(1);
        mMovement.add(5);
        mMovement.add(3);
        mMovement.add(6);
        mMovement.add(9);

        nMovement.add(0);
        nMovement.add(7);
        nMovement.add(4);
        nMovement.add(1);
        nMovement.add(5);
        nMovement.add(9);
        nMovement.add(6);
        nMovement.add(3);

        vMovement.add(0);
        vMovement.add(1);
        vMovement.add(8);
        vMovement.add(3);

        textTimeLeft = (TextView) findViewById(R.id.TimeLeft); // This is the timer
        camera = Camera.open();

        view = (SurfaceView) findViewById(R.id.cpPreview);
        view.setVisibility(View.INVISIBLE);

    }

    public void refreshPreview() {
        try {
            camera.stopPreview();
        } catch (Exception e) {
        }

        try {
            camera.startPreview();
        } catch (Exception e) {
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        try {
            camera.setPreviewTexture(new SurfaceTexture(10));
        } catch (IOException e) {
        }

    }

    Camera.PictureCallback jpegCallBack = new Camera.PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {
            // Set file destination and file name
            //refreshPreview();
            String fec = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            String nombre = "JPEGAPPGESTOSFOTO_" + fec + "_.jpg";

            File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
            File destination = new File(storageDir, nombre);

            try {
                Bitmap userImage = BitmapFactory.decodeByteArray(data, 0, data.length);
                // Set file out stream
                FileOutputStream out = new FileOutputStream(destination);
                // Set compress format quality and stream
                userImage.compress(Bitmap.CompressFormat.JPEG, 90, out);

            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };

    // This method starts a timer (3 seconds) and upon finishing takes a photo
    public void startTimer(View v) {
        // 3000ms=3s at intervals of 1000ms=1s so that means it lasts 3 seconds
        new CountDownTimer(3000, 1000) {

            @Override
            public void onFinish() {
                // When the timer has finished, the picture is taken
                textTimeLeft.setText("Picture Taken");
                camera.takePicture(null, null, null, jpegCallBack);
            }

            @Override
            public void onTick(long millisUntilFinished) {
                // Every second the textView gets updated
                textTimeLeft.setTextSize(16);
                textTimeLeft.setTextColor(Color.GREEN);
                textTimeLeft.setText("Seconds Left: " + millisUntilFinished / 1000);
            }

        }.start();
    }

    // This method manages the touch input done by the user
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Get the event in order to switch between the options
        int action = MotionEventCompat.getActionMasked(event);

        a1.getLocationInWindow(p1);
        a2.getLocationInWindow(p2);
        a3.getLocationInWindow(p3);
        b1.getLocationInWindow(p4);
        b2.getLocationInWindow(p5);
        b3.getLocationInWindow(p6);
        c1.getLocationInWindow(p7);
        c2.getLocationInWindow(p8);
        c3.getLocationInWindow(p9);

        switch (action) {
        // If the movement has just begun
        case (MotionEvent.ACTION_DOWN):
            helper.setText("Do a recognized pattern");

            // Get the initial point
            initialX = event.getX(event.getPointerId(0));
            initialY = event.getY(event.getPointerId(0));

            Log.d("X:", Float.toString(initialX));
            Log.d("Y:", Float.toString(initialY));
            break;

        // If the user is moving across the screen
        case (MotionEvent.ACTION_MOVE):
            // Get the current point
            currentX = event.getX(event.getPointerId(0));
            currentY = event.getY(event.getPointerId(0));

            // Depending on the current position and where are we moving we add to the current movement
            if ((currentX > p1[0] - 60 && currentX < p1[0] + 70) && (currentY > p1[1] - 60)
                    && (currentY < p1[1] + 70) && (movement.get(movement.size() - 1) != 1)) {
                Log.d("Movement:", Float.toString(1));
                movement.add(1);
            } else if ((currentX > p2[0] - 60 && currentX < p2[0] + 70) && (currentY > p2[1] - 60)
                    && (currentY < p2[1] + 70) && (movement.get(movement.size() - 1) != 2)) {
                Log.d("Movement:", Float.toString(2));
                movement.add(2);
            } else if ((currentX > p3[0] - 60 && currentX < p3[0] + 70) && (currentY > p3[1] - 60)
                    && (currentY < p3[1] + 70) && (movement.get(movement.size() - 1) != 3)) {
                Log.d("Movement:", Float.toString(3));
                movement.add(3);
            } else if ((currentX > p4[0] - 60 && currentX < p4[0] + 70) && (currentY > p4[1] - 60)
                    && (currentY < p4[1] + 70) && (movement.get(movement.size() - 1) != 4)) {
                Log.d("Movement:", Float.toString(4));
                movement.add(4);
            } else if ((currentX > p5[0] - 60 && currentX < p5[0] + 70) && (currentY > p5[1] - 60)
                    && (currentY < p5[1] + 70) && (movement.get(movement.size() - 1) != 5)) {
                Log.d("Movement:", Float.toString(5));
                movement.add(5);
            } else if ((currentX > p6[0] - 60 && currentX < p6[0] + 70) && (currentY > p6[1] - 60)
                    && (currentY < p6[1] + 70) && (movement.get(movement.size() - 1) != 6)) {
                Log.d("Movement:", Float.toString(6));
                movement.add(6);
            } else if ((currentX > p7[0] - 60 && currentX < p7[0] + 70) && (currentY > p7[1] - 60)
                    && (currentY < p7[1] + 70) && (movement.get(movement.size() - 1) != 7)) {
                Log.d("Movement:", Float.toString(7));
                movement.add(7);
            } else if ((currentX > p8[0] - 50 && currentX < p8[0] + 70) && (currentY > p8[1] - 60)
                    && (currentY < p8[1] + 70) && (movement.get(movement.size() - 1) != 8)) {
                Log.d("Movement:", Float.toString(8));
                movement.add(8);
            } else if ((currentX > p9[0] - 60 && currentX < p9[0] + 70) && (currentY > p9[1] - 60)
                    && (currentY < p9[1] + 70) && (movement.get(movement.size() - 1) != 9)) {
                Log.d("Movement:", Float.toString(9));
                movement.add(9);
            }
            break;

        // If the user stops touching the screen then we check if the pattern matches with any of the recognized ones
        case (MotionEvent.ACTION_UP):
            if (movement.equals(zMovement) || movement.equals(lMovement) || movement.equals(mMovement)
                    || movement.equals(nMovement) || movement.equals(vMovement)) {
                rightPattern = true;
                helper.setText("Recognized pattern");

                view.setVisibility(View.VISIBLE);
                a1.setVisibility(View.INVISIBLE);
                a2.setVisibility(View.INVISIBLE);
                a3.setVisibility(View.INVISIBLE);
                b1.setVisibility(View.INVISIBLE);
                b2.setVisibility(View.INVISIBLE);
                b3.setVisibility(View.INVISIBLE);
                c1.setVisibility(View.INVISIBLE);
                c2.setVisibility(View.INVISIBLE);
                c3.setVisibility(View.INVISIBLE);

                try {
                    camera.setPreviewDisplay(view.getHolder()); // Associate the holder with the preview
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                camera.setDisplayOrientation(90);
                camera.startPreview();
                // A recognized pattern has been done, now we start the timer
                startTimer(view);
            } else {
                helper.setText("Unrecognized pattern");
            }

            movement.clear();
            movement.add(0);
            break;
        }
        return true;
    }
}