To understand Camera2 API take a fast look into sample repo and official documentation
First of all create empty project in Android Studio, like on tutorial
So let's create instrumented tests for running tests on android device, according to documentation. Why? Because good programmer write tests. For testing hid own code, for testing other's code. Running tests on android device is wonderful solution. According to tutorial we have to do:
app/src/androidTest/java
- if yes you have already configured instrumented tests.
com.example.myapplication
.
build.gradle
you should have in dependencies test:runner
and test:rules
as follows (versions may differs, if these packages are from com.android.support.test
change it to androidx.text
):
dependencies { androidTestImplementation 'androidx.test:runner:1.1.0' androidTestImplementation 'androidx.test:rules:1.1.0' }
testInstrumentationRunner
in build.gradle
as follows:
android { ... defaultConfig { ... testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } }
First of all we would like to just "open camera" using method:
so we need cameraId (obtained from CameraManager
),
// get context (remember to use getTargetContext()) Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); // get camera manager CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); // iterate over all device's cameras String cameraId = null; for (String camId : manager.getCameraIdList()) { // and choose apropriete one, based on camera characteristics CameraCharacteristics characteristics = manager.getCameraCharacteristics(camId); Integer LENS_FACING = characteristics.get(CameraCharacteristics.LENS_FACING); if (LENS_FACING != null && LENS_FACING == CameraCharacteristics.LENS_FACING_BACK) { cameraId = camId; break; } }
CameraDevice.StateCallback
object (which we will create),
(to avoid problems, define these elements inside test class, not inside of test method)
// create variable for holding device private CameraDevice cameraDevice; // create state object, to pass to open method. Implements required methods private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { // this method is most important for us. Assign opened device to our variable defined above cameraDevice = camera; } @Override public void onDisconnected(@NonNull CameraDevice camera) { camera.close(); } @Override public void onError(@NonNull CameraDevice camera, int error) { camera.close(); } };
and Handler
object.
HandlerThread mBackgroundThread = new HandlerThread("CameraThread"); mBackgroundThread.start(); Handler backgroundHandler = new Handler(mBackgroundThread.getLooper());
Open camera
manager.openCamera(cameraId, mStateCallback, backgroundHandler);
At the end run test class
<uses-permission android:name="android.permission.CAMERA" />
into AndroidManifest.xml
If you got error Lacking privileges to access camera service
, google for it! and add
@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Manifest.permission.<PROPER_PREMISSION>);
If you got error No instrumentation registered! Must run under a registering instrumentation
, google for it! and change android.support
to androidx
packages. According to documentation. At the end, if no method helps, remove Run configuration
from Android Studio, and create new one for invoking tests.
Test can be run on VirtualMachine as well
package com.example.myapplication; import android.Manifest; import android.content.Context; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.os.Handler; import android.os.HandlerThread; import android.util.Log; import androidx.annotation.NonNull; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.rule.GrantPermissionRule; import androidx.test.runner.AndroidJUnit4; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest public class ExampleInstrumentedTest { @Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Manifest.permission.CAMERA); // create variable for holding device private CameraDevice cameraDevice; // create state object, to pass to open method. Implements required methods private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { // this method is most important for us. Assign opened device to our variable defined above cameraDevice = camera; Log.d("ExampleInstrumentedTest", "CameraDevice.StateCallback::onOpened"); } @Override public void onDisconnected(@NonNull CameraDevice camera) { camera.close(); } @Override public void onError(@NonNull CameraDevice camera, int error) { camera.close(); } }; @Test public void test1() throws CameraAccessException { // get context (remember to use getTargetContext()) Context context = InstrumentationRegistry.getTargetContext(); // get camera manager CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); // iterate over all device's cameras String cameraId = null; for (String camId : manager.getCameraIdList()) { // and choose apropriete one, based on camera characteristics CameraCharacteristics characteristics = manager.getCameraCharacteristics(camId); Integer LENS_FACING = characteristics.get(CameraCharacteristics.LENS_FACING); if (LENS_FACING != null && LENS_FACING == CameraCharacteristics.LENS_FACING_BACK) { cameraId = camId; break; } } HandlerThread mBackgroundThread = new HandlerThread("CameraThread"); mBackgroundThread.start(); Handler backgroundHandler = new Handler(mBackgroundThread.getLooper()); if (cameraId != null) { manager.openCamera(cameraId, mStateCallback, backgroundHandler); } } }
In next post we will create CaptureSession and capture first photo.