Compatible with all Android versions of Androidx camera preview and image acquisition
1. Add reference dependencies {<!-- --> def camerax_version = "1.0.0-beta06" // CameraX core library implementation "androidx.camera:camera-camera2:$camerax_version" // CameraX life cycle implementation "androidx.camera:camera-lifecycle:$camerax_version" // CameraX view collection, such as cameraview, preview, etc. implementation "androidx.camera:camera-view:1.0.0-alpha10"
2. Add permissions to AndroidManifest.xml
<uses-feature android:name="android.hardware.camera.autofocus" /> <uses-feature android:name="android.hardware.camera.any" />
3. Layout file
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@ + id/btn_trans" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Switch camera" app:layout_constraintStart_toStartOf="@ + id/viewFinder" app:layout_constraintTop_toTopOf="@ + id/viewFinder" /> <Button android:id="@ + id/btn_takePhoto" android:layout_width="100dp" android:layout_height="60dp" android:layout_marginBottom="50dp" android:elevation="2dp" android:scaleType="fitCenter" android:text="photograph" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" /> <androidx.camera.view.PreviewView android:id="@ + id/viewFinder" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> </LinearLayout>
4. All source codes in the activity
package cn.wildfire.chat.app; import android.Manifest; import android.annotation.SuppressLint; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.google.common.util.concurrent.ListenableFuture; import java.io.File; import java.io.IOException; import androidx.camera.core.Camera; import androidx.camera.core.CameraSelector; import androidx.camera.core.ImageCapture; import androidx.camera.core.ImageCaptureException; import androidx.camera.core.Preview; import androidx.camera.lifecycle.ProcessCameraProvider; import androidx.camera.view.PreviewView; import androidx.core.content.ContextCompat; import cn.wildfirechat.chat.R; public class RLSB2Activity extends AppCompatActivity implements View.OnClickListener {<!-- --> SurfaceView surfaceview; SurfaceHolder holder; Camera mCamera; PreviewView mViewFinder; private ImageCapture mImageCapture; private int mFacing = CameraSelector.LENS_FACING_BACK; @Override protected void onCreate(Bundle savedInstanceState) {<!-- --> super.onCreate(savedInstanceState); setContentView(R.layout.activity_rlsb2); ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this); mViewFinder=findViewById(R.id.viewFinder); initView(); findViewById(R.id.btn_trans).setOnClickListener(this); findViewById(R.id.btn_takePhoto).setOnClickListener(this); } private static final String TAG = "MainActivity"; protected void initView() {<!-- --> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {<!-- --> if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {<!-- --> requestPermissions(new String[] {<!-- -->Manifest.permission.CAMERA}, 1); } } startCamera(); } private void startCamera() {<!-- --> //Return the ProcessCameraProvider that can currently bind the life cycle ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this); cameraProviderFuture.addListener(new Runnable() {<!-- --> @SuppressLint("RestrictedApi") @Override public void run() {<!-- --> try {<!-- --> //Bind the life cycle of the camera with the life cycle of the activity, camerax will release itself, don't worry ProcessCameraProvider cameraProvider = cameraProviderFuture.get(); //Preview capture, which supports angle conversion Preview preview = new Preview. Builder(). build(); //Create a capture of the image mImageCapture = new ImageCapture. Builder() .setFlashMode(ImageCapture.FLASH_MODE_AUTO) .build(); // select rear camera CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(mFacing).build(); //Unbind before preview cameraProvider. unbindAll(); //Bind the data into the life cycle of the camera Camera camera = cameraProvider.bindToLifecycle(RLSB2Activity.this, cameraSelector, preview, mImageCapture); // Give the surface of the previewview to the camera to preview preview.setSurfaceProvider(mViewFinder.createSurfaceProvider(camera.getCameraInfo())); } catch (Exception e) {<!-- --> e.printStackTrace(); } } }, ContextCompat. getMainExecutor(this)); } @Override public void onClick(View v) {<!-- --> switch (v.getId()) {<!-- --> case R.id.btn_trans: switchCamera(); break; case R.id.btn_takePhoto: takePhoto(); break; } } public void switchCamera() {<!-- --> /** * The problem with the white screen is that PreviewView removes all Views and no data is sent to Surface. * So only the background color is left, and it can be processed next time */ mFacing = mFacing == CameraSelector.LENS_FACING_FRONT? CameraSelector.LENS_FACING_BACK: CameraSelector.LENS_FACING_FRONT; startCamera(); } public void takePhoto() {<!-- --> //Get the root directory String path="" + Environment. getExternalStorageDirectory(); if (mImageCapture != null) {<!-- --> File dir = new File(path); if (!dir. exists()) {<!-- --> dir.mkdirs(); } //Create a file File file = new File(path,"testx.jpg"); if (file. exists()) {<!-- --> file.delete(); } //Create the data of the package file, such as creating a file ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).build(); //Start taking pictures mImageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {<!-- --> @Override public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {<!-- --> // Uri savedUri = outputFileResults. getSavedUri(); Toast.makeText(RLSB2Activity.this, "Saved successfully: ", Toast.LENGTH_SHORT).show(); } @Override public void onError(@NonNull ImageCaptureException exception) {<!-- --> Toast.makeText(RLSB2Activity.this, "Failed to save", Toast.LENGTH_SHORT).show(); } }); } } }