Skip to content

Instantly share code, notes, and snippets.

@iegrsy
Last active March 27, 2019 08:00
Show Gist options
  • Save iegrsy/eb0a707ac0cbd069a45d926e771b4df0 to your computer and use it in GitHub Desktop.
Save iegrsy/eb0a707ac0cbd069a45d926e771b4df0 to your computer and use it in GitHub Desktop.
Android Camera Preview Fragment
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
import android.content.Context;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.Display;
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.view.WindowManager;
import java.util.List;
import static java.lang.Math.ceil;
public class CameraPreviewFragment extends Fragment implements SurfaceHolder.Callback, Camera.PreviewCallback {
private Camera mCamera;
private Camera.Size mPreviewSize;
private byte[] mPreviewBuffer;
private Context context;
private SurfaceHolder holder;
private boolean isPreviewRunning = false;
public CameraPreviewFragment() {
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_camera_preview, container, false);
SurfaceView surfaceView = (SurfaceView) rootView.findViewById(R.id.preview_surface);
holder = surfaceView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
return rootView;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
camera.addCallbackBuffer(mPreviewBuffer);
// TODO: Implement this: [data ==> Frame format YV12]
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
startCamera(holder);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
setupCameraParameters(context, mCamera);
mCamera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
stopCamera();
}
private void startCamera(SurfaceHolder surfaceHolder) throws Exception {
if (isPreviewRunning)
stopCamera();
mCamera = Camera.open();
mPreviewSize = setupCameraParameters(context, mCamera);
mPreviewBuffer = new byte[calculateBufferSize(mPreviewSize.width, mPreviewSize.height)];
surfaceHolder.setFixedSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.addCallbackBuffer(mPreviewBuffer);
mCamera.setPreviewCallbackWithBuffer(this);
mCamera.startPreview();
isPreviewRunning = true;
}
private void stopCamera() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
isPreviewRunning = false;
}
private static Camera.Size setupCameraParameters(Context context, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
Camera.Size previewSize = previewSizes.get(0); //Max preview size
parameters.setPreviewFormat(ImageFormat.YV12);
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
parameters.setPreviewSize(previewSize.width, previewSize.height);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
camera.setParameters(parameters);
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
camera.setDisplayOrientation(90);
} else if (display.getRotation() == Surface.ROTATION_270) {
camera.setDisplayOrientation(180);
}
return previewSize;
}
private static int calculateBufferSize(int w, int h) {
int yStride = (int) ceil(w / 16.0) * 16;
int uvStride = (int) ceil((yStride / 2.0) / 16.0) * 16;
int ySize = yStride * h;
int uvSize = uvStride * h / 2;
return ySize + uvSize * 2;
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CameraPreviewFragment">
<SurfaceView
android:id="@+id/preview_surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" />
</FrameLayout>
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
public static final String[] PERMISSION_STRINGS = new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
public static final int REQUEST_CAMERA_PERMISSION = 123;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setContainer(new CameraPreviewFragment());
}
private void setContainer(Fragment fragment) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
requestCameraPermission();
return;
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.main_container, fragment).commitNow();
}
private void requestCameraPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
new ConfirmationDialog().show(getSupportFragmentManager(), "Camera Permission");
} else {
requestPermissions(PERMISSION_STRINGS, REQUEST_CAMERA_PERMISSION);
}
}
public static class ConfirmationDialog extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Fragment parent = getParentFragment();
return new AlertDialog.Builder(getActivity())
.setMessage("Need permissions")
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
parent.requestPermissions(PERMISSION_STRINGS, REQUEST_CAMERA_PERMISSION);
}
})
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Activity activity = parent.getActivity();
if (activity != null) {
activity.finish();
}
}
})
.create();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment