A quick guide to get you started on using the new Android Jetpack CameraX API using 4 different use cases.
In this tutorial, we will implement Google's new camera API called Camera X using Java. The camera X implemented in our app will contain use cases such as Image Preview, Image Capture, Image analysis and video capture use case.
Create a blank Project
When prompted, click Sync Now.
Let's add a basic layout for the application. Our layout will contain two buttons, the first one is to capture the image and the second one is to record video and a preview view to display the camera x preview.
The following topics will be covered in this lesson:
- Implement basic camera x in java
- Image Capture use case
- Image Analysis use case
- Video Capture use case
This tutorial is also covered in detail in this video:
Step by Step Implementation
Let's start by creating a new blank project.
- Start a new Android Studio Project
- Choose Empty Activity, Next
- Name: CameraX In Java
- Package name: com.codingreel.cameraxjava
- Language: Java
- Finish
- Start your project now
This is a simple hello world project containing only one activity, i.e: MainActivity.
def cameraxVersion = "1.1.0-alpha05"
implementation "androidx.camera:camera-core:${cameraxVersion}"
implementation "androidx.camera:camera-camera2:${cameraxVersion}"
implementation "androidx.camera:camera-lifecycle:${cameraxVersion}"
// CameraX View class
implementation 'androidx.camera:camera-view:1.0.0-alpha25'
When prompted, click Sync Now.
Our project is ready with dependencies.
Add permissions in the AndroidManifest.xml
We need four permissions in the manifest file
- CAMERA
- RECORD_AUDIO
- WRITE_EXTERNAL_STORAGE
- READ_EXTERNAL_STORAGE
Let's add a basic layout for the application. Our layout will contain two buttons, the first one is to capture the image and the second one is to record video and a preview view to display the camera x preview.
Our application will now look like this, great!
Note: Layout code is omitted.
Java Code Implementation:
Now, let's move on to the Java code implementation. We'll start by initializing the CameraX provider and camera provider instance.
cameraProviderFuture = ProcessCameraProvider.getInstance(this);
cameraProviderFuture.addListener(() -> {
try {
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
startCameraX(cameraProvider);
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}, getExecutor());
We'll also create a utility function to get the executor.
Executor getExecutor() {
return ContextCompat.getMainExecutor(this);
}
Next, we'll unbind any previous use case bindings and select the default camera (in this case, the back camera). We'll implement the preview use case by attaching a surface provider to the preview view obtained from the layout.
cameraProvider.unbindAll();
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();
Preview preview = new Preview.Builder()
.build();
preview.setSurfaceProvider(previewView.getSurfaceProvider());
Following that, we'll implement the image capture use case, allowing users to capture photos. We'll create a function to handle the capture photo action, which involves obtaining the photo directory, checking its existence, and creating a file with a timestamp as the file name. We'll use the image capture use case to capture the photo.
// Image capture use case
imageCapture = new ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build();
private void capturePhoto() {
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(),
getExecutor(),
new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
Toast.makeText(MainActivity.this, "Photo has been saved successfully.", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(@NonNull ImageCaptureException exception) {
Toast.makeText(MainActivity.this, "Error saving photo: " + exception.getMessage(), Toast.LENGTH_SHORT).show();
}
}
);
}
To enable video recording, we'll implement the video capture use case. When the user clicks on the start recording button, the video capture use case will begin recording. We'll handle the stop recording action and show a toast message indicating the success or failure of video saving.
// Video capture use case
videoCapture = new VideoCapture.Builder()
.setVideoFrameRate(30)
.build();
@SuppressLint("RestrictedApi")
private void recordVideo() {
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");
try {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
videoCapture.startRecording(
new VideoCapture.OutputFileOptions.Builder(
getContentResolver(),
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
contentValues
).build(),
getExecutor(),
new VideoCapture.OnVideoSavedCallback() {
@Override
public void onVideoSaved(@NonNull VideoCapture.OutputFileResults outputFileResults) {
Toast.makeText(MainActivity.this, "Video has been saved successfully.", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) {
Toast.makeText(MainActivity.this, "Error saving video: " + message, Toast.LENGTH_SHORT).show();
}
}
);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Lastly, we'll explore the image analysis use case, which allows for image processing and manipulation. We'll implement the image analysis analyzer callback and perform our desired image processing operations within the analyze method.
// Image analysis use case
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build();
imageAnalysis.setAnalyzer(getExecutor(), this);
@Override
public void analyze(@NonNull ImageProxy image) {
// image processing here for the current frame
Log.d("TAG", "analyze: got the frame at: " + image.getImageInfo().getTimestamp());
image.close();
}
Run the Application:
After implementing the code, we can run the application to test its
functionality. We should be able to see the camera preview, capture
photos, and record videos successfully.
Complete Code: https://github.com/Faisal-FS/CameraX-In-Java
Conclusion:
In this blog post, we learned how to implement the CameraX API in Java using Android Studio. We covered the preview, image capture, video capture, and image analysis use cases. CameraX simplifies camera development and provides a powerful set of features for creating camera-related applications. Feel free to explore further and enhance your app with additional functionalities using the CameraX API.
No comments:
Post a Comment
Share your thoughts ...