[MUSIC PLAYING]
DONOVAN MCMURRAY: Hi, Donovan here.
And in this video, we're going to create an Android
app that uses the CameraX API.
The app will show a camera preview
and have a button that allows the user to take a photo.
This video covers adding all of the required dependencies,
creating the view layout, and requesting
the necessary permissions.
Most of this setup applies to both the camera controller
and camera provider code paths, unless I specify otherwise.
This video is part of the CameraX foundation series.
So, if you aren't familiar with the basics of CameraX,
go back and watch the CameraX Concepts video.
The link is in this video's description.
After this video, you can watch the CameraController video
or the CameraProvider video to see
how to finish this photo taking app with each code path.
All right, I've got my Android developer shirt on.
So, I'm ready to go.
Let's jump into Android Studio.
OK, we'll start off in Android Studio
by creating a new project with the Empty Activity template.
You can name your project whatever you'd like.
I'm going to call it "CameraX App"
for the purposes of this video.
Once Android Studio has finished its setup,
open the module build.gradle file
to add dependencies for CameraX.
First, define the version of CameraX that you need.
1.2.0 is the most recent stable release.
You can check all of the CameraX versions
in the CameraX releases link in this video's description.
CameraX has separate libraries so that you only
need to include the dependencies that you need.
First, import the camera-core library
and the camera-camera2 library.
These are the fundamental CameraX libraries.
CameraX is built on camera2, Android's low-level framework
camera API.
Conceptually, CameraX takes the set of use cases specified
by the developer and combines them
into a running camera2 capture session.
Technically, camera-camera2 will indirectly import camera-core,
but we're explicitly including it for demonstration purposes.
Next, we need to import the camera-view library to get
CameraX's preview view class.
Then if you'll be using a camera provider,
you need to import the camera-lifecycle library
as well.
Also for camera provider, there are
some non-CameraX dependencies that we'll use.
Add the concurrent future's KTX dependency
and the lifecycle runtime KTX dependency, like so.
Also, check the version of Java your app is using.
CameraX needs some methods that are part of Java 8.
So, we need to set our compile options accordingly.
Finally, this example will use view binding.
So, at the end of the Android block,
add a build features block, setting view binding to true.
Next, go into res/values/string.XML to add
a label for our Take Photo button.
Then go to res/layout/activitymain.XML
to set up the views for this app.
First, add CameraX's preview view.
You don't have to use a preview view with CameraX
if you're using a camera provider, but doing so
allows CameraX to handle a number of details
for you, like managing the preview lifecycle
and choosing a surface implementation on your behalf.
Next, define a button that will trigger taking a photo.
It has a number of layout settings,
and we want to add the take photo text to it.
Now, to declare the permissions that the app needs to request,
go to the Android manifest.XML file.
The first thing to add is a uses-feature tag
to declare that this app needs camera hardware.
For example, Google Play makes use
of this uses-feature element from your app
manifest to filter your app from devices
that do not have a camera.
Then add these uses-permission tags to request camera access
and, on devices running Android P
and before, write external storage access.
Now, let's head over to the main activity for the app.
First, add a private variable to the main activity for the view
binding.
We'll initialize this later in the On Create method.
Now, if you're going to use a CameraController,
declare it here so that we can access it throughout the file
once it's initialized.
I'll explain this more in the CameraController video.
On the other hand, if you're going
to use a CameraProvider, then instead we
need to declare an image capture use case here
to have a reference to it throughout the file.
Now, we're back on the code for both CameraController
and CameraProvider.
In the On Create method, initialize
the view binding with ActivityMainBinding.inflate.
Also, change the call to set content view
to pass in viewBinding.root.
Next, add a companion object to main activity
with some app constants.
The tag, constant, is used whenever we need the app
name, such as for logging.
The file name format will be used to name saved images.
Then we'll have some permission utilities
that we'll use in a minute.
Set the required permissions to have camera,
and if your app targets Android P or before,
you'll also want to add write external storage.
If you don't need to target those older versions,
you can remove this call to apply.
The has permissions function will tell us
if all permissions have already been granted.
Then save a reference to the activity result launcher
returned from calling register for activity
result for multiple permissions, passing in an activity result
callback as a Lambda function where
we check if all of the required permissions
were indeed granted.
This app can't do anything without camera permissions.
So, if they aren't granted, the app is unusable.
In any app you release to users, you
should gracefully handle cases where
permissions aren't granted.
See the guide on requesting runtime permissions
in the video description below for more.
In this app, if their permissions weren't granted,
all we can do is display a message
stating that the permissions were denied.
If all permissions were granted, then start the camera.
The start camera implementation will
be discussed in the next video.
We have one more thing to do.
So, finally, add this code to the On Create method
to check if the required permissions were
granted in a previous session.
If not, then launch the permissions activity request
launcher to request them now.
If all of the necessary permissions are there,
then you can go ahead and start the camera.
The next thing to do is to define the start camera
function, but like I mentioned earlier, that will
be covered in the next video.
There are two ways to implement Start Camera using CameraX.
You can use a CameraController or a CameraProvider.
CameraController requires less setup code, and as a result,
CameraController handles more functionality for you.
For example, it provides out-of-the-box tap to focus
and pinch to zoom functionality.
On the other hand, CameraProvider
allows for more control, but that
means that you'll have to handle more of this set up yourself.
Examples of customizations you can add with CameraProvider
are enabling output image rotation
or setting the output image format in image analysis.
Both CameraController and CameraProvider
have their own videos that I hope you check out next.
So, pick the one best for your needs,
and I'll see you in the next one.