废话不多说直接上代码
一,导入依赖
// CameraX 相关依赖
def cameraxVersion = "1.1.0-alpha05"
implementation "androidx.camera:camera-core:${cameraxVersion}"
implementation "androidx.camera:camera-camera2:${cameraxVersion}"
implementation "androidx.camera:camera-lifecycle:${cameraxVersion}"
implementation 'androidx.camera:camera-view:1.0.0-alpha25'
二、添加权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-permission android:name="android.permission.CAMERA" />
<!-- 这个权限允许应用程序录制音频。 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
三、实现代码
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.core.VideoCapture;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.google.common.util.concurrent.ListenableFuture;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final int REQUEST_CODE_RECORD_AUDIO_PERMISSION = 1001;
private static final int REQUEST_CODE_CAMERA_PERMISSION = 1002;
private static final int REQUEST_CODE_STORAGE_PERMISSION = 1003;
private ListenableFuture<ProcessCameraProvider> processCameraProviderListenableFuture;
private PreviewView previewView;
private Button btn_photograph; //拍照
private ImageCapture imageCapture;
private CameraSelector cameraSelector;
private boolean isUsingFrontCamera = false; // 默认使用前置摄像头
private Button btn_picture_recording; //录像
private VideoCapture videoCapture;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
previewView = findViewById(R.id.previewView);
btn_photograph = findViewById(R.id.btn_photograph);
btn_picture_recording = findViewById(R.id.btn_picture_recording);
btn_photograph.setOnClickListener(this);
btn_picture_recording.setOnClickListener(this);
// 检查权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_RECORD_AUDIO_PERMISSION);
} else {
initializeCamera();
}
}
// 初始化相机
private void initializeCamera() {
processCameraProviderListenableFuture = ProcessCameraProvider.getInstance(this);
processCameraProviderListenableFuture.addListener(() -> {
try {
ProcessCameraProvider processCameraProvider = processCameraProviderListenableFuture.get();
start(processCameraProvider);
} catch (Exception e) {
throw new RuntimeException(e);
}
}, ContextCompat.getMainExecutor(this));
}
@SuppressLint("RestrictedApi")
private void start(ProcessCameraProvider processCameraProvider) {
processCameraProvider.unbindAll();
cameraSelector = new CameraSelector.Builder()
.requireLensFacing(isUsingFrontCamera ? CameraSelector.LENS_FACING_FRONT : CameraSelector.LENS_FACING_BACK)
.build();
Preview preview = new Preview.Builder().build();
preview.setSurfaceProvider(previewView.getSurfaceProvider());
imageCapture = new ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build();
videoCapture = new VideoCapture.Builder()
.setVideoFrameRate(30)
.build();
processCameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture, videoCapture);
}
@SuppressLint("RestrictedApi")
@Override
public void onClick(View view) {
if (view.getId() == R.id.btn_photograph) {
captureImage();
}
if (view.getId() == R.id.btn_picture_recording) {
if (btn_picture_recording.getText().equals("录像")) {
btn_picture_recording.setText("停止");
captureVideo();
} else {
btn_picture_recording.setText("录像");
videoCapture.stopRecording();
}
}
}
// 拍照
private void captureImage() {
long timeStamp = System.currentTimeMillis();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, timeStamp);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
imageCapture.takePicture(
new ImageCapture.OutputFileOptions.Builder(
getContentResolver(),
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
).build(),
ContextCompat.getMainExecutor(this),
new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
Toast.makeText(MainActivity.this, "拍照保存成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(@NonNull ImageCaptureException exception) {
Toast.makeText(MainActivity.this, "拍照保存失败: " + exception.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
// 录像
@SuppressLint("RestrictedApi")
private void captureVideo() {
if (videoCapture != null) {
long timeStamp = System.currentTimeMillis();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, timeStamp);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4");
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
return;
}
videoCapture.startRecording(
new VideoCapture.OutputFileOptions.Builder(
getContentResolver(),
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
contentValues
).build(),
ContextCompat.getMainExecutor(this),
new VideoCapture.OnVideoSavedCallback() {
@Override
public void onVideoSaved(@NonNull VideoCapture.OutputFileResults outputFileResults) {
Toast.makeText(MainActivity.this, "视频拍摄成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) {
Toast.makeText(MainActivity.this, "视频拍摄失败: " + message, Toast.LENGTH_SHORT).show();
}
}
);
} else {
Toast.makeText(MainActivity.this, "视频录制功能未初始化", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE_RECORD_AUDIO_PERMISSION) {
for (int i = 0; i < permissions.length; i++) {
if (permissions[i].equals(Manifest.permission.RECORD_AUDIO) && grantResults[i] == PackageManager.PERMISSION_GRANTED) {
// 录音权限已授予
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_CAMERA_PERMISSION);
} else {
initializeCamera();
}
} else if (permissions[i].equals(Manifest.permission.RECORD_AUDIO) && grantResults[i] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "录音权限被拒绝", Toast.LENGTH_SHORT).show();
}
}
} else if (requestCode == REQUEST_CODE_CAMERA_PERMISSION) {
for (int i = 0; i < permissions.length; i++) {
if ((permissions[i].equals(Manifest.permission.CAMERA) || permissions[i].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) &&
grantResults[i] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "相机或存储权限被拒绝", Toast.LENGTH_SHORT).show();
}
}
}
}
}
布局代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/black"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.camera.view.PreviewView
android:id="@+id/previewView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="3" />
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_photograph"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_weight="1"
android:text="拍照" />
<Button
android:id="@+id/btn_picture_recording"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_weight="1"
android:text="录像" />
</LinearLayout>
</LinearLayout>
以上就是整个完整案例