com.nextgis.mobile.forms.CameraFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.nextgis.mobile.forms.CameraFragment.java

Source

/******************************************************************************
 * Project:  NextGIS mobile
 * Purpose:  Mobile GIS for Android.
 * Author:   Dmitry Baryshnikov (aka Bishop), polimax@mail.ru
 ******************************************************************************
*   Copyright (C) 2012-2013 NextGIS
*
*    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 2 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 com.nextgis.mobile.forms;

import java.io.File;
import java.io.IOException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationManager;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import com.nextgis.mobile.InputPointActivity;
import com.nextgis.mobile.R;

import static com.nextgis.mobile.util.Constants.*;

public class CameraFragment extends Fragment {

    private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 7;
    private String fileName;
    private File imgFile;
    private SensorManager sensorManager;
    private float declination;
    protected Location currentLocation;
    protected Map<Long, Float> mAngles = new HashMap<Long, Float>();

    private ArrayList<HashMap<String, Object>> listItems = new ArrayList<HashMap<String, Object>>();
    private static final String IMG_NAME = "image_name";
    private static final String IMG_ROT = "image_rotation";

    //DEFINING STRING ADAPTER WHICH WILL HANDLE DATA OF LISTVIEW
    private SimpleAdapter adapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        setRetainInstance(true);

        View view = inflater.inflate(R.layout.camfragment, container, false);

        Button button = (Button) view.findViewById(R.id.insert_take_photo);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onCapturePhoto();
            }
        });

        ListView photoList = (ListView) view.findViewById(R.id.poi_photos_list);

        adapter = new SimpleAdapter(view.getContext(), listItems, R.layout.row, new String[] { IMG_NAME, IMG_ROT, },
                new int[] { R.id.image_name, R.id.image_rotation });

        photoList.setAdapter(adapter);

        final LocationManager locationManager = (LocationManager) getActivity()
                .getSystemService(Context.LOCATION_SERVICE);

        if (currentLocation == null) {
            currentLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            if (currentLocation == null) {
                currentLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            }
        }
        long now = System.currentTimeMillis();
        declination = CompassFragment.getDeclination(currentLocation, now);

        sensorManager = (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE);

        return view;
    }

    public void onStoreValues() {
        if (getView() != null) {
            InputPointActivity activity = (InputPointActivity) getActivity();
            if (activity == null)
                return;

            //if (getView().findViewById(R.id.poi_notes_text) != null) {
            //   activity.SetNotes(((TextView) getView().findViewById(R.id.poi_notes_text)).getText().toString());
            //}
        }
        //UpdateSummary();
    }

    private Uri getOutputMediaFileUri() {
        return Uri.fromFile(getOutputMediaFile());
    }

    private File getOutputMediaFile() {
        // To be safe, you should check that the SDCard is mounted
        // using Environment.getExternalStorageState() before doing this.
        File mediaStorageDir = new File(getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES), "");

        // Create the storage directory if it does not exist
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                Log.d(TAG, "failed to create directory");
                return null;
            }
        }

        // Create a media file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        fileName = "IMG_" + timeStamp + ".jpg";
        imgFile = new File(mediaStorageDir, fileName);

        return imgFile;
    }

    private Date stringToDate(String aDate, String aFormat) {

        if (aDate == null)
            return null;
        ParsePosition pos = new ParsePosition(0);
        SimpleDateFormat simpledateformat = new SimpleDateFormat(aFormat);
        Date stringDate = simpledateformat.parse(aDate, pos);
        return stringDate;

    }

    protected SensorEventListener sensorListener = new SensorEventListener() {

        public void onSensorChanged(SensorEvent event) {
            //long stamp = event.timestamp;
            long stamp = System.currentTimeMillis();
            float dfAz = event.values[0] + declination + CameraFragment.this.getDeviceRotation();
            mAngles.put(stamp, dfAz);

            /*         if(mAngles.size() > 5000)
                     {
                        Set set = mAngles.keySet();
                         Iterator itr = set.iterator();
                         while(itr.hasNext()){
            if(mAngles.size() < 5000)
               break;
            itr.remove();
                         }
                     }
                     //bundle.putFloat("pitch", event.values[1]);
                     //bundle.putFloat("roll", event.values[2]);      */
        }

        public void onAccuracyChanged(Sensor arg0, int arg1) {
        }
    };

    public int getDeviceRotation() {

        if (getActivity() == null)
            return 0;
        if (getActivity().getWindowManager() == null)
            return 0;
        Display display = getActivity().getWindowManager().getDefaultDisplay();
        if (display != null) {
            if (display.getRotation() == Surface.ROTATION_90) {
                return 90;
            } else if (display.getRotation() == Surface.ROTATION_180) {
                return 180;
            } else if (display.getRotation() == Surface.ROTATION_270) {
                return 270;
            }
        }
        return 0;
    }

    public void onCapturePhoto() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        Uri fileUri = getOutputMediaFileUri(); // create a file to save the image
        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

        mAngles.clear();
        sensorManager.registerListener(sensorListener, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
                SensorManager.SENSOR_DELAY_NORMAL);
        // start the image capture Intent
        startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        sensorManager.unregisterListener(sensorListener);
        if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            //add angle
            float dfAngle = 0;
            try {
                ExifInterface exif = new ExifInterface(imgFile.getPath());
                String sDate = exif.getAttribute(ExifInterface.TAG_DATETIME);
                Date datetime = stringToDate(sDate, "yyyy:MM:dd HH:mm:ss");
                Log.d(TAG, "image date: " + datetime.toString());
                long testMilli = datetime.getTime();

                long nDif = 1000000;
                for (long n : mAngles.keySet()) {
                    long nDifTmp = Math.abs(testMilli - n);
                    if (nDifTmp < nDif) {
                        nDif = nDifTmp;
                        dfAngle = (Float) mAngles.get(n);
                    }
                }
                Log.d(TAG, "image angle: " + dfAngle);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            String listItem;
            if (data != null) {
                Uri outPath = data.getData();
                listItem = outPath.getLastPathSegment();
            } else {
                listItem = fileName;
            }
            HashMap<String, Object> hm = new HashMap<String, Object>();
            hm.put(IMG_NAME, listItem);
            String sAngle = CompassFragment.formatNumber(dfAngle, 0, 0) + CompassFragment.DEGREE_CHAR + " "
                    + CompassFragment.getDirectionCode(dfAngle, getResources());
            hm.put(IMG_ROT, sAngle);

            listItems.add(hm);

            adapter.notifyDataSetChanged();

            InputPointActivity activity = (InputPointActivity) getActivity();
            if (activity == null)
                return;
            activity.AddImage(listItem, dfAngle);
        }
    }

}