Skip to content

Instantly share code, notes, and snippets.

@devrath
Last active May 30, 2016 08:27
Show Gist options
  • Select an option

  • Save devrath/4aad9a7df943b505d0438c188592ecde to your computer and use it in GitHub Desktop.

Select an option

Save devrath/4aad9a7df943b505d0438c188592ecde to your computer and use it in GitHub Desktop.
Camera front and back feature
surface_view_camera_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.traktion.doctor.CameraUtils.CameraFrameLayout
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/vLowerPanel"
android:layout_width="match_parent"
android:background="@android:color/white"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_weight="1">
<ImageView
android:id="@+id/switchCamera"
android:layout_width="45dp"
android:layout_height="45dp"
android:visibility="visible"
android:layout_gravity="center"
android:src="@drawable/flip_camera" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_weight="1">
<ImageView
android:id="@+id/btnTakePhoto"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:src="@android:drawable/ic_menu_camera" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_weight="1">
<ImageView
android:id="@+id/cameraFlash"
android:layout_width="45dp"
android:layout_height="45dp"
android:adjustViewBounds="true"
android:layout_gravity="center"
android:src="@drawable/flash" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</FrameLayout>
------------------------------------------------------------------------------------------------------------------------------------
CameraFrameLayout.java
public class CameraFrameLayout extends FrameLayout {
public CameraFrameLayout(Context context) {
super(context);
}
public CameraFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CameraFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CameraFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight();
int heigthWithoutPadding = height - getPaddingTop() - getPaddingBottom();
int maxWidth = (int) (heigthWithoutPadding * Constants.RATIO);
int maxHeight = (int) (widthWithoutPadding / Constants.RATIO);
if (widthWithoutPadding > maxWidth) {
width = maxWidth + getPaddingLeft() + getPaddingRight();
} else {
height = maxHeight + getPaddingTop() + getPaddingBottom();
}
setMeasuredDimension(width, height);
}
}
------------------------------------------------------------------------------------------------------------------------------------
CameraView.java
public class CameraView extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
private static final int PICTURE_SIZE_MAX_WIDTH = 1280;
private static final int PREVIEW_SIZE_MAX_WIDTH = 640;
public List<Camera.Size> mSupportedPreviewSizes;
private SurfaceHolder mHolder;
private Activity mActivity;
private Camera mCamera;
private Camera.Size mPreviewSize;
private Camera.Parameters parameters;
public CameraView(Activity activity, Camera camera) {
super(activity.getApplicationContext());
mActivity = activity;
//mContext = context;
mCamera = camera;
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
for (Camera.Size str : mSupportedPreviewSizes)
Log.e(TAG, str.width + "/" + str.height);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// empty. surfaceChanged will take care of stuff
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.e(TAG, "surfaceChanged => w=" + w + ", h=" + h);
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
try {
parameters = mCamera.getParameters();
Camera.Size bestPreviewSize = determineBestPreviewSize(parameters);
Camera.Size bestPictureSize = determineBestPictureSize(parameters);
parameters.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height);
parameters.setPictureSize(bestPictureSize.width, bestPictureSize.height);
// Set continuous picture focus, if it's supported
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(getCameraRotation());
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
public int getCameraRotation() {
int cameraId = findBackFacingCamera();
Camera.CameraInfo info =
new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = mActivity.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;
}
return result;
}
private int findBackFacingCamera() {
int cameraId = -1;
int numberOfCameras = Camera.getNumberOfCameras();
//for every camera check
for (int i = 0; i < numberOfCameras; i++) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
break;
}
}
return cameraId;
}
private Camera.Size determineBestPreviewSize(Camera.Parameters parameters) {
return determineBestSize(parameters.getSupportedPreviewSizes(), PREVIEW_SIZE_MAX_WIDTH);
}
private Camera.Size determineBestPictureSize(Camera.Parameters parameters) {
return determineBestSize(parameters.getSupportedPictureSizes(), PICTURE_SIZE_MAX_WIDTH);
}
private Camera.Size determineBestSize(List<Camera.Size> sizes, int widthThreshold) {
Camera.Size bestSize = null;
Camera.Size size;
int numOfSizes = sizes.size();
for (int i = 0; i < numOfSizes; i++) {
size = sizes.get(i);
boolean isDesireRatio = (size.width / 4) == (size.height / 3);
boolean isBetterSize = (bestSize == null) || size.width > bestSize.width;
if (isDesireRatio && isBetterSize) {
bestSize = size;
}
}
if (bestSize == null) {
Log.d(TAG, "cannot find the best camera size");
return sizes.get(sizes.size() - 1);
}
return bestSize;
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera.Parameters parameters) {
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result = size;
} else {
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea) {
result = size;
}
}
}
}
return (result);
}
public void refreshCamera(Camera camera) {
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
mCamera = camera;
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
public void turnOnFlash() {
if (mCamera == null || parameters == null) {
return;
}
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
mCamera.setParameters(parameters);
}
public void turnOffFlash() {
if (mCamera == null || parameters == null) {
return;
}
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mCamera.setParameters(parameters);
}
}
------------------------------------------------------------------------------------------------------------------------------------
ActCamera.java
public class ActCamera extends AppCompatActivity implements View.OnClickListener {
private static final int REQUEST_CAMERA_PERMISSION = 1;
private Camera mCamera;
private CameraView maPreview;
private FrameLayout maLayoutPreview;
private ImageView btnTakePhoto, btnSwitchCamera, btnCameraFlash;
private boolean cameraFront = false;
private boolean isFlashOn = false;
private ProgressDialog progressDialog;
private byte[] pictureCallBackData;
private Camera pictureCallBackCamera;
TransparentProgressDialog pd;
public static ActCamera newInstance() {
ActCamera fragment = new ActCamera();
return fragment;
}
public Bitmap resizeImageForImageView(Bitmap bitmap) {
Bitmap resizedBitmap = null;
int originalWidth = bitmap.getWidth();
int originalHeight = bitmap.getHeight();
int height = (int) (originalWidth * 0.75f);
try {
resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, originalWidth, height);
}catch (OutOfMemoryError e){
e.printStackTrace();
Toast.makeText(ActCamera.this,"Device low on memory",Toast.LENGTH_LONG).show();
}
return resizedBitmap;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.surface_view_camera_fragment);
initialize();
}
private void initialize() {
requestForCameraPermission();
maLayoutPreview = (FrameLayout) findViewById(R.id.camera_preview);
maPreview = new CameraView(ActCamera.this, mCamera);
maLayoutPreview.addView(maPreview);
btnTakePhoto = (ImageView) findViewById(R.id.btnTakePhoto);
btnSwitchCamera = (ImageView) findViewById(R.id.switchCamera);
btnCameraFlash = (ImageView) findViewById(R.id.cameraFlash);
btnTakePhoto.setOnClickListener(this);
btnSwitchCamera.setOnClickListener(this);
btnCameraFlash.setOnClickListener(this);
}
public void takePhoto() {
mCamera.takePicture(null, null, pictureCallback());
}
private Camera.PictureCallback pictureCallback() {
Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
pictureCallBackData = data;
pictureCallBackCamera = camera;
new SaveFileTask().execute();
}
};
return mPicture;
}
private String getFilePath(Uri data){
String path = "";
// For non-gallery application
path = data.getPath();
// For gallery application
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(data, filePathColumn, null, null, null);
if(cursor!=null){
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
path = cursor.getString(columnIndex);
cursor.close();
}
return path;
}
public Bitmap rotate(Bitmap bitmap, int degree) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
mtx.setRotate(degree);
if(Build.VERSION.SDK_INT>13 && cameraFront)
{
float[] mirrorY = { -1, 0, 0, 0, 1, 0, 0, 0, 1};
mtx = new Matrix();
Matrix matrixMirrorY = new Matrix();
matrixMirrorY.setValues(mirrorY);
mtx.postConcat(matrixMirrorY);
mtx.preRotate(270);
}
// Logger.error("Device is "," "+Build.MODEL);
if (Build.MODEL.equalsIgnoreCase("Nexus 5x")|| Build.MODEL.equalsIgnoreCase("Nexus 6p")){
mtx.setRotate(270);
}
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}
private void gotoFeedPostScreen() {
CommonFunctions.dismissCircularLoadingDialog();
Intent intent = new Intent(this, MainActivity.class);
setResult(RESULT_OK,intent);
finish();
/* Intent intent = new Intent(getActivity(), CreatePostSubmitActivity.class);
intent.putExtra(CreatePostSubmitActivity.SCREEN, "camera");
startActivity(intent);*/
}
@Override
public void onResume() {
super.onResume();
if(!cameraFront) {
btnCameraFlash.setVisibility(View.VISIBLE);
}else {
btnCameraFlash.setVisibility(View.GONE);
}
if (mCamera == null) {
mCamera = Camera.open(0);
maPreview = new CameraView(ActCamera.this, mCamera);
}
}
@Override
public void onPause() {
super.onPause();
if (mCamera != null) {
mCamera.setPreviewCallback(null);
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mCamera != null) {
mCamera.release();
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnTakePhoto:
takePhoto();
break;
case R.id.switchCamera:
btnCameraFlash.setVisibility(View.VISIBLE);
int camerasNumber = Camera.getNumberOfCameras();
if (camerasNumber > 1) {
//release the old camera instance
//switch camera, from the front and the back and vice versa
releaseCamera();
chooseCamera();
} else {
Toast toast = Toast.makeText(ActCamera.this, "Sorry, your phone has only one camera!", Toast.LENGTH_LONG);
toast.show();
}
break;
case R.id.cameraFlash:
btnCameraFlash.setImageResource(0);
if (isFlashOn) {
isFlashOn = false;
maPreview.turnOffFlash();
btnCameraFlash.setImageResource(R.drawable.flash);
} else {
isFlashOn = true;
maPreview.turnOnFlash();
btnCameraFlash.setImageResource(R.drawable.flash_active);
}
break;
}
}
public void chooseCamera() {
//if the camera preview is the front
if (cameraFront) {
int cameraId = findBackFacingCamera();
if (cameraId >= 0) {
mCamera = Camera.open(cameraId);
mCamera.setDisplayOrientation(90);
pictureCallback();
maPreview.refreshCamera(mCamera);
btnSwitchCamera.setImageResource(0);
btnSwitchCamera.setImageResource(R.drawable.flip_camera);
btnCameraFlash.setVisibility(View.VISIBLE);
}
} else {
int cameraId = findFrontFacingCamera();
if (cameraId >= 0) {
mCamera = Camera.open(cameraId);
mCamera.setDisplayOrientation(90);
pictureCallback();
maPreview.refreshCamera(mCamera);
btnSwitchCamera.setImageResource(0);
btnSwitchCamera.setImageResource(R.drawable.flip_camera_active);
btnCameraFlash.setVisibility(View.GONE);
}
}
}
private int findFrontFacingCamera() {
int cameraId = -1;
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
cameraId = i;
cameraFront = true;
break;
}
}
return cameraId;
}
private int findBackFacingCamera() {
int cameraId = -1;
int numberOfCameras = Camera.getNumberOfCameras();
//for every camera check
for (int i = 0; i < numberOfCameras; i++) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
cameraFront = false;
break;
}
}
return cameraId;
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
private void launchCamera() {
mCamera = Camera.open(findBackFacingCamera());
}
public void requestForCameraPermission() {
final String permission = Manifest.permission.CAMERA;
if (ContextCompat.checkSelfPermission(ActCamera.this, permission)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(ActCamera.this, permission)) {
showPermissionRationaleDialog("Test", permission);
} else {
requestForPermission(permission);
}
} else {
launchCamera();
}
}
private void showPermissionRationaleDialog(final String message, final String permission) {
new AlertDialog.Builder(ActCamera.this)
.setMessage(message)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestForPermission(permission);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create()
.show();
}
private void requestForPermission(final String permission) {
ActivityCompat.requestPermissions(ActCamera.this, new String[]{permission}, REQUEST_CAMERA_PERMISSION);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CAMERA_PERMISSION:
final int numOfRequest = grantResults.length;
final boolean isGranted = numOfRequest == 1
&& PackageManager.PERMISSION_GRANTED == grantResults[numOfRequest - 1];
if (isGranted) {
launchCamera();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private class SaveFileTask extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
CommonFunctions.showCircularLoadingDialog(pd, getActivity());
}
@Override
protected String doInBackground(String... path) {
File sampleImg = new File(Environment.getExternalStorageDirectory()
+ File.separator + "test.jpg");
Constants.CAMERA_FOLDER_PATH = Environment.getExternalStorageDirectory()
+ File.separator + "test.jpg";
Bitmap capturedBitmap = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(pictureCallBackData, 0, pictureCallBackData.length, options);
options.inSampleSize = CommonFunctions.calculateInSampleSize(options, Constants.REQ_WIDTH, Constants.REQ_HEIGHT);
options.inJustDecodeBounds = false;
options.inPurgeable = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
capturedBitmap = BitmapFactory.decodeByteArray(pictureCallBackData, 0, pictureCallBackData.length, options);
FileOutputStream fos = new FileOutputStream(sampleImg);
ExifInterface ei = new ExifInterface(getFilePath(Uri.fromFile(sampleImg)));
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
capturedBitmap = rotate(capturedBitmap, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
capturedBitmap = rotate(capturedBitmap, 180);
break;
default:
capturedBitmap = rotate(capturedBitmap, 90);
break;
}
capturedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
fos = null;
capturedBitmap = null;
} catch (FileNotFoundException e) {
Log.d("Info", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("TAG", "Error accessing file: " + e.getMessage());
}
return null;
}
@Override
protected void onPostExecute(String result) {
gotoFeedPostScreen();
}
}
}
------------------------------------------------------------------------------------------------------------------------------------
Constants.java
public static final int RATIO = 4/3;
------------------------------------------------------------------------------------------------------------------------------------
Manifest
<!-- CAMERA -->
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- CAMERA -->
------------------------------------------------------------------------------------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment