Android camera2 使用方法

    private TextureView textureview;
    private Camera2 camera;

    protected void onCreate(@Nullable Bundle savedInstanceState) {
             textureview = findViewById(R.id.textureview);

//進入這個頁面之前要申請相機權限
             camera = new Camera2(textureview, this, new Camera.OnCameraListener() {
                  @Override
                   public void onCall(Bitmap bitmap) {
                          //拍照的bitmap
                    }
              });

            findViewById(R.id.btn).setOnClickListener(new OnClickLimitListener() {
                    @Override
                    public void click(View v) {
                        Log.d(TAG, "click: 拍照");
                        camera.takePic();
                    }
        });
   }

import android.Manifest;
import android.app.Activity;
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.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


public class Camera {

    private Activity mActivity;
    private TextureView mTextureView;
    private HandlerThread handlerThread;
    private CameraManager mCameraManager;
    private ImageReader mImageReader;
    private CameraDevice mCameraDevice;
    private CameraCaptureSession mCameraCaptureSession;
    private String mCameraId;
    private CameraCharacteristics mCameraCharacteristics;
    private int mCameraSensorOrientation;
    private boolean canTakePic;
    private Handler mCameraHandler;
    private Size mPreviewSize;
    private Size mSavePicSize;
    private ImageReader.OnImageAvailableListener onImageAvailableListener;
    private CameraCaptureSession.CaptureCallback mCaptureCallBack;

    public Camera(TextureView textureView, Activity activity, OnCameraListener listener) {
        mTextureView = textureView;
        mActivity = activity;
        handlerThread = new HandlerThread("CameraThread");
        handlerThread.start();
        mCameraHandler = new Handler(handlerThread.getLooper());

        mPreviewSize = new Size(720, 1280);
        mSavePicSize = new Size(720, 1280);

        onImageAvailableListener = new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                Image image = reader.acquireNextImage();
                ByteBuffer byteBuffer = image.getPlanes()[0].getBuffer();
                byte[] byteArray = new byte[byteBuffer.remaining()];
                byteBuffer.get(byteArray);
                image.close();

                Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
                listener.onCall(bitmap);
            }
        };
        mCaptureCallBack = new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                super.onCaptureCompleted(session, request, result);
                canTakePic = true;
            }
        };

        textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
                initInfo();
            }

            @Override
            public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {

            }

            @Override
            public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
                release();
                return true;
            }

            @Override
            public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {

            }
        });

    }

    public void release() {
        if (mCameraCaptureSession != null) {
            mCameraCaptureSession.close();
            mCameraCaptureSession = null;
        }
        if (mCameraDevice != null) {
            mCameraDevice.close();
            mCameraDevice = null;
        }
        if (mImageReader != null) {
            mImageReader.close();
            mImageReader = null;
        }
    }

    private void initInfo() {
        try {
            mCameraManager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
            String[] cameraIdList = mCameraManager.getCameraIdList();
            if (cameraIdList == null || cameraIdList.length == 0) {
                Toast.makeText(mActivity, "沒有可用相機", Toast.LENGTH_SHORT).show();
                return;
            }

            for (int i = 0; i < cameraIdList.length; i++) {
                String id = cameraIdList[i];
                CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics(id);
                Integer integer = cameraCharacteristics.get(CameraCharacteristics.LENS_FACING);
                if (integer == CameraCharacteristics.LENS_FACING_BACK ) {
                    mCameraId = id;
                    mCameraCharacteristics = cameraCharacteristics;
                }
            }

            mCameraSensorOrientation = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
            StreamConfigurationMap configurationMap = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            if (configurationMap != null) {
                Size[] savePicSize = configurationMap.getOutputSizes(ImageFormat.JPEG);
                Size[] previewSize = configurationMap.getOutputSizes(SurfaceTexture.class);

                int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
                boolean exchange = exchangeWidthAndHeight(rotation, mCameraSensorOrientation);


                mSavePicSize = getBestSize(
                        exchange ? mSavePicSize.getHeight() : mSavePicSize.getWidth(),
                        exchange ? mSavePicSize.getWidth() : mSavePicSize.getHeight(),
                        exchange ? mSavePicSize.getHeight() : mSavePicSize.getWidth(),
                        exchange ? mSavePicSize.getWidth() : mSavePicSize.getHeight(),
                        Arrays.asList(savePicSize));

                mPreviewSize = getBestSize(
                        exchange ? mPreviewSize.getHeight() : mPreviewSize.getWidth(),
                        exchange ? mPreviewSize.getWidth() : mPreviewSize.getHeight(),
                        exchange ? mTextureView.getHeight() : mTextureView.getWidth(),
                        exchange ? mTextureView.getWidth() : mTextureView.getHeight(),
                        Arrays.asList(previewSize));


                mTextureView.getSurfaceTexture().setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
                mImageReader = ImageReader.newInstance(mSavePicSize.getWidth(), mSavePicSize.getHeight(), ImageFormat.JPEG, 1);
                mImageReader.setOnImageAvailableListener(onImageAvailableListener, mCameraHandler);
                openCamera();
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void openCamera() {

        if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(mActivity, "沒有相機權限!", Toast.LENGTH_SHORT).show();
            return;
        }

        try {
            mCameraManager.openCamera(mCameraId, new CameraDevice.StateCallback() {
                @Override
                public void onOpened(CameraDevice camera) {
                    mCameraDevice = camera;
                    createCaptureSession(camera);
                }

                @Override
                public void onDisconnected(CameraDevice camera) {
                }

                @Override
                public void onError(CameraDevice camera, int error) {
                }
            }, mCameraHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void createCaptureSession(CameraDevice cameraDevice) {
        try {
            CaptureRequest.Builder captureRequest = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            Surface surface = new Surface(mTextureView.getSurfaceTexture());
            captureRequest.addTarget(surface);
            captureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            captureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);

            cameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigureFailed(CameraCaptureSession session) {
                    Toast.makeText(mActivity, "開啟預覽會話失敗缕陕!", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onConfigured(CameraCaptureSession session) {
                    mCameraCaptureSession = session;
                    try {
                        session.setRepeatingRequest(captureRequest.build(), mCaptureCallBack, mCameraHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

            }, mCameraHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private boolean exchangeWidthAndHeight(int displayRotation, int sensorOrientation) {
        boolean exchange = false;
        if (displayRotation == Surface.ROTATION_0 || displayRotation == Surface.ROTATION_180) {
            if (sensorOrientation == 90 || sensorOrientation == 270) {
                exchange = true;
            } else if (sensorOrientation == 0 || sensorOrientation == 180) {
                exchange = true;
            }
        }
        return exchange;
    }

    private Size getBestSize(int targetWidth, int targetHeight, int maxWidth, int maxHeight, List<Size> sizeList) {
        List<Size> bigEnough = new ArrayList<>();
        List<Size> notBigEnough = new ArrayList<>();

        for (Size size : sizeList) {
            if (size.getWidth() <= maxWidth && size.getHeight() <= maxHeight && size.getWidth() == size.getHeight() * targetWidth / targetHeight) {
                if (size.getWidth() >= targetWidth && size.getHeight() >= targetHeight)
                    bigEnough.add(size);
                else {
                    notBigEnough.add(size);
                }
            }
        }
        if (bigEnough.size() > 0) {
            return Collections.min(bigEnough, new CompareSizesByArea());
        } else if (notBigEnough.size() > 0) {
            return Collections.max(notBigEnough, new CompareSizesByArea());
        }
        return sizeList.get(0);
    }

    /**
     * 拍照
     */
    public void takePic() {
        if (mCameraDevice == null || !mTextureView.isAvailable() || !canTakePic) {
            return;
        }

        if (mCameraDevice != null) {
            try {
                CaptureRequest.Builder captureRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
                captureRequest.addTarget(mImageReader.getSurface());
                captureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                captureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                captureRequest.set(CaptureRequest.JPEG_ORIENTATION, mCameraSensorOrientation);
                mCameraCaptureSession.capture(captureRequest.build(), null, mCameraHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
                Toast.makeText(mActivity, "拍照異常撬即!", Toast.LENGTH_SHORT).show();
            }
        }
    }

    class CompareSizesByArea implements Comparator<Size> {
        @Override
        public int compare(Size size1, Size size2) {
            return java.lang.Long.signum(
                    size1.getWidth() * size1.getHeight() -
                            size2.getWidth() * size2.getHeight());
        }
    }

    public interface OnCameraListener {
        void onCall(Bitmap bitmap);
    }
}
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市茴丰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖骑疆,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異替废,居然都是意外死亡箍铭,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門椎镣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诈火,“玉大人,你說我怎么就攤上這事状答±涫兀” “怎么了刀崖?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長教沾。 經(jīng)常有香客問我蒲跨,道長,這世上最難降的妖魔是什么授翻? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任或悲,我火速辦了婚禮,結(jié)果婚禮上堪唐,老公的妹妹穿的比我還像新娘巡语。我一直安慰自己,他們只是感情好淮菠,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布男公。 她就那樣靜靜地躺著,像睡著了一般合陵。 火紅的嫁衣襯著肌膚如雪枢赔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天拥知,我揣著相機與錄音踏拜,去河邊找鬼。 笑死低剔,一個胖子當著我的面吹牛速梗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播襟齿,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼姻锁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了猜欺?” 一聲冷哼從身側(cè)響起位隶,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎开皿,沒想到半個月后涧黄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡副瀑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年弓熏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片糠睡。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡挽鞠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情信认,我是刑警寧澤材义,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站嫁赏,受9級特大地震影響其掂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜潦蝇,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一款熬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧攘乒,春花似錦贤牛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至沽讹,卻和暖如春般卑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爽雄。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工蝠检, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盲链。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓蝇率,卻偏偏與公主長得像迟杂,于是被迫代替她去往敵國和親刽沾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361