Add CameraActivity utility class to automate Camera permission request handling

This commit is contained in:
Giles Payne 2019-07-20 13:40:10 +09:00
parent f6ec0cd827
commit 2734291b35
10 changed files with 186 additions and 35 deletions

View File

@ -0,0 +1,60 @@
package org.opencv.android;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import static android.Manifest.permission.CAMERA;
public class CameraActivity extends Activity {
private static final int CAMERA_PERMISSION_REQUEST_CODE = 200;
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return new ArrayList<CameraBridgeViewBase>();
}
protected void onCameraPermissionGranted() {
List<? extends CameraBridgeViewBase> cameraViews = getCameraViewList();
if (cameraViews == null) {
return;
}
for (CameraBridgeViewBase cameraBridgeViewBase: cameraViews) {
if (cameraBridgeViewBase != null) {
cameraBridgeViewBase.setCameraPermissionGranted();
}
}
}
@Override
protected void onStart() {
super.onStart();
boolean havePermission = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
havePermission = false;
}
}
if (havePermission) {
onCameraPermissionGranted();
}
}
@Override
@TargetApi(Build.VERSION_CODES.M)
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == CAMERA_PERMISSION_REQUEST_CODE && grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
onCameraPermissionGranted();
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

View File

@ -48,6 +48,7 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac
protected int mPreviewFormat = RGBA;
protected int mCameraIndex = CAMERA_ID_ANY;
protected boolean mEnabled;
protected boolean mCameraPermissionGranted = false;
protected FpsMeter mFpsMeter = null;
public static final int CAMERA_ID_ANY = -1;
@ -219,9 +220,24 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac
}
}
/**
* This method is provided for clients, so they can signal camera permission has been granted.
* The actual onCameraViewStarted callback will be delivered only after setCameraPermissionGranted
* and enableView have been called and surface is available
*/
public void setCameraPermissionGranted() {
synchronized(mSyncObject) {
mCameraPermissionGranted = true;
checkCurrentState();
}
}
/**
* This method is provided for clients, so they can enable the camera connection.
* The actual onCameraViewStarted callback will be delivered only after both this method is called and surface is available
* The actual onCameraViewStarted callback will be delivered only after setCameraPermissionGranted
* and enableView have been called and surface is available
*/
public void enableView() {
synchronized(mSyncObject) {
@ -300,7 +316,7 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac
Log.d(TAG, "call checkCurrentState");
int targetState;
if (mEnabled && mSurfaceExist && getVisibility() == VISIBLE) {
if (mEnabled && mCameraPermissionGranted && mSurfaceExist && getVisibility() == VISIBLE) {
targetState = STARTED;
} else {
targetState = STOPPED;

View File

@ -1,6 +1,7 @@
package org.opencv.samples.puzzle15;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
@ -9,7 +10,6 @@ import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener;
import org.opencv.android.JavaCameraView;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@ -17,7 +17,10 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
public class Puzzle15Activity extends Activity implements CvCameraViewListener, View.OnTouchListener {
import java.util.Collections;
import java.util.List;
public class Puzzle15Activity extends CameraActivity implements CvCameraViewListener, View.OnTouchListener {
private static final String TAG = "Sample::Puzzle15::Activity";
@ -86,6 +89,11 @@ public class Puzzle15Activity extends Activity implements CvCameraViewListener,
}
}
@Override
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)

View File

@ -14,6 +14,7 @@
package org.opencv.samples.cameracalibration;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
@ -21,7 +22,6 @@ import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.res.Resources;
import android.os.AsyncTask;
@ -36,12 +36,16 @@ import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.Toast;
public class CameraCalibrationActivity extends Activity implements CvCameraViewListener2, OnTouchListener {
import java.util.Collections;
import java.util.List;
public class CameraCalibrationActivity extends CameraActivity implements CvCameraViewListener2, OnTouchListener {
private static final String TAG = "OCVSample::Activity";
private CameraBridgeViewBase mOpenCvCameraView;
private CameraCalibrator mCalibrator;
private OnCameraFrameRender mOnCameraFrameRender;
private Menu mMenu;
private int mWidth;
private int mHeight;
@ -101,6 +105,11 @@ public class CameraCalibrationActivity extends Activity implements CvCameraViewL
}
}
@Override
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
@ -111,7 +120,7 @@ public class CameraCalibrationActivity extends Activity implements CvCameraViewL
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.calibration, menu);
mMenu = menu;
return true;
}
@ -119,9 +128,9 @@ public class CameraCalibrationActivity extends Activity implements CvCameraViewL
public boolean onPrepareOptionsMenu (Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.preview_mode).setEnabled(true);
if (!mCalibrator.isCalibrated())
if (mCalibrator != null && !mCalibrator.isCalibrated()) {
menu.findItem(R.id.preview_mode).setEnabled(false);
}
return true;
}
@ -199,6 +208,10 @@ public class CameraCalibrationActivity extends Activity implements CvCameraViewL
mCalibrator = new CameraCalibrator(mWidth, mHeight);
if (CalibrationResult.tryLoad(this, mCalibrator.getCameraMatrix(), mCalibrator.getDistortionCoefficients())) {
mCalibrator.setCalibrated();
} else {
if (mMenu != null && !mCalibrator.isCalibrated()) {
mMenu.findItem(R.id.preview_mode).setEnabled(false);
}
}
mOnCameraFrameRender = new OnCameraFrameRender(new CalibrationFrameRender(mCalibrator));

View File

@ -1,8 +1,10 @@
package org.opencv.samples.colorblobdetect;
import java.util.Collections;
import java.util.List;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
@ -27,7 +29,7 @@ import android.view.WindowManager;
import android.view.View.OnTouchListener;
import android.view.SurfaceView;
public class ColorBlobDetectionActivity extends Activity implements OnTouchListener, CvCameraViewListener2 {
public class ColorBlobDetectionActivity extends CameraActivity implements OnTouchListener, CvCameraViewListener2 {
private static final String TAG = "OCVSample::Activity";
private boolean mIsColorSelected = false;
@ -99,6 +101,11 @@ public class ColorBlobDetectionActivity extends Activity implements OnTouchListe
}
}
@Override
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)

View File

@ -4,8 +4,11 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
@ -28,7 +31,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.WindowManager;
public class FdActivity extends Activity implements CvCameraViewListener2 {
public class FdActivity extends CameraActivity implements CvCameraViewListener2 {
private static final String TAG = "OCVSample::Activity";
private static final Scalar FACE_RECT_COLOR = new Scalar(0, 255, 0, 255);
@ -150,6 +153,11 @@ public class FdActivity extends Activity implements CvCameraViewListener2 {
}
}
@Override
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
public void onDestroy() {
super.onDestroy();
mOpenCvCameraView.disableView();

View File

@ -1,8 +1,11 @@
package org.opencv.samples.imagemanipulations;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
@ -18,14 +21,13 @@ import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.imgproc.Imgproc;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.WindowManager;
public class ImageManipulationsActivity extends Activity implements CvCameraViewListener2 {
public class ImageManipulationsActivity extends CameraActivity implements CvCameraViewListener2 {
private static final String TAG = "OCVSample::Activity";
public static final int VIEW_MODE_RGBA = 0;
@ -121,6 +123,11 @@ public class ImageManipulationsActivity extends Activity implements CvCameraView
}
}
@Override
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)

View File

@ -1,6 +1,7 @@
package org.opencv.samples.tutorial1;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
@ -8,16 +9,16 @@ import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.Toast;
public class Tutorial1Activity extends Activity implements CvCameraViewListener2 {
import java.util.Collections;
import java.util.List;
public class Tutorial1Activity extends CameraActivity implements CvCameraViewListener2 {
private static final String TAG = "OCVSample::Activity";
private CameraBridgeViewBase mOpenCvCameraView;
@ -82,6 +83,11 @@ public class Tutorial1Activity extends Activity implements CvCameraViewListener2
}
}
@Override
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)

View File

@ -1,6 +1,7 @@
package org.opencv.samples.tutorial2;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
@ -10,14 +11,16 @@ import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.imgproc.Imgproc;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.WindowManager;
public class Tutorial2Activity extends Activity implements CvCameraViewListener2 {
import java.util.Collections;
import java.util.List;
public class Tutorial2Activity extends CameraActivity implements CvCameraViewListener2 {
private static final String TAG = "OCVSample::Activity";
private static final int VIEW_MODE_RGBA = 0;
@ -107,6 +110,11 @@ public class Tutorial2Activity extends Activity implements CvCameraViewListener2
}
}
@Override
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)

View File

@ -1,11 +1,14 @@
package org.opencv.samples.tutorial3;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.ListIterator;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
@ -13,7 +16,6 @@ import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Environment;
@ -28,11 +30,14 @@ import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.Toast;
public class Tutorial3Activity extends Activity implements CvCameraViewListener2, OnTouchListener {
public class Tutorial3Activity extends CameraActivity implements CvCameraViewListener2, OnTouchListener {
private static final String TAG = "OCVSample::Activity";
private Tutorial3View mOpenCvCameraView;
private List<Size> mResolutionList;
private Menu mMenu;
private boolean mCameraStarted = false;
private boolean mMenuItemsCreated = false;
private MenuItem[] mEffectMenuItems;
private SubMenu mColorEffectsMenu;
private MenuItem[] mResolutionMenuItems;
@ -97,13 +102,21 @@ public class Tutorial3Activity extends Activity implements CvCameraViewListener2
}
}
@Override
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
@Override
public void onCameraViewStarted(int width, int height) {
mCameraStarted = true;
setupMenuItems();
}
public void onCameraViewStopped() {
@ -115,38 +128,43 @@ public class Tutorial3Activity extends Activity implements CvCameraViewListener2
@Override
public boolean onCreateOptionsMenu(Menu menu) {
mMenu = menu;
setupMenuItems();
return true;
}
private void setupMenuItems() {
if (mMenu == null || !mCameraStarted || mMenuItemsCreated) {
return;
}
List<String> effects = mOpenCvCameraView.getEffectList();
if (effects == null) {
Log.e(TAG, "Color effects are not supported by device!");
return true;
return;
}
mColorEffectsMenu = menu.addSubMenu("Color Effect");
mColorEffectsMenu = mMenu.addSubMenu("Color Effect");
mEffectMenuItems = new MenuItem[effects.size()];
int idx = 0;
ListIterator<String> effectItr = effects.listIterator();
while(effectItr.hasNext()) {
String element = effectItr.next();
mEffectMenuItems[idx] = mColorEffectsMenu.add(1, idx, Menu.NONE, element);
idx++;
for (String effect: effects) {
mEffectMenuItems[idx] = mColorEffectsMenu.add(1, idx, Menu.NONE, effect);
idx++;
}
mResolutionMenu = menu.addSubMenu("Resolution");
mResolutionMenu = mMenu.addSubMenu("Resolution");
mResolutionList = mOpenCvCameraView.getResolutionList();
mResolutionMenuItems = new MenuItem[mResolutionList.size()];
ListIterator<Size> resolutionItr = mResolutionList.listIterator();
idx = 0;
while(resolutionItr.hasNext()) {
Size element = resolutionItr.next();
for (Size resolution: mResolutionList) {
mResolutionMenuItems[idx] = mResolutionMenu.add(2, idx, Menu.NONE,
Integer.valueOf(element.width).toString() + "x" + Integer.valueOf(element.height).toString());
Integer.valueOf(resolution.width).toString() + "x" + Integer.valueOf(resolution.height).toString());
idx++;
}
return true;
}
mMenuItemsCreated = true;
}
public boolean onOptionsItemSelected(MenuItem item) {