赞
踩
目录
此文章我会用Camera2 和CameraX 分别实现预览拍照录制视频
相机相对于手机屏幕默认方向不一致:
前置摄像头(指向与显示屏方向相同的摄像头)的传感器相对于手机旋转 270 度(顺时针),以符合 Android 兼容性定义
手机的传感器是顺时针旋转的 左横屏就是90度
手机的传感器是顺时针旋转的 右横屏就是270度或者-90度
Camera 只是Android的一部分 所以框架层级整体跟Android一样为
Applications 应用层 -----------------------------对应camera APP
Framework层 -----------------------------对应Java Framework
Libraries 系统运行库层 -----------------------------对应Native Framework (CameraService)
Hardwre Abstraction layer HAL硬件抽象层-----------------------------对应Camera Provider
Linux Kernel 内核层 -----------------------------对应Camera Driver
Camera根据Android 架构从上至下可分为
1)Applications: 最上层的应用,编译后生成Camera APK;
2)Application Framework: 主要为Applications提供API;
3)JNI: 使Application Framework和Libraries可交互;
4)Libraries: 包括Camera Framework和Camera Service(camera service和camera client);
5)HAL: 硬件抽象层, 用来链接driver和 Camera Service;
6)Kernel: image sensor driver的实作.
解释下来 其实就是CameraManager调用openCamera 下发open指令到底层,然后在CameraDevice.StateCallback 的onOpened 中 拿到底层返回来的CameraDevice 通过CameraDevice去创建Session(createCaptureSession) 创建Session是需要添加对应的surface 预览的surface 有TextureView SurfaceView 拍照对应的Surface 为ImageReader 然后在Session的状态回调的onConfigured里(CameraCaptureSession.StateCallback)拿到CameraCaptureSession对象 通过CameraCaptureSession 可以申请预览 setRepeatingRequest 或者是 拍照 Capture 录制视频 需要配置 MediaRecorder
首先利用AndroidStudio 创建工程
Next
Finish
打开布局文件
一步步实现 就慢慢来,activity_main.xml布局文件代码
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#000000"
- >
-
- <TextureView
- android:id="@+id/previewSurfaceView"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
- <ImageButton
- android:id="@+id/takePictureButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="70dp"
- android:background="@drawable/shape_white_ring"
- android:src="@drawable/shape_take_photo" />
-
- </RelativeLayout>
看到我放了两个控件一个TextureView 用来预览的控件 SurfaceView 等等也可以 还有一个拍照按钮 ImageButton
首先我们实现预览 预览是一切的基础
- package com.example.camera2demo;
-
- import androidx.appcompat.app.AppCompatActivity;
-
- import android.os.Bundle;
- import android.util.Log;
- import android.view.TextureView;
- import android.view.View;
- import android.widget.ImageButton;
-
- public class MainActivity extends AppCompatActivity implements View.OnClickListener {
- //预览画面控件
- private TextureView mTextureView;
- //拍照按钮
- private ImageButton mTakePictureButton;
- //日志的tag
- private final String TAG = "Camera2Demo" ;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //初始化预览控件
- mTextureView = findViewById(R.id.previewSurfaceView);
- //初始化拍照按钮
- mTakePictureButton = findViewById(R.id.takePictureButton);
-
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- //设置拍照按钮监听
- mTakePictureButton.setOnClickListener(this);
- }
-
- @Override
- public void onClick(View v) {
- switch (v.getId()){
- case R.id.takePictureButton:
- takePicture();
- break;
- }
- }
-
- private void takePicture() {
- Log.d(TAG,"-----takePicture");
- }
-
- }
可以看到 就是在onCreate 里去 初始化 预览控件和拍照按钮 并在 onStart 里去设置按钮 监听
在点击时间里 写了空函数 takePicture 基本框架已经实现
要实现预览 我们是需要 申请Camera权限的 所以接下来我们先申请权限
Android 6.0 之前只需要在 AndroidManifest.xml 中加入 就OK 6.0 之后需要加入并且动态申请权限
<uses-permission android:name="android.permission.CAMERA" />
代码 块如下
- package com.example.camera2demo;
-
- import androidx.annotation.NonNull;
- import androidx.appcompat.app.AppCompatActivity;
- import androidx.core.app.ActivityCompat;
- import androidx.core.content.ContextCompat;
-
- import android.content.pm.PackageManager;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.TextureView;
- import android.view.View;
- import android.widget.ImageButton;
-
- public class MainActivity extends AppCompatActivity implements View.OnClickListener {
- //预览画面控件
- private TextureView mTextureView;
- //拍照按钮
- private ImageButton mTakePictureButton;
- //日志的tag
- private final String TAG = "Camera2Demo";
- //权限字符串数组 因为还需要其他 便于添加权限 选择字符串数组的形式
- private final String[] REQUIRED_PERMISSIONS = new String[]{
- "android.permission.CAMERA",
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //初始化预览控件
- mTextureView = findViewById(R.id.previewSurfaceView);
- //初始化拍照按钮
- mTakePictureButton = findViewById(R.id.takePictureButton);
-
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- //检查权限申请权限
- if (allPermissionsGranted()) {
- Log.d(TAG, "权限已授予");
- } else {
- Log.d(TAG, "申请权限");
- ActivityCompat.requestPermissions(MainActivity.this, REQUIRED_PERMISSIONS, 1);
- }
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- //设置拍照按钮监听
- mTakePictureButton.setOnClickListener(this);
- }
-
- @Override
- public void onClick(View v) {
- switch (v.getId()){
- case R.id.takePictureButton:
- takePicture();
- break;
- }
- }
-
- private boolean allPermissionsGranted() {
- Log.d(TAG, "----- 检查权限");
- for (String permission : REQUIRED_PERMISSIONS) {
- if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
- return false;
- }
- }
- return true;
- }
-
- //权限回调 申请完权限之后 返回的结果在这里接收
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- //这个1 是申请权限时的第三个参数
- if (requestCode == 1) {
- if (allPermissionsGranted()) {
- openCamera();
- } else {
- ActivityCompat.requestPermissions(MainActivity.this, REQUIRED_PERMISSIONS, 1);
- }
- }
- }
-
- private void openCamera() {
- Log.d(TAG,"----------openCamera");
- }
-
- private void takePicture() {
- Log.d(TAG,"-----takePicture");
- }
-
- }
在刚刚 的基础之上加了三个函数 一个检查权限的函数 一个权限回调函数 一个 openCamera的空函数 权限获取之后我们就正式进入openCamera
- package com.example.camera2demo;
-
- import static java.lang.String.valueOf;
-
- import androidx.annotation.NonNull;
- import androidx.appcompat.app.AppCompatActivity;
- import androidx.core.app.ActivityCompat;
- import androidx.core.content.ContextCompat;
-
- import android.annotation.SuppressLint;
- import android.content.pm.PackageManager;
- import android.graphics.ImageFormat;
- import android.hardware.camera2.CameraAccessException;
- import android.hardware.camera2.CameraCharacteristics;
- import android.hardware.camera2.CameraDevice;
- import android.hardware.camera2.CameraManager;
- import android.hardware.camera2.params.StreamConfigurationMap;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.HandlerThread;
- import android.util.Log;
- import android.util.Size;
- import android.view.TextureView;
- import android.view.View;
- import android.widget.ImageButton;
-
- public class MainActivity extends AppCompatActivity implements View.OnClickListener {
- //预览画面控件
- private TextureView mTextureView;
- //拍照按钮
- private ImageButton mTakePictureButton;
- //日志的tag
- private final String TAG = "Camera2Demo";
- //权限字符串数组 因为还需要其他 便于添加权限 选择字符串数组的形式
- private final String[] REQUIRED_PERMISSIONS = new String[]{
- "android.permission.CAMERA",
- };
- //处理回调函数的线程
- private HandlerThread mCameraThread;
- private Handler mCameraHandler;
-
- //具体的相机设备
- private CameraDevice mCameraDevice;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInst
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。