aboutsummaryrefslogtreecommitdiff
path: root/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/HdrViewfinderActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/HdrViewfinderActivity.java')
-rw-r--r--media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/HdrViewfinderActivity.java283
1 files changed, 213 insertions, 70 deletions
diff --git a/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/HdrViewfinderActivity.java b/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/HdrViewfinderActivity.java
index 79f1bb61..ca49ea0b 100644
--- a/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/HdrViewfinderActivity.java
+++ b/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/HdrViewfinderActivity.java
@@ -16,7 +16,9 @@
package com.example.android.hdrviewfinder;
-import android.app.Activity;
+import android.Manifest;
+import android.content.Intent;
+import android.content.pm.PackageManager;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
@@ -26,10 +28,16 @@ import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.provider.Settings;
import android.renderscript.RenderScript;
+import android.support.annotation.NonNull;
+import android.support.design.widget.Snackbar;
+import android.support.v4.app.ActivityCompat;
+import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.util.Size;
import android.view.GestureDetector;
@@ -76,19 +84,26 @@ import java.util.List;
* Android {@link android.view.Surface} class, which allows for zero-copy transport of large
* buffers between processes and subsystems.</p>
*/
-public class HdrViewfinderActivity extends Activity implements
+public class HdrViewfinderActivity extends AppCompatActivity implements
SurfaceHolder.Callback, CameraOps.ErrorDisplayer, CameraOps.CameraReadyListener {
private static final String TAG = "HdrViewfinderDemo";
private static final String FRAGMENT_DIALOG = "dialog";
+ private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
+
/**
* View for the camera preview.
*/
private FixedAspectSurfaceView mPreviewView;
/**
+ * Root view of this activity.
+ */
+ private View rootView;
+
+ /**
* This shows the current mode of the app.
*/
private TextView mModeText;
@@ -132,6 +147,8 @@ public class HdrViewfinderActivity extends Activity implements
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
+ rootView = findViewById(R.id.panels);
+
mPreviewView = (FixedAspectSurfaceView) findViewById(R.id.preview);
mPreviewView.getHolder().addCallback(this);
mPreviewView.setGestureListener(this, mViewListener);
@@ -146,23 +163,20 @@ public class HdrViewfinderActivity extends Activity implements
mUiHandler = new Handler(Looper.getMainLooper());
- mCameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
- mCameraOps = new CameraOps(mCameraManager,
- /*errorDisplayer*/ this,
- /*readyListener*/ this,
- /*readyHandler*/ mUiHandler);
-
- mHdrRequests.add(null);
- mHdrRequests.add(null);
-
mRS = RenderScript.create(this);
+
+ // When permissions are revoked the app is restarted so onCreate is sufficient to check for
+ // permissions core to the Activity's functionality.
+ if (!checkCameraPermissions()) {
+ requestCameraPermissions();
+ } else {
+ findAndOpenCamera();
+ }
}
@Override
protected void onResume() {
super.onResume();
-
- findAndOpenCamera();
}
@Override
@@ -170,7 +184,10 @@ public class HdrViewfinderActivity extends Activity implements
super.onPause();
// Wait until camera is closed to ensure the next application can open it
- mCameraOps.closeCameraAndWait();
+ if (mCameraOps != null) {
+ mCameraOps.closeCameraAndWait();
+ mCameraOps = null;
+ }
}
@Override
@@ -232,7 +249,9 @@ public class HdrViewfinderActivity extends Activity implements
}
};
- // Show help dialog
+ /**
+ * Show help dialogs.
+ */
private View.OnClickListener mHelpButtonListener = new View.OnClickListener() {
public void onClick(View v) {
MessageDialogFragment.newInstance(R.string.help_text)
@@ -240,54 +259,176 @@ public class HdrViewfinderActivity extends Activity implements
}
};
- private void findAndOpenCamera() {
+ /**
+ * Return the current state of the camera permissions.
+ */
+ private boolean checkCameraPermissions() {
+ int permissionState = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
+
+ // Check if the Camera permission is already available.
+ if (permissionState != PackageManager.PERMISSION_GRANTED) {
+ // Camera permission has not been granted.
+ Log.i(TAG, "CAMERA permission has NOT been granted.");
+ return false;
+ } else {
+ // Camera permissions are available.
+ Log.i(TAG, "CAMERA permission has already been granted.");
+ return true;
+ }
+ }
- String errorMessage = "Unknown error";
- boolean foundCamera = false;
- try {
- // Find first back-facing camera that has necessary capability
- String[] cameraIds = mCameraManager.getCameraIdList();
- for (String id : cameraIds) {
- CameraCharacteristics info = mCameraManager.getCameraCharacteristics(id);
- int facing = info.get(CameraCharacteristics.LENS_FACING);
-
- int level = info.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
- boolean hasFullLevel
- = (level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
-
- int[] capabilities = info.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
- int syncLatency = info.get(CameraCharacteristics.SYNC_MAX_LATENCY);
- boolean hasManualControl = hasCapability(capabilities,
- CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
- boolean hasEnoughCapability = hasManualControl &&
- syncLatency == CameraCharacteristics.SYNC_MAX_LATENCY_PER_FRAME_CONTROL;
-
- // All these are guaranteed by
- // CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL, but checking for only
- // the things we care about expands range of devices we can run on
- // We want:
- // - Back-facing camera
- // - Manual sensor control
- // - Per-frame synchronization (so that exposure can be changed every frame)
- if (facing == CameraCharacteristics.LENS_FACING_BACK &&
- (hasFullLevel || hasEnoughCapability)) {
- // Found suitable camera - get info, open, and set up outputs
- mCameraInfo = info;
- mCameraOps.openCamera(id);
- configureSurfaces();
- foundCamera = true;
- break;
- }
- }
- if (!foundCamera) {
- errorMessage = getString(R.string.camera_no_good);
+ /**
+ * Attempt to initialize the camera.
+ */
+ private void initializeCamera() {
+ mCameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
+ if (mCameraManager != null) {
+ mCameraOps = new CameraOps(mCameraManager,
+ /*errorDisplayer*/ this,
+ /*readyListener*/ this,
+ /*readyHandler*/ mUiHandler);
+
+ mHdrRequests.add(null);
+ mHdrRequests.add(null);
+ } else {
+ Log.e(TAG, "Couldn't initialize the camera");
+ }
+ }
+
+ private void requestCameraPermissions() {
+ boolean shouldProvideRationale =
+ ActivityCompat.shouldShowRequestPermissionRationale(this,
+ Manifest.permission.CAMERA);
+
+ // Provide an additional rationale to the user. This would happen if the user denied the
+ // request previously, but didn't check the "Don't ask again" checkbox.
+ if (shouldProvideRationale) {
+ Log.i(TAG, "Displaying camera permission rationale to provide additional context.");
+ Snackbar.make(rootView, R.string.camera_permission_rationale, Snackbar
+ .LENGTH_INDEFINITE)
+ .setAction(R.string.ok, new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ // Request Camera permission
+ ActivityCompat.requestPermissions(HdrViewfinderActivity.this,
+ new String[]{Manifest.permission.CAMERA},
+ REQUEST_PERMISSIONS_REQUEST_CODE);
+ }
+ })
+ .show();
+ } else {
+ Log.i(TAG, "Requesting camera permission");
+ // Request Camera permission. It's possible this can be auto answered if device policy
+ // sets the permission in a given state or the user denied the permission
+ // previously and checked "Never ask again".
+ ActivityCompat.requestPermissions(HdrViewfinderActivity.this,
+ new String[]{Manifest.permission.CAMERA},
+ REQUEST_PERMISSIONS_REQUEST_CODE);
+ }
+ }
+
+ /**
+ * Callback received when a permissions request has been completed.
+ */
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+ @NonNull int[] grantResults) {
+ Log.i(TAG, "onRequestPermissionResult");
+ if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
+ if (grantResults.length <= 0) {
+ // If user interaction was interrupted, the permission request is cancelled and you
+ // receive empty arrays.
+ Log.i(TAG, "User interaction was cancelled.");
+ } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ // Permission was granted.
+ findAndOpenCamera();
+ } else {
+ // Permission denied.
+
+ // In this Activity we've chosen to notify the user that they
+ // have rejected a core permission for the app since it makes the Activity useless.
+ // We're communicating this message in a Snackbar since this is a sample app, but
+ // core permissions would typically be best requested during a welcome-screen flow.
+
+ // Additionally, it is important to remember that a permission might have been
+ // rejected without asking the user for permission (device policy or "Never ask
+ // again" prompts). Therefore, a user interface affordance is typically implemented
+ // when permissions are denied. Otherwise, your app could appear unresponsive to
+ // touches or interactions which have required permissions.
+ Snackbar.make(rootView, R.string.camera_permission_denied_explanation, Snackbar
+ .LENGTH_INDEFINITE)
+ .setAction(R.string.settings, new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ // Build intent that displays the App settings screen.
+ Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ Uri uri = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null);
+ intent.setData(uri);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ }
+ })
+ .show();
}
- } catch (CameraAccessException e) {
- errorMessage = getErrorString(e);
}
+ }
- if (!foundCamera) {
- showErrorDialog(errorMessage);
+ private void findAndOpenCamera() {
+ boolean cameraPermissions = checkCameraPermissions();
+ if (cameraPermissions) {
+ String errorMessage = "Unknown error";
+ boolean foundCamera = false;
+ initializeCamera();
+ if (cameraPermissions && mCameraOps != null) {
+ try {
+ // Find first back-facing camera that has necessary capability.
+ String[] cameraIds = mCameraManager.getCameraIdList();
+ for (String id : cameraIds) {
+ CameraCharacteristics info = mCameraManager.getCameraCharacteristics(id);
+ int facing = info.get(CameraCharacteristics.LENS_FACING);
+
+ int level = info.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
+ boolean hasFullLevel
+ = (level
+ == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
+
+ int[] capabilities = info
+ .get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+ int syncLatency = info.get(CameraCharacteristics.SYNC_MAX_LATENCY);
+ boolean hasManualControl = hasCapability(capabilities,
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
+ boolean hasEnoughCapability = hasManualControl &&
+ syncLatency
+ == CameraCharacteristics.SYNC_MAX_LATENCY_PER_FRAME_CONTROL;
+
+ // All these are guaranteed by
+ // CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL, but checking
+ // for only the things we care about expands range of devices we can run on.
+ // We want:
+ // - Back-facing camera
+ // - Manual sensor control
+ // - Per-frame synchronization (so that exposure can be changed every frame)
+ if (facing == CameraCharacteristics.LENS_FACING_BACK &&
+ (hasFullLevel || hasEnoughCapability)) {
+ // Found suitable camera - get info, open, and set up outputs
+ mCameraInfo = info;
+ mCameraOps.openCamera(id);
+ configureSurfaces();
+ foundCamera = true;
+ break;
+ }
+ }
+ if (!foundCamera) {
+ errorMessage = getString(R.string.camera_no_good);
+ }
+ } catch (CameraAccessException e) {
+ errorMessage = getErrorString(e);
+ }
+ if (!foundCamera) {
+ showErrorDialog(errorMessage);
+ }
+ }
}
}
@@ -299,23 +440,25 @@ public class HdrViewfinderActivity extends Activity implements
}
private void switchRenderMode(int direction) {
- mRenderMode = (mRenderMode + direction) % 3;
+ if (mCameraOps != null) {
+ mRenderMode = (mRenderMode + direction) % 3;
- mModeText.setText(getResources().getStringArray(R.array.mode_label_array)[mRenderMode]);
+ mModeText.setText(getResources().getStringArray(R.array.mode_label_array)[mRenderMode]);
- if (mProcessor != null) {
- mProcessor.setRenderMode(mRenderMode);
- }
- if (mRenderMode == ViewfinderProcessor.MODE_NORMAL) {
- mCameraOps.setRepeatingRequest(mPreviewRequest,
- mCaptureCallback, mUiHandler);
- } else {
- setHdrBurst();
+ if (mProcessor != null) {
+ mProcessor.setRenderMode(mRenderMode);
+ }
+ if (mRenderMode == ViewfinderProcessor.MODE_NORMAL) {
+ mCameraOps.setRepeatingRequest(mPreviewRequest,
+ mCaptureCallback, mUiHandler);
+ } else {
+ setHdrBurst();
+ }
}
}
/**
- * Configure the surfaceview and RS processing
+ * Configure the surfaceview and RS processing.
*/
private void configureSurfaces() {
// Find a good size for output - largest 16:9 aspect ratio that's less than 720p