package org.adaptlab.chpir.android.survey;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import org.adaptlab.chpir.android.survey.Models.ResponsePhoto;
import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
public class CameraFragment extends Fragment {
private static final String TAG = "CameraFragment";
public static final String EXTRA_PHOTO_FILENAME = "CameraFragment.filename";
public static final String EXTRA_RESPONSE_PHOTO = "CameraFragment.photo";
public static final String EXTRA_CAMERA = "CameraFragment.camera_index";
public static int CAMERA;
private View mProgressIndicator;
private Camera mCamera;
private SurfaceView mSurfaceView;
private static ResponsePhoto mPhoto;
public static CameraFragment newCameraFragmentInstance(ResponsePhoto picture, int camera_index) {
mPhoto = picture;
CAMERA = camera_index;
Bundle args = new Bundle();
args.putSerializable(EXTRA_RESPONSE_PHOTO, mPhoto);
args.putSerializable(EXTRA_CAMERA, CAMERA);
CameraFragment fragment = new CameraFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(EXTRA_CAMERA, CAMERA);
}
private Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback() {
public void onShutter() {
mProgressIndicator.setVisibility(View.VISIBLE);
}
};
private Camera.PictureCallback mJPEGCallBack = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
String filename = UUID.randomUUID().toString() + ".jpg";
FileOutputStream os = null;
boolean success = true;
try {
os = getActivity().openFileOutput(filename, Context.MODE_PRIVATE);
os.write(data);
} catch (Exception e) {
success = false;
} finally {
try {
if (os != null)
os.close();
} catch (Exception e) {
success = false;
}
}
if (success) {
ResponsePhoto picture = (ResponsePhoto) getArguments().getSerializable(EXTRA_RESPONSE_PHOTO);
picture.setPicturePath(filename);
picture.setCameraOrientation(getResources().getConfiguration().orientation);
picture.setCamera(CAMERA);
picture.save();
releaseCamera();
popBackQuestionFragment();
} else {
Log.i(TAG, "Not Successful");
}
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_camera, parent, false);
mProgressIndicator = v.findViewById(R.id.camera_progressIndicator);
mProgressIndicator.setVisibility(View.INVISIBLE);
Button takePictureButton = (Button) v.findViewById(R.id.camera_takePictureButton);
takePictureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mCamera != null) {
mCamera.takePicture(mShutterCallback, null, mJPEGCallBack);
}
}
});
mSurfaceView = (SurfaceView)v.findViewById(R.id.camera_surfaceView);
SurfaceHolder holder = mSurfaceView.getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch(IOException e) {
Log.e(TAG, "Error setting up surface preview display", e);
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
releaseCamera();
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mCamera == null) {
return;
}
try {
Camera.Parameters parameters = mCamera.getParameters();
Size s = getBestSupportedSize(parameters.getSupportedPreviewSizes(), w, h);
parameters.setPreviewSize(s.width, s.height);
mCamera.setParameters(parameters);
setCameraDisplayOrientation(getActivity(), CAMERA, mCamera);
mCamera.startPreview();
} catch (Exception e) {
Log.e(TAG, "Unable to start preview",e);
mCamera.release();
mCamera = null;
popBackQuestionFragment();
}
}
});
return v;
}
public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
private Size getBestSupportedSize(List<Size> sizes, int width, int height) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) width / height;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = height;
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
@Override
public void onResume() {
super.onResume();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
mCamera = Camera.open(CAMERA);
} else {
mCamera = Camera.open();
}
}
//TODO Open the Camera on a different thread from main
@Override
public void onPause() {
super.onPause();
releaseCamera();
}
public void releaseCamera() {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
protected void popBackQuestionFragment() {
FragmentManager fm = getActivity().getSupportFragmentManager();
fm.popBackStack();
FragmentTransaction transaction = fm.beginTransaction();
transaction.detach(CameraFragment.this);
transaction.commit();
}
}