diff options
author | Eino-Ville Talvala <etalvala@google.com> | 2015-04-08 17:32:28 -0700 |
---|---|---|
committer | Eino-Ville Talvala <etalvala@google.com> | 2015-04-08 17:32:28 -0700 |
commit | 36dcae7c5cbc7ea8bef1e14d0be005c8c8c75ecf (patch) | |
tree | e093766a3eddb22d07fc768117ef0b963ab6405d /apps | |
parent | 6a0fcc827ef8b03b5648b0d3b4c14f8bde82e551 (diff) | |
download | pdk-36dcae7c5cbc7ea8bef1e14d0be005c8c8c75ecf.tar.gz |
TestingCamera, TestingCamera2: Add runtime permission checking
The permission requests are placed largely where it is easiest to do,
though some effort is made to not ask for a permission before it's actually
needed.
Change-Id: Ia484d6741da6a6c5ab812ecf2bbadc5d9ce81572
Diffstat (limited to 'apps')
8 files changed, 193 insertions, 17 deletions
diff --git a/apps/TestingCamera/AndroidManifest.xml b/apps/TestingCamera/AndroidManifest.xml index 36c21ca..415364c 100644 --- a/apps/TestingCamera/AndroidManifest.xml +++ b/apps/TestingCamera/AndroidManifest.xml @@ -22,7 +22,7 @@ <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" /> - <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="17"/> + <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="10000"/> <uses-feature android:name="android.hardware.camera.front" android:required="false"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> diff --git a/apps/TestingCamera/src/com/android/testingcamera/SnapshotDialogFragment.java b/apps/TestingCamera/src/com/android/testingcamera/SnapshotDialogFragment.java index 6995320..3b1f19d 100644 --- a/apps/TestingCamera/src/com/android/testingcamera/SnapshotDialogFragment.java +++ b/apps/TestingCamera/src/com/android/testingcamera/SnapshotDialogFragment.java @@ -4,6 +4,8 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import android.Manifest; +import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.ExifInterface; @@ -118,6 +120,17 @@ class SnapshotDialogFragment extends DialogFragment mJpegImage = image; } + public void onRequestPermissionsResult(int requestCode, String[] permissions, + int[] grantResults) { + TestingCamera parent = (TestingCamera) getActivity(); + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + parent.log("Storage write permission granted"); + saveFile(); + } else { + parent.log("Denied storage write permission; cannot save"); + } + } + private String getAttrib(ExifInterface exif, String tag) { String attribute = exif.getAttribute(tag); return (attribute == null) ? "???" : attribute; @@ -128,6 +141,14 @@ class SnapshotDialogFragment extends DialogFragment TestingCamera parent = (TestingCamera) getActivity(); parent.log("Saving image"); + if (parent.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + parent.log("Requesting storage write permission"); + parent.requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, + parent.PERMISSIONS_REQUEST_SNAPSHOT); + return; + } + File targetFile = parent.getOutputMediaFile(TestingCamera.MEDIA_TYPE_IMAGE); if (targetFile == null) { parent.logE("Unable to create file name"); diff --git a/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java b/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java index e5ecd0c..8b9dd4f 100644 --- a/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java +++ b/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java @@ -16,9 +16,11 @@ package com.android.testingcamera; +import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; import android.app.FragmentManager; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.ImageFormat; import android.hardware.Camera; @@ -114,6 +116,8 @@ public class TestingCamera extends Activity private TextView mLogView; + SnapshotDialogFragment mSnapshotDialog = null; + private Set<View> mOpenOnlyControls = new HashSet<View>(); private Set<View> mPreviewOnlyControls = new HashSet<View>(); @@ -172,7 +176,9 @@ public class TestingCamera extends Activity /** Misc variables */ private static final String TAG = "TestingCamera"; - + private static final int PERMISSIONS_REQUEST_CAMERA = 1; + private static final int PERMISSIONS_REQUEST_RECORDING = 2; + static final int PERMISSIONS_REQUEST_SNAPSHOT = 3; /** Activity lifecycle */ @@ -331,7 +337,6 @@ public class TestingCamera extends Activity public void onResume() { super.onResume(); log("onResume: Setting up"); - mPreviewHolder = null; setUpCamera(); } @@ -358,6 +363,36 @@ public class TestingCamera extends Activity } } + @Override + public void onRequestPermissionsResult (int requestCode, String[] permissions, + int[] grantResults) { + if (requestCode == PERMISSIONS_REQUEST_CAMERA) { + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + log("Camera permission granted"); + setUpCamera(); + } else { + log("Camera permission denied, can't do anything"); + finish(); + } + } else if (requestCode == PERMISSIONS_REQUEST_RECORDING) { + mRecordToggle.setChecked(false); + for (int i = 0; i < grantResults.length; i++) { + if (grantResults[i] == PackageManager.PERMISSION_DENIED) { + log("Recording permission " + permissions[i] + " denied"); + return; + } + log("Recording permissions granted"); + setUpCamera(); + } + } else if (requestCode == PERMISSIONS_REQUEST_SNAPSHOT) { + if (mSnapshotDialog != null) { + mSnapshotDialog.onRequestPermissionsResult(requestCode, permissions, + grantResults); + } + } + + } + /** SurfaceHolder.Callback methods */ @Override public void surfaceChanged(SurfaceHolder holder, @@ -860,10 +895,10 @@ public class TestingCamera extends Activity public void onPictureTaken(byte[] data, Camera camera) { log("JPEG picture callback received"); FragmentManager fm = getFragmentManager(); - SnapshotDialogFragment snapshotDialog = new SnapshotDialogFragment(); + mSnapshotDialog = new SnapshotDialogFragment(); - snapshotDialog.updateImage(data); - snapshotDialog.show(fm, "snapshot_dialog_fragment"); + mSnapshotDialog.updateImage(data); + mSnapshotDialog.show(fm, "snapshot_dialog_fragment"); mPreviewToggle.setEnabled(true); @@ -945,6 +980,15 @@ public class TestingCamera extends Activity if (mState < CAMERA_OPEN) { log("Opening camera " + mCameraId); + if (checkSelfPermission(Manifest.permission.CAMERA) + != PackageManager.PERMISSION_GRANTED) { + log("Requested camera permission"); + requestPermissions(new String[] {Manifest.permission.CAMERA}, + PERMISSIONS_REQUEST_CAMERA); + return; + } + + try { mCamera = Camera.open(mCameraId); } catch (RuntimeException e) { @@ -1523,6 +1567,19 @@ public class TestingCamera extends Activity private void startRecording() { log("Starting recording"); + + if ((checkSelfPermission(Manifest.permission.RECORD_AUDIO) + != PackageManager.PERMISSION_GRANTED) + || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED)) { + log("Requesting recording permissions (audio, storage)"); + requestPermissions(new String[] { + Manifest.permission.RECORD_AUDIO, + Manifest.permission.WRITE_EXTERNAL_STORAGE}, + PERMISSIONS_REQUEST_RECORDING); + return; + } + logIndent(1); log("Configuring MediaRecoder"); diff --git a/apps/TestingCamera2/AndroidManifest.xml b/apps/TestingCamera2/AndroidManifest.xml index 5127f0e..79c1b7f 100644 --- a/apps/TestingCamera2/AndroidManifest.xml +++ b/apps/TestingCamera2/AndroidManifest.xml @@ -30,7 +30,7 @@ <uses-sdk android:minSdkVersion="21" - android:targetSdkVersion="21" /> + android:targetSdkVersion="10000" /> <uses-feature android:name="android.hardware.camera.front" diff --git a/apps/TestingCamera2/src/com/android/testingcamera2/CameraControlPane.java b/apps/TestingCamera2/src/com/android/testingcamera2/CameraControlPane.java index 00f721e..b220328 100644 --- a/apps/TestingCamera2/src/com/android/testingcamera2/CameraControlPane.java +++ b/apps/TestingCamera2/src/com/android/testingcamera2/CameraControlPane.java @@ -376,8 +376,7 @@ public class CameraControlPane extends ControlPane { if (isChecked) { // Open camera mCurrentCamera = null; - boolean success = mCameraOps.openCamera(mCurrentCameraId, mCameraListener); - buttonView.setChecked(success); + mCameraOps.openCamera(mCurrentCameraId, mCameraListener); } else { // Close camera closeCurrentCamera(); @@ -520,6 +519,7 @@ public class CameraControlPane extends ControlPane { @Override public void onClosed(CameraDevice camera) { // Don't change state on close, tracked by callers of close() + mOpenButton.setChecked(false); } @Override @@ -558,7 +558,6 @@ public class CameraControlPane extends ControlPane { mCurrentCamera.close(); mCurrentCamera = null; setCameraState(CameraState.CLOSED); - mOpenButton.setChecked(false); } } diff --git a/apps/TestingCamera2/src/com/android/testingcamera2/CameraOps2.java b/apps/TestingCamera2/src/com/android/testingcamera2/CameraOps2.java index dcb3cab..ddf0098 100644 --- a/apps/TestingCamera2/src/com/android/testingcamera2/CameraOps2.java +++ b/apps/TestingCamera2/src/com/android/testingcamera2/CameraOps2.java @@ -19,7 +19,9 @@ package com.android.testingcamera2; import java.util.HashSet; import java.util.Set; -import android.content.Context; +import android.Manifest; +import android.app.Activity; +import android.content.pm.PackageManager; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; @@ -32,11 +34,17 @@ import android.hardware.camera2.CameraAccessException; public class CameraOps2 extends CameraManager.AvailabilityCallback { private final CameraManager mCameraManager; - + private final Activity mActivity; private final Set<CameraDevice> mOpenCameras = new HashSet<CameraDevice>(); - public CameraOps2(Context context) { - mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); + // For persisting values for permission requests + private static final int PERMISSIONS_REQUEST_CAMERA = 1; + private String mDelayedOpenId = null; + private CameraDevice.StateCallback mDelayedOpenListener = null; + + public CameraOps2(Activity activity) { + mActivity = activity; + mCameraManager = (CameraManager) activity.getSystemService(Activity.CAMERA_SERVICE); if (mCameraManager == null) { throw new AssertionError("Can't connect to camera manager!"); } @@ -101,6 +109,26 @@ public class CameraOps2 extends CameraManager.AvailabilityCallback { return false; } } + if ((mActivity.checkSelfPermission(Manifest.permission.CAMERA) + != PackageManager.PERMISSION_GRANTED) + || (mActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED)) { + TLog.i("Requesting camera/storage permissions"); + + mDelayedOpenId = cameraId; + mDelayedOpenListener = listener; + + mActivity.requestPermissions(new String[] { + Manifest.permission.CAMERA, + Manifest.permission.WRITE_EXTERNAL_STORAGE }, + PERMISSIONS_REQUEST_CAMERA); + return false; + } + + return doOpenCamera(cameraId, listener); + } + + private boolean doOpenCamera(String cameraId, CameraDevice.StateCallback listener) { try { DeviceStateCallback proxyListener = new DeviceStateCallback(listener); mCameraManager.openCamera(cameraId, proxyListener, null); @@ -112,6 +140,33 @@ public class CameraOps2 extends CameraManager.AvailabilityCallback { return true; } + public void onRequestPermissionsResult (int requestCode, String[] permissions, + int[] grantResults) { + if (requestCode == PERMISSIONS_REQUEST_CAMERA) { + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + TLog.i("Camera permission granted"); + if (mDelayedOpenId != null && mDelayedOpenListener != null) { + doOpenCamera(mDelayedOpenId, mDelayedOpenListener); + } + mDelayedOpenId = null; + mDelayedOpenListener = null; + } else { + TLog.i("Camera permission denied, not opening camera"); + if (mDelayedOpenId != null && mDelayedOpenListener != null) { + mDelayedOpenListener.onError(null, + CameraDevice.StateCallback.ERROR_CAMERA_DISABLED); + mDelayedOpenId = null; + mDelayedOpenListener = null; + } + } + if (grantResults[1] == PackageManager.PERMISSION_GRANTED) { + TLog.i("Storage permission granted"); + } else { + TLog.i("Storage permission not granted; saving will not work"); + } + } + } + public CameraCharacteristics getCameraInfo(String cameraId) { try { return mCameraManager.getCameraCharacteristics(cameraId); diff --git a/apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera21.java b/apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera21.java index c78c401..c15a78c 100644 --- a/apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera21.java +++ b/apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera21.java @@ -184,6 +184,12 @@ public class TestingCamera21 extends Activity implements CameraControlPane.InfoD return super.onOptionsItemSelected(item); } + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, + int[] grantResults) { + mCameraOps.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + /** * Get shared camera controls */ diff --git a/apps/TestingCamera2/src/com/android/testingcamera2/v1/TestingCamera2.java b/apps/TestingCamera2/src/com/android/testingcamera2/v1/TestingCamera2.java index 64fa8a4..9bd3113 100644 --- a/apps/TestingCamera2/src/com/android/testingcamera2/v1/TestingCamera2.java +++ b/apps/TestingCamera2/src/com/android/testingcamera2/v1/TestingCamera2.java @@ -16,7 +16,9 @@ package com.android.testingcamera2.v1; +import android.Manifest; import android.app.Activity; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -108,7 +110,7 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback { private final Set<View> mManualControls = new HashSet<View>(); private final Set<View> mAutoControls = new HashSet<View>(); - + private static final int PERMISSIONS_REQUEST_CAMERA = 1; Handler mMainHandler; boolean mUseMediaCodec; @@ -196,9 +198,45 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback { @Override public void onResume() { super.onResume(); - try { - if (VERBOSE) Log.v(TAG, String.format("onResume")); + if (VERBOSE) Log.v(TAG, String.format("onResume")); + + if ((checkSelfPermission(Manifest.permission.CAMERA) + != PackageManager.PERMISSION_GRANTED ) + || (checkSelfPermission(Manifest.permission.RECORD_AUDIO) + != PackageManager.PERMISSION_GRANTED) + || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED)) { + Log.i(TAG, "Requested camera/video permissions"); + requestPermissions(new String[] { + Manifest.permission.CAMERA, + Manifest.permission.RECORD_AUDIO, + Manifest.permission.WRITE_EXTERNAL_STORAGE}, + PERMISSIONS_REQUEST_CAMERA); + return; + } + setUpPreview(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, + int[] grantResults) { + if (requestCode == PERMISSIONS_REQUEST_CAMERA) { + for (int i = 0; i < grantResults.length; i++) { + if (grantResults[i] == PackageManager.PERMISSION_DENIED) { + Log.i(TAG, "At least one permission denied, can't continue: " + permissions[i]); + finish(); + return; + } + } + + Log.i(TAG, "All permissions granted"); + setUpPreview(); + } + } + + private void setUpPreview() { + try { mCameraOps.minimalPreviewConfig(mPreviewView.getHolder()); mCurrentPreviewHolder = mPreviewView.getHolder(); } catch (ApiFailureException e) { |