Preface
The goal is very simple. Use CameraX to open the camera preview and display it on the interface in real time. See if CameraX is as useful as Google says. First click the simplest one to display the preview.
Introduce dependencies
Some configurations of module gradle use Android SDK version 31, databinding is enabled
apply plugin: '' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' android { compileSdkVersion 31 buildToolsVersion "31.0.0" defaultConfig { minSdkVersion 21 targetSdkVersion 31 } dataBinding { enabled = true } }
Introduced CameraX dependencies (CameraX core library is implemented with camera2), currently mainly using version 1.1.0-alpha11
dependencies { implementation ":camera-core:1.1.0-alpha11" implementation ":camera-camera2:1.1.0-alpha11" implementation ":camera-lifecycle:1.1.0-alpha11" implementation ":camera-view:1.0.0-alpha31" implementation ":camera-extensions:1.0.0-alpha31" }
Using the CameraX core library in version 1.0.2 will report an error and cannot be foundgetOrCreateInstance
method.
??? bug "NoSuchMethodError getOrCreateInstance"
```log CrashHandler: In thread: Thread[main,5,main] UncaughtException detected: : No static method getOrCreateInstance(Landroid/content/Context;)Lcom/google/common/util/concurrent/ListenableFuture; in class Landroidx/camera/core/CameraX; or its super classes (declaration of '' appears in /data/app/.tutorial2020-1/) at (:149) at .(:36) at (:6161) at (:1112) at (:2507) at (:2640) at $800(:182) at $(:1493) at (:111) at (:194) at (:5682) at (Native Method) at (:372) at $(:963) at (:758) ```
Permissions
Need to apply dynamicallyPermissions
<uses-permission android:name="" />
This article skips the places where dynamic application permissions are applied
interface
CameraX has prepared for developers with thoughtfulness
Put it in a FrameLayout, as shown below act_simple_preivew_x.layout
<?xml version="1.0" encoding="utf-8"?> <layout> <FrameLayout xmlns:andro android: android:layout_width="match_parent" android:layout_height="match_parent"> < android: android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> </layout>
Turn on preview
Turn on camera preview in activity
// import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; // import .; // import .; import ; public class SimplePreviewXAct extends AppCompatActivity { private ActSimplePreivewXBinding mBinding; private ListenableFuture<ProcessCameraProvider> cameraProviderFuture; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { (savedInstanceState); mBinding = (this, .act_simple_preivew_x); cameraProviderFuture = (this); (() -> { try { ProcessCameraProvider cameraProvider = (); bindPreview(cameraProvider); } catch (ExecutionException | InterruptedException e) { // No need to deal with it here } }, (this)); } void bindPreview(@NonNull ProcessCameraProvider cameraProvider) { Preview preview = new ().build(); CameraSelector cameraSelector = new () .requireLensFacing(CameraSelector.LENS_FACING_BACK) .build(); (()); Camera camera = (this, cameraSelector, preview); } }
Note that we are using
To obtain ProcessCameraProvider, useMethod to get one
cameraProviderFuture
。
existcameraProviderFuture
Remove ProcessCameraProvider after completion (cameraProvider
)。
To enable preview,Build a Preview. Use CameraSelector to select the rear camera.
Preview's SurfaceProvider is provided by the layout.
After binding, start the camera preview
Run the test
Run it to your phone, open this Activity and you can see the camera preview. The aspect ratio of the image is normal and there is no stretching phenomenon.
Honor EMUI 3.1 Lite, Android 5.1 is running normally
Redmi 9A, MIUI 12.5.1 stable version, Android 10 runs normally
OnePlus 5, H2OS 10.0.3, Android 10 is running normally
Add switch
Add 2 buttons to the layout to control the camera switch
<?xml version="1.0" encoding="utf-8"?> <layout> <LinearLayout xmlns:andro android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimaryDark" android:gravity="center" android:orientation="horizontal" android:padding="4dp"> <Button android: style="@style/NormalBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Open" /> <Button android: style="@style/NormalBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="12dp" android:text="closure" /> </LinearLayout> <FrameLayout xmlns:andro android: android:layout_width="match_parent" android:layout_height="match_parent"> < android: android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> </LinearLayout> </layout>
Change the root layout to LinearLayout
RevisebindPreview
Method, first check whether the incoming ProcessCameraProvider is empty
private void bindPreview(ProcessCameraProvider cameraProvider) { if (cameraProvider == null) { (getApplicationContext(), "No camera was obtained", Toast.LENGTH_SHORT).show(); return; } Preview preview = new ().build(); CameraSelector cameraSelector = new () .requireLensFacing(CameraSelector.LENS_FACING_BACK) .build(); (()); Camera camera = (this, cameraSelector, preview); }
Modified activity part code
import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; // import .; // import .; import ; public class SimplePreviewXAct extends AppCompatActivity { private ActSimplePreivewXBinding mBinding; private ListenableFuture<ProcessCameraProvider> mCameraProviderFuture; private ProcessCameraProvider mCameraProvider; private boolean mRunning = false; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { (savedInstanceState); mBinding = (this, .act_simple_preivew_x); mCameraProviderFuture = (this); (() -> { try { mCameraProvider = (); } catch (ExecutionException | InterruptedException e) { // No need to deal with it here } }, (this)); (v -> { if (mCameraProvider != null && !mRunning) { bindPreview(mCameraProvider); } }); (v -> { (); mRunning = false; }); } private void bindPreview(ProcessCameraProvider cameraProvider) { if (cameraProvider == null) { (getApplicationContext(), "No camera was obtained", Toast.LENGTH_SHORT).show(); return; } Preview preview = new ().build(); CameraSelector cameraSelector = new () .requireLensFacing(CameraSelector.LENS_FACING_BACK) .build(); (()); Camera camera = (this, cameraSelector, preview); mRunning = true; } }
Get itmCameraProvider
Do not bind the life cycle immediately afterwards.
If you want to enable preview, callbindPreview(mCameraProvider)
. Record that the camera has now been turned onmRunning = true
。
If you want to stop previewing, unbind your life cycle()
. This method needs to be called in the main thread.
After running, you can use buttons to control the switch for the camera preview. Compared to before, the height of the PreviewView has become a little smaller (let the point position to the button).
However, the video's aspect ratio is normal and it is not stretched. Under the default configuration, there is also the function of autofocus.
summary
Judging from the simple camera preview, CameraX simplifies the work of developers. PreviewView is provided, developers do not need to customize SurfaceView or TextureView. In real-time preview, the camera can focus automatically. This article uses 1.1.0-alpha11, while CameraX is still in development.
This is the end of this article about Android CameraX's preview tutorial. For more information about Android CameraX's preview content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!