Android 编程开发之camera2
程序员文章站
2022-07-03 20:28:14
Android 编程开发之camera2。
布局只用到了SurfaceView跟Button。有的手机黑屏,需要给SurfaceViewHolder设置FixedSize。...
Android 编程开发之camera2。
布局只用到了SurfaceView跟Button。有的手机黑屏,需要给SurfaceViewHolder设置FixedSize。
public class CameraActivity extends AppCompatActivity implements SurfaceHolder.Callback { private SurfaceView mCameraSurfaceView; private SurfaceHolder mSurfaceHolder; //相机相关代码,三个必须的 private CameraManager mCameraManager; private CameraDevice mCameraDevice; private CameraCaptureSession mCameraCaptureSession; //阻止相机关闭前退出app private Semaphore mCameraOpenCloseLock = new Semaphore(1); //摄像头id 0:后摄像头 1:前摄像头 private static final String mCameraId = "" + CameraCharacteristics.LENS_FACING_FRONT; //opencamera方法中需要ImageReader和handler private ImageReader mImageReader; private Handler mHandler; private Size previewsize; private ImageReader.OnImageAvailableListener mImageAvailableListenter = new ImageReader.OnImageAvailableListener() { @SuppressLint("NewApi") @Override public void onImageAvailable(ImageReader reader) { mCameraDevice.close(); //这里获取到图片数据 …… } }; private 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); } /** * 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; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); initView(); initSurfaceView(); } private void initView() { mCameraSurfaceView = (SurfaceView) findViewById(R.id.camera_surfaceview); mFrameIv = (ImageView) findViewById(R.id.frame_imageview); mTakePhotoBt = (Button) findViewById(R.id.takephoto_bt); mFocusView = findViewById(R.id.focus_index); } private void initSurfaceView() { mCameraSurfaceView.setBackgroundColor(TRIM_MEMORY_BACKGROUND); mSurfaceHolder = mCameraSurfaceView.getHolder(); mSurfaceHolder.setKeepScreenOn(true); mSurfaceHolder.addCallback(this); } @Override protected void onResume() { mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); //这里可以设置也可以不设置,使用过程中发现有的手机不设置这个时会出现黑屏现象 mSurfaceHolder.setFixedSize(800, 600); super.onResume(); } @Override public void surfaceCreated(SurfaceHolder holder) { //不设置holder的Fixedsize时设置initCamera2(mCameraSurfaceView.getWidth(),mCameraSurfaceView.getHeight()); initCamera2(800, 600); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @SuppressLint("NewApi") @Override public void surfaceDestroyed(SurfaceHolder holder) { if (mCameraDevice != null) { mCameraDevice.close(); } } @SuppressLint("NewApi") private void initCamera2(int width, int height) { if (checkCameraPermission()) { try { String camerId = mCameraManager.getCameraIdList()[0]; CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(camerId); StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); previewsize = map.getOutputSizes(SurfaceTexture.class)[0]; HandlerThread handlerthread = new HandlerThread("Camera2"); handlerthread.start(); mHandler = new Handler(handlerthread.getLooper()); mImageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG, /*maxImages*/2); mImageReader.setOnImageAvailableListener(mImageAvailableListenter, mHandler); mCameraManager.openCamera(mCameraId, mCameraDeviceCallBack, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } else { finish(); return; } } private boolean checkCameraPermission() { if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(getApplicationContext(), "没有相机权限", Toast.LENGTH_LONG).show(); return false; } else { return true; } } @SuppressLint("NewApi") private CameraDevice.StateCallback mCameraDeviceCallBack = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { try { //当相机被打开,该方法将被回调,因此再这里进行相机预览设置 mCameraOpenCloseLock.release(); mCameraDevice = camera; //开启预览 createCameraCaptureSession(); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onDisconnected(@NonNull CameraDevice camera) { mCameraOpenCloseLock.release(); if (mCameraDevice != null) { mCameraDevice.close(); mCameraDevice = null; } } @Override public void onError(@NonNull CameraDevice camera, int error) { } }; private CaptureRequest.Builder mCaptureRequestBuilder; @SuppressLint("NewApi")//开启预览 private void createCameraCaptureSession() throws CameraAccessException { //创建预览需要的CaptureRequest.Builder mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); //添加surface为CaptureRequest.Builder的目标 mCaptureRequestBuilder.addTarget(mSurfaceHolder.getSurface()); //创建CameraCaptureSession该对象负责管理处理预览请求和拍照请求 mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(), mImageReader.getSurface()), mSessionPreviewStateCallback, mHandler); } @SuppressLint("NewApi") private CameraCaptureSession.StateCallback mSessionPreviewStateCallback = new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { try { //摄像头已经准备好,开始显示预览 mCameraCaptureSession = session; //自动对焦 mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); //打开闪光灯 // mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); //显示预览 CaptureRequest previewRequest = mCaptureRequestBuilder.build(); mCameraCaptureSession.setRepeatingRequest(previewRequest, null, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { Log.e("Camera2", "相机预览失败"); } }; // public void takePicture(View view) { takePic(); } @SuppressLint("NewApi") public void takePic() { if (mCameraDevice == null) return; // 创建拍照需要的CaptureRequest.Builder try { // 将imageReader的surface作为CaptureRequest.Builder的目标 mCaptureRequestBuilder.addTarget(mImageReader.getSurface()); // 自动对焦 mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); // 自动曝光 mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); // 获取手机方向 int rotation = getWindowManager().getDefaultDisplay().getRotation(); // 根据设备方向计算设置照片的方向 mCaptureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); //拍照 CaptureRequest mCaptureRequest = mCaptureRequestBuilder.build(); mCameraCaptureSession.capture(mCaptureRequest, null, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } }
推荐阅读
-
Android开发之获取单选与复选框的值操作示例
-
Android开发之android_gps定位服务简单实现
-
Android开发经验谈:并发编程(线程与线程池)(推荐)
-
Android开发之TextView使用intent传递信息,实现注册界面功能示例
-
Android开发之设置开机自动启动的几种方法
-
Android之使用Android-query框架开发实战(二)
-
Android开发之拼音转换工具类PinyinUtils示例
-
Android开发之ListView功能扩展,实现高性能的瀑布流布局讲解
-
Android开发之通过NITZ获取时区出错的解决
-
Android 开发艺术探索之Window和WindowManager解析