Skip to content

Most visited

Recently visited

navigation
Camera2Basic / src / com.example.android.camera2basic /

Camera2BasicFragment.java

1
/*
2
 * Copyright 2014 The Android Open Source Project
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *       http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
 
17
package com.example.android.camera2basic;
18
 
19
import android.Manifest;
20
import android.app.Activity;
21
import android.app.AlertDialog;
22
import android.app.Dialog;
23
import android.app.DialogFragment;
24
import android.app.Fragment;
25
import android.content.Context;
26
import android.content.DialogInterface;
27
import android.content.pm.PackageManager;
28
import android.content.res.Configuration;
29
import android.graphics.ImageFormat;
30
import android.graphics.Matrix;
31
import android.graphics.Point;
32
import android.graphics.RectF;
33
import android.graphics.SurfaceTexture;
34
import android.hardware.camera2.CameraAccessException;
35
import android.hardware.camera2.CameraCaptureSession;
36
import android.hardware.camera2.CameraCharacteristics;
37
import android.hardware.camera2.CameraDevice;
38
import android.hardware.camera2.CameraManager;
39
import android.hardware.camera2.CameraMetadata;
40
import android.hardware.camera2.CaptureRequest;
41
import android.hardware.camera2.CaptureResult;
42
import android.hardware.camera2.TotalCaptureResult;
43
import android.hardware.camera2.params.StreamConfigurationMap;
44
import android.media.Image;
45
import android.media.ImageReader;
46
import android.os.Bundle;
47
import android.os.Handler;
48
import android.os.HandlerThread;
49
import android.support.annotation.NonNull;
50
import android.support.v13.app.FragmentCompat;
51
import android.support.v4.content.ContextCompat;
52
import android.util.Log;
53
import android.util.Size;
54
import android.util.SparseIntArray;
55
import android.view.LayoutInflater;
56
import android.view.Surface;
57
import android.view.TextureView;
58
import android.view.View;
59
import android.view.ViewGroup;
60
import android.widget.Toast;
61
 
62
import java.io.File;
63
import java.io.FileOutputStream;
64
import java.io.IOException;
65
import java.nio.ByteBuffer;
66
import java.util.ArrayList;
67
import java.util.Arrays;
68
import java.util.Collections;
69
import java.util.Comparator;
70
import java.util.List;
71
import java.util.concurrent.Semaphore;
72
import java.util.concurrent.TimeUnit;
73
 
74
public class Camera2BasicFragment extends Fragment
75
        implements View.OnClickListener, FragmentCompat.OnRequestPermissionsResultCallback {
76
 
77
    /**
78
     * Conversion from screen rotation to JPEG orientation.
79
     */
80
    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
81
    private static final int REQUEST_CAMERA_PERMISSION = 1;
82
    private static final String FRAGMENT_DIALOG = "dialog";
83
 
84
    static {
85
        ORIENTATIONS.append(Surface.ROTATION_0, 90);
86
        ORIENTATIONS.append(Surface.ROTATION_90, 0);
87
        ORIENTATIONS.append(Surface.ROTATION_180, 270);
88
        ORIENTATIONS.append(Surface.ROTATION_270, 180);
89
    }
90
 
91
    /**
92
     * Tag for the {@link Log}.
93
     */
94
    private static final String TAG = "Camera2BasicFragment";
95
 
96
    /**
97
     * Camera state: Showing camera preview.
98
     */
99
    private static final int STATE_PREVIEW = 0;
100
 
101
    /**
102
     * Camera state: Waiting for the focus to be locked.
103
     */
104
    private static final int STATE_WAITING_LOCK = 1;
105
 
106
    /**
107
     * Camera state: Waiting for the exposure to be precapture state.
108
     */
109
    private static final int STATE_WAITING_PRECAPTURE = 2;
110
 
111
    /**
112
     * Camera state: Waiting for the exposure state to be something other than precapture.
113
     */
114
    private static final int STATE_WAITING_NON_PRECAPTURE = 3;
115
 
116
    /**
117
     * Camera state: Picture was taken.
118
     */
119
    private static final int STATE_PICTURE_TAKEN = 4;
120
 
121
    /**
122
     * Max preview width that is guaranteed by Camera2 API
123
     */
124
    private static final int MAX_PREVIEW_WIDTH = 1920;
125
 
126
    /**
127
     * Max preview height that is guaranteed by Camera2 API
128
     */
129
    private static final int MAX_PREVIEW_HEIGHT = 1080;
130
 
131
    /**
132
     * {@link TextureView.SurfaceTextureListener} handles several lifecycle events on a
133
     * {@link TextureView}.
134
     */
135
    private final TextureView.SurfaceTextureListener mSurfaceTextureListener
136
            = new TextureView.SurfaceTextureListener() {
137
 
138
        @Override
139
        public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
140
            openCamera(width, height);
141
        }
142
 
143
        @Override
144
        public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
145
            configureTransform(width, height);
146
        }
147
 
148
        @Override
149
        public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
150
            return true;
151
        }
152
 
153
        @Override
154
        public void onSurfaceTextureUpdated(SurfaceTexture texture) {
155
        }
156
 
157
    };
158
 
159
    /**
160
     * ID of the current {@link CameraDevice}.
161
     */
162
    private String mCameraId;
163
 
164
    /**
165
     * An {@link AutoFitTextureView} for camera preview.
166
     */
167
    private AutoFitTextureView mTextureView;
168
 
169
    /**
170
     * A {@link CameraCaptureSession } for camera preview.
171
     */
172
    private CameraCaptureSession mCaptureSession;
173
 
174
    /**
175
     * A reference to the opened {@link CameraDevice}.
176
     */
177
    private CameraDevice mCameraDevice;
178
 
179
    /**
180
     * The {@link android.util.Size} of camera preview.
181
     */
182
    private Size mPreviewSize;
183
 
184
    /**
185
     * {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its state.
186
     */
187
    private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
188
 
189
        @Override
190
        public void onOpened(@NonNull CameraDevice cameraDevice) {
191
            // This method is called when the camera is opened.  We start camera preview here.
192
            mCameraOpenCloseLock.release();
193
            mCameraDevice = cameraDevice;
194
            createCameraPreviewSession();
195
        }
196
 
197
        @Override
198
        public void onDisconnected(@NonNull CameraDevice cameraDevice) {
199
            mCameraOpenCloseLock.release();
200
            cameraDevice.close();
201
            mCameraDevice = null;
202
        }
203
 
204
        @Override
205
        public void onError(@NonNull CameraDevice cameraDevice, int error) {
206
            mCameraOpenCloseLock.release();
207
            cameraDevice.close();
208
            mCameraDevice = null;
209
            Activity activity = getActivity();
210
            if (null != activity) {
211
                activity.finish();
212
            }
213
        }
214
 
215
    };
216
 
217
    /**
218
     * An additional thread for running tasks that shouldn't block the UI.
219
     */
220
    private HandlerThread mBackgroundThread;
221
 
222
    /**
223
     * A {@link Handler} for running tasks in the background.
224
     */
225
    private Handler mBackgroundHandler;
226
 
227
    /**
228
     * An {@link ImageReader} that handles still image capture.
229
     */
230
    private ImageReader mImageReader;
231
 
232
    /**
233
     * This is the output file for our picture.
234
     */
235
    private File mFile;
236
 
237
    /**
238
     * This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
239
     * still image is ready to be saved.
240
     */
241
    private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
242
            = new ImageReader.OnImageAvailableListener() {
243
 
244
        @Override
245
        public void onImageAvailable(ImageReader reader) {
246
            mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), mFile));
247
        }
248
 
249
    };
250
 
251
    /**
252
     * {@link CaptureRequest.Builder} for the camera preview
253
     */
254
    private CaptureRequest.Builder mPreviewRequestBuilder;
255
 
256
    /**
257
     * {@link CaptureRequest} generated by {@link #mPreviewRequestBuilder}
258
     */
259
    private CaptureRequest mPreviewRequest;
260
 
261
    /**
262
     * The current state of camera state for taking pictures.
263
     *
264
     * @see #mCaptureCallback
265
     */
266
    private int mState = STATE_PREVIEW;
267
 
268
    /**
269
     * A {@link Semaphore} to prevent the app from exiting before closing the camera.
270
     */
271
    private Semaphore mCameraOpenCloseLock = new Semaphore(1);
272
 
273
    /**
274
     * Whether the current camera device supports Flash or not.
275
     */
276
    private boolean mFlashSupported;
277
 
278
    /**
279
     * Orientation of the camera sensor
280
     */
281
    private int mSensorOrientation;
282
 
283
    /**
284
     * A {@link CameraCaptureSession.CaptureCallback} that handles events related to JPEG capture.
285
     */
286
    private CameraCaptureSession.CaptureCallback mCaptureCallback
287
            = new CameraCaptureSession.CaptureCallback() {
288
 
289
        private void process(CaptureResult result) {
290
            switch (mState) {
291
                case STATE_PREVIEW: {
292
                    // We have nothing to do when the camera preview is working normally.
293
                    break;
294
                }
295
                case STATE_WAITING_LOCK: {
296
                    Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
297
                    if (afState == null) {
298
                        captureStillPicture();
299
                    } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
300
                            CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
301
                        // CONTROL_AE_STATE can be null on some devices
302
                        Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
303
                        if (aeState == null ||
304
                                aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
305
                            mState = STATE_PICTURE_TAKEN;
306
                            captureStillPicture();
307
                        } else {
308
                            runPrecaptureSequence();
309
                        }
310
                    }
311
                    break;
312
                }
313
                case STATE_WAITING_PRECAPTURE: {
314
                    // CONTROL_AE_STATE can be null on some devices
315
                    Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
316
                    if (aeState == null ||
317
                            aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
318
                            aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
319