android 5.0以上相机模块 照相

来源:互联网 发布:mac电脑numbers教程 编辑:程序博客网 时间:2024/04/29 20:22


package com.example.lxb.camerademo;import android.Manifest;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import android.graphics.ImageFormat;import android.graphics.Matrix;import android.graphics.RectF;import android.graphics.SurfaceTexture;import android.hardware.camera2.CameraAccessException;import android.hardware.camera2.CameraCaptureSession;import android.hardware.camera2.CameraCharacteristics;import android.hardware.camera2.CameraDevice;import android.hardware.camera2.CameraManager;import android.hardware.camera2.CameraMetadata;import android.hardware.camera2.CaptureRequest;import android.hardware.camera2.CaptureResult;import android.hardware.camera2.TotalCaptureResult;import android.hardware.camera2.params.StreamConfigurationMap;import android.media.Image;import android.media.ImageReader;import android.media.MediaRecorder;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.HandlerThread;import android.os.Message;import android.os.PersistableBundle;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.support.v4.app.ActivityCompat;import android.util.Size;import android.util.SparseIntArray;import android.view.Surface;import android.view.TextureView;import android.view.View;import android.widget.Button;import android.widget.Toast;import java.io.File;import java.io.IOException;import java.util.Arrays;import java.util.List;import java.util.concurrent.Semaphore;import java.util.concurrent.TimeUnit;/** * Created by lxb on 2017/5/3. */public class VideoActivity extends Activity {    private MediaRecorder mMediaRecorder;    private ImageReader mImageReader;    private boolean isOpened;    private TextureView textureView;    private Size imageDimension;    private CameraDevice mCameraDevice;    private Semaphore mCameraOpenCloseLock = new Semaphore(1);    private Handler mBackgroundHandler;    private HandlerThread mBackgroundThread;    private CameraCaptureSession mCaptureSession;    private CaptureRequest mPreviewRequest;    private boolean mFlashSupported;    private String cameraId;    private static final int STATE_PREVIEW = 0;    private static final int STATE_WAITING_LOCK = 1;    private static final int STATE_WAITING_PRECAPTURE = 2;    private static final int STATE_WAITING_NON_PRECAPTURE = 3;    private static final int STATE_PICTURE_TAKEN = 4;    private int mState = STATE_PREVIEW;    private int mSensorOrientation;    private CaptureRequest.Builder mPreviewRequestBuilder;    static final SparseIntArray ORIENTATIONS = new SparseIntArray();    static {        ORIENTATIONS.append(Surface.ROTATION_0, 90);        ORIENTATIONS.append(Surface.ROTATION_90, 0);        ORIENTATIONS.append(Surface.ROTATION_180, 270);        ORIENTATIONS.append(Surface.ROTATION_270, 180);    }    private int nOperation = -1;    //1 拍照  2:录像    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_video_layout);        initView();        nOperation = getIntent().getIntExtra("type",1);    }    private void initView() {        textureView = (TextureView) findViewById(R.id.texture_video_preview);        Button photo = (Button) findViewById(R.id.photo);        photo.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                takePicture();            }        });    }    /**     * 实时预览监听器     */    TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {        public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {            openCamera();        }        public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {            configureTransform(width, height);        }        public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {            return true;        }        public void onSurfaceTextureUpdated(SurfaceTexture texture) {        }    };    /**     * texture size发生改变时重新配置     *     * @param viewWidth     * @param viewHeight     */    private void configureTransform(int viewWidth, int viewHeight) {        if (null == textureView || null == imageDimension) return;        int rotation = getWindowManager().getDefaultDisplay().getRotation();        Matrix matrix = new Matrix();        RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);        RectF bufferRect = new RectF(0, 0, imageDimension.getHeight(), imageDimension.getWidth());        float centerX = viewRect.centerX();        float centerY = viewRect.centerY();        if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {            bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());            matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);            float scale = Math.max((float) viewHeight / imageDimension.getHeight(), (float) viewWidth / imageDimension.getWidth());            matrix.postScale(scale, scale, centerX, centerY);            matrix.postRotate(90 * (rotation - 2), centerX, centerY);        } else if (Surface.ROTATION_180 == rotation) {            matrix.postRotate(180, centerX, centerY);        }        textureView.setTransform(matrix);    }    private void startBackgroundThread() {        mBackgroundThread = new HandlerThread("CameraBackground");        mBackgroundThread.start();        mBackgroundHandler = new Handler(mBackgroundThread.getLooper());    }    private void stopBackgroundThread() {        mBackgroundThread.quitSafely();        try {            mBackgroundThread.join();            mBackgroundThread = null;            mBackgroundHandler = null;        } catch (Exception e) {            e.printStackTrace();        }    }    private void openCamera() {        if (isOpened) {            return;        }        try {            if (!mCameraOpenCloseLock.tryAcquire(4, TimeUnit.SECONDS))                throw new RuntimeException("Time out waiting to lock camera opening.");        } catch (InterruptedException e) {            e.printStackTrace();        }        isOpened = true;        CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);        try {            cameraId = manager.getCameraIdList()[0];//这个可能会有很多个,但是通常都是两个,第一个是后置,第二个是前置;            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);            assert map != null;            imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {                // TODO: Consider calling                //    ActivityCompat#requestPermissions                // here to request the missing permissions, and then overriding                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,                //                                          int[] grantResults)                // to handle the case where the user grants the permission. See the documentation                // for ActivityCompat#requestPermissions for more details.                return;            }            manager.openCamera(cameraId, new CameraDevice.StateCallback() {                @Override                public void onOpened(final CameraDevice camera) {                    mCameraDevice = camera;                    createCameraPreview(camera);                }                @Override                public void onDisconnected(CameraDevice camera) {                    camera.close();                    mCameraDevice = null;                }                @Override                public void onError(CameraDevice camera, int error) {                    camera.close();                    mCameraDevice = null;                }            }, mBackgroundHandler);     //这个指定其后台运行,如果直接UI线程也可以,直接填null        } catch (CameraAccessException e) {            e.printStackTrace();        }    }    protected void createCameraPreview(final CameraDevice cameraDevice) {        try {            if (null == cameraDevice) {                return;            }            final CaptureRequest.Builder captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);            SurfaceTexture texture = textureView.getSurfaceTexture();            texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());            Surface textureSurface = new Surface(texture);            captureRequestBuilder.addTarget(textureSurface);            switch(nOperation){                case 1:                    setUpImageReader();                    Surface imageSurface = mImageReader.getSurface();                    captureRequestBuilder.addTarget(imageSurface);                    List<Surface> surfaceList = Arrays.asList(textureSurface, imageSurface);                    createPhotoView(cameraDevice, surfaceList, captureRequestBuilder);                    break;                case 2:                    setUpMediaRecorder();                    Surface recorderSurface = mMediaRecorder.getSurface();                    captureRequestBuilder.addTarget(recorderSurface);                    List<Surface> surfaceList2 = Arrays.asList(textureSurface, recorderSurface);                    createVideoView(cameraDevice,surfaceList2,captureRequestBuilder);                    break;            }            /*List<Surface> surfaceList = Arrays.asList(textureSurface, recorderSurface);            cameraDevice.createCaptureSession(surfaceList, new CameraCaptureSession.StateCallback() {//配置要接受图像的surface                @Override                public void onConfigured(CameraCaptureSession cameraCaptureSession) {                    captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);                    try {                        cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);//成功配置后,便开始进行相机图像的监听                    } catch (CameraAccessException e) {                        e.printStackTrace();                    }                    mMediaRecorder.start();                }                @Override                public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {                }            }, null);*/        } catch (CameraAccessException e) {            e.printStackTrace();        }    }    /**     * 创建录像视图     *     * @param cameraDevice     * @param surfaceList     * @param captureRequestBuilder     */    private void createVideoView(final CameraDevice cameraDevice, List<Surface> surfaceList, final CaptureRequest.Builder captureRequestBuilder) {        try {            cameraDevice.createCaptureSession(surfaceList, new CameraCaptureSession.StateCallback() {//配置要接受图像的surface                @Override                public void onConfigured(CameraCaptureSession cameraCaptureSession) {                    captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);                    try {                        cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);//成功配置后,便开始进行相机图像的监听                    } catch (CameraAccessException e) {                        e.printStackTrace();                    }                    mMediaRecorder.start();                }                @Override                public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {                }            }, null);        } catch (CameraAccessException e) {            e.printStackTrace();        }    }    /**     * 初始化媒体类     */    private void setUpMediaRecorder() {        mMediaRecorder = new MediaRecorder();        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);        mMediaRecorder.setMaxFileSize(0);        mMediaRecorder.setOrientationHint(0);        mMediaRecorder.setOutputFile(CommonUtils.createFile(CommonUtils.getCurTime() + ".mp4").getAbsolutePath());        try {            mMediaRecorder.prepare();        } catch (IOException e) {            e.printStackTrace();        }    }    /**     * 创建拍照视图     *     * @param cameraDevice     * @param surface     * @param captureRequestBuilder     */    private void createPhotoView(final CameraDevice cameraDevice, List<Surface> surface, final CaptureRequest.Builder captureRequestBuilder) {        try {            mPreviewRequestBuilder = captureRequestBuilder;            mCameraDevice.createCaptureSession(surface, new CameraCaptureSession.StateCallback() {                @Override                public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {                    if (null == mCameraDevice) return;                    mCaptureSession = cameraCaptureSession;                    try {                        captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);                        setAutoFlash(captureRequestBuilder);                        mPreviewRequest = captureRequestBuilder.build();                        mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler);                    } catch (Exception e) {                        e.printStackTrace();                        Toast.makeText(AppContext.sApp, "开启相机预览失败,再试一次吧", Toast.LENGTH_LONG).show();                        // mFinishCalled = true;                        finish();                    }                }                @Override                public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {                    Toast.makeText(AppContext.sApp, "开启相机预览失败,再试一次吧", Toast.LENGTH_LONG).show();                    //mFinishCalled = true;                    finish();                }            }, null);        } catch (CameraAccessException e) {            e.printStackTrace();        }    }    /**     * 拍照的所需的对象资源     */    private void setUpImageReader() {        mImageReader = ImageReader.newInstance(imageDimension.getWidth(), imageDimension.getHeight(), ImageFormat.YUV_420_888, 10);        mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {            @Override            public void onImageAvailable(ImageReader reader) {                Image image = reader.acquireLatestImage();                if (image != null) {                    image.close();                }            }        }, mBackgroundHandler);    }    /**     * 设置闪光灯     *     * @param requestBuilder     */    private void setAutoFlash(CaptureRequest.Builder requestBuilder) {        try {            CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);            mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);            Boolean available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);            mFlashSupported = available == null ? false : available;            /**             * 若相机支持自动开启/关闭闪光灯,则使用. 否则闪光灯总是关闭的.             */            if (mFlashSupported)                requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);        } catch (CameraAccessException e) {            e.printStackTrace();        }    }    /**     * 拍照的回调     */    CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {        @Override        public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {            process(partialResult);        }        @Override        public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {            process(result);        }    };    /**     * 处理拍照的过程     *     * @param result     */    private void process(CaptureResult result) {        switch (mState) {            case STATE_PREVIEW: {   // We have nothing to do when the camera preview is working normally.                break;            }            case STATE_WAITING_LOCK: {                Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);                /**                 * 判断可以立即拍摄的autoFocusState增加到4.                 */                if (afState == null) {                    captureStillPicture();                } else if (CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED == afState ||                        CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||                        CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {                    // CONTROL_AE_STATE can be null on some devices                    Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);                    /**                     * 判断可以立即拍摄的autoExposureState增加到4.                     */                    if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED ||                            aeState == CaptureResult.CONTROL_AE_STATE_LOCKED ||                            aeState == CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED) {                        mState = STATE_PICTURE_TAKEN;                        captureStillPicture();                    } else {                        runPrecaptureSequence();                    }                }                break;            }            case STATE_WAITING_PRECAPTURE: {                // CONTROL_AE_STATE can be null on some devices                Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);                if (aeState == null ||                        aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||                        aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {                    mState = STATE_WAITING_NON_PRECAPTURE;                }                break;            }            case STATE_WAITING_NON_PRECAPTURE: {                // CONTROL_AE_STATE can be null on some devices                Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);                if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {                    mState = STATE_PICTURE_TAKEN;                    captureStillPicture();                }                break;            }        }    }    /**     * 捕获图片     */    private void captureStillPicture() {        try {            if (null == mCameraDevice) return;            // This is the CaptureRequest.Builder that we use to take a picture.            final CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);            captureBuilder.addTarget(mImageReader.getSurface());            // Use the same AE and AF modes as the preview.            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);            setAutoFlash(captureBuilder);            // Orientation            int rotation = getWindowManager().getDefaultDisplay().getRotation();            captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));            CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() {                @Override                public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {                    System.out.println("757----------------filepath:");                    unlockFocus();                }            };            mCaptureSession.stopRepeating();            mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);        } catch (Exception e) {            e.printStackTrace();        }    }    private void runPrecaptureSequence() {        try {            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);            mState = STATE_WAITING_PRECAPTURE;            mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);        } catch (Exception e) {            e.printStackTrace();        }    }    private int getOrientation(int rotation) {        return (ORIENTATIONS.get(rotation) + mSensorOrientation + 270) % 360;    }    /**     * 开始拍照     */    private void takePicture() {        try {            // This is how to tell the camera to lock focus.            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);            // Tell #mCaptureCallback to wait for the lock.            mState = STATE_WAITING_LOCK;            mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * 释放照相机     */    private void unlockFocus() {        try {            // Reset the auto-focus trigger            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);            setAutoFlash(mPreviewRequestBuilder);            mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);            // After this, the camera will go back to the normal state of preview.            mState = STATE_PREVIEW;            mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler);        } catch (Exception e) {            e.printStackTrace();        }    }    @Override    public void onResume() {        super.onResume();        startBackgroundThread();        if (textureView.isAvailable()) {            openCamera();        } else {            textureView.setSurfaceTextureListener(mSurfaceTextureListener);        }    }    @Override    protected void onPause() {        super.onPause();        releaseRes();        stopBackgroundThread();        finish();    }    @Override    protected void onDestroy() {        super.onDestroy();    }    private void releaseRes() {        try {            if (mCameraDevice != null) {                mCameraDevice.close();                mCameraDevice = null;            }            if (mMediaRecorder != null) {                mMediaRecorder.stop();                mMediaRecorder.reset();                mMediaRecorder.release();                mMediaRecorder = null;            }        } catch (Exception e) {            e.printStackTrace();        }    }}


布局文件:

<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <TextureView        android:id="@+id/texture_video_preview"        android:layout_width="match_parent"        android:layout_height="match_parent" />    <!--<ImageView        android:id="@+id/iv_video_button"        android:layout_width="50dp"        android:layout_height="50dp"        android:layout_gravity="center_horizontal|bottom"        android:layout_marginBottom="40dp"        android:src="@drawable/selector" />-->    <Button        android:id="@+id/button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:onClick="trigger"        android:layout_gravity="center_horizontal|bottom"        android:layout_marginBottom="40dp"        android:text="stop"/>    <Button        android:id="@+id/photo"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:onClick="trigger"        android:layout_gravity="left|bottom"        android:layout_marginBottom="40dp"        android:text="photo"/></FrameLayout>

测试方法:

private void photo(){   /* Intent intent;    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {        intent = new Intent(MainActivity.this, PhotoActivity.class);        intent.putExtra("type",1);    } else {        System.out.println("权限不够");        return;    }    //文件保存的路径和名称    //intent.putExtra("file", mFile.toString());    //拍照时的提示文本    // intent.putExtra("hint", "请将证件放入框内。将裁剪图片,只保留框内区域的图像");    //是否使用整个画面作为取景区域(全部为亮色区域)    // intent.putExtra("hideBounds", true);    //最大允许的拍照尺寸(像素数)    //intent.putExtra("maxPicturePixels", 3840 * 2160);    startActivityForResult(intent, AppContext.TAKE_PHOTO_CUSTOM);*/    Intent intent = new Intent(MainActivity.this, VideoActivity.class);    intent.putExtra("type",1);    startActivity(intent);}private void vedioTape(){    Intent intent = new Intent(MainActivity.this, VideoActivity.class);    intent.putExtra("type",2);    startActivity(intent);}




0 0