365bet手机网址是多少-正规365彩票平台app下载-365bet游戏开户

Android Camere开发入门(2):Camera2的使用

Android Camere开发入门(2):Camera2的使用 Camera2 API简介 在上一篇文章《Android Camere开发入门(1):Camera1的使用》中,我们了解了如何在Android应用

Android Camere开发入门(2):Camera2的使用

Android Camere开发入门(2):Camera2的使用

Camera2 API简介

在上一篇文章《Android Camere开发入门(1):Camera1的使用》中,我们了解了如何在Android应用中使用Camera API来访问设备的摄像头。然而,随着Android设备的发展和硬件的提升,我们需要使用更强大、更灵活的API来满足日益增长的需求。这就是我们今天要介绍的Camera2 API。

Camera2 API是Android 5.0(API 21)引入的一种全新的相机API,它提供了对设备摄像头的全面控制,包括预览、捕获、图像格式、图像质量、视频录制等。相比于Camera API,Camera2 API更加强大和灵活,可以更好地满足开发者的需求。

本文将介绍如何使用Camera2 API来进行相机操作,包括预览、拍照和录制视频等功能。

获取相机权限

首先,我们需要在AndroidManifest.xml文件中添加相机权限的申请,以便应用能够访问设备的相机。

这里使用了一个第三方权限申请框架,在build.gradle添加依赖

implementation 'com.github.getActivity:XXPermissions:18.0'

在Activity中去申请权限,当用户拒绝时给出相应提示。

private String[] permissionArray = {Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE};

XXPermissions.with(this).permission(permissionArray).request((permissions, allGranted) -> {

if (!allGranted) {

Toast.makeText(Camera2Activity.this, "请务必开启所有权限", Toast.LENGTH_LONG).show();

return;

}

//获取权限成功

initCamera2();

});

创建CameraManager实例

在Camera2中,我们需要首先创建一个CameraManager实例,它用于获取和管理设备上的相机资源。

CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);

获取可用的相机列表

通过CameraManager实例,我们可以获取设备上所有可用的相机列表。

String[] cameraIdList = cameraManager.getCameraIdList();

打开相机

选择一个相机ID,然后使用CameraManager打开相机。在这之前,需要实现一个CameraDevice.StateCallback来处理打开相机的结果。

cameraManager.openCamera(cameraIdList[1], new CameraDevice.StateCallback() {

@Override

public void onOpened(@NonNull CameraDevice cameraDevice) {

// 相机打开成功,可以进行后续操作

createCaptureSession(cameraDevice);

}

@Override

public void onDisconnected(@NonNull CameraDevice cameraDevice) {

// 相机断开连接

mCameraDevice.close();

mCameraDevice = null;

}

@Override

public void onError(@NonNull CameraDevice cameraDevice, int error) {

// 打开相机发生错误

mCameraDevice.close();

mCameraDevice = null;

}

}, null);

创建预览会话

一旦相机打开成功,我们可以通过CameraDevice创建一个预览会话。预览会话是实现相机预览的关键。

这里和Camera1不太一样,预览不管使用的是SurfaceView还是TextureView最后都是以Surface的方式进行添加,且Camera可以同时添加多个Surface通道。

private CameraDevice mCameraDevice;

private CameraCaptureSession captureSession;

private int imageWidth = 1920;

private int imageHeight = 1080;

private ImageReader mImageReader;

private void createCaptureSession(CameraDevice cameraDevice) {

mCameraDevice = cameraDevice;

List surfaces = new ArrayList<>();

// 预览Surface

SurfaceHolder surfaceHolder = binding.camera2SurfaceView.getHolder();

Surface previewSurface = surfaceHolder.getSurface();

surfaces.add(previewSurface);

// 创建ImageReader对象(拍照)

mImageReader = ImageReader.newInstance(imageWidth, imageHeight, ImageFormat.JPEG, 1);

mImageReader.setOnImageAvailableListener(mImageReaderListener, null);

surfaces.add(mImageReader.getSurface());

//添加录制Surface

initRecording();

surfaces.add(mMediaRecorder.getSurface());

try {

cameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {

@Override

public void onConfigured(@NonNull CameraCaptureSession session) {

try {

// 预览会话已创建成功,可以开始预览

captureSession = session;

// 创建预览请求

CaptureRequest.Builder previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

previewRequestBuilder.addTarget(previewSurface); // 设置预览目标Surface

// 开启连续预览

captureSession.setRepeatingRequest(previewRequestBuilder.build(), null, null);

} catch (CameraAccessException e) {

e.printStackTrace();

}

}

@Override

public void onConfigureFailed(@NonNull CameraCaptureSession session) {

// 预览会话创建失败

}

}, null);

} catch (CameraAccessException e) {

e.printStackTrace();

}

}

拍照和录制视频

在预览会话创建成功之后,我们可以通过创建不同类型的CaptureRequest来实现拍照和录制视频功能。

//给一个按钮点击事件进行拍照

binding.camera2TakePicture.setOnClickListener(v -> takePicture());

private void takePicture() {

try {

// 创建拍照请求

CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);

captureBuilder.addTarget(mImageReader.getSurface());

// 设置自动对焦

captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,

CaptureRequest.CONTROL_AF_MODE_AUTO);

// 设置闪光灯

captureBuilder.set(CaptureRequest.CONTROL_AE_MODE,

CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

// 获取设备方向

int rotation = getWindowManager().getDefaultDisplay().getRotation();

captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, rotation);

captureSession.capture(captureBuilder.build(), null, null);

// 播放拍照音效或显示闪光灯动画等

} catch (CameraAccessException e) {

e.printStackTrace();

}

}

private ImageReader.OnImageAvailableListener mImageReaderListener = reader -> {

// 获取到拍照的图像数据

Image image = reader.acquireLatestImage();

// 获取图片的字节数组

ByteBuffer buffer = image.getPlanes()[0].getBuffer();

byte[] data = new byte[buffer.remaining()];

buffer.get(data);

// 保存图片到相册

saveImageToGallery(data);

// 释放图像资源

image.close();

};

private void saveImageToGallery(byte[] data) {

// 定义图片的保存路径和文件名

String fileName = "IMG_" + System.currentTimeMillis() + ".jpg";

String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() + File.separator + fileName;

// 创建文件输出流

try {

FileOutputStream fos = new FileOutputStream(filePath);

fos.write(data);

fos.close();

// 通知图库更新

MediaScannerConnection.scanFile(this, new String[]{filePath}, null, null);

// 在某些设备上,可能需要发送广播通知才能使图片立即出现在相册中

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(filePath))));

// 显示保存成功的提示

Toast.makeText(this, "图片保存成功", Toast.LENGTH_SHORT).show();

} catch (IOException e) {

e.printStackTrace();

// 显示保存失败的提示

Toast.makeText(this, "图片保存失败", Toast.LENGTH_SHORT).show();

}

}

给一个按钮进行开启和关闭录制

binding.camera2Recording.setOnClickListener(v -> {

if (!isRecording) startRecordingVideo();

else stopRecordingVideo();

binding.camera2Recording.setText(isRecording ? "关闭录制" : "开启录制");

});

private MediaRecorder mMediaRecorder;

private int videoWidth = 1920;

private int videoHeight = 1080;

private File recorderFile;

private String recorderPath;

private boolean isRecording = false;

private void initRecording() {

recorderFile = new File(Camera2Activity.this.getExternalFilesDir(null).getAbsolutePath() + "/video/");

if (!recorderFile.exists()) {

recorderFile.mkdir();

}

recorderPath = recorderFile.getAbsolutePath() + "/" + System.currentTimeMillis() + ".mp4";

Log.e(TAG, "视频路径:" + recorderPath);

mMediaRecorder = new MediaRecorder();

mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);

mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);

mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);

mMediaRecorder.setOutputFile(recorderPath);

mMediaRecorder.setVideoEncodingBitRate(10000000);

mMediaRecorder.setVideoFrameRate(30);

mMediaRecorder.setVideoSize(videoWidth, videoHeight);

mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);

mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);

// 开始录制

try {

mMediaRecorder.prepare();

mMediaRecorder.start();

} catch (IOException e) {

e.printStackTrace();

}

}

private void startRecordingVideo() {

// 创建录制视频请求

try {

CaptureRequest.Builder recordRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);

recordRequestBuilder.addTarget(mMediaRecorder.getSurface()); // 设置录制目标Surface

captureSession.setRepeatingRequest(recordRequestBuilder.build(), null, null); // 开始录制视频

isRecording = true;

} catch (CameraAccessException e) {

e.printStackTrace();

}

}

private void stopRecordingVideo() {

// 停止录制视频

try {

mMediaRecorder.stop();

} catch (IllegalStateException e) {

e.printStackTrace();

} finally {

mMediaRecorder.reset();

mMediaRecorder.release();

mMediaRecorder = null;

}

isRecording = false;

// 关闭相机预览会话

// if (captureSession != null) {

// captureSession.close();

// captureSession = null;

// }

//图库更新

addToGallery(recorderPath);

}

private void addToGallery(String videoFilePath) {

// 发送广播通知图库更新

MediaScannerConnection.scanFile(this, new String[]{videoFilePath}, null,

(path, uri) -> {

// 添加到相册成功的回调

Toast.makeText(this, "视频已保存至相册", Toast.LENGTH_SHORT).show();

});

}

总结

这些只是Camera2 API的基本用法,它还提供了更多的功能和选项,如自动对焦、闪光灯控制、镜头切换等。你可以在官方文档中进一步了解这些功能。

通过上述步骤,我们可以实现相机的预览、拍照和录制视频等基本功能。

参考链接

Android官方文档:https://developer.android.com/reference/android/hardware/camera2

Google Sample代码:https://github.com/android/camera-samples/tree/main/Camera2Basic

Codelab教程:https://codelabs.developers.google.com/codelabs/camerax-getting-started

DEMO

gitee:https://gitee.com/yunianvh/camera-demo github:https://github.com/yunianvh/CameraDemo

编辑:玉念聿辉 感谢查阅

← 上一篇: 什么是网络销售
下一篇: 105装备掉落地汇总 主刷这2张图加速毕业 →

相关推荐

魔兽世界游戏任务德拉诺之王的破碎骨格肿么得
奥利司他60mg和120mg的区别 奥利司他一盒多少粒多少钱
火线指令攻略指南大全 火线指令官方正式版
淘宝为什么运营越来越差?淘宝如何运营才有销量
Windows系统更新KB2847927、KB947821更新失败
2014世界杯英格兰队九号是谁
世界杯史上最快进球(11秒,一个创造奇迹的瞬间)
美丽说品牌店铺招商规则
做网络分销商城怎么样(网上分销的优缺点)
【经验分享】图文讲解6步小技巧,教你轻松磨好钻头,实用
更换佳能打印机中的墨盒
Windows系统更新KB2847927、KB947821更新失败