美文网首页
android camera2 demo

android camera2 demo

作者: 简简单单敲代码 | 来源:发表于2018-05-09 16:26 被阅读100次

    android camera2 demo

    效果图


    package com.pepe.aplayer;
    
    import android.Manifest;
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.ImageFormat;
    import android.graphics.Rect;
    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.hardware.camera2.params.StreamConfigurationMap;
    import android.media.AudioAttributes;
    import android.media.Image;
    import android.media.ImageReader;
    import android.media.Ringtone;
    import android.media.RingtoneManager;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.Handler;
    import android.os.HandlerThread;
    import android.os.Message;
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.app.Fragment;
    import android.support.v4.content.ContextCompat;
    import android.util.Log;
    import android.util.Size;
    import android.view.LayoutInflater;
    import android.view.Surface;
    import android.view.TextureView;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Button;
    import android.widget.ImageView;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
    
    public class AFragment extends Fragment {
        private static final String TAG = "Camera2Fragment";
        private static final int SETIMAGE = 1;
        private static final int MOVE_FOCK = 2;
        /**
         * Max preview width that is guaranteed by Camera2 API
         */
        private static final int MAX_PREVIEW_WIDTH = 1920;
    
        /**
         * Max preview height that is guaranteed by Camera2 API
         */
        private static final int MAX_PREVIEW_HEIGHT = 1080;
    
        private TextureView mTextureView;
        private ImageView mThumbnail;
        private Button mButton;
        private Handler mHandler;
        private Handler mUIHandler;
        private ImageReader mImageReader;
        private CaptureRequest.Builder mPreViewBuidler;
        private CameraCaptureSession mCameraSession;
        private CameraCharacteristics mCameraCharacteristics;
        private Ringtone ringtone;
        private Surface surface;
        private Size mPreViewSize;
        private Rect maxZoomrect;
        private int maxRealRadio;
        //相机缩放相关
        private Rect picRect;
    
    
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
                savedInstanceState) {
            View v = inflater.inflate(R.layout.activity_main, container,false);
            findView(v);
            mUIHandler = new Handler(new InnerCallBack());
            //初始化拍照的声音
            ringtone = RingtoneManager.getRingtone(getActivity(), Uri.parse
                    ("file:///system/media/audio/ui/camera_click.ogg"));
            AudioAttributes.Builder attr = new AudioAttributes.Builder();
            attr.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION);
            ringtone.setAudioAttributes(attr.build());
            //初始化相机布局
            mTextureView.setSurfaceTextureListener(mSurfacetextlistener);
    //        mTextureView.setOnTouchListener(textTureOntuchListener);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                int i = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
                if (i != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(getActivity(),
                            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE},
                            111);
                }
            }
            return v;
        }
    
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            if (mCameraSession != null) {
                mCameraSession.getDevice().close();
                mCameraSession.close();
            }
        }
    
        private void findView(View v) {
            mTextureView = v.findViewById(R.id.tv_textview);
            mButton = v.findViewById(R.id.btn_takepic);
            mThumbnail = v.findViewById(R.id.iv_Thumbnail);
            mThumbnail.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                        //调用相册
                        Intent intent = new Intent(Intent.ACTION_PICK,
                                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                        startActivity(intent);
                }
            });
        }
    
    
    
        //打开相机时候的监听器,通过他可以得到相机实例,这个实例可以创建请求建造者
        private CameraDevice.StateCallback cameraOpenCallBack = new CameraDevice.StateCallback() {
            @Override
            public void onOpened(CameraDevice cameraDevice) {
                Log.d(TAG, "相机已经打开");
                try {
                    mPreViewBuidler = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                    SurfaceTexture texture = mTextureView.getSurfaceTexture();
                    texture.setDefaultBufferSize(mPreViewSize.getWidth(), mPreViewSize.getHeight());
                    surface = new Surface(texture);
                    mPreViewBuidler.addTarget(surface);
                    cameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface
                            ()), new CameraCaptureSession
                            .StateCallback() {
                        @Override
                        public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                            try {
                                mCameraSession = cameraCaptureSession;
                                cameraCaptureSession.setRepeatingRequest(mPreViewBuidler.build(), null, mHandler);
                            } catch (CameraAccessException e) {
                                e.printStackTrace();
                            }
                        }
    
                        @Override
                        public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
    
                        }
                    }, mHandler);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onDisconnected(@NonNull CameraDevice cameraDevice) {
                Log.d(TAG, "相机连接断开");
            }
    
            @Override
            public void onError(@NonNull CameraDevice cameraDevice, int i) {
                Log.d(TAG, "相机打开失败");
            }
        };
    
        //预览图显示控件的监听器,可以监听这个surface的状态
        private TextureView.SurfaceTextureListener mSurfacetextlistener = new TextureView
                .SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
                HandlerThread thread = new HandlerThread("Ceamera3");
                thread.start();
                mHandler = new Handler(thread.getLooper());
                CameraManager manager = (CameraManager) getActivity().getSystemService(Context
                        .CAMERA_SERVICE);
                String cameraid = CameraCharacteristics.LENS_FACING_FRONT + "";
                try {
                    mCameraCharacteristics = manager.getCameraCharacteristics(cameraid);
    
                    //画面传感器的面积,单位是像素。
                    maxZoomrect = mCameraCharacteristics.get(CameraCharacteristics
                            .SENSOR_INFO_ACTIVE_ARRAY_SIZE);
                    //最大的数字缩放
                    maxRealRadio = mCameraCharacteristics.get(CameraCharacteristics
                            .SCALER_AVAILABLE_MAX_DIGITAL_ZOOM).intValue();
                    picRect = new Rect(maxZoomrect);
    
                    StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics
                            .SCALER_STREAM_CONFIGURATION_MAP);
                    Size largest = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)
                    ), new CompareSizeByArea());
                    mPreViewSize = map.getOutputSizes(SurfaceTexture.class)[0];
                    choosePreSize(i, i1, map, largest);
                    mImageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(),
                            ImageFormat.JPEG, 5);
                    mImageReader.setOnImageAvailableListener(new ImageReader
                            .OnImageAvailableListener() {
                        @Override
                        public void onImageAvailable(ImageReader imageReader) {
                            mHandler.post(new ImageSaver(imageReader.acquireNextImage()));
                        }
                    }, mHandler);
                    if (ActivityCompat.checkSelfPermission(getActivity(), 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, cameraOpenCallBack, mHandler);
                    //设置点击拍照的监听
                    mButton.setOnClickListener(picOnClickListener);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }
    
            private void choosePreSize(int i, int i1, StreamConfigurationMap map, Size largest) {
                int displayRotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
                //noinspection ConstantConditions
                Integer mSensorOrientation = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
                boolean swappedDimensions = false;
                switch (displayRotation) {
                    case Surface.ROTATION_0:
                    case Surface.ROTATION_180:
                        if (mSensorOrientation == 90 || mSensorOrientation == 270) {
                            swappedDimensions = true;
                        }
                        break;
                    case Surface.ROTATION_90:
                    case Surface.ROTATION_270:
                        if (mSensorOrientation == 0 || mSensorOrientation == 180) {
                            swappedDimensions = true;
                        }
                        break;
                    default:
                        Log.e(TAG, "Display rotation is invalid: " + displayRotation);
                }
                android.graphics.Point displaySize = new android.graphics.Point();
                getActivity().getWindowManager().getDefaultDisplay().getSize(displaySize);
                int rotatedPreviewWidth = i;
                int rotatedPreviewHeight = i1;
                int maxPreviewWidth = displaySize.x;
                int maxPreviewHeight = displaySize.y;
    
                if (swappedDimensions) {
                    rotatedPreviewWidth = i1;
                    rotatedPreviewHeight = i;
                    maxPreviewWidth = displaySize.x;
                    maxPreviewHeight = displaySize.y;
                }
    
                if (maxPreviewWidth > MAX_PREVIEW_WIDTH) {
                    maxPreviewWidth = MAX_PREVIEW_WIDTH;
                }
    
                if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) {
                    maxPreviewHeight = MAX_PREVIEW_HEIGHT;
                }
                mPreViewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
                        rotatedPreviewWidth, rotatedPreviewHeight, maxPreviewWidth,
                        maxPreviewHeight, largest);
            }
    
            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
    
            }
    
            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
                return false;
            }
    
            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
    
            }
    
            private Size chooseOptimalSize(Size[] choices, int textureViewWidth,
                                           int textureViewHeight, int maxWidth, int maxHeight, Size aspectRatio) {
    
                // Collect the supported resolutions that are at least as big as the preview Surface
                List<Size> bigEnough = new ArrayList<>();
                // Collect the supported resolutions that are smaller than the preview Surface
                List<Size> notBigEnough = new ArrayList<>();
                int w = aspectRatio.getWidth();
                int h = aspectRatio.getHeight();
                for (Size option : choices) {
                    if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight &&
                            option.getHeight() == option.getWidth() * 3 / 4) {
                        if (option.getWidth() >= textureViewWidth &&
                                option.getHeight() >= textureViewHeight) {
                            bigEnough.add(option);
                        } else {
                            notBigEnough.add(option);
                        }
                    }
                }
    
                // Pick the smallest of those big enough. If there is no one big enough, pick the
                // largest of those not big enough.
                if (bigEnough.size() > 0) {
                    return Collections.min(bigEnough, new CompareSizeByArea());
                } else if (notBigEnough.size() > 0) {
                    return Collections.max(notBigEnough, new CompareSizeByArea());
                } else {
                    Log.e(TAG, "Couldn't find any suitable preview size");
                    return choices[0];
                }
            }
        };
    
    //    private View.OnTouchListener onTouchListener = new View.OnTouchListener() {
    //        @Override
    //        public boolean onTouch(View v, MotionEvent event) {
    //            switch (event.getAction()) {
    //                case MotionEvent.ACTION_DOWN:
    //                    try {
    //                        mCameraSession.setRepeatingRequest(initDngBuilder().build(), null, mHandler);
    //                    } catch (CameraAccessException e) {
    //                        Toast.makeText(getActivity(), "请求相机权限被拒绝", Toast.LENGTH_SHORT).show();
    //                    }
    //                    break;
    //                case MotionEvent.ACTION_UP:
    //                    try {
    //                        updateCameraPreviewSession();
    //                    } catch (CameraAccessException e) {
    //                        Toast.makeText(getActivity(), "请求相机权限被拒绝", Toast.LENGTH_SHORT).show();
    //                    }
    //                    break;
    //            }
    //            return true;
    //        }
    //    };
    
    //    private void updateCameraPreviewSession() throws CameraAccessException {
    //        mPreViewBuidler.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
    //        mPreViewBuidler.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
    //        mCameraSession.setRepeatingRequest(mPreViewBuidler.build(), null, mHandler);
    //    }
    
    //    /**
    //     * 设置连拍参数
    //     *
    //     * @return
    //     */
    //    private CaptureRequest.Builder initDngBuilder() {
    //        CaptureRequest.Builder captureBuilder = null;
    //        try {
    //            captureBuilder = mCameraSession.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
    //
    //            captureBuilder.addTarget(mImageReader.getSurface());
    //            captureBuilder.addTarget(surface);
    //            // Required for RAW capture
    //            captureBuilder.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE, CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_ON);
    //            captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
    //            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
    //            captureBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, (long) ((214735991 - 13231) / 2));
    //            captureBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
    ////            captureBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, (10000 - 100) / 2);//设置 ISO,感光度
    //            captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, 90);
    //            //设置每秒30帧
    //            CameraManager cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
    //            String cameraid = CameraCharacteristics.LENS_FACING_FRONT + "";
    //            CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraid);
    //            Range<Integer> fps[] = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
    //            captureBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fps[fps.length - 1]);
    //        } catch (CameraAccessException e) {
    //            Toast.makeText(getActivity(), "请求相机权限被拒绝", Toast.LENGTH_SHORT).show();
    //        } catch (NullPointerException e) {
    //            Toast.makeText(getActivity(), "打开相机失败", Toast.LENGTH_SHORT).show();
    //        }
    //        return captureBuilder;
    //    }
    
        private View.OnClickListener picOnClickListener = new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    shootSound();
                    Log.d(TAG, "正在拍照");
                    CaptureRequest.Builder builder = mCameraSession.getDevice().createCaptureRequest
                            (CameraDevice.TEMPLATE_STILL_CAPTURE);
                    builder.addTarget(mImageReader.getSurface());
    //                builder.set(CaptureRequest.SCALER_CROP_REGION, picRect);
    //                builder.set(CaptureRequest.CONTROL_AF_MODE,
    //                        CaptureRequest.CONTROL_AF_MODE_EDOF);
    //                builder.set(CaptureRequest.SENSOR_SENSITIVITY, (10000 - 100) / 2);//设置 ISO,感光度
    //                builder.set(CaptureRequest.CONTROL_AF_TRIGGER,
    //                        CameraMetadata.CONTROL_AF_TRIGGER_START);
    //                builder.set(CaptureRequest.JPEG_ORIENTATION, 90);
                    mCameraSession.capture(builder.build(), null, mHandler);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }
        };
    //    private View.OnTouchListener textTureOntuchListener = new View.OnTouchListener() {
    //        //时时当前的zoom
    //        public double zoom;
    //        // 0<缩放比<mCameraCharacteristics.get(CameraCharacteristics
    //        // .SCALER_AVAILABLE_MAX_DIGITAL_ZOOM).intValue();
    //        //上次缩放前的zoom
    //        public double lastzoom;
    //        //两个手刚一起碰到手机屏幕的距离
    //        public double lenth;
    //        int count;
    //
    //        @Override
    //        public boolean onTouch(View v, MotionEvent event) {
    //            switch (event.getAction() & MotionEvent.ACTION_MASK) {
    //                case MotionEvent.ACTION_DOWN:
    //                    count = 1;
    //                    break;
    //                case MotionEvent.ACTION_MOVE:
    //                    if (count >= 2) {
    //                        float x1 = event.getX(0);
    //                        float y1 = event.getY(0);
    //                        float x2 = event.getX(1);
    //                        float y2 = event.getY(1);
    //                        float x = x1 - x2;
    //                        float y = y1 - y2;
    //                        Double lenthRec = Math.sqrt(x * x + y * y) - lenth;
    //                        Double viewLenth = Math.sqrt(v.getWidth() * v.getWidth() + v.getHeight()
    //                                * v.getHeight());
    //                        zoom = ((lenthRec / viewLenth) * maxRealRadio) + lastzoom;
    //                        picRect.top = (int) (maxZoomrect.top / (zoom));
    //                        picRect.left = (int) (maxZoomrect.left / (zoom));
    //                        picRect.right = (int) (maxZoomrect.right / (zoom));
    //                        picRect.bottom = (int) (maxZoomrect.bottom / (zoom));
    //                        Message.obtain(mUIHandler, MOVE_FOCK).sendToTarget();
    //                    }
    //                    break;
    //                case MotionEvent.ACTION_UP:
    //                    count = 0;
    //                    break;
    //                case MotionEvent.ACTION_POINTER_DOWN:
    //                    count++;
    //                    if (count == 2) {
    //                        float x1 = event.getX(0);
    //                        float y1 = event.getY(0);
    //                        float x2 = event.getX(1);
    //                        float y2 = event.getY(1);
    //                        float x = x1 - x2;
    //                        float y = y1 - y2;
    //                        lenth = Math.sqrt(x * x + y * y);
    //                    }
    //                    break;
    //                case MotionEvent.ACTION_POINTER_UP:
    //                    count--;
    //                    if (count < 2)
    //                        lastzoom = zoom;
    //                    break;
    //            }
    //            return true;
    //        }
    //    };
    //
    
    
        /**
         * 播放系统的拍照的声音
         */
        public void shootSound() {
            ringtone.stop();
            ringtone.play();
        }
    
        private class ImageSaver implements Runnable {
            Image reader;
    
            public ImageSaver(Image reader) {
                this.reader = reader;
            }
    
            @Override
            public void run() {
                Log.d(TAG, "正在保存图片");
                File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
                        .getAbsoluteFile();
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File file = new File(dir, System.currentTimeMillis() + ".jpg");
                FileOutputStream outputStream = null;
                try {
                    outputStream = new FileOutputStream(file);
                    ByteBuffer buffer = reader.getPlanes()[0].getBuffer();
                    byte[] buff = new byte[buffer.remaining()];
                    buffer.get(buff);
                    BitmapFactory.Options ontain = new BitmapFactory.Options();
                    ontain.inSampleSize = 50;
                    Bitmap bm = BitmapFactory.decodeByteArray(buff, 0, buff.length, ontain);
                    Message.obtain(mUIHandler, SETIMAGE, bm).sendToTarget();
                    outputStream.write(buff);
                    Log.d(TAG, "保存图片完成");
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (reader != null) {
                        reader.close();
                    }
                    if (outputStream != null) {
                        try {
                            outputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    
        private class InnerCallBack implements Handler.Callback {
            @Override
            public boolean handleMessage(Message message) {
                switch (message.what) {
                    case SETIMAGE:
                        Bitmap bm = (Bitmap) message.obj;
                        mThumbnail.setImageBitmap(bm);
                        break;
                    case MOVE_FOCK:
                        mPreViewBuidler.set(CaptureRequest.SCALER_CROP_REGION, picRect);
                        try {
                            mCameraSession.setRepeatingRequest(mPreViewBuidler.build(), null,
                                    mHandler);
                        } catch (CameraAccessException e) {
                            e.printStackTrace();
                        }
                        break;
                }
                return false;
            }
        }
    
        class CompareSizeByArea implements java.util.Comparator<Size> {
            @Override
            public int compare(Size lhs, Size rhs) {
                // We cast here to ensure the multiplications won't overflow
                return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
                        (long) rhs.getWidth() * rhs.getHeight());
            }
        }
    }
    
    

    demo 地址

    相关文章

      网友评论

          本文标题:android camera2 demo

          本文链接:https://www.haomeiwen.com/subject/gqcorftx.html