Sync sample prebuilts for mnc-docs
Synced to //developers/samples/android commit 7c1cbd61d1dea342322530bee4228d0d86bdeca1. Change-Id: I682ebe15bb1d495866dbc8d43453cd7351aef5db
This commit is contained in:
@@ -16,4 +16,6 @@
|
||||
<resources>
|
||||
<string name="picture">Picture</string>
|
||||
<string name="description_info">Info</string>
|
||||
<string name="request_permission">This sample needs camera permission.</string>
|
||||
<string name="camera_error">This device doesn\'t support Camera2 API.</string>
|
||||
</resources>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.example.android.camera2basic;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
@@ -23,6 +24,7 @@ import android.app.DialogFragment;
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.ImageFormat;
|
||||
import android.graphics.Matrix;
|
||||
@@ -43,7 +45,8 @@ import android.media.ImageReader;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Message;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v13.app.FragmentCompat;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.util.SparseIntArray;
|
||||
@@ -66,12 +69,15 @@ import java.util.List;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Camera2BasicFragment extends Fragment implements View.OnClickListener {
|
||||
public class Camera2BasicFragment extends Fragment
|
||||
implements View.OnClickListener, FragmentCompat.OnRequestPermissionsResultCallback {
|
||||
|
||||
/**
|
||||
* Conversion from screen rotation to JPEG orientation.
|
||||
*/
|
||||
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
|
||||
private static final int REQUEST_CAMERA_PERMISSION = 1;
|
||||
private static final String FRAGMENT_DIALOG = "dialog";
|
||||
|
||||
static {
|
||||
ORIENTATIONS.append(Surface.ROTATION_0, 90);
|
||||
@@ -94,14 +100,17 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
* Camera state: Waiting for the focus to be locked.
|
||||
*/
|
||||
private static final int STATE_WAITING_LOCK = 1;
|
||||
|
||||
/**
|
||||
* Camera state: Waiting for the exposure to be precapture state.
|
||||
*/
|
||||
private static final int STATE_WAITING_PRECAPTURE = 2;
|
||||
|
||||
/**
|
||||
* Camera state: Waiting for the exposure state to be something other than precapture.
|
||||
*/
|
||||
private static final int STATE_WAITING_NON_PRECAPTURE = 3;
|
||||
|
||||
/**
|
||||
* Camera state: Picture was taken.
|
||||
*/
|
||||
@@ -148,17 +157,16 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
/**
|
||||
* A {@link CameraCaptureSession } for camera preview.
|
||||
*/
|
||||
|
||||
private CameraCaptureSession mCaptureSession;
|
||||
|
||||
/**
|
||||
* A reference to the opened {@link CameraDevice}.
|
||||
*/
|
||||
|
||||
private CameraDevice mCameraDevice;
|
||||
|
||||
/**
|
||||
* The {@link android.util.Size} of camera preview.
|
||||
*/
|
||||
|
||||
private Size mPreviewSize;
|
||||
|
||||
/**
|
||||
@@ -167,7 +175,7 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
|
||||
|
||||
@Override
|
||||
public void onOpened(CameraDevice cameraDevice) {
|
||||
public void onOpened(@NonNull CameraDevice cameraDevice) {
|
||||
// This method is called when the camera is opened. We start camera preview here.
|
||||
mCameraOpenCloseLock.release();
|
||||
mCameraDevice = cameraDevice;
|
||||
@@ -175,14 +183,14 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(CameraDevice cameraDevice) {
|
||||
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
|
||||
mCameraOpenCloseLock.release();
|
||||
cameraDevice.close();
|
||||
mCameraDevice = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(CameraDevice cameraDevice, int error) {
|
||||
public void onError(@NonNull CameraDevice cameraDevice, int error) {
|
||||
mCameraOpenCloseLock.release();
|
||||
cameraDevice.close();
|
||||
mCameraDevice = null;
|
||||
@@ -303,43 +311,36 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
|
||||
CaptureResult partialResult) {
|
||||
public void onCaptureProgressed(@NonNull CameraCaptureSession session,
|
||||
@NonNull CaptureRequest request,
|
||||
@NonNull CaptureResult partialResult) {
|
||||
process(partialResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
|
||||
TotalCaptureResult result) {
|
||||
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
|
||||
@NonNull CaptureRequest request,
|
||||
@NonNull TotalCaptureResult result) {
|
||||
process(result);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* A {@link Handler} for showing {@link Toast}s.
|
||||
*/
|
||||
private Handler mMessageHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null) {
|
||||
Toast.makeText(activity, (String) msg.obj, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows a {@link Toast} on the UI thread.
|
||||
*
|
||||
* @param text The message to show
|
||||
*/
|
||||
private void showToast(String text) {
|
||||
// We show a Toast by sending request message to mMessageHandler. This makes sure that the
|
||||
// Toast is shown on the UI thread.
|
||||
Message message = Message.obtain();
|
||||
message.obj = text;
|
||||
mMessageHandler.sendMessage(message);
|
||||
private void showToast(final String text) {
|
||||
final Activity activity = getActivity();
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(activity, text, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -355,7 +356,7 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
*/
|
||||
private static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
|
||||
// Collect the supported resolutions that are at least as big as the preview Surface
|
||||
List<Size> bigEnough = new ArrayList<Size>();
|
||||
List<Size> bigEnough = new ArrayList<>();
|
||||
int w = aspectRatio.getWidth();
|
||||
int h = aspectRatio.getHeight();
|
||||
for (Size option : choices) {
|
||||
@@ -375,9 +376,7 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
}
|
||||
|
||||
public static Camera2BasicFragment newInstance() {
|
||||
Camera2BasicFragment fragment = new Camera2BasicFragment();
|
||||
fragment.setRetainInstance(true);
|
||||
return fragment;
|
||||
return new Camera2BasicFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -422,6 +421,28 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private void requestCameraPermission() {
|
||||
if (FragmentCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
|
||||
new ConfirmationDialog().show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
} else {
|
||||
FragmentCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
|
||||
REQUEST_CAMERA_PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
|
||||
@NonNull int[] grantResults) {
|
||||
if (requestCode == REQUEST_CAMERA_PERMISSION) {
|
||||
if (grantResults.length != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
|
||||
ErrorDialog.newInstance(getString(R.string.request_permission))
|
||||
.show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
}
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up member variables related to camera.
|
||||
*
|
||||
@@ -437,13 +458,16 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
= manager.getCameraCharacteristics(cameraId);
|
||||
|
||||
// We don't use a front facing camera in this sample.
|
||||
if (characteristics.get(CameraCharacteristics.LENS_FACING)
|
||||
== CameraCharacteristics.LENS_FACING_FRONT) {
|
||||
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
|
||||
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
StreamConfigurationMap map = characteristics.get(
|
||||
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
|
||||
if (map == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// For still image captures, we use the largest available size.
|
||||
Size largest = Collections.max(
|
||||
@@ -478,7 +502,8 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
} catch (NullPointerException e) {
|
||||
// Currently an NPE is thrown when the Camera2API is used but not supported on the
|
||||
// device this code runs.
|
||||
new ErrorDialog().show(getFragmentManager(), "dialog");
|
||||
ErrorDialog.newInstance(getString(R.string.camera_error))
|
||||
.show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,6 +511,11 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
* Opens the camera specified by {@link Camera2BasicFragment#mCameraId}.
|
||||
*/
|
||||
private void openCamera(int width, int height) {
|
||||
if (getActivity().checkSelfPermission(Manifest.permission.CAMERA)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
requestCameraPermission();
|
||||
return;
|
||||
}
|
||||
setUpCameraOutputs(width, height);
|
||||
configureTransform(width, height);
|
||||
Activity activity = getActivity();
|
||||
@@ -574,7 +604,7 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
new CameraCaptureSession.StateCallback() {
|
||||
|
||||
@Override
|
||||
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
|
||||
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
|
||||
// The camera is already closed
|
||||
if (null == mCameraDevice) {
|
||||
return;
|
||||
@@ -600,7 +630,8 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
|
||||
public void onConfigureFailed(
|
||||
@NonNull CameraCaptureSession cameraCaptureSession) {
|
||||
showToast("Failed");
|
||||
}
|
||||
}, null
|
||||
@@ -668,8 +699,8 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the precapture sequence for capturing a still image. This method should be called when we
|
||||
* get a response in {@link #mCaptureCallback} from {@link #lockFocus()}.
|
||||
* Run the precapture sequence for capturing a still image. This method should be called when
|
||||
* we get a response in {@link #mCaptureCallback} from {@link #lockFocus()}.
|
||||
*/
|
||||
private void runPrecaptureSequence() {
|
||||
try {
|
||||
@@ -714,9 +745,11 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
= new CameraCaptureSession.CaptureCallback() {
|
||||
|
||||
@Override
|
||||
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
|
||||
TotalCaptureResult result) {
|
||||
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
|
||||
@NonNull CaptureRequest request,
|
||||
@NonNull TotalCaptureResult result) {
|
||||
showToast("Saved: " + mFile);
|
||||
Log.d(TAG, mFile.toString());
|
||||
unlockFocus();
|
||||
}
|
||||
};
|
||||
@@ -729,11 +762,12 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock the focus. This method should be called when still image capture sequence is finished.
|
||||
* Unlock the focus. This method should be called when still image capture sequence is
|
||||
* finished.
|
||||
*/
|
||||
private void unlockFocus() {
|
||||
try {
|
||||
// Reset the autofucos trigger
|
||||
// Reset the auto-focus trigger
|
||||
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
|
||||
CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
|
||||
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
|
||||
@@ -827,13 +861,26 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows an error message dialog.
|
||||
*/
|
||||
public static class ErrorDialog extends DialogFragment {
|
||||
|
||||
private static final String ARG_MESSAGE = "message";
|
||||
|
||||
public static ErrorDialog newInstance(String message) {
|
||||
ErrorDialog dialog = new ErrorDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_MESSAGE, message);
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Activity activity = getActivity();
|
||||
return new AlertDialog.Builder(activity)
|
||||
.setMessage("This device doesn't support Camera2 API.")
|
||||
.setMessage(getArguments().getString(ARG_MESSAGE))
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
@@ -845,4 +892,36 @@ public class Camera2BasicFragment extends Fragment implements View.OnClickListen
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows OK/Cancel confirmation dialog about camera permission.
|
||||
*/
|
||||
public static class ConfirmationDialog extends DialogFragment {
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Fragment parent = getParentFragment();
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setMessage(R.string.request_permission)
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
FragmentCompat.requestPermissions(parent,
|
||||
new String[]{Manifest.permission.CAMERA},
|
||||
REQUEST_CAMERA_PERMISSION);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Activity activity = parent.getActivity();
|
||||
if (activity != null) {
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,4 +16,5 @@
|
||||
<resources>
|
||||
<string name="picture">Picture</string>
|
||||
<string name="description_info">Info</string>
|
||||
<string name="request_permission">This app needs camera permission.</string>
|
||||
</resources>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.example.android.camera2raw;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
@@ -23,6 +24,7 @@ import android.app.DialogFragment;
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.ImageFormat;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
@@ -52,6 +54,8 @@ import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.support.v13.app.FragmentCompat;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.util.SparseIntArray;
|
||||
@@ -84,7 +88,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A fragment that demonstrates use of the Camera2 API to capture RAW and JPEG photos.
|
||||
*
|
||||
* <p/>
|
||||
* In this example, the lifecycle of a single request to take a photo is:
|
||||
* <ul>
|
||||
* <li>
|
||||
@@ -113,7 +117,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
public class Camera2RawFragment extends Fragment implements View.OnClickListener {
|
||||
public class Camera2RawFragment extends Fragment
|
||||
implements View.OnClickListener, FragmentCompat.OnRequestPermissionsResultCallback {
|
||||
|
||||
/**
|
||||
* Conversion from screen rotation to JPEG orientation.
|
||||
*/
|
||||
@@ -126,6 +132,20 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
ORIENTATIONS.append(Surface.ROTATION_270, 270);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request code for camera permissions.
|
||||
*/
|
||||
private static final int REQUEST_CAMERA_PERMISSIONS = 1;
|
||||
|
||||
/**
|
||||
* Permissions required to take a picture.
|
||||
*/
|
||||
private static final String[] CAMERA_PERMISSIONS = {
|
||||
Manifest.permission.CAMERA,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Timeout for the pre-capture sequence.
|
||||
*/
|
||||
@@ -264,9 +284,9 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
private Handler mBackgroundHandler;
|
||||
|
||||
/**
|
||||
* A reference counted holder wrapping the {@link ImageReader} that handles JPEG image captures.
|
||||
* This is used to allow us to clean up the {@link ImageReader} when all background tasks using
|
||||
* its {@link Image}s have completed.
|
||||
* A reference counted holder wrapping the {@link ImageReader} that handles JPEG image
|
||||
* captures. This is used to allow us to clean up the {@link ImageReader} when all background
|
||||
* tasks using its {@link Image}s have completed.
|
||||
*/
|
||||
private RefCountedAutoCloseable<ImageReader> mJpegImageReader;
|
||||
|
||||
@@ -310,8 +330,8 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
private int mState = STATE_CLOSED;
|
||||
|
||||
/**
|
||||
* Timer to use with pre-capture sequence to ensure a timely capture if 3A convergence is taking
|
||||
* too long.
|
||||
* Timer to use with pre-capture sequence to ensure a timely capture if 3A convergence is
|
||||
* taking too long.
|
||||
*/
|
||||
private long mCaptureTimer;
|
||||
|
||||
@@ -352,7 +372,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
@Override
|
||||
public void onError(CameraDevice cameraDevice, int error) {
|
||||
Log.e(TAG, "Received camera device error: " + error);
|
||||
synchronized(mCameraStateLock) {
|
||||
synchronized (mCameraStateLock) {
|
||||
mState = STATE_CLOSED;
|
||||
mCameraOpenCloseLock.release();
|
||||
cameraDevice.close();
|
||||
@@ -402,7 +422,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
= new CameraCaptureSession.CaptureCallback() {
|
||||
|
||||
private void process(CaptureResult result) {
|
||||
synchronized(mCameraStateLock) {
|
||||
synchronized (mCameraStateLock) {
|
||||
switch (mState) {
|
||||
case STATE_PREVIEW: {
|
||||
// We have nothing to do when the camera preview is running normally.
|
||||
@@ -559,9 +579,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
};
|
||||
|
||||
public static Camera2RawFragment newInstance() {
|
||||
Camera2RawFragment fragment = new Camera2RawFragment();
|
||||
fragment.setRetainInstance(true);
|
||||
return fragment;
|
||||
return new Camera2RawFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -620,6 +638,20 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
if (requestCode == REQUEST_CAMERA_PERMISSIONS) {
|
||||
for (int result : grantResults) {
|
||||
if (result != PackageManager.PERMISSION_GRANTED) {
|
||||
showMissingPermissionError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
@@ -676,7 +708,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
Arrays.asList(map.getOutputSizes(ImageFormat.RAW_SENSOR)),
|
||||
new CompareSizesByArea());
|
||||
|
||||
synchronized(mCameraStateLock) {
|
||||
synchronized (mCameraStateLock) {
|
||||
// Set up ImageReaders for JPEG and RAW outputs. Place these in a reference
|
||||
// counted wrapper to ensure they are only closed when all background tasks
|
||||
// using them are finished.
|
||||
@@ -718,6 +750,10 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
if (!setUpCameraOutputs()) {
|
||||
return;
|
||||
}
|
||||
if (!hasAllPermissionsGranted()) {
|
||||
requestCameraPermissions();
|
||||
return;
|
||||
}
|
||||
|
||||
Activity activity = getActivity();
|
||||
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
|
||||
@@ -744,13 +780,64 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests permissions necessary to use camera and save pictures.
|
||||
*/
|
||||
private void requestCameraPermissions() {
|
||||
if (shouldShowRationale()) {
|
||||
PermissionConfirmationDialog.newInstance().show(getChildFragmentManager(), "dialog");
|
||||
} else {
|
||||
FragmentCompat.requestPermissions(this, CAMERA_PERMISSIONS, REQUEST_CAMERA_PERMISSIONS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether all the necessary permissions are granted to this app.
|
||||
*
|
||||
* @return True if all the required permissions are granted.
|
||||
*/
|
||||
private boolean hasAllPermissionsGranted() {
|
||||
for (String permission : CAMERA_PERMISSIONS) {
|
||||
if (ActivityCompat.checkSelfPermission(getActivity(), permission)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether you should show UI with rationale for requesting the permissions.
|
||||
*
|
||||
* @return True if the UI should be shown.
|
||||
*/
|
||||
private boolean shouldShowRationale() {
|
||||
for (String permission : CAMERA_PERMISSIONS) {
|
||||
if (FragmentCompat.shouldShowRequestPermissionRationale(this, permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows that this app really needs the permission and finishes the app.
|
||||
*/
|
||||
private void showMissingPermissionError() {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null) {
|
||||
Toast.makeText(activity, R.string.request_permission, Toast.LENGTH_SHORT).show();
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the current {@link CameraDevice}.
|
||||
*/
|
||||
private void closeCamera() {
|
||||
try {
|
||||
mCameraOpenCloseLock.acquire();
|
||||
synchronized(mCameraStateLock) {
|
||||
synchronized (mCameraStateLock) {
|
||||
|
||||
// Reset state and clean up resources used by the camera.
|
||||
// Note: After calling this, the ImageReaders will be closed after any background
|
||||
@@ -787,7 +874,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
private void startBackgroundThread() {
|
||||
mBackgroundThread = new HandlerThread("CameraBackground");
|
||||
mBackgroundThread.start();
|
||||
synchronized(mCameraStateLock) {
|
||||
synchronized (mCameraStateLock) {
|
||||
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
|
||||
}
|
||||
}
|
||||
@@ -810,7 +897,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
|
||||
/**
|
||||
* Creates a new {@link CameraCaptureSession} for camera preview.
|
||||
*
|
||||
* <p/>
|
||||
* Call this only with {@link #mCameraStateLock} held.
|
||||
*/
|
||||
private void createCameraPreviewSessionLocked() {
|
||||
@@ -846,7 +933,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
mPreviewRequestBuilder.build(),
|
||||
mPreCaptureCallback, mBackgroundHandler);
|
||||
mState = STATE_PREVIEW;
|
||||
} catch (CameraAccessException|IllegalStateException e) {
|
||||
} catch (CameraAccessException | IllegalStateException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
@@ -869,7 +956,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
/**
|
||||
* Configure the given {@link CaptureRequest.Builder} to use auto-focus, auto-exposure, and
|
||||
* auto-white-balance controls if available.
|
||||
*
|
||||
* <p/>
|
||||
* Call this only with {@link #mCameraStateLock} held.
|
||||
*
|
||||
* @param builder the builder to configure.
|
||||
@@ -923,7 +1010,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
/**
|
||||
* Configure the necessary {@link android.graphics.Matrix} transformation to `mTextureView`,
|
||||
* and start/restart the preview capture session if necessary.
|
||||
*
|
||||
* <p/>
|
||||
* This method should be called after the camera state has been initialized in
|
||||
* setUpCameraOutputs.
|
||||
*
|
||||
@@ -932,7 +1019,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
*/
|
||||
private void configureTransform(int viewWidth, int viewHeight) {
|
||||
Activity activity = getActivity();
|
||||
synchronized(mCameraStateLock) {
|
||||
synchronized (mCameraStateLock) {
|
||||
if (null == mTextureView || null == activity) {
|
||||
return;
|
||||
}
|
||||
@@ -1027,14 +1114,14 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
|
||||
/**
|
||||
* Initiate a still image capture.
|
||||
*
|
||||
* <p/>
|
||||
* This function sends a capture request that initiates a pre-capture sequence in our state
|
||||
* machine that waits for auto-focus to finish, ending in a "locked" state where the lens is no
|
||||
* longer moving, waits for auto-exposure to choose a good exposure value, and waits for
|
||||
* auto-white-balance to converge.
|
||||
*/
|
||||
private void takePicture() {
|
||||
synchronized(mCameraStateLock) {
|
||||
synchronized (mCameraStateLock) {
|
||||
mPendingUserCaptures++;
|
||||
|
||||
// If we already triggered a pre-capture sequence, or are in a state where we cannot
|
||||
@@ -1078,7 +1165,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
/**
|
||||
* Send a capture request to the camera device that initiates a capture targeting the JPEG and
|
||||
* RAW outputs.
|
||||
*
|
||||
* <p/>
|
||||
* Call this only with {@link #mCameraStateLock} held.
|
||||
*/
|
||||
private void captureStillPictureLocked() {
|
||||
@@ -1127,7 +1214,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
/**
|
||||
* Called after a RAW/JPEG capture has completed; resets the AF trigger state for the
|
||||
* pre-capture sequence.
|
||||
*
|
||||
* <p/>
|
||||
* Call this only with {@link #mCameraStateLock} held.
|
||||
*/
|
||||
private void finishedCaptureLocked() {
|
||||
@@ -1156,8 +1243,8 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
* thread.
|
||||
*
|
||||
* @param pendingQueue the currently active requests.
|
||||
* @param reader a reference counted wrapper containing an {@link ImageReader} from which to
|
||||
* acquire an image.
|
||||
* @param reader a reference counted wrapper containing an {@link ImageReader} from which
|
||||
* to acquire an image.
|
||||
*/
|
||||
private void dequeueAndSaveImage(TreeMap<Integer, ImageSaver.ImageSaverBuilder> pendingQueue,
|
||||
RefCountedAutoCloseable<ImageReader> reader) {
|
||||
@@ -1195,7 +1282,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
/**
|
||||
* Runnable that saves an {@link Image} into the specified {@link File}, and updates
|
||||
* {@link android.provider.MediaStore} to include the resulting file.
|
||||
*
|
||||
* <p/>
|
||||
* This can be constructed through an {@link ImageSaverBuilder} as the necessary image and
|
||||
* result information becomes available.
|
||||
*/
|
||||
@@ -1245,7 +1332,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
public void run() {
|
||||
boolean success = false;
|
||||
int format = mImage.getFormat();
|
||||
switch(format) {
|
||||
switch (format) {
|
||||
case ImageFormat.JPEG: {
|
||||
ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
|
||||
byte[] bytes = new byte[buffer.remaining()];
|
||||
@@ -1289,7 +1376,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
|
||||
// If saving the file succeeded, update MediaStore.
|
||||
if (success) {
|
||||
MediaScannerConnection.scanFile(mContext, new String[] { mFile.getPath()},
|
||||
MediaScannerConnection.scanFile(mContext, new String[]{mFile.getPath()},
|
||||
/*mimeTypes*/null, new MediaScannerConnection.MediaScannerConnectionClient() {
|
||||
@Override
|
||||
public void onMediaScannerConnected() {
|
||||
@@ -1307,7 +1394,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
|
||||
/**
|
||||
* Builder class for constructing {@link ImageSaver}s.
|
||||
*
|
||||
* <p/>
|
||||
* This class is thread safe.
|
||||
*/
|
||||
public static class ImageSaverBuilder {
|
||||
@@ -1320,6 +1407,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
|
||||
/**
|
||||
* Construct a new ImageSaverBuilder using the given {@link Context}.
|
||||
*
|
||||
* @param context a {@link Context} to for accessing the
|
||||
* {@link android.provider.MediaStore}.
|
||||
*/
|
||||
@@ -1329,7 +1417,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
|
||||
public synchronized ImageSaverBuilder setRefCountedReader(
|
||||
RefCountedAutoCloseable<ImageReader> reader) {
|
||||
if (reader == null ) throw new NullPointerException();
|
||||
if (reader == null) throw new NullPointerException();
|
||||
|
||||
mReader = reader;
|
||||
return this;
|
||||
@@ -1440,6 +1528,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
|
||||
/**
|
||||
* Wrap the given object.
|
||||
*
|
||||
* @param object an object to wrap.
|
||||
*/
|
||||
public RefCountedAutoCloseable(T object) {
|
||||
@@ -1582,7 +1671,9 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
/**
|
||||
* Rotation need to transform from the camera sensor orientation to the device's current
|
||||
* orientation.
|
||||
* @param c the {@link CameraCharacteristics} to query for the camera sensor orientation.
|
||||
*
|
||||
* @param c the {@link CameraCharacteristics} to query for the camera sensor
|
||||
* orientation.
|
||||
* @param deviceOrientation the current device orientation relative to the native device
|
||||
* orientation.
|
||||
* @return the total rotation from the sensor orientation to the current device orientation.
|
||||
@@ -1620,7 +1711,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
* If the given request has been completed, remove it from the queue of active requests and
|
||||
* send an {@link ImageSaver} with the results from this request to a background thread to
|
||||
* save a file.
|
||||
*
|
||||
* <p/>
|
||||
* Call this only with {@link #mCameraStateLock} held.
|
||||
*
|
||||
* @param requestId the ID of the {@link CaptureRequest} to handle.
|
||||
@@ -1639,7 +1730,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
|
||||
/**
|
||||
* Check if we are using a device that only supports the LEGACY hardware level.
|
||||
*
|
||||
* <p/>
|
||||
* Call this only with {@link #mCameraStateLock} held.
|
||||
*
|
||||
* @return true if this is a legacy device.
|
||||
@@ -1651,7 +1742,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
|
||||
/**
|
||||
* Start the timer for the pre-capture sequence.
|
||||
*
|
||||
* <p/>
|
||||
* Call this only with {@link #mCameraStateLock} held.
|
||||
*/
|
||||
private void startTimerLocked() {
|
||||
@@ -1660,7 +1751,7 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
|
||||
/**
|
||||
* Check if the timer for the pre-capture sequence has been hit.
|
||||
*
|
||||
* <p/>
|
||||
* Call this only with {@link #mCameraStateLock} held.
|
||||
*
|
||||
* @return true if the timeout occurred.
|
||||
@@ -1669,6 +1760,37 @@ public class Camera2RawFragment extends Fragment implements View.OnClickListener
|
||||
return (SystemClock.elapsedRealtime() - mCaptureTimer) > PRECAPTURE_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
// *********************************************************************************************
|
||||
/**
|
||||
* A dialog that explains about the necessary permissions.
|
||||
*/
|
||||
public static class PermissionConfirmationDialog extends DialogFragment {
|
||||
|
||||
public static PermissionConfirmationDialog newInstance() {
|
||||
return new PermissionConfirmationDialog();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Fragment parent = getParentFragment();
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setMessage(R.string.request_permission)
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
FragmentCompat.requestPermissions(parent, CAMERA_PERMISSIONS,
|
||||
REQUEST_CAMERA_PERMISSIONS);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
getActivity().finish();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,4 +3,6 @@
|
||||
<string name="record">Record</string>
|
||||
<string name="stop">Stop</string>
|
||||
<string name="description_info">Info</string>
|
||||
<string name="permission_request">This sample needs permission for camera and audio recording.</string>
|
||||
<string name="camera_error">This device doesn\'t support Camera2 API.</string>
|
||||
</resources>
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.example.android.camera2video;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
@@ -23,6 +24,7 @@ import android.app.DialogFragment;
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
@@ -39,6 +41,9 @@ import android.media.MediaRecorder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v13.app.FragmentCompat;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.util.SparseIntArray;
|
||||
@@ -59,11 +64,19 @@ import java.util.List;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Camera2VideoFragment extends Fragment implements View.OnClickListener {
|
||||
public class Camera2VideoFragment extends Fragment
|
||||
implements View.OnClickListener, FragmentCompat.OnRequestPermissionsResultCallback {
|
||||
|
||||
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
|
||||
|
||||
private static final String TAG = "Camera2VideoFragment";
|
||||
private static final int REQUEST_VIDEO_PERMISSIONS = 1;
|
||||
private static final String FRAGMENT_DIALOG = "dialog";
|
||||
|
||||
private static final String[] VIDEO_PERMISSIONS = {
|
||||
Manifest.permission.CAMERA,
|
||||
Manifest.permission.RECORD_AUDIO,
|
||||
};
|
||||
|
||||
static {
|
||||
ORIENTATIONS.append(Surface.ROTATION_0, 90);
|
||||
@@ -88,7 +101,8 @@ public class Camera2VideoFragment extends Fragment implements View.OnClickListen
|
||||
private CameraDevice mCameraDevice;
|
||||
|
||||
/**
|
||||
* A reference to the current {@link android.hardware.camera2.CameraCaptureSession} for preview.
|
||||
* A reference to the current {@link android.hardware.camera2.CameraCaptureSession} for
|
||||
* preview.
|
||||
*/
|
||||
private CameraCaptureSession mPreviewSession;
|
||||
|
||||
@@ -198,14 +212,12 @@ public class Camera2VideoFragment extends Fragment implements View.OnClickListen
|
||||
};
|
||||
|
||||
public static Camera2VideoFragment newInstance() {
|
||||
Camera2VideoFragment fragment = new Camera2VideoFragment();
|
||||
fragment.setRetainInstance(true);
|
||||
return fragment;
|
||||
return new Camera2VideoFragment();
|
||||
}
|
||||
|
||||
/**
|
||||
* In this sample, we choose a video size with 3x4 aspect ratio. Also, we don't use sizes larger
|
||||
* than 1080p, since MediaRecorder cannot handle such a high-resolution video.
|
||||
* In this sample, we choose a video size with 3x4 aspect ratio. Also, we don't use sizes
|
||||
* larger than 1080p, since MediaRecorder cannot handle such a high-resolution video.
|
||||
*
|
||||
* @param choices The list of available sizes
|
||||
* @return The video size
|
||||
@@ -331,16 +343,79 @@ public class Camera2VideoFragment extends Fragment implements View.OnClickListen
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether you should show UI with rationale for requesting permissions.
|
||||
*
|
||||
* @param permissions The permissions your app wants to request.
|
||||
* @return Whether you can show permission rationale UI.
|
||||
*/
|
||||
private boolean shouldShowRequestPermissionRationale(String[] permissions) {
|
||||
for (String permission : permissions) {
|
||||
if (FragmentCompat.shouldShowRequestPermissionRationale(this, permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests permissions needed for recording video.
|
||||
*/
|
||||
private void requestVideoPermissions() {
|
||||
if (shouldShowRequestPermissionRationale(VIDEO_PERMISSIONS)) {
|
||||
new ConfirmationDialog().show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
} else {
|
||||
FragmentCompat.requestPermissions(this, VIDEO_PERMISSIONS, REQUEST_VIDEO_PERMISSIONS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
|
||||
@NonNull int[] grantResults) {
|
||||
Log.d(TAG, "onRequestPermissionsResult");
|
||||
if (requestCode == REQUEST_VIDEO_PERMISSIONS) {
|
||||
if (grantResults.length == VIDEO_PERMISSIONS.length) {
|
||||
for (int result : grantResults) {
|
||||
if (result != PackageManager.PERMISSION_GRANTED) {
|
||||
ErrorDialog.newInstance(getString(R.string.permission_request))
|
||||
.show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ErrorDialog.newInstance(getString(R.string.permission_request))
|
||||
.show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
}
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasPermissionsGranted(String[] permissions) {
|
||||
for (String permission : permissions) {
|
||||
if (ActivityCompat.checkSelfPermission(getActivity(), permission)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to open a {@link CameraDevice}. The result is listened by `mStateCallback`.
|
||||
*/
|
||||
private void openCamera(int width, int height) {
|
||||
if (!hasPermissionsGranted(VIDEO_PERMISSIONS)) {
|
||||
requestVideoPermissions();
|
||||
return;
|
||||
}
|
||||
final Activity activity = getActivity();
|
||||
if (null == activity || activity.isFinishing()) {
|
||||
return;
|
||||
}
|
||||
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
|
||||
try {
|
||||
Log.d(TAG, "tryAcquire");
|
||||
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
|
||||
throw new RuntimeException("Time out waiting to lock camera opening.");
|
||||
}
|
||||
@@ -369,7 +444,8 @@ public class Camera2VideoFragment extends Fragment implements View.OnClickListen
|
||||
} catch (NullPointerException e) {
|
||||
// Currently an NPE is thrown when the Camera2API is used but not supported on the
|
||||
// device this code runs.
|
||||
new ErrorDialog().show(getFragmentManager(), "dialog");
|
||||
ErrorDialog.newInstance(getString(R.string.camera_error))
|
||||
.show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Interrupted while trying to lock camera opening.");
|
||||
}
|
||||
@@ -559,11 +635,21 @@ public class Camera2VideoFragment extends Fragment implements View.OnClickListen
|
||||
|
||||
public static class ErrorDialog extends DialogFragment {
|
||||
|
||||
private static final String ARG_MESSAGE = "message";
|
||||
|
||||
public static ErrorDialog newInstance(String message) {
|
||||
ErrorDialog dialog = new ErrorDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_MESSAGE, message);
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Activity activity = getActivity();
|
||||
return new AlertDialog.Builder(activity)
|
||||
.setMessage("This device doesn't support Camera2 API.")
|
||||
.setMessage(getArguments().getString(ARG_MESSAGE))
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
@@ -575,4 +661,30 @@ public class Camera2VideoFragment extends Fragment implements View.OnClickListen
|
||||
|
||||
}
|
||||
|
||||
public static class ConfirmationDialog extends DialogFragment {
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Fragment parent = getParentFragment();
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setMessage(R.string.permission_request)
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
FragmentCompat.requestPermissions(parent, VIDEO_PERMISSIONS,
|
||||
REQUEST_VIDEO_PERMISSIONS);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
parent.getActivity().finish();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user