add toggling between front/rear camera

This commit is contained in:
tibbi 2016-04-19 13:02:52 +02:00
parent 22d2b16ab3
commit 6ce7b5e2e4
4 changed files with 109 additions and 24 deletions

View File

@ -37,7 +37,13 @@ public class MainActivity extends AppCompatActivity {
@OnClick(R.id.toggle_camera) @OnClick(R.id.toggle_camera)
public void toggleCamera() { public void toggleCamera() {
if (currCamera == Camera.CameraInfo.CAMERA_FACING_BACK)
currCamera = Camera.CameraInfo.CAMERA_FACING_FRONT;
else
currCamera = Camera.CameraInfo.CAMERA_FACING_BACK;
preview.releaseCamera();
preview.setCamera(currCamera);
} }
@OnClick(R.id.shutter) @OnClick(R.id.shutter)
@ -53,8 +59,7 @@ public class MainActivity extends AppCompatActivity {
if (cnt == 1) { if (cnt == 1) {
toggleCameraBtn.setVisibility(View.INVISIBLE); toggleCameraBtn.setVisibility(View.INVISIBLE);
} }
Camera camera = Camera.open(currCamera); preview.setCamera(currCamera);
preview.setCamera(camera);
} }
@Override @Override

View File

@ -4,6 +4,7 @@ import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.hardware.Camera;
import android.media.ExifInterface; import android.media.ExifInterface;
import android.media.MediaScannerConnection; import android.media.MediaScannerConnection;
import android.os.AsyncTask; import android.os.AsyncTask;
@ -19,10 +20,12 @@ import java.util.Date;
public class PhotoProcessor extends AsyncTask<byte[], Void, Void> { public class PhotoProcessor extends AsyncTask<byte[], Void, Void> {
private static final String TAG = PhotoProcessor.class.getSimpleName(); private static final String TAG = PhotoProcessor.class.getSimpleName();
private static Context context; private static Context mContext;
private static int mCameraId;
public PhotoProcessor(Context cxt) { public PhotoProcessor(Context context, int cameraId) {
context = cxt; mContext = context;
mCameraId = cameraId;
} }
@Override @Override
@ -51,7 +54,7 @@ public class PhotoProcessor extends AsyncTask<byte[], Void, Void> {
} }
private static File getOutputMediaFile() { private static File getOutputMediaFile() {
final String appName = context.getResources().getString(R.string.app_name); final String appName = mContext.getResources().getString(R.string.app_name);
final File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), appName); final File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), appName);
if (!mediaStorageDir.exists()) { if (!mediaStorageDir.exists()) {
@ -67,21 +70,28 @@ public class PhotoProcessor extends AsyncTask<byte[], Void, Void> {
private Bitmap setBitmapRotation(Bitmap bitmap, String path) throws IOException { private Bitmap setBitmapRotation(Bitmap bitmap, String path) throws IOException {
final ExifInterface exif = new ExifInterface(path); final ExifInterface exif = new ExifInterface(path);
final String orientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION); final String orientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
float angle = 0f;
if (orientation.equalsIgnoreCase("6")) { if (orientation.equalsIgnoreCase("6")) {
bitmap = rotateImage(bitmap, 90); angle = 90;
} else if (orientation.equalsIgnoreCase("8")) { } else if (orientation.equalsIgnoreCase("8")) {
bitmap = rotateImage(bitmap, 270); angle = 270;
} else if (orientation.equalsIgnoreCase("3")) { } else if (orientation.equalsIgnoreCase("3")) {
bitmap = rotateImage(bitmap, 180); angle = 180;
} else if (orientation.equalsIgnoreCase("0")) { } else if (orientation.equalsIgnoreCase("0")) {
bitmap = rotateImage(bitmap, 90); angle = 90;
} }
return bitmap; return rotateImage(bitmap, angle);
} }
public static Bitmap rotateImage(Bitmap source, float angle) { public static Bitmap rotateImage(Bitmap source, float angle) {
final Matrix matrix = new Matrix(); final Matrix matrix = new Matrix();
matrix.postRotate(angle); matrix.postRotate(angle);
final Camera.CameraInfo info = Utils.getCameraInfo(mCameraId);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
matrix.preScale(-1.f, 1.f);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true); return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
} }
@ -100,6 +110,6 @@ public class PhotoProcessor extends AsyncTask<byte[], Void, Void> {
private void scanPhoto(File photo) { private void scanPhoto(File photo) {
final String[] photoPath = {photo.getAbsolutePath()}; final String[] photoPath = {photo.getAbsolutePath()};
MediaScannerConnection.scanFile(context, photoPath, null, null); MediaScannerConnection.scanFile(mContext, photoPath, null, null);
} }
} }

View File

@ -1,11 +1,13 @@
package com.simplemobiletools.camera; package com.simplemobiletools.camera;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.hardware.Camera; import android.hardware.Camera;
import android.os.Handler; import android.os.Handler;
import android.util.Log; import android.util.Log;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import android.view.SurfaceView; import android.view.SurfaceView;
import android.view.View; import android.view.View;
@ -26,23 +28,28 @@ public class Preview extends ViewGroup implements SurfaceHolder.Callback, View.O
private static SurfaceView surfaceView; private static SurfaceView surfaceView;
private static Camera.Size previewSize; private static Camera.Size previewSize;
private static boolean canTakePicture; private static boolean canTakePicture;
private static Activity activity;
private static int currCameraId;
public Preview(Context cxt) { public Preview(Context context) {
super(cxt); super(context);
} }
public Preview(Context cxt, SurfaceView sv) { public Preview(Activity act, SurfaceView sv) {
super(cxt); super(act);
activity = act;
surfaceView = sv; surfaceView = sv;
surfaceHolder = surfaceView.getHolder(); surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this); surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
canTakePicture = true; canTakePicture = false;
surfaceView.setOnTouchListener(this); surfaceView.setOnTouchListener(this);
} }
public void setCamera(Camera newCamera) { public void setCamera(int cameraId) {
currCameraId = cameraId;
final Camera newCamera = Camera.open(cameraId);
if (camera == newCamera) { if (camera == newCamera) {
return; return;
} }
@ -55,12 +62,53 @@ public class Preview extends ViewGroup implements SurfaceHolder.Callback, View.O
requestLayout(); requestLayout();
final Camera.Parameters params = camera.getParameters(); final Camera.Parameters params = camera.getParameters();
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); final List<String> focusModes = params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
camera.setParameters(params); camera.setParameters(params);
camera.setDisplayOrientation(90); setCameraDisplayOrientation(cameraId, camera);
if (canTakePicture) {
try {
camera.setPreviewDisplay(surfaceHolder);
} catch (IOException e) {
Log.e(TAG, "setCamera " + e.getMessage());
}
setupPreview();
}
} }
} }
public static void setCameraDisplayOrientation(int cameraId, android.hardware.Camera camera) {
final Camera.CameraInfo info = Utils.getCameraInfo(cameraId);
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;
} else {
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
public void takePicture() { public void takePicture() {
if (canTakePicture) { if (canTakePicture) {
camera.takePicture(null, null, takePictureCallback); camera.takePicture(null, null, takePictureCallback);
@ -74,12 +122,15 @@ public class Preview extends ViewGroup implements SurfaceHolder.Callback, View.O
new Handler().postDelayed(new Runnable() { new Handler().postDelayed(new Runnable() {
@Override @Override
public void run() { public void run() {
camera.startPreview(); if (camera != null)
camera.startPreview();
canTakePicture = true; canTakePicture = true;
} }
}, PHOTO_PREVIEW_LENGTH); }, PHOTO_PREVIEW_LENGTH);
new PhotoProcessor(getContext()).execute(data); final Camera.CameraInfo info = Utils.getCameraInfo(currCameraId);
new PhotoProcessor(getContext(), info.facing).execute(data);
} }
}; };
@ -101,7 +152,10 @@ public class Preview extends ViewGroup implements SurfaceHolder.Callback, View.O
@Override @Override
public void onAutoFocus(boolean success, Camera camera) { public void onAutoFocus(boolean success, Camera camera) {
camera.cancelAutoFocus(); camera.cancelAutoFocus();
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); final List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
camera.setParameters(parameters); camera.setParameters(parameters);
} }
}); });
@ -134,7 +188,7 @@ public class Preview extends ViewGroup implements SurfaceHolder.Callback, View.O
public void surfaceCreated(SurfaceHolder holder) { public void surfaceCreated(SurfaceHolder holder) {
try { try {
if (camera != null) { if (camera != null) {
camera.setPreviewDisplay(holder); camera.setPreviewDisplay(surfaceHolder);
} }
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "surfaceCreated IOException " + e.getMessage()); Log.e(TAG, "surfaceCreated IOException " + e.getMessage());
@ -143,6 +197,11 @@ public class Preview extends ViewGroup implements SurfaceHolder.Callback, View.O
@Override @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
setupPreview();
}
private void setupPreview() {
canTakePicture = true;
if (camera != null) { if (camera != null) {
final Camera.Parameters parameters = camera.getParameters(); final Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(previewSize.width, previewSize.height); parameters.setPreviewSize(previewSize.width, previewSize.height);

View File

@ -0,0 +1,11 @@
package com.simplemobiletools.camera;
import android.hardware.Camera;
public class Utils {
public static Camera.CameraInfo getCameraInfo(int cameraId) {
final Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
return info;
}
}