android 摄像头的调用

来源:互联网 发布:网络电视机顶盒哪个牌子好 编辑:程序博客网 时间:2024/05/22 00:48

记录一下自己写的camera2 Demo

布局文件:
TextureView 预览
ImageView 显示照片
Button 点击拍照

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <TextureView        android:id="@+id/textureView"        android:layout_width="match_parent"        android:layout_height="match_parent" />    <ImageView        android:id="@+id/iv_show_camera2_activity"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:visibility="visible"        android:layout_centerInParent="true"        android:scaleType="centerCrop" />    <Button        android:id="@+id/take"        android:layout_width="100dp"        android:layout_height="50dp"        android:text="拍照"        android:layout_centerHorizontal="true"        android:layout_alignParentBottom="true"        android:layout_marginBottom="30dp"/></RelativeLayout>

MainActivity.class

import android.Manifest;import android.content.Context;import android.content.pm.PackageManager;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.ImageFormat;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.CaptureRequest;import android.media.Image;import android.media.ImageReader;import android.os.Build;import android.os.Handler;import android.os.HandlerThread;import android.support.annotation.NonNull;import android.support.annotation.RequiresApi;import android.support.v4.app.ActivityCompat;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.util.SparseIntArray;import android.view.Surface;import android.view.TextureView;import android.view.View;import android.widget.Button;import android.widget.ImageView;import android.widget.Toast;import java.nio.ByteBuffer;import java.util.Arrays;import java.util.concurrent.Semaphore;import java.util.concurrent.TimeUnit;@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)public class MainActivity extends AppCompatActivity {    private final static String TAG = "tsb";    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();    //在关闭摄像机之前阻止应用程序退出的{链接信号量}。    private Semaphore mCameraOpenCloseLock = new Semaphore(1);    ///为了使照片竖直显示    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);    }    //预览textureView    private TextureView textureView;    //摄像头管理器    private CameraManager mCameraManager;    //摄像头id 通常0代表后置摄像头,1代表前置摄像头    private String mCameraID;    //处理静态图像捕获    private ImageReader mImageReader;    private CameraCaptureSession mCameraCaptureSession;    private CameraDevice mCameraDevice;    private CaptureRequest.Builder previewBuilder;    private CaptureRequest.Builder pictureBuilder;    private HandlerThread mHandlerThread;    private Handler childHandler;    private Button button;    private ImageView imageView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //查看是否拥有摄像头权限 没有就申请        if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},100);        }        button = (Button)findViewById(R.id.button);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {                    Toast.makeText(MainActivity.this,"没有照相机权限",Toast.LENGTH_LONG).show();                    return;                }                if (button.getText().equals("拍照")) {                    takePicture();                    button.setText("返回");                }                else{                    button.setText("拍照");                    imageView.setVisibility(View.GONE);                    textureView.setVisibility(View.VISIBLE);                }            }        });        imageView = (ImageView) findViewById(R.id.imageView);        textureView = (TextureView) findViewById(R.id.textureView);        textureView.setSurfaceTextureListener(surfaceTextureListener);    }    //TextureView 监听事件    TextureView.SurfaceTextureListener surfaceTextureListener = new TextureView.SurfaceTextureListener() {        @Override        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {            openCamera();        }        @Override        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {        }        @Override        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {            return false;        }        @Override        public void onSurfaceTextureUpdated(SurfaceTexture surface) {        }    };    /**     * 打开摄像头     */    private void openCamera() {        if (mHandlerThread == null){            mHandlerThread = new HandlerThread("Camera2");            mHandlerThread.start();            childHandler = new Handler(mHandlerThread.getLooper());        }        if (mImageReader == null){            mImageReader = ImageReader.newInstance(1080, 1920, ImageFormat.JPEG, 3);            mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {             //可以在这里处理拍照得到的临时照片 例如,写入本地                @Override                public void onImageAvailable(ImageReader reader) {                    // 拿到拍照照片数据                    Image image = null;                    try{                        image = reader.acquireLatestImage();                        final Bitmap bitmap = imageToBitmap(image);                        if (bitmap != null) {                            runOnUiThread(new Runnable() {                                @Override                                public void run() {                                    textureView.setVisibility(View.GONE);                                    imageView.setVisibility(View.VISIBLE);                                    imageView.setImageBitmap(bitmap);                                }                            });                        }                    }catch (Exception e){                        e.printStackTrace();                    }finally {                        if (image!=null){                            image.close();                            image = null;                        }                    }                }            }, childHandler);        }        if (mCameraManager == null)            mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);        String cameraIds[] = {};        try {            //获取所有摄像头ID            cameraIds = mCameraManager.getCameraIdList();        } catch (CameraAccessException e) {            Log.e(TAG, "Cam access exception getting IDs", e);        }        if (cameraIds.length < 1) {            Log.e(TAG, "No cameras found");            return;        }        //通常0代表后置摄像头,1代表前置摄像头        mCameraID = cameraIds[0];        try {            if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {                throw new RuntimeException("Time out waiting to lock camera opening.");            }            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {                Log.e(TAG,"没有照相机权限");                return;            }else{                Log.e(TAG,"有照相机权限");            }            //开启摄像头            mCameraManager.openCamera(mCameraID, stateCallback, null);        } catch (CameraAccessException e) {            e.printStackTrace();        } catch (InterruptedException e) {            throw new RuntimeException("Interrupted while trying to lock camera opening.", e);        }    }    //摄像头监听事件    private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {        @Override        public void onOpened(@NonNull CameraDevice camera) {            mCameraOpenCloseLock.release();            //打开摄像头            mCameraDevice = camera;            takePreview();        }        @Override        public void onDisconnected(@NonNull CameraDevice camera) {            mCameraOpenCloseLock.release();            //关闭摄像头            if (null != mCameraDevice) {                mCameraDevice.close();                mImageReader.close();                mImageReader = null;            }            mCameraDevice = null;        }        @Override        public void onError(@NonNull CameraDevice camera, int error) {            mCameraOpenCloseLock.release();            mCameraDevice = null;            //有错误            Log.e(TAG,"摄像头开启失败");        }    };    /**     * 预览     */    private void takePreview() {        SurfaceTexture texture = textureView.getSurfaceTexture();        texture.setDefaultBufferSize(textureView.getWidth(), textureView.getHeight());        Surface surface = new Surface(texture);        try {            if (previewBuilder == null){                previewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);                previewBuilder.addTarget(surface);                // 自动对焦                previewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);                //   打开闪光灯                previewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);            }            mCameraDevice.createCaptureSession(Arrays.asList(surface,mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {                @Override                public void onConfigured(@NonNull CameraCaptureSession session) {                    if (mCameraDevice == null)                        return;                    mCameraCaptureSession = session;                    try {                        mCameraCaptureSession.setRepeatingRequest(previewBuilder.build(), null, childHandler);                    } catch (CameraAccessException e) {                        e.printStackTrace();                    }                }                @Override                public void onConfigureFailed(@NonNull CameraCaptureSession session) {                    Log.e(TAG,"配置错误");                }            }, null);        } catch (CameraAccessException e) {            e.printStackTrace();        }    }    /**     * 拍照     */    private void takePicture(){        try {            if (pictureBuilder == null){                pictureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);                pictureBuilder.addTarget(mImageReader.getSurface());                // 自动对焦                pictureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);                //   打开闪光灯                pictureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);                int rotation = getWindowManager().getDefaultDisplay().getRotation();                // 根据设备方向计算设置照片的方向                pictureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));            }            mCameraCaptureSession.capture(pictureBuilder.build(), null, childHandler);        } catch (CameraAccessException e) {            e.printStackTrace();        }    }    /**     * 关闭摄像头     */    private void closeCamera(){        try{            mCameraOpenCloseLock.acquire();            if (mCameraCaptureSession !=null){                mCameraCaptureSession.close();                mCameraCaptureSession = null;            }            if (mCameraDevice!= null){                mCameraDevice.close();                mCameraDevice = null;            }            if (mImageReader !=null){                mImageReader.close();                mImageReader = null;            }            stopBackgroundThread();        }catch (Exception e){            e.printStackTrace();        }finally {            mCameraOpenCloseLock.release();        }    }    /**     * 停止线程     */    private void stopBackgroundThread(){       if (mHandlerThread !=null){           mHandlerThread.quitSafely();           try {               mHandlerThread.join();               mHandlerThread = null;               childHandler = null;           } catch (InterruptedException e) {               e.printStackTrace();           }       }    }    /**     * image转bitmap     * @param image     * @return     */    private Bitmap imageToBitmap(Image image){        ByteBuffer buffer = image.getPlanes()[0].getBuffer();        byte[] bytes = new byte[buffer.remaining()];        buffer.get(bytes);//由缓冲区存入字节数组        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);    }    @Override    protected void onPause() {        super.onPause();        closeCamera();    }    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        if (permissions[0].equals(Manifest.permission.CAMERA) && grantResults[0] == PackageManager.PERMISSION_GRANTED) {            closeCamera();            openCamera();        }    }}

注意:

  • TextureView初始化之后 执行 打开摄像头
mCameraManager.openCamera(mCameraID, stateCallback, null);
  • 打开摄像头之后 执行 预览
private void takePreview(){...}
  • 用文中拍照方法会出现卡顿

在textureView中已经预览,所以可以不用

mCameraCaptureSession.capture(pictureBuilder.build(), null, childHandler);

来拍照
可以直接用

textureView.getBitmap();

获取预览中的图片就OK了

CameraView

在网上有看到别人直接导入一个CameraView来实现预览以及拍照

首先导入

compile 'com.flurgle:camerakit:0.9.13'

在xml中调用

<com.flurgle.camerakit.CameraView        android:id="@+id/cameraView"        android:layout_width="300dp"        android:layout_height="300dp"        android:layout_gravity="center|top" />

在java文件中

CameraView cameraView = (CameraView) findViewById(R.id.cameraView);cameraView.setCameraListener(new CameraListener() {    @Override    public void onPictureTaken(byte[] picture) {    super.onPictureTaken(picture);    //拍到照片处理    Bitmap bitmap = BitmapFactory.decodeByteArray(picture, 0, picture.length)    }});//换摄像头cameraView.toggleFacing();//拍照cameraView.captureImage();