camera2 api to android marshmallow
Tutorial that describes how to upgrade the android camera2 api to android marshmallow. For this android tutorial we need camera & write storage permissions.
The android camera2 api application requires in theory three permissions to function, read external storage access for the recyclerview gallery, camera permission to access the camera2 services and write external storage permission for saving the captured images to external storage.
But because with write external external storage already providing by default the read external storage permission, we will just be setting up two android marshmallow runtime permissions for this tutorial, camera & write external storage.
This tutorial will describe the steps required to provide the write external storage & camera services using the new android marshmallow runtime permissions.
Get Code
The code is now on github you can get it from here
https://github.com/mobapptuts/recyclerview_image_gallery.git Tag camera2-marshmallow
or else run this command
git clone –branch camera2-marshmallow https://github.com/mobapptuts/recyclerview_image_gallery.git
Code Samples
Change SDK version & add appcompat v7 library support
build.gradle
apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion "23.0.1" defaultConfig { applicationId "com.nigelhenshaw.camera2apiapp" minSdkVersion 21 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:recyclerview-v7:21.0.+' compile 'com.android.support:appcompat-v7:23.1.1' }
Add activity members for the camera & write external storage request results
private static final int REQUEST_WRITE_STORAGE_RESULT = 1; private static final int REQUEST_CAMERA_RESULT = 2;
Inside the activity’s onCreate method add the runtime request for write external storage
The write external storage permission will support both the reading of images for the recyclerview gallery & the saving captured images to external storage
mRecyclerView.setLayoutManager(layoutManager); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { RecyclerView.Adapter imageAdapter = new ImageAdapter(sortFilesToLatest(mGalleryFolder), this); mRecyclerView.setAdapter(imageAdapter); } else { if(shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { Toast.makeText(this, "We need write storage permission to start the gallery and save images", Toast.LENGTH_SHORT).show(); } requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE_RESULT); } } else { RecyclerView.Adapter imageAdapter = new ImageAdapter(sortFilesToLatest(mGalleryFolder), this); mRecyclerView.setAdapter(imageAdapter); }
Inside the openCamera method add the runtime permission request for camera
private void openCamera() { CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler); } else { if(shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) { Toast.makeText(this, "No permission to use the camera services", Toast.LENGTH_SHORT).show(); } requestPermissions(new String[] {Manifest.permission.CAMERA}, REQUEST_CAMERA_RESULT); } } else { cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler); } } catch (CameraAccessException e) { e.printStackTrace(); } }
Implement the request permission results callback
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch(requestCode) { case REQUEST_CAMERA_RESULT: if(grantResults[0] != PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "Cannot run application because camera service permissions have not been granted", Toast.LENGTH_SHORT).show(); } break; case REQUEST_WRITE_STORAGE_RESULT: if(grantResults[0] == PackageManager.PERMISSION_GRANTED) { RecyclerView.Adapter imageAdapter = new ImageAdapter(sortFilesToLatest(mGalleryFolder), this); mRecyclerView.setAdapter(imageAdapter); } else { Toast.makeText(this, "Don't have permission to start the gallery or save images", Toast.LENGTH_SHORT).show(); } break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } }
Add the lock focus support
private CameraCaptureSession.CaptureCallback mSessionCaptureCallback = new CameraCaptureSession.CaptureCallback() { private void process(CaptureResult result) { switch(mState) { case STATE_PREVIEW: // Do nothing break; case STATE__WAIT_LOCK: Integer afState = result.get(CaptureResult.CONTROL_AF_STATE); if(afState == CaptureRequest.CONTROL_AF_STATE_FOCUSED_LOCKED || afState == CaptureRequest.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) { /* unLockFocus(); Toast.makeText(getApplicationContext(), "Focus Lock Successful", Toast.LENGTH_SHORT).show(); */ mState = STATE__PICTURE_CAPTURED; captureStillImage(); } break; } }