├── README.md
└── androidCamera2Sample
├── .classpath
├── .gitignore
├── .project
├── AndroidManifest.xml
├── ic_launcher-web.png
├── proguard-project.txt
├── project.properties
├── res
├── drawable-mdpi
│ └── ic_launcher.png
├── layout
│ └── activity_main.xml
├── menu
│ └── main.xml
├── values-v11
│ └── styles.xml
├── values-v14
│ └── styles.xml
├── values-w820dp
│ └── dimens.xml
└── values
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
└── src
└── org
└── kotemaru
└── android
└── camera2sample
├── AutoFitTextureView.java
├── Camera2StateMachine.java
├── Camera2Util.java
└── MainActivity.java
/README.md:
--------------------------------------------------------------------------------
1 | # androidCamera2Sample
2 | Android Camera2 API sample code.
3 |
4 | See http://blog.kotemaru.org/2015/05/23/android-camera2-sample.html
5 |
6 |
--------------------------------------------------------------------------------
/androidCamera2Sample/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/androidCamera2Sample/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /gen/
3 |
--------------------------------------------------------------------------------
/androidCamera2Sample/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | androidCamera2Sample
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/androidCamera2Sample/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/androidCamera2Sample/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kotemaru/androidCamera2Sample/98a707accdc5126c67d7f19c5fba1061ef3df8cb/androidCamera2Sample/ic_launcher-web.png
--------------------------------------------------------------------------------
/androidCamera2Sample/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/androidCamera2Sample/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-22
15 |
--------------------------------------------------------------------------------
/androidCamera2Sample/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kotemaru/androidCamera2Sample/98a707accdc5126c67d7f19c5fba1061ef3df8cb/androidCamera2Sample/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/androidCamera2Sample/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
12 |
13 |
18 |
19 |
25 |
26 |
27 |
33 |
34 |
--------------------------------------------------------------------------------
/androidCamera2Sample/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/androidCamera2Sample/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/androidCamera2Sample/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/androidCamera2Sample/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 | 64dp
9 |
10 |
11 |
--------------------------------------------------------------------------------
/androidCamera2Sample/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/androidCamera2Sample/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | androidCamera2Sample
5 | Hello world!
6 | Settings
7 |
8 |
9 |
--------------------------------------------------------------------------------
/androidCamera2Sample/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/androidCamera2Sample/src/org/kotemaru/android/camera2sample/AutoFitTextureView.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 org.kotemaru.android.camera2sample;
18 |
19 | import android.content.Context;
20 | import android.util.AttributeSet;
21 | import android.view.TextureView;
22 |
23 | /**
24 | * A {@link TextureView} that can be adjusted to a specified aspect ratio.
25 | */
26 | public class AutoFitTextureView extends TextureView {
27 |
28 | private int mRatioWidth = 0;
29 | private int mRatioHeight = 0;
30 |
31 | public AutoFitTextureView(Context context) {
32 | this(context, null);
33 | }
34 |
35 | public AutoFitTextureView(Context context, AttributeSet attrs) {
36 | this(context, attrs, 0);
37 | }
38 |
39 | public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
40 | super(context, attrs, defStyle);
41 | }
42 |
43 | /**
44 | * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
45 | * calculated from the parameters. Note that the actual sizes of parameters don't matter, that
46 | * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
47 | *
48 | * @param width Relative horizontal size
49 | * @param height Relative vertical size
50 | */
51 | public void setAspectRatio(int width, int height) {
52 | if (width < 0 || height < 0) {
53 | throw new IllegalArgumentException("Size cannot be negative.");
54 | }
55 | mRatioWidth = width;
56 | mRatioHeight = height;
57 | requestLayout();
58 | }
59 |
60 | @Override
61 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
62 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
63 | int width = MeasureSpec.getSize(widthMeasureSpec);
64 | int height = MeasureSpec.getSize(heightMeasureSpec);
65 | if (0 == mRatioWidth || 0 == mRatioHeight) {
66 | setMeasuredDimension(width, height);
67 | } else {
68 | if (width < height * mRatioWidth / mRatioHeight) {
69 | setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
70 | } else {
71 | setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
72 | }
73 | }
74 | }
75 |
76 | //-----------------------------------------------------------
77 | // added by kotemaru.org
78 | public void setPreviewSize(int width, int height) {
79 | setAspectRatio(width, height);
80 | }
81 | public int getPreviewWidth() {
82 | return mRatioWidth;
83 | }
84 | public int getPreviewHeight() {
85 | return mRatioHeight;
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/androidCamera2Sample/src/org/kotemaru/android/camera2sample/Camera2StateMachine.java:
--------------------------------------------------------------------------------
1 | // Copyright 2015 kotemaru.org. (http://www.apache.org/licenses/LICENSE-2.0)
2 | package org.kotemaru.android.camera2sample;
3 |
4 | import java.util.Arrays;
5 | import java.util.List;
6 |
7 | import android.app.Activity;
8 | import android.content.Context;
9 | import android.graphics.ImageFormat;
10 | import android.graphics.SurfaceTexture;
11 | import android.hardware.camera2.CameraAccessException;
12 | import android.hardware.camera2.CameraCaptureSession;
13 | import android.hardware.camera2.CameraCharacteristics;
14 | import android.hardware.camera2.CameraDevice;
15 | import android.hardware.camera2.CameraManager;
16 | import android.hardware.camera2.CameraMetadata;
17 | import android.hardware.camera2.CaptureRequest;
18 | import android.hardware.camera2.CaptureResult;
19 | import android.hardware.camera2.TotalCaptureResult;
20 | import android.hardware.camera2.params.StreamConfigurationMap;
21 | import android.media.ImageReader;
22 | import android.os.Handler;
23 | import android.util.Log;
24 | import android.util.Size;
25 | import android.view.Surface;
26 | import android.view.TextureView;
27 |
28 | public class Camera2StateMachine {
29 | private static final String TAG = Camera2StateMachine.class.getSimpleName();
30 | private CameraManager mCameraManager;
31 |
32 | private CameraDevice mCameraDevice;
33 | private CameraCaptureSession mCaptureSession;
34 | private ImageReader mImageReader;
35 | private CaptureRequest.Builder mPreviewRequestBuilder;
36 |
37 | private AutoFitTextureView mTextureView;
38 | private Handler mHandler = null; // default current thread.
39 | private State mState = null;
40 | private ImageReader.OnImageAvailableListener mTakePictureListener;
41 |
42 | public void open(Activity activity, AutoFitTextureView textureView) {
43 | if (mState != null) throw new IllegalStateException("Alrady started state=" + mState);
44 | mTextureView = textureView;
45 | mCameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
46 | nextState(mInitSurfaceState);
47 | }
48 | public boolean takePicture(ImageReader.OnImageAvailableListener listener) {
49 | if (mState != mPreviewState) return false;
50 | mTakePictureListener = listener;
51 | nextState(mAutoFocusState);
52 | return true;
53 | }
54 | public void close() {
55 | nextState(mAbortState);
56 | }
57 |
58 | // ----------------------------------------------------------------------------------------
59 | // The following private
60 | private void shutdown() {
61 | if (null != mCaptureSession) {
62 | mCaptureSession.close();
63 | mCaptureSession = null;
64 | }
65 | if (null != mCameraDevice) {
66 | mCameraDevice.close();
67 | mCameraDevice = null;
68 | }
69 | if (null != mImageReader) {
70 | mImageReader.close();
71 | mImageReader = null;
72 | }
73 | }
74 |
75 | private void nextState(State nextState) {
76 | Log.d(TAG, "state: " + mState + "->" + nextState);
77 | try {
78 | if (mState != null) mState.finish();
79 | mState = nextState;
80 | if (mState != null) mState.enter();
81 | } catch (CameraAccessException e) {
82 | Log.e(TAG, "next(" + nextState + ")", e);
83 | shutdown();
84 | }
85 | }
86 |
87 | private abstract class State {
88 | private String mName;
89 |
90 | public State(String name) {
91 | mName = name;
92 | }
93 | //@formatter:off
94 | public String toString() {return mName;}
95 | public void enter() throws CameraAccessException {}
96 | public void onSurfaceTextureAvailable(int width, int height){}
97 | public void onCameraOpened(CameraDevice cameraDevice){}
98 | public void onSessionConfigured(CameraCaptureSession cameraCaptureSession) {}
99 | public void onCaptureResult(CaptureResult result, boolean isCompleted) throws CameraAccessException {}
100 | public void finish() throws CameraAccessException {}
101 | //@formatter:on
102 | }
103 |
104 | // ===================================================================================
105 | // State Definition
106 | private final State mInitSurfaceState = new State("InitSurface") {
107 | public void enter() throws CameraAccessException {
108 | if (mTextureView.isAvailable()) {
109 | nextState(mOpenCameraState);
110 | } else {
111 | mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
112 | }
113 | }
114 | public void onSurfaceTextureAvailable(int width, int height) {
115 | nextState(mOpenCameraState);
116 | }
117 |
118 | private final TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
119 | @Override
120 | public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
121 | if (mState != null) mState.onSurfaceTextureAvailable(width, height);
122 | }
123 | @Override
124 | public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
125 | // TODO: ratation changed.
126 | }
127 | @Override
128 | public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
129 | return true;
130 | }
131 | @Override
132 | public void onSurfaceTextureUpdated(SurfaceTexture texture) {
133 | }
134 | };
135 | };
136 | // -----------------------------------------------------------------------------------
137 | private final State mOpenCameraState = new State("OpenCamera") {
138 | public void enter() throws CameraAccessException {
139 | // configureTransform(width, height);
140 | String cameraId = Camera2Util.getCameraId(mCameraManager, CameraCharacteristics.LENS_FACING_BACK);
141 | CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);
142 | StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
143 |
144 | mImageReader = Camera2Util.getMaxSizeImageReader(map, ImageFormat.JPEG);
145 | Size previewSize = Camera2Util.getBestPreviewSize(map, mImageReader);
146 | mTextureView.setPreviewSize(previewSize.getHeight(), previewSize.getWidth());
147 |
148 | mCameraManager.openCamera(cameraId, mStateCallback, mHandler);
149 | Log.d(TAG, "openCamera:" + cameraId);
150 | }
151 | public void onCameraOpened(CameraDevice cameraDevice) {
152 | mCameraDevice = cameraDevice;
153 | nextState(mCreateSessionState);
154 | }
155 |
156 | private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
157 | @Override
158 | public void onOpened(CameraDevice cameraDevice) {
159 | if (mState != null) mState.onCameraOpened(cameraDevice);
160 | }
161 | @Override
162 | public void onDisconnected(CameraDevice cameraDevice) {
163 | nextState(mAbortState);
164 | }
165 | @Override
166 | public void onError(CameraDevice cameraDevice, int error) {
167 | Log.e(TAG, "CameraDevice:onError:" + error);
168 | nextState(mAbortState);
169 | }
170 | };
171 | };
172 | // -----------------------------------------------------------------------------------
173 | private final State mCreateSessionState = new State("CreateSession") {
174 | public void enter() throws CameraAccessException {
175 | mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
176 | SurfaceTexture texture = mTextureView.getSurfaceTexture();
177 | texture.setDefaultBufferSize(mTextureView.getPreviewWidth(), mTextureView.getPreviewHeight());
178 | Surface surface = new Surface(texture);
179 | mPreviewRequestBuilder.addTarget(surface);
180 | List outputs = Arrays.asList(surface, mImageReader.getSurface());
181 | mCameraDevice.createCaptureSession(outputs, mSessionCallback, mHandler);
182 | }
183 | public void onSessionConfigured(CameraCaptureSession cameraCaptureSession) {
184 | mCaptureSession = cameraCaptureSession;
185 | nextState(mPreviewState);
186 | }
187 |
188 | private final CameraCaptureSession.StateCallback mSessionCallback = new CameraCaptureSession.StateCallback() {
189 | @Override
190 | public void onConfigured(CameraCaptureSession cameraCaptureSession) {
191 | if (mState != null) mState.onSessionConfigured(cameraCaptureSession);
192 | }
193 | @Override
194 | public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
195 | nextState(mAbortState);
196 | }
197 | };
198 | };
199 | // -----------------------------------------------------------------------------------
200 | private final State mPreviewState = new State("Preview") {
201 | public void enter() throws CameraAccessException {
202 | mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
203 | mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
204 | mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mHandler);
205 | }
206 | };
207 | private final CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
208 | @Override
209 | public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult) {
210 | onCaptureResult(partialResult, false);
211 | }
212 | @Override
213 | public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
214 | onCaptureResult(result, true);
215 | }
216 | private void onCaptureResult(CaptureResult result, boolean isCompleted) {
217 | try {
218 | if (mState != null) mState.onCaptureResult(result, isCompleted);
219 | } catch (CameraAccessException e) {
220 | Log.e(TAG, "handle():", e);
221 | nextState(mAbortState);
222 | }
223 | }
224 | };
225 | // -----------------------------------------------------------------------------------
226 | private final State mAutoFocusState = new State("AutoFocus") {
227 | public void enter() throws CameraAccessException {
228 | mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
229 | mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mHandler);
230 | }
231 | public void onCaptureResult(CaptureResult result, boolean isCompleted) throws CameraAccessException {
232 | Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
233 | boolean isAfReady = afState == null
234 | || afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED
235 | || afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
236 | if (isAfReady) {
237 | nextState(mAutoExposureState);
238 | }
239 | }
240 | };
241 | // -----------------------------------------------------------------------------------
242 | private final State mAutoExposureState = new State("AutoExposure") {
243 | public void enter() throws CameraAccessException {
244 | mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
245 | CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);
246 | mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mHandler);
247 | }
248 | public void onCaptureResult(CaptureResult result, boolean isCompleted) throws CameraAccessException {
249 | Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
250 | boolean isAeReady = aeState == null
251 | || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED
252 | || aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED;
253 | if (isAeReady) {
254 | nextState(mTakePictureState);
255 | }
256 | }
257 | };
258 | // -----------------------------------------------------------------------------------
259 | private final State mTakePictureState = new State("TakePicture") {
260 | public void enter() throws CameraAccessException {
261 | final CaptureRequest.Builder captureBuilder =
262 | mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
263 | captureBuilder.addTarget(mImageReader.getSurface());
264 | captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
265 | captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
266 | captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, 90); // portraito
267 | mImageReader.setOnImageAvailableListener(mTakePictureListener, mHandler);
268 |
269 | mCaptureSession.stopRepeating();
270 | mCaptureSession.capture(captureBuilder.build(), mCaptureCallback, mHandler);
271 | }
272 | public void onCaptureResult(CaptureResult result, boolean isCompleted) throws CameraAccessException {
273 | if (isCompleted) {
274 | nextState(mPreviewState);
275 | }
276 | }
277 | public void finish() throws CameraAccessException {
278 | mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
279 | mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
280 | mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mHandler);
281 | mTakePictureListener = null;
282 | }
283 | };
284 | // -----------------------------------------------------------------------------------
285 | private final State mAbortState = new State("Abort") {
286 | public void enter() throws CameraAccessException {
287 | shutdown();
288 | nextState(null);
289 | }
290 | };
291 | }
292 |
--------------------------------------------------------------------------------
/androidCamera2Sample/src/org/kotemaru/android/camera2sample/Camera2Util.java:
--------------------------------------------------------------------------------
1 | package org.kotemaru.android.camera2sample;
2 |
3 | import android.graphics.SurfaceTexture;
4 | import android.hardware.camera2.CameraAccessException;
5 | import android.hardware.camera2.CameraCharacteristics;
6 | import android.hardware.camera2.CameraManager;
7 | import android.hardware.camera2.params.StreamConfigurationMap;
8 | import android.media.ImageReader;
9 | import android.util.Size;
10 |
11 | public class Camera2Util {
12 | public static String getCameraId(CameraManager cameraManager, int facing) throws CameraAccessException {
13 | for (String cameraId : cameraManager.getCameraIdList()) {
14 | CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
15 | if (characteristics.get(CameraCharacteristics.LENS_FACING) == facing) {
16 | return cameraId;
17 | }
18 | }
19 | return null;
20 | }
21 |
22 | public static ImageReader getMaxSizeImageReader(StreamConfigurationMap map, int imageFormat) throws CameraAccessException {
23 | Size[] sizes = map.getOutputSizes(imageFormat);
24 | Size maxSize = sizes[0];
25 | for (Size size:sizes) {
26 | if (size.getWidth() > maxSize.getWidth()) {
27 | maxSize = size;
28 | }
29 | }
30 | ImageReader imageReader = ImageReader.newInstance(
31 | //maxSize.getWidth(), maxSize.getHeight(), // for landscape.
32 | maxSize.getHeight(), maxSize.getWidth(), // for portrait.
33 | imageFormat, /*maxImages*/1);
34 | return imageReader;
35 | }
36 |
37 | public static Size getBestPreviewSize(StreamConfigurationMap map, ImageReader imageSize) throws CameraAccessException {
38 | //float imageAspect = (float) imageSize.getWidth() / imageSize.getHeight(); // for landscape.
39 | float imageAspect = (float) imageSize.getHeight() / imageSize.getWidth(); // for portrait
40 | float minDiff = 1000000000000F;
41 | Size[] previewSizes = map.getOutputSizes(SurfaceTexture.class);
42 | Size previewSize = previewSizes[0];
43 | for (Size size : previewSizes) {
44 | float previewAspect = (float) size.getWidth() / size.getHeight();
45 | float diff = Math.abs(imageAspect - previewAspect);
46 | if (diff < minDiff) {
47 | previewSize = size;
48 | minDiff = diff;
49 | }
50 | if (diff == 0.0F) break;
51 | }
52 | return previewSize;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/androidCamera2Sample/src/org/kotemaru/android/camera2sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package org.kotemaru.android.camera2sample;
2 |
3 | import java.nio.ByteBuffer;
4 |
5 | import android.app.Activity;
6 | import android.graphics.Bitmap;
7 | import android.graphics.BitmapFactory;
8 | import android.media.Image;
9 | import android.media.ImageReader;
10 | import android.os.Bundle;
11 | import android.view.KeyEvent;
12 | import android.view.View;
13 | import android.widget.ImageView;
14 |
15 | public class MainActivity extends Activity {
16 | private AutoFitTextureView mTextureView;
17 | private ImageView mImageView;
18 | private Camera2StateMachine mCamera2;
19 |
20 | @Override
21 | protected void onCreate(Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 | setContentView(R.layout.activity_main);
24 |
25 | mTextureView = (AutoFitTextureView) findViewById(R.id.TextureView);
26 | mImageView = (ImageView) findViewById(R.id.ImageView);
27 | mCamera2 = new Camera2StateMachine();
28 | }
29 |
30 | @Override
31 | protected void onResume() {
32 | super.onResume();
33 | mCamera2.open(this, mTextureView);
34 | }
35 | @Override
36 | protected void onPause() {
37 | mCamera2.close();
38 | super.onPause();
39 | }
40 | @Override
41 | public boolean onKeyDown(int keyCode, KeyEvent event) {
42 | if (keyCode == KeyEvent.KEYCODE_BACK && mImageView.getVisibility() == View.VISIBLE) {
43 | mTextureView.setVisibility(View.VISIBLE);
44 | mImageView.setVisibility(View.INVISIBLE);
45 | return false;
46 | }
47 | return super.onKeyDown(keyCode, event);
48 | }
49 | public void onClickShutter(View view) {
50 | mCamera2.takePicture(new ImageReader.OnImageAvailableListener() {
51 | @Override
52 | public void onImageAvailable(ImageReader reader) {
53 | // 撮れた画像をImageViewに貼り付けて表示。
54 | final Image image = reader.acquireLatestImage();
55 | ByteBuffer buffer = image.getPlanes()[0].getBuffer();
56 | byte[] bytes = new byte[buffer.remaining()];
57 | buffer.get(bytes);
58 | Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
59 | image.close();
60 |
61 | mImageView.setImageBitmap(bitmap);
62 | mImageView.setVisibility(View.VISIBLE);
63 | mTextureView.setVisibility(View.INVISIBLE);
64 | }
65 | });
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------