package com.whyc;
|
|
import android.Manifest;
|
import android.annotation.SuppressLint;
|
import android.app.Activity;
|
import android.content.Context;
|
import android.content.Intent;
|
import android.graphics.ImageFormat;
|
import android.hardware.camera2.CameraAccessException;
|
import android.hardware.camera2.CameraCaptureSession;
|
import android.hardware.camera2.CameraDevice;
|
import android.hardware.camera2.CameraManager;
|
import android.hardware.camera2.CaptureRequest;
|
import android.media.Image;
|
import android.media.ImageReader;
|
import android.media.MediaCodec;
|
import android.media.MediaRecorder;
|
import android.media.MediaScannerConnection;
|
import android.net.Uri;
|
import android.os.Bundle;
|
import android.os.Environment;
|
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
import android.support.v4.app.ActivityCompat;
|
import android.util.Log;
|
import android.util.Size;
|
import android.view.Surface;
|
import android.view.SurfaceHolder;
|
import android.view.SurfaceView;
|
import android.widget.Button;
|
import android.widget.Toast;
|
|
import java.io.File;
|
import java.io.FileOutputStream;
|
import java.io.IOException;
|
import java.nio.ByteBuffer;
|
import java.util.ArrayList;
|
import java.util.List;
|
|
public class Camera2Activity extends Activity {
|
private static final String TAG = Camera2Activity.class.getSimpleName();
|
private Button camera2TakePicture;
|
private Button camera2Recording;
|
private SurfaceView camera2SurfaceView;
|
private String[] permissionArray = {Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
|
private Surface previewSurface;
|
|
@Override
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
super.onCreate(savedInstanceState);
|
setContentView(R.layout.activity_camera2);
|
|
camera2TakePicture = findViewById(R.id.camera2_takePicture);
|
camera2Recording = findViewById(R.id.camera2_recording);
|
camera2SurfaceView = findViewById(R.id.camera2_surface_view);
|
SurfaceHolder surfaceHolder = camera2SurfaceView.getHolder();
|
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
|
@Override
|
public void surfaceCreated(SurfaceHolder holder) {
|
Log.e(TAG, "surfaceCreated");
|
// 设置相机预览到Surface
|
previewSurface = holder.getSurface();
|
//获取权限
|
ActivityCompat.requestPermissions(Camera2Activity.this, permissionArray, 1);
|
initCamera2();
|
}
|
|
@Override
|
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
|
|
}
|
|
@Override
|
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
|
|
}
|
});
|
previewSurface = surfaceHolder.getSurface();
|
boolean valid = previewSurface.isValid();
|
if (!valid) {
|
Log.e(TAG, "previewSurface is not valid");
|
}
|
camera2TakePicture.setOnClickListener(v -> takePicture());
|
camera2Recording.setOnClickListener(v -> {
|
if (!isRecording) {
|
startRecordingVideo();
|
}else{
|
stopRecordingVideo();
|
}
|
camera2Recording.setText(isRecording ? "关闭录制" : "开启录制");
|
});
|
|
}
|
|
@SuppressLint("MissingPermission")
|
private void initCamera2() {
|
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
|
try {
|
String[] cameraIdList = cameraManager.getCameraIdList();
|
// CameraCharacteristics cc = cameraManager.getCameraCharacteristics(cameraIdList[0]);
|
// StreamConfigurationMap map = cc.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
|
// Size largest = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new CompareSizeByArea());
|
// imageHeight = largest.getHeight();
|
// imageWidth = largest.getWidth();
|
|
cameraManager.openCamera(cameraIdList[0], 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);
|
|
} catch (CameraAccessException e) {
|
e.printStackTrace();
|
}
|
|
}
|
private class CompareSizeByArea implements java.util.Comparator<Size> {
|
@Override
|
public int compare(Size lhs, Size rhs) {
|
return Long.signum((long) lhs.getWidth() * lhs.getHeight()
|
- (long) rhs.getWidth() * rhs.getHeight());
|
}
|
}
|
|
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<Surface> surfaces = new ArrayList<>();
|
|
// 预览Surface
|
|
surfaces.add(previewSurface);
|
// 创建ImageReader对象(拍照)
|
mImageReader = ImageReader.newInstance(imageWidth, imageHeight, ImageFormat.JPEG, 1);
|
mImageReader.setOnImageAvailableListener(mImageReaderListener, null);
|
surfaces.add(mImageReader.getSurface());
|
|
//添加录制Surface
|
initRecording();
|
// surfaces.add(((SurfaceView)findViewById(R.id.camera2_surface_view2)).getHolder().getSurface());
|
// surfaces.add(mMediaRecorder.getSurface());
|
surfaces.add(recorderSurface);
|
|
|
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
|
// previewRequestBuilder.addTarget(mMediaRecorder.getSurface());
|
previewRequestBuilder.addTarget(recorderSurface);
|
|
// 开启连续预览
|
captureSession.setRepeatingRequest(previewRequestBuilder.build(), null, null);
|
} catch (CameraAccessException e) {
|
e.printStackTrace();
|
}
|
}
|
|
@Override
|
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
|
// 预览会话创建失败
|
}
|
}, null);
|
} catch (CameraAccessException e) {
|
e.printStackTrace();
|
}
|
}
|
|
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();
|
}
|
}
|
|
private MediaRecorder mMediaRecorder;
|
private Surface recorderSurface;
|
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();
|
recorderSurface = MediaCodec.createPersistentInputSurface();
|
mMediaRecorder.setInputSurface(recorderSurface);
|
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
|
// recordRequestBuilder.addTarget(previewSurface); // 设置录制目标Surface
|
recordRequestBuilder.addTarget(recorderSurface); // 设置录制目标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();
|
});
|
}
|
}
|