赞
踩
【项目代码】https://gitee.com/hellosunshine/camerax_android_java.git
启动
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
dependencies { implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'com.google.android.material:material:1.5.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.3' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' //CameraX添加依赖 def camerax_version = "1.1.0-alpha08" def lifecycle_version = "2.5.1" implementation "androidx.camera:camera-camera2:$camerax_version" implementation "androidx.camera:camera-lifecycle:$camerax_version" implementation "androidx.camera:camera-view:1.3.0-alpha07" implementation 'androidx.camera:camera-video:' implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" }
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.camera.view.PreviewView android:id="@+id/preview_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <Button android:id="@+id/takeVideoBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/startRecord" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/takePhotoBtn" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias=".9" /> <Button android:id="@+id/takePhotoBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/takePhoto" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/takeVideoBtn" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias=".9" /> </androidx.constraintlayout.widget.ConstraintLayout>
<!-- 拍照权限 -->
<uses-feature android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
package com.example.cameraxjavaactivity; import androidx.appcompat.app.AppCompatActivity; import androidx.camera.view.PreviewView; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.Manifest; import android.content.pm.PackageManager; import android.os.Bundle; import android.widget.Button; public class MainActivity extends AppCompatActivity { //按钮 Button takePhotoButton; Button takeVideoButton; //预览 PreviewView previewView; //权限 private static final String[] REQUIRE_PERMISSIONS = new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}; public static final int REQUEST_CODE_PERMISSIONS = 10; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定控件 takePhotoButton = findViewById(R.id.takePhotoBtn); takeVideoButton = findViewById(R.id.takeVideoBtn); previewView = findViewById(R.id.preview_view); takePhotoButton.setOnClickListener(v -> takePhoto()); takeVideoButton.setOnClickListener(v -> takeVideo()); //获取权限 if (havePermissions()) { initCamera(); } else { ActivityCompat.requestPermissions(this, REQUIRE_PERMISSIONS, REQUEST_CODE_PERMISSIONS); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode == REQUEST_CODE_PERMISSIONS) { initCamera(); } else { finish(); } } //判断权限是否获取 private boolean havePermissions() { for (String permission : REQUIRE_PERMISSIONS) { if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } //初始化Camera private void initCamera() { } //拍照 private void takePhoto() { } //录像 private void takeVideo() { } }
运行没有报错,继续下步骤
//capture
ImageCapture imageCapture;
ListenableFuture<ProcessCameraProvider> processCameraProviderListenableFuture;
//初始化Camera private void initCamera() { ///实例化(可以设置许多属性) imageCapture = new ImageCapture.Builder().build(); processCameraProviderListenableFuture = ProcessCameraProvider.getInstance(this); processCameraProviderListenableFuture.addListener(() -> { try { //配置预览(https://developer.android.google.cn/training/camerax/preview?hl=zh-cn) previewView.setScaleType(PreviewView.ScaleType.FIT_CENTER); Preview preview = new Preview.Builder().build(); preview.setSurfaceProvider(previewView.getSurfaceProvider()); //绑定到生命周期 ProcessCameraProvider processCameraProvider = processCameraProviderListenableFuture.get(); processCameraProvider.unbindAll(); processCameraProvider.bindToLifecycle(MainActivity.this, CameraSelector.DEFAULT_BACK_CAMERA, preview, imageCapture); } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); } }, ContextCompat.getMainExecutor(this)); }
//拍照 private void takePhoto() { if (imageCapture != null) { //ContentValues String name = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.SIMPLIFIED_CHINESE).format(System.currentTimeMillis()) ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name); contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "Pictures/CameraXImage"); } //图片输出 ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions .Builder(getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) .build(); imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() { @Override public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) { Log.i("CameraXTest", Objects.requireNonNull(outputFileResults.getSavedUri()).toString()); } @Override public void onError(@NonNull ImageCaptureException exception) { Log.e("CameraXTest", exception.toString()); } }); } }
定义videoCapture、recording
VideoCapture videoCapture;
Recording recording;
Recorder recorder = new Recorder.Builder().build();
videoCapture = VideoCapture.withOutput(recorder);
添加videoCapture
processCameraProvider.bindToLifecycle(MainActivity.this, CameraSelector.DEFAULT_BACK_CAMERA, preview, imageCapture, videoCapture);
//processCameraProvider.bindToLifecycle(MainActivity.this, CameraSelector.DEFAULT_BACK_CAMERA, preview, imageCapture);
//录像 private void takeVideo() { if (videoCapture != null) { takeVideoButton.setEnabled(false); if (recording != null) { recording.stop(); recording = null; return; } String name = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.SIMPLIFIED_CHINESE).format(System.currentTimeMillis()) + ".mp4"; ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name); contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "Movies/CameraX-Video"); } MediaStoreOutputOptions mediaStoreOutputOptions = new MediaStoreOutputOptions .Builder(getContentResolver(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI) .setContentValues(contentValues) .build(); Recorder recorder = (Recorder) videoCapture.getOutput(); if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, REQUIRE_PERMISSIONS, REQUEST_CODE_PERMISSIONS); return; } recording = recorder.prepareRecording(this, mediaStoreOutputOptions) .withAudioEnabled() .start(ContextCompat.getMainExecutor(this), videoRecordEvent -> { if (videoRecordEvent instanceof VideoRecordEvent.Start) { takeVideoButton.setText(getString(R.string.stopRecord)); takeVideoButton.setEnabled(true); } else if (videoRecordEvent instanceof VideoRecordEvent.Finalize) { if (((VideoRecordEvent.Finalize) videoRecordEvent).hasError()) { if (recording != null) { recording.close(); recording = null; } } else { String msg = "视频为" + ((VideoRecordEvent.Finalize) videoRecordEvent).getOutputResults().getOutputUri(); Log.i("CameraXTest", msg); } takeVideoButton.setEnabled(true); takeVideoButton.setText(getString(R.string.startRecord)); } }); } }
https://developer.android.google.cn/training/camerax/extensions-api?hl=zh-cn
本人设备不支持
//executor & imageAnalysis
private ExecutorService cameraExecutor;
private ImageAnalysis imageAnalysis;
//图片分析
@SuppressLint("UnsafeOptInUsageError")
private void initImageAnalysis() {
imageAnalysis = new ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build();
imageAnalysis.setAnalyzer(cameraExecutor, imageProxy -> {
int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees();
Log.i("CameraXTest", String.valueOf(Objects.requireNonNull(imageProxy.getImage()).getTimestamp()));
Log.i("CameraXTest", String.valueOf(rotationDegrees));
imageProxy.close();
});
}
processCameraProvider.bindToLifecycle(MainActivity.this, CameraSelector.DEFAULT_BACK_CAMERA, imageAnalysis, preview, imageCapture, videoCapture);
imageCapture = new ImageCapture.Builder()
//控制闪光灯模式 FLASH_MODE_ON(拍照时,闪光灯会亮起)
.setFlashMode(ImageCapture.FLASH_MODE_ON)
.build();
///旋转 //orientation为北为0,顺时针度数0-360 //Surface.ROTATION_270将拍摄好的图片顺时针旋转270度 private void setOrientationEventListener() { OrientationEventListener orientationEventListener = new OrientationEventListener(this) { @Override public void onOrientationChanged(int orientation) { int rotation; if (orientation >= 45 && orientation < 135) { rotation = Surface.ROTATION_270; } else if (orientation >= 135 && orientation < 225) { rotation = Surface.ROTATION_180; } else if (orientation >= 225 && orientation < 315) { rotation = Surface.ROTATION_90; } else { rotation = Surface.ROTATION_0; } Log.i("CameraXTest", String.valueOf(rotation)); Log.i("CameraXTest", String.valueOf(orientation)); imageCapture.setTargetRotation(rotation); } }; orientationEventListener.enable(); }
//剪裁矩形(拍摄之后,对图片进行裁剪) ViewPort viewPort = null; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) { viewPort = new ViewPort.Builder( new Rational(100, 100), getDisplay().getRotation() ).build(); } else { viewPort = new ViewPort.Builder( new Rational(100, 100), Surface.ROTATION_0 ).build(); } UseCaseGroup useCaseGroup = new UseCaseGroup.Builder() .addUseCase(preview) .addUseCase(imageAnalysis) .addUseCase(imageCapture) .addUseCase(videoCapture) .setViewPort(viewPort) .build(); processCameraProvider.unbindAll(); processCameraProvider.bindToLifecycle(MainActivity.this, CameraSelector.DEFAULT_BACK_CAMERA, useCaseGroup);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。