@capacitor-community/camera-preview 2.1.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,11 +2,10 @@ package com.ahm.capacitor.camera.preview;
2
2
 
3
3
  import android.app.Activity;
4
4
  import android.app.Fragment;
5
- import android.content.pm.PackageManager;
6
5
  import android.content.Context;
6
+ import android.content.pm.PackageManager;
7
7
  import android.graphics.Bitmap;
8
8
  import android.graphics.Bitmap.CompressFormat;
9
- import android.media.AudioManager;
10
9
  import android.graphics.BitmapFactory;
11
10
  import android.graphics.Canvas;
12
11
  import android.graphics.ImageFormat;
@@ -16,19 +15,19 @@ import android.graphics.YuvImage;
16
15
  import android.hardware.Camera;
17
16
  import android.hardware.Camera.PictureCallback;
18
17
  import android.hardware.Camera.ShutterCallback;
18
+ import android.media.AudioManager;
19
19
  import android.media.CamcorderProfile;
20
20
  import android.media.MediaRecorder;
21
- import androidx.exifinterface.media.ExifInterface;
22
- import android.view.Surface;
23
21
  import android.os.Bundle;
24
22
  import android.util.Base64;
25
- import android.util.Log;
26
23
  import android.util.DisplayMetrics;
24
+ import android.util.Log;
27
25
  import android.view.GestureDetector;
28
26
  import android.view.Gravity;
29
27
  import android.view.LayoutInflater;
30
28
  import android.view.MotionEvent;
31
29
  import android.view.Surface;
30
+ import android.view.Surface;
32
31
  import android.view.SurfaceHolder;
33
32
  import android.view.SurfaceView;
34
33
  import android.view.View;
@@ -36,7 +35,7 @@ import android.view.ViewGroup;
36
35
  import android.view.ViewTreeObserver;
37
36
  import android.widget.FrameLayout;
38
37
  import android.widget.RelativeLayout;
39
-
38
+ import androidx.exifinterface.media.ExifInterface;
40
39
  import java.io.ByteArrayInputStream;
41
40
  import java.io.ByteArrayOutputStream;
42
41
  import java.io.File;
@@ -48,884 +47,921 @@ import java.util.UUID;
48
47
 
49
48
  public class CameraActivity extends Fragment {
50
49
 
51
- public interface CameraPreviewListener {
52
- void onPictureTaken(String originalPicture);
53
- void onPictureTakenError(String message);
54
- void onSnapshotTaken(String originalPicture);
55
- void onSnapshotTakenError(String message);
56
- void onFocusSet(int pointX, int pointY);
57
- void onFocusSetError(String message);
58
- void onBackButton();
59
- void onCameraStarted();
60
- void onStartRecordVideo();
61
- void onStartRecordVideoError(String message);
62
- void onStopRecordVideo(String file);
63
- void onStopRecordVideoError(String error);
64
- }
65
-
66
- private CameraPreviewListener eventListener;
67
- private static final String TAG = "CameraActivity";
68
- public FrameLayout mainLayout;
69
- public FrameLayout frameContainerLayout;
70
-
71
- private Preview mPreview;
72
- private boolean canTakePicture = true;
73
-
74
- private View view;
75
- private Camera.Parameters cameraParameters;
76
- private Camera mCamera;
77
- private int numberOfCameras;
78
- private int cameraCurrentlyLocked;
79
- private int currentQuality;
80
- private enum RecordingState {INITIALIZING, STARTED, STOPPED}
81
- private RecordingState mRecordingState = RecordingState.INITIALIZING;
82
- private MediaRecorder mRecorder = null;
83
- private String recordFilePath;
84
- private float opacity;
85
-
86
-
87
- // The first rear facing camera
88
- private int defaultCameraId;
89
- public String defaultCamera;
90
- public boolean tapToTakePicture;
91
- public boolean dragEnabled;
92
- public boolean tapToFocus;
93
- public boolean disableExifHeaderStripping;
94
- public boolean storeToFile;
95
- public boolean toBack;
96
- public boolean enableOpacity = false;
97
- public boolean enableZoom = false;
98
-
99
-
100
- public int width;
101
- public int height;
102
- public int x;
103
- public int y;
104
-
105
- public void setEventListener(CameraPreviewListener listener){
106
- eventListener = listener;
107
- }
108
-
109
- private String appResourcesPackage;
110
-
111
- @Override
112
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
113
- appResourcesPackage = getActivity().getPackageName();
114
-
115
- // Inflate the layout for this fragment
116
- view = inflater.inflate(getResources().getIdentifier("camera_activity", "layout", appResourcesPackage), container, false);
117
- createCameraPreview();
118
- return view;
119
- }
120
-
121
- public void setRect(int x, int y, int width, int height){
122
- this.x = x;
123
- this.y = y;
124
- this.width = width;
125
- this.height = height;
126
- }
127
-
128
- private void createCameraPreview(){
129
- if(mPreview == null) {
130
- setDefaultCameraId();
131
-
132
- //set box position and size
133
- FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(width, height);
134
- layoutParams.setMargins(x, y, 0, 0);
135
- frameContainerLayout = (FrameLayout) view.findViewById(getResources().getIdentifier("frame_container", "id", appResourcesPackage));
136
- frameContainerLayout.setLayoutParams(layoutParams);
137
-
138
- //video view
139
- mPreview = new Preview(getActivity(), enableOpacity);
140
- mainLayout = (FrameLayout) view.findViewById(getResources().getIdentifier("video_view", "id", appResourcesPackage));
141
- mainLayout.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
142
- mainLayout.addView(mPreview);
143
- mainLayout.setEnabled(false);
144
-
145
- if (enableZoom) {
146
- this.setupTouchAndBackButton();
147
- }
50
+ public interface CameraPreviewListener {
51
+ void onPictureTaken(String originalPicture);
52
+ void onPictureTakenError(String message);
53
+ void onSnapshotTaken(String originalPicture);
54
+ void onSnapshotTakenError(String message);
55
+ void onFocusSet(int pointX, int pointY);
56
+ void onFocusSetError(String message);
57
+ void onBackButton();
58
+ void onCameraStarted();
59
+ void onStartRecordVideo();
60
+ void onStartRecordVideoError(String message);
61
+ void onStopRecordVideo(String file);
62
+ void onStopRecordVideoError(String error);
63
+ }
148
64
 
65
+ private CameraPreviewListener eventListener;
66
+ private static final String TAG = "CameraActivity";
67
+ public FrameLayout mainLayout;
68
+ public FrameLayout frameContainerLayout;
69
+
70
+ private Preview mPreview;
71
+ private boolean canTakePicture = true;
72
+
73
+ private View view;
74
+ private Camera.Parameters cameraParameters;
75
+ private Camera mCamera;
76
+ private int numberOfCameras;
77
+ private int cameraCurrentlyLocked;
78
+ private int currentQuality;
79
+
80
+ private enum RecordingState {
81
+ INITIALIZING,
82
+ STARTED,
83
+ STOPPED
149
84
  }
150
- }
151
- private void setupTouchAndBackButton() {
152
-
153
- final GestureDetector gestureDetector = new GestureDetector(getActivity().getApplicationContext(), new TapGestureDetector());
154
-
155
- getActivity().runOnUiThread(new Runnable() {
156
- @Override
157
- public void run() {
158
- frameContainerLayout.setClickable(true);
159
- frameContainerLayout.setOnTouchListener(new View.OnTouchListener() {
160
-
161
- private int mLastTouchX;
162
- private int mLastTouchY;
163
- private int mPosX = 0;
164
- private int mPosY = 0;
165
-
166
- @Override
167
- public boolean onTouch(View v, MotionEvent event) {
168
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) frameContainerLayout.getLayoutParams();
169
-
170
-
171
- boolean isSingleTapTouch = gestureDetector.onTouchEvent(event);
172
- int action = event.getAction();
173
- int eventCount = event.getPointerCount();
174
- Log.d(TAG, "onTouch event, action, count: " + event + ", " + action + ", " + eventCount);
175
- if (eventCount > 1) {
176
- // handle multi-touch events
177
- Camera.Parameters params = mCamera.getParameters();
178
- if (action == MotionEvent.ACTION_POINTER_DOWN) {
179
- mDist = getFingerSpacing(event);
180
- } else if (action == MotionEvent.ACTION_MOVE && params.isZoomSupported()) {
181
- handleZoom(event, params);
182
- }
183
- } else {
184
- if (action != MotionEvent.ACTION_MOVE && isSingleTapTouch) {
185
- if (tapToTakePicture && tapToFocus) {
186
- setFocusArea((int) event.getX(0), (int) event.getY(0), new Camera.AutoFocusCallback() {
187
- public void onAutoFocus(boolean success, Camera camera) {
188
- if (success) {
189
- takePicture(0, 0, 85);
190
- } else {
191
- Log.d(TAG, "onTouch:" + " setFocusArea() did not suceed");
192
- }
193
- }
194
- });
195
-
196
- } else if (tapToTakePicture) {
197
- takePicture(0, 0, 85);
198
-
199
- } else if (tapToFocus) {
200
- setFocusArea((int) event.getX(0), (int) event.getY(0), new Camera.AutoFocusCallback() {
201
- public void onAutoFocus(boolean success, Camera camera) {
202
- if (success) {
203
- // A callback to JS might make sense here.
204
- } else {
205
- Log.d(TAG, "onTouch:" + " setFocusArea() did not suceed");
206
- }
207
- }
208
- });
209
- }
210
- return true;
211
- } else {
212
- if (dragEnabled) {
213
- int x;
214
- int y;
215
-
216
- switch (event.getAction()) {
217
- case MotionEvent.ACTION_DOWN:
218
- if (mLastTouchX == 0 || mLastTouchY == 0) {
219
- mLastTouchX = (int) event.getRawX() - layoutParams.leftMargin;
220
- mLastTouchY = (int) event.getRawY() - layoutParams.topMargin;
221
- } else {
222
- mLastTouchX = (int) event.getRawX();
223
- mLastTouchY = (int) event.getRawY();
224
- }
225
- break;
226
- case MotionEvent.ACTION_MOVE:
227
-
228
- x = (int) event.getRawX();
229
- y = (int) event.getRawY();
230
-
231
- final float dx = x - mLastTouchX;
232
- final float dy = y - mLastTouchY;
233
-
234
- mPosX += dx;
235
- mPosY += dy;
236
-
237
- layoutParams.leftMargin = mPosX;
238
- layoutParams.topMargin = mPosY;
239
-
240
- frameContainerLayout.setLayoutParams(layoutParams);
241
-
242
- // Remember this touch position for the next move event
243
- mLastTouchX = x;
244
- mLastTouchY = y;
245
-
246
- break;
247
- default:
248
- break;
249
- }
250
- }
251
- }
252
- }
253
- return true;
254
- }
255
- });
256
- frameContainerLayout.setFocusableInTouchMode(true);
257
- frameContainerLayout.requestFocus();
258
- frameContainerLayout.setOnKeyListener(new View.OnKeyListener() {
259
- @Override
260
- public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
261
-
262
- if (keyCode == android.view.KeyEvent.KEYCODE_BACK) {
263
- eventListener.onBackButton();
264
- return true;
265
- }
266
- return false;
267
- }
268
- });
269
85
 
270
- }
271
- private float mDist = 0F;
272
-
273
- private void handleZoom(MotionEvent event, Camera.Parameters params) {
274
- if (mCamera != null) {
275
- mCamera.cancelAutoFocus();
276
- int maxZoom = params.getMaxZoom();
277
- int zoom = params.getZoom();
278
- float newDist = getFingerSpacing(event);
279
- if (newDist > mDist) {
280
- //zoom in
281
- if (zoom < maxZoom)
282
- zoom++;
283
- } else if (newDist < mDist) {
284
- //zoom out
285
- if (zoom > 0)
286
- zoom--;
287
- }
288
- mDist = newDist;
289
- params.setZoom(zoom);
290
- mCamera.setParameters(params);
291
- }
292
- }
293
- });
294
-
295
- }
296
-
297
- private void setDefaultCameraId(){
298
- // Find the total number of cameras available
299
- numberOfCameras = Camera.getNumberOfCameras();
300
-
301
- int facing = "front".equals(defaultCamera) ? Camera.CameraInfo.CAMERA_FACING_FRONT : Camera.CameraInfo.CAMERA_FACING_BACK;
302
-
303
- // Find the ID of the default camera
304
- Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
305
- for (int i = 0; i < numberOfCameras; i++) {
306
- Camera.getCameraInfo(i, cameraInfo);
307
- if (cameraInfo.facing == facing) {
308
- defaultCameraId = i;
309
- break;
310
- }
86
+ private RecordingState mRecordingState = RecordingState.INITIALIZING;
87
+ private MediaRecorder mRecorder = null;
88
+ private String recordFilePath;
89
+ private float opacity;
90
+
91
+ // The first rear facing camera
92
+ private int defaultCameraId;
93
+ public String defaultCamera;
94
+ public boolean tapToTakePicture;
95
+ public boolean dragEnabled;
96
+ public boolean tapToFocus;
97
+ public boolean disableExifHeaderStripping;
98
+ public boolean storeToFile;
99
+ public boolean toBack;
100
+ public boolean enableOpacity = false;
101
+ public boolean enableZoom = false;
102
+
103
+ public int width;
104
+ public int height;
105
+ public int x;
106
+ public int y;
107
+
108
+ public void setEventListener(CameraPreviewListener listener) {
109
+ eventListener = listener;
110
+ }
111
+
112
+ private String appResourcesPackage;
113
+
114
+ @Override
115
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
116
+ appResourcesPackage = getActivity().getPackageName();
117
+
118
+ // Inflate the layout for this fragment
119
+ view = inflater.inflate(getResources().getIdentifier("camera_activity", "layout", appResourcesPackage), container, false);
120
+ createCameraPreview();
121
+ return view;
311
122
  }
312
- }
313
123
 
314
- @Override
315
- public void onResume() {
316
- super.onResume();
124
+ public void setRect(int x, int y, int width, int height) {
125
+ this.x = x;
126
+ this.y = y;
127
+ this.width = width;
128
+ this.height = height;
129
+ }
317
130
 
318
- mCamera = Camera.open(defaultCameraId);
131
+ private void createCameraPreview() {
132
+ if (mPreview == null) {
133
+ setDefaultCameraId();
134
+
135
+ //set box position and size
136
+ FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(width, height);
137
+ layoutParams.setMargins(x, y, 0, 0);
138
+ frameContainerLayout =
139
+ (FrameLayout) view.findViewById(getResources().getIdentifier("frame_container", "id", appResourcesPackage));
140
+ frameContainerLayout.setLayoutParams(layoutParams);
141
+
142
+ //video view
143
+ mPreview = new Preview(getActivity(), enableOpacity);
144
+ mainLayout = (FrameLayout) view.findViewById(getResources().getIdentifier("video_view", "id", appResourcesPackage));
145
+ mainLayout.setLayoutParams(
146
+ new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)
147
+ );
148
+ mainLayout.addView(mPreview);
149
+ mainLayout.setEnabled(false);
150
+
151
+ if (enableZoom) {
152
+ this.setupTouchAndBackButton();
153
+ }
154
+ }
155
+ }
319
156
 
320
- if (cameraParameters != null) {
321
- mCamera.setParameters(cameraParameters);
157
+ private void setupTouchAndBackButton() {
158
+ final GestureDetector gestureDetector = new GestureDetector(getActivity().getApplicationContext(), new TapGestureDetector());
159
+
160
+ getActivity()
161
+ .runOnUiThread(
162
+ new Runnable() {
163
+ @Override
164
+ public void run() {
165
+ frameContainerLayout.setClickable(true);
166
+ frameContainerLayout.setOnTouchListener(
167
+ new View.OnTouchListener() {
168
+ private int mLastTouchX;
169
+ private int mLastTouchY;
170
+ private int mPosX = 0;
171
+ private int mPosY = 0;
172
+
173
+ @Override
174
+ public boolean onTouch(View v, MotionEvent event) {
175
+ FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) frameContainerLayout.getLayoutParams();
176
+
177
+ boolean isSingleTapTouch = gestureDetector.onTouchEvent(event);
178
+ int action = event.getAction();
179
+ int eventCount = event.getPointerCount();
180
+ Log.d(TAG, "onTouch event, action, count: " + event + ", " + action + ", " + eventCount);
181
+ if (eventCount > 1) {
182
+ // handle multi-touch events
183
+ Camera.Parameters params = mCamera.getParameters();
184
+ if (action == MotionEvent.ACTION_POINTER_DOWN) {
185
+ mDist = getFingerSpacing(event);
186
+ } else if (action == MotionEvent.ACTION_MOVE && params.isZoomSupported()) {
187
+ handleZoom(event, params);
188
+ }
189
+ } else {
190
+ if (action != MotionEvent.ACTION_MOVE && isSingleTapTouch) {
191
+ if (tapToTakePicture && tapToFocus) {
192
+ setFocusArea(
193
+ (int) event.getX(0),
194
+ (int) event.getY(0),
195
+ new Camera.AutoFocusCallback() {
196
+ public void onAutoFocus(boolean success, Camera camera) {
197
+ if (success) {
198
+ takePicture(0, 0, 85);
199
+ } else {
200
+ Log.d(TAG, "onTouch:" + " setFocusArea() did not suceed");
201
+ }
202
+ }
203
+ }
204
+ );
205
+ } else if (tapToTakePicture) {
206
+ takePicture(0, 0, 85);
207
+ } else if (tapToFocus) {
208
+ setFocusArea(
209
+ (int) event.getX(0),
210
+ (int) event.getY(0),
211
+ new Camera.AutoFocusCallback() {
212
+ public void onAutoFocus(boolean success, Camera camera) {
213
+ if (success) {
214
+ // A callback to JS might make sense here.
215
+ } else {
216
+ Log.d(TAG, "onTouch:" + " setFocusArea() did not suceed");
217
+ }
218
+ }
219
+ }
220
+ );
221
+ }
222
+ return true;
223
+ } else {
224
+ if (dragEnabled) {
225
+ int x;
226
+ int y;
227
+
228
+ switch (event.getAction()) {
229
+ case MotionEvent.ACTION_DOWN:
230
+ if (mLastTouchX == 0 || mLastTouchY == 0) {
231
+ mLastTouchX = (int) event.getRawX() - layoutParams.leftMargin;
232
+ mLastTouchY = (int) event.getRawY() - layoutParams.topMargin;
233
+ } else {
234
+ mLastTouchX = (int) event.getRawX();
235
+ mLastTouchY = (int) event.getRawY();
236
+ }
237
+ break;
238
+ case MotionEvent.ACTION_MOVE:
239
+ x = (int) event.getRawX();
240
+ y = (int) event.getRawY();
241
+
242
+ final float dx = x - mLastTouchX;
243
+ final float dy = y - mLastTouchY;
244
+
245
+ mPosX += dx;
246
+ mPosY += dy;
247
+
248
+ layoutParams.leftMargin = mPosX;
249
+ layoutParams.topMargin = mPosY;
250
+
251
+ frameContainerLayout.setLayoutParams(layoutParams);
252
+
253
+ // Remember this touch position for the next move event
254
+ mLastTouchX = x;
255
+ mLastTouchY = y;
256
+
257
+ break;
258
+ default:
259
+ break;
260
+ }
261
+ }
262
+ }
263
+ }
264
+ return true;
265
+ }
266
+ }
267
+ );
268
+ frameContainerLayout.setFocusableInTouchMode(true);
269
+ frameContainerLayout.requestFocus();
270
+ frameContainerLayout.setOnKeyListener(
271
+ new View.OnKeyListener() {
272
+ @Override
273
+ public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
274
+ if (keyCode == android.view.KeyEvent.KEYCODE_BACK) {
275
+ eventListener.onBackButton();
276
+ return true;
277
+ }
278
+ return false;
279
+ }
280
+ }
281
+ );
282
+ }
283
+
284
+ private float mDist = 0F;
285
+
286
+ private void handleZoom(MotionEvent event, Camera.Parameters params) {
287
+ if (mCamera != null) {
288
+ mCamera.cancelAutoFocus();
289
+ int maxZoom = params.getMaxZoom();
290
+ int zoom = params.getZoom();
291
+ float newDist = getFingerSpacing(event);
292
+ if (newDist > mDist) {
293
+ //zoom in
294
+ if (zoom < maxZoom) zoom++;
295
+ } else if (newDist < mDist) {
296
+ //zoom out
297
+ if (zoom > 0) zoom--;
298
+ }
299
+ mDist = newDist;
300
+ params.setZoom(zoom);
301
+ mCamera.setParameters(params);
302
+ }
303
+ }
304
+ }
305
+ );
322
306
  }
323
307
 
324
- cameraCurrentlyLocked = defaultCameraId;
308
+ private void setDefaultCameraId() {
309
+ // Find the total number of cameras available
310
+ numberOfCameras = Camera.getNumberOfCameras();
325
311
 
326
- if(mPreview.mPreviewSize == null){
327
- mPreview.setCamera(mCamera, cameraCurrentlyLocked);
328
- eventListener.onCameraStarted();
329
- } else {
330
- mPreview.switchCamera(mCamera, cameraCurrentlyLocked);
331
- mCamera.startPreview();
312
+ int facing = "front".equals(defaultCamera) ? Camera.CameraInfo.CAMERA_FACING_FRONT : Camera.CameraInfo.CAMERA_FACING_BACK;
313
+
314
+ // Find the ID of the default camera
315
+ Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
316
+ for (int i = 0; i < numberOfCameras; i++) {
317
+ Camera.getCameraInfo(i, cameraInfo);
318
+ if (cameraInfo.facing == facing) {
319
+ defaultCameraId = i;
320
+ break;
321
+ }
322
+ }
332
323
  }
333
324
 
334
- Log.d(TAG, "cameraCurrentlyLocked:" + cameraCurrentlyLocked);
325
+ @Override
326
+ public void onResume() {
327
+ super.onResume();
335
328
 
336
- final FrameLayout frameContainerLayout = (FrameLayout) view.findViewById(getResources().getIdentifier("frame_container", "id", appResourcesPackage));
329
+ mCamera = Camera.open(defaultCameraId);
337
330
 
338
- ViewTreeObserver viewTreeObserver = frameContainerLayout.getViewTreeObserver();
331
+ if (cameraParameters != null) {
332
+ mCamera.setParameters(cameraParameters);
333
+ }
339
334
 
340
- if (viewTreeObserver.isAlive()) {
341
- viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
342
- @Override
343
- public void onGlobalLayout() {
344
- frameContainerLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
345
- frameContainerLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
346
- Activity activity = getActivity();
347
- if (isAdded() && activity != null) {
348
- final RelativeLayout frameCamContainerLayout = (RelativeLayout) view.findViewById(getResources().getIdentifier("frame_camera_cont", "id", appResourcesPackage));
335
+ cameraCurrentlyLocked = defaultCameraId;
336
+
337
+ if (mPreview.mPreviewSize == null) {
338
+ mPreview.setCamera(mCamera, cameraCurrentlyLocked);
339
+ eventListener.onCameraStarted();
340
+ } else {
341
+ mPreview.switchCamera(mCamera, cameraCurrentlyLocked);
342
+ mCamera.startPreview();
343
+ }
344
+
345
+ Log.d(TAG, "cameraCurrentlyLocked:" + cameraCurrentlyLocked);
346
+
347
+ final FrameLayout frameContainerLayout = (FrameLayout) view.findViewById(
348
+ getResources().getIdentifier("frame_container", "id", appResourcesPackage)
349
+ );
350
+
351
+ ViewTreeObserver viewTreeObserver = frameContainerLayout.getViewTreeObserver();
352
+
353
+ if (viewTreeObserver.isAlive()) {
354
+ viewTreeObserver.addOnGlobalLayoutListener(
355
+ new ViewTreeObserver.OnGlobalLayoutListener() {
356
+ @Override
357
+ public void onGlobalLayout() {
358
+ frameContainerLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
359
+ frameContainerLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
360
+ Activity activity = getActivity();
361
+ if (isAdded() && activity != null) {
362
+ final RelativeLayout frameCamContainerLayout = (RelativeLayout) view.findViewById(
363
+ getResources().getIdentifier("frame_camera_cont", "id", appResourcesPackage)
364
+ );
365
+
366
+ FrameLayout.LayoutParams camViewLayout = new FrameLayout.LayoutParams(
367
+ frameContainerLayout.getWidth(),
368
+ frameContainerLayout.getHeight()
369
+ );
370
+ camViewLayout.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
371
+ frameCamContainerLayout.setLayoutParams(camViewLayout);
372
+ }
373
+ }
374
+ }
375
+ );
376
+ }
377
+ }
349
378
 
350
- FrameLayout.LayoutParams camViewLayout = new FrameLayout.LayoutParams(frameContainerLayout.getWidth(), frameContainerLayout.getHeight());
351
- camViewLayout.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
352
- frameCamContainerLayout.setLayoutParams(camViewLayout);
353
- }
379
+ @Override
380
+ public void onPause() {
381
+ super.onPause();
382
+
383
+ // Because the Camera object is a shared resource, it's very important to release it when the activity is paused.
384
+ if (mCamera != null) {
385
+ setDefaultCameraId();
386
+ mPreview.setCamera(null, -1);
387
+ mCamera.setPreviewCallback(null);
388
+ mCamera.release();
389
+ mCamera = null;
354
390
  }
355
- });
356
391
  }
357
- }
358
-
359
- @Override
360
- public void onPause() {
361
- super.onPause();
362
-
363
- // Because the Camera object is a shared resource, it's very important to release it when the activity is paused.
364
- if (mCamera != null) {
365
- setDefaultCameraId();
366
- mPreview.setCamera(null, -1);
367
- mCamera.setPreviewCallback(null);
368
- mCamera.release();
369
- mCamera = null;
392
+
393
+ public Camera getCamera() {
394
+ return mCamera;
370
395
  }
371
- }
372
-
373
- public Camera getCamera() {
374
- return mCamera;
375
- }
376
-
377
- public void switchCamera() {
378
- // check for availability of multiple cameras
379
- if (numberOfCameras == 1) {
380
- //There is only one camera available
381
- }else{
382
- Log.d(TAG, "numberOfCameras: " + numberOfCameras);
383
-
384
- // OK, we have multiple cameras. Release this camera -> cameraCurrentlyLocked
385
- if (mCamera != null) {
386
- mCamera.stopPreview();
387
- mPreview.setCamera(null, -1);
388
- mCamera.release();
389
- mCamera = null;
390
- }
391
-
392
- Log.d(TAG, "cameraCurrentlyLocked := " + Integer.toString(cameraCurrentlyLocked));
393
- try {
394
- cameraCurrentlyLocked = (cameraCurrentlyLocked + 1) % numberOfCameras;
395
- Log.d(TAG, "cameraCurrentlyLocked new: " + cameraCurrentlyLocked);
396
- } catch (Exception exception) {
397
- Log.d(TAG, exception.getMessage());
398
- }
399
-
400
- // Acquire the next camera and request Preview to reconfigure parameters.
401
- mCamera = Camera.open(cameraCurrentlyLocked);
402
-
403
- if (cameraParameters != null) {
404
- Log.d(TAG, "camera parameter not null");
405
-
406
- // Check for flashMode as well to prevent error on frontward facing camera.
407
- List<String> supportedFlashModesNewCamera = mCamera.getParameters().getSupportedFlashModes();
408
- String currentFlashModePreviousCamera = cameraParameters.getFlashMode();
409
- if (supportedFlashModesNewCamera != null && supportedFlashModesNewCamera.contains(currentFlashModePreviousCamera)) {
410
- Log.d(TAG, "current flash mode supported on new camera. setting params");
411
- /* mCamera.setParameters(cameraParameters);
396
+
397
+ public void switchCamera() {
398
+ // check for availability of multiple cameras
399
+ if (numberOfCameras == 1) {
400
+ //There is only one camera available
401
+ } else {
402
+ Log.d(TAG, "numberOfCameras: " + numberOfCameras);
403
+
404
+ // OK, we have multiple cameras. Release this camera -> cameraCurrentlyLocked
405
+ if (mCamera != null) {
406
+ mCamera.stopPreview();
407
+ mPreview.setCamera(null, -1);
408
+ mCamera.release();
409
+ mCamera = null;
410
+ }
411
+
412
+ Log.d(TAG, "cameraCurrentlyLocked := " + Integer.toString(cameraCurrentlyLocked));
413
+ try {
414
+ cameraCurrentlyLocked = (cameraCurrentlyLocked + 1) % numberOfCameras;
415
+ Log.d(TAG, "cameraCurrentlyLocked new: " + cameraCurrentlyLocked);
416
+ } catch (Exception exception) {
417
+ Log.d(TAG, exception.getMessage());
418
+ }
419
+
420
+ // Acquire the next camera and request Preview to reconfigure parameters.
421
+ mCamera = Camera.open(cameraCurrentlyLocked);
422
+
423
+ if (cameraParameters != null) {
424
+ Log.d(TAG, "camera parameter not null");
425
+
426
+ // Check for flashMode as well to prevent error on frontward facing camera.
427
+ List<String> supportedFlashModesNewCamera = mCamera.getParameters().getSupportedFlashModes();
428
+ String currentFlashModePreviousCamera = cameraParameters.getFlashMode();
429
+ if (supportedFlashModesNewCamera != null && supportedFlashModesNewCamera.contains(currentFlashModePreviousCamera)) {
430
+ Log.d(TAG, "current flash mode supported on new camera. setting params");
431
+ /* mCamera.setParameters(cameraParameters);
412
432
  The line above is disabled because parameters that can actually be changed are different from one device to another. Makes less sense trying to reconfigure them when changing camera device while those settings gan be changed using plugin methods.
413
433
  */
414
- } else {
415
- Log.d(TAG, "current flash mode NOT supported on new camera");
434
+ } else {
435
+ Log.d(TAG, "current flash mode NOT supported on new camera");
436
+ }
437
+ } else {
438
+ Log.d(TAG, "camera parameter NULL");
439
+ }
440
+
441
+ mPreview.switchCamera(mCamera, cameraCurrentlyLocked);
442
+
443
+ mCamera.startPreview();
416
444
  }
445
+ }
417
446
 
418
- } else {
419
- Log.d(TAG, "camera parameter NULL");
420
- }
447
+ public void setCameraParameters(Camera.Parameters params) {
448
+ cameraParameters = params;
421
449
 
422
- mPreview.switchCamera(mCamera, cameraCurrentlyLocked);
450
+ if (mCamera != null && cameraParameters != null) {
451
+ mCamera.setParameters(cameraParameters);
452
+ }
453
+ }
423
454
 
424
- mCamera.startPreview();
455
+ public boolean hasFrontCamera() {
456
+ return getActivity().getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
425
457
  }
426
- }
427
458
 
428
- public void setCameraParameters(Camera.Parameters params) {
429
- cameraParameters = params;
459
+ public static Bitmap applyMatrix(Bitmap source, Matrix matrix) {
460
+ return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
461
+ }
430
462
 
431
- if (mCamera != null && cameraParameters != null) {
432
- mCamera.setParameters(cameraParameters);
463
+ ShutterCallback shutterCallback = new ShutterCallback() {
464
+ public void onShutter() {
465
+ // do nothing, availabilty of this callback causes default system shutter sound to work
466
+ }
467
+ };
468
+
469
+ private static int exifToDegrees(int exifOrientation) {
470
+ if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
471
+ return 90;
472
+ } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
473
+ return 180;
474
+ } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
475
+ return 270;
476
+ }
477
+ return 0;
433
478
  }
434
- }
435
479
 
436
- public boolean hasFrontCamera(){
437
- return getActivity().getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
438
- }
480
+ private String getTempDirectoryPath() {
481
+ File cache = null;
439
482
 
440
- public static Bitmap applyMatrix(Bitmap source, Matrix matrix) {
441
- return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
442
- }
483
+ // Use internal storage
484
+ cache = getActivity().getCacheDir();
443
485
 
444
- ShutterCallback shutterCallback = new ShutterCallback(){
445
- public void onShutter(){
446
- // do nothing, availabilty of this callback causes default system shutter sound to work
486
+ // Create the cache directory if it doesn't exist
487
+ cache.mkdirs();
488
+ return cache.getAbsolutePath();
447
489
  }
448
- };
449
-
450
- private static int exifToDegrees(int exifOrientation) {
451
- if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { return 90; }
452
- else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) { return 180; }
453
- else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) { return 270; }
454
- return 0;
455
- }
456
-
457
- private String getTempDirectoryPath() {
458
- File cache = null;
459
-
460
- // Use internal storage
461
- cache = getActivity().getCacheDir();
462
-
463
- // Create the cache directory if it doesn't exist
464
- cache.mkdirs();
465
- return cache.getAbsolutePath();
466
- }
467
-
468
- private String getTempFilePath() {
469
- return getTempDirectoryPath() + "/cpcp_capture_" + UUID.randomUUID().toString().replace("-", "").substring(0, 8) + ".jpg";
470
- }
471
-
472
- PictureCallback jpegPictureCallback = new PictureCallback(){
473
- public void onPictureTaken(byte[] data, Camera arg1){
474
- Log.d(TAG, "CameraPreview jpegPictureCallback");
475
-
476
- try {
477
- if (!disableExifHeaderStripping) {
478
- Matrix matrix = new Matrix();
479
- if (cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT) {
480
- matrix.preScale(1.0f, -1.0f);
481
- }
482
-
483
- ExifInterface exifInterface = new ExifInterface(new ByteArrayInputStream(data));
484
- int rotation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
485
- int rotationInDegrees = exifToDegrees(rotation);
486
-
487
- if (rotation != 0f) {
488
- matrix.preRotate(rotationInDegrees);
489
- }
490
-
491
- // Check if matrix has changed. In that case, apply matrix and override data
492
- if (!matrix.isIdentity()) {
493
- Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
494
- bitmap = applyMatrix(bitmap, matrix);
495
-
496
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
497
- bitmap.compress(CompressFormat.JPEG, currentQuality, outputStream);
498
- data = outputStream.toByteArray();
499
- }
500
- }
501
490
 
502
- if (!storeToFile) {
503
- String encodedImage = Base64.encodeToString(data, Base64.NO_WRAP);
504
-
505
- eventListener.onPictureTaken(encodedImage);
506
- } else {
507
- String path = getTempFilePath();
508
- FileOutputStream out = new FileOutputStream(path);
509
- out.write(data);
510
- out.close();
511
- eventListener.onPictureTaken(path);
512
- }
513
- Log.d(TAG, "CameraPreview pictureTakenHandler called back");
514
- } catch (OutOfMemoryError e) {
515
- // most likely failed to allocate memory for rotateBitmap
516
- Log.d(TAG, "CameraPreview OutOfMemoryError");
517
- // failed to allocate memory
518
- eventListener.onPictureTakenError("Picture too large (memory)");
519
- } catch (IOException e) {
520
- Log.d(TAG, "CameraPreview IOException");
521
- eventListener.onPictureTakenError("IO Error when extracting exif");
522
- } catch (Exception e) {
523
- Log.d(TAG, "CameraPreview onPictureTaken general exception");
524
- } finally {
525
- canTakePicture = true;
526
- mCamera.startPreview();
527
- }
491
+ private String getTempFilePath() {
492
+ return getTempDirectoryPath() + "/cpcp_capture_" + UUID.randomUUID().toString().replace("-", "").substring(0, 8) + ".jpg";
528
493
  }
529
- };
530
494
 
531
- private Camera.Size getOptimalPictureSize(final int width, final int height, final Camera.Size previewSize, final List<Camera.Size> supportedSizes){
532
- /*
495
+ PictureCallback jpegPictureCallback = new PictureCallback() {
496
+ public void onPictureTaken(byte[] data, Camera arg1) {
497
+ Log.d(TAG, "CameraPreview jpegPictureCallback");
498
+
499
+ try {
500
+ if (!disableExifHeaderStripping) {
501
+ Matrix matrix = new Matrix();
502
+ if (cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT) {
503
+ matrix.preScale(1.0f, -1.0f);
504
+ }
505
+
506
+ ExifInterface exifInterface = new ExifInterface(new ByteArrayInputStream(data));
507
+ int rotation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
508
+ int rotationInDegrees = exifToDegrees(rotation);
509
+
510
+ if (rotation != 0f) {
511
+ matrix.preRotate(rotationInDegrees);
512
+ }
513
+
514
+ // Check if matrix has changed. In that case, apply matrix and override data
515
+ if (!matrix.isIdentity()) {
516
+ Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
517
+ bitmap = applyMatrix(bitmap, matrix);
518
+
519
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
520
+ bitmap.compress(CompressFormat.JPEG, currentQuality, outputStream);
521
+ data = outputStream.toByteArray();
522
+ }
523
+ }
524
+
525
+ if (!storeToFile) {
526
+ String encodedImage = Base64.encodeToString(data, Base64.NO_WRAP);
527
+
528
+ eventListener.onPictureTaken(encodedImage);
529
+ } else {
530
+ String path = getTempFilePath();
531
+ FileOutputStream out = new FileOutputStream(path);
532
+ out.write(data);
533
+ out.close();
534
+ eventListener.onPictureTaken(path);
535
+ }
536
+ Log.d(TAG, "CameraPreview pictureTakenHandler called back");
537
+ } catch (OutOfMemoryError e) {
538
+ // most likely failed to allocate memory for rotateBitmap
539
+ Log.d(TAG, "CameraPreview OutOfMemoryError");
540
+ // failed to allocate memory
541
+ eventListener.onPictureTakenError("Picture too large (memory)");
542
+ } catch (IOException e) {
543
+ Log.d(TAG, "CameraPreview IOException");
544
+ eventListener.onPictureTakenError("IO Error when extracting exif");
545
+ } catch (Exception e) {
546
+ Log.d(TAG, "CameraPreview onPictureTaken general exception");
547
+ } finally {
548
+ canTakePicture = true;
549
+ mCamera.startPreview();
550
+ }
551
+ }
552
+ };
553
+
554
+ private Camera.Size getOptimalPictureSize(
555
+ final int width,
556
+ final int height,
557
+ final Camera.Size previewSize,
558
+ final List<Camera.Size> supportedSizes
559
+ ) {
560
+ /*
533
561
  get the supportedPictureSize that:
534
562
  - matches exactly width and height
535
563
  - has the closest aspect ratio to the preview aspect ratio
536
564
  - has picture.width and picture.height closest to width and height
537
565
  - has the highest supported picture width and height up to 2 Megapixel if width == 0 || height == 0
538
566
  */
539
- Camera.Size size = mCamera.new Size(width, height);
567
+ Camera.Size size = mCamera.new Size(width, height);
540
568
 
541
- // convert to landscape if necessary
542
- if (size.width < size.height) {
543
- int temp = size.width;
544
- size.width = size.height;
545
- size.height = temp;
546
- }
569
+ // convert to landscape if necessary
570
+ if (size.width < size.height) {
571
+ int temp = size.width;
572
+ size.width = size.height;
573
+ size.height = temp;
574
+ }
547
575
 
548
- Camera.Size requestedSize = mCamera.new Size(size.width, size.height);
576
+ Camera.Size requestedSize = mCamera.new Size(size.width, size.height);
549
577
 
550
- double previewAspectRatio = (double)previewSize.width / (double)previewSize.height;
578
+ double previewAspectRatio = (double) previewSize.width / (double) previewSize.height;
551
579
 
552
- if (previewAspectRatio < 1.0) {
553
- // reset ratio to landscape
554
- previewAspectRatio = 1.0 / previewAspectRatio;
555
- }
580
+ if (previewAspectRatio < 1.0) {
581
+ // reset ratio to landscape
582
+ previewAspectRatio = 1.0 / previewAspectRatio;
583
+ }
556
584
 
557
- Log.d(TAG, "CameraPreview previewAspectRatio " + previewAspectRatio);
585
+ Log.d(TAG, "CameraPreview previewAspectRatio " + previewAspectRatio);
558
586
 
559
- double aspectTolerance = 0.1;
560
- double bestDifference = Double.MAX_VALUE;
587
+ double aspectTolerance = 0.1;
588
+ double bestDifference = Double.MAX_VALUE;
561
589
 
562
- for (int i = 0; i < supportedSizes.size(); i++) {
563
- Camera.Size supportedSize = supportedSizes.get(i);
590
+ for (int i = 0; i < supportedSizes.size(); i++) {
591
+ Camera.Size supportedSize = supportedSizes.get(i);
564
592
 
565
- // Perfect match
566
- if (supportedSize.equals(requestedSize)) {
567
- Log.d(TAG, "CameraPreview optimalPictureSize " + supportedSize.width + 'x' + supportedSize.height);
568
- return supportedSize;
569
- }
593
+ // Perfect match
594
+ if (supportedSize.equals(requestedSize)) {
595
+ Log.d(TAG, "CameraPreview optimalPictureSize " + supportedSize.width + 'x' + supportedSize.height);
596
+ return supportedSize;
597
+ }
570
598
 
571
- double difference = Math.abs(previewAspectRatio - ((double)supportedSize.width / (double)supportedSize.height));
599
+ double difference = Math.abs(previewAspectRatio - ((double) supportedSize.width / (double) supportedSize.height));
572
600
 
573
- if (difference < bestDifference - aspectTolerance) {
574
- // better aspectRatio found
575
- if ((width != 0 && height != 0) || (supportedSize.width * supportedSize.height < 2048 * 1024)) {
576
- size.width = supportedSize.width;
577
- size.height = supportedSize.height;
578
- bestDifference = difference;
601
+ if (difference < bestDifference - aspectTolerance) {
602
+ // better aspectRatio found
603
+ if ((width != 0 && height != 0) || (supportedSize.width * supportedSize.height < 2048 * 1024)) {
604
+ size.width = supportedSize.width;
605
+ size.height = supportedSize.height;
606
+ bestDifference = difference;
607
+ }
608
+ } else if (difference < bestDifference + aspectTolerance) {
609
+ // same aspectRatio found (within tolerance)
610
+ if (width == 0 || height == 0) {
611
+ // set highest supported resolution below 2 Megapixel
612
+ if ((size.width < supportedSize.width) && (supportedSize.width * supportedSize.height < 2048 * 1024)) {
613
+ size.width = supportedSize.width;
614
+ size.height = supportedSize.height;
615
+ }
616
+ } else {
617
+ // check if this pictureSize closer to requested width and height
618
+ if (
619
+ Math.abs(width * height - supportedSize.width * supportedSize.height) <
620
+ Math.abs(width * height - size.width * size.height)
621
+ ) {
622
+ size.width = supportedSize.width;
623
+ size.height = supportedSize.height;
624
+ }
625
+ }
626
+ }
579
627
  }
580
- } else if (difference < bestDifference + aspectTolerance) {
581
- // same aspectRatio found (within tolerance)
582
- if (width == 0 || height == 0) {
583
- // set highest supported resolution below 2 Megapixel
584
- if ((size.width < supportedSize.width) && (supportedSize.width * supportedSize.height < 2048 * 1024)) {
585
- size.width = supportedSize.width;
586
- size.height = supportedSize.height;
587
- }
588
- } else {
589
- // check if this pictureSize closer to requested width and height
590
- if (Math.abs(width * height - supportedSize.width * supportedSize.height) < Math.abs(width * height - size.width * size.height)) {
591
- size.width = supportedSize.width;
592
- size.height = supportedSize.height;
593
- }
628
+ Log.d(TAG, "CameraPreview optimalPictureSize " + size.width + 'x' + size.height);
629
+ return size;
630
+ }
631
+
632
+ static byte[] rotateNV21(final byte[] yuv, final int width, final int height, final int rotation) {
633
+ if (rotation == 0) return yuv;
634
+ if (rotation % 90 != 0 || rotation < 0 || rotation > 270) {
635
+ throw new IllegalArgumentException("0 <= rotation < 360, rotation % 90 == 0");
636
+ }
637
+
638
+ final byte[] output = new byte[yuv.length];
639
+ final int frameSize = width * height;
640
+ final boolean swap = rotation % 180 != 0;
641
+ final boolean xflip = rotation % 270 != 0;
642
+ final boolean yflip = rotation >= 180;
643
+
644
+ for (int j = 0; j < height; j++) {
645
+ for (int i = 0; i < width; i++) {
646
+ final int yIn = j * width + i;
647
+ final int uIn = frameSize + (j >> 1) * width + (i & ~1);
648
+ final int vIn = uIn + 1;
649
+
650
+ final int wOut = swap ? height : width;
651
+ final int hOut = swap ? width : height;
652
+ final int iSwapped = swap ? j : i;
653
+ final int jSwapped = swap ? i : j;
654
+ final int iOut = xflip ? wOut - iSwapped - 1 : iSwapped;
655
+ final int jOut = yflip ? hOut - jSwapped - 1 : jSwapped;
656
+
657
+ final int yOut = jOut * wOut + iOut;
658
+ final int uOut = frameSize + (jOut >> 1) * wOut + (iOut & ~1);
659
+ final int vOut = uOut + 1;
660
+
661
+ output[yOut] = (byte) (0xff & yuv[yIn]);
662
+ output[uOut] = (byte) (0xff & yuv[uIn]);
663
+ output[vOut] = (byte) (0xff & yuv[vIn]);
664
+ }
594
665
  }
595
- }
666
+ return output;
596
667
  }
597
- Log.d(TAG, "CameraPreview optimalPictureSize " + size.width + 'x' + size.height);
598
- return size;
599
- }
600
- static byte[] rotateNV21(final byte[] yuv,
601
- final int width,
602
- final int height,
603
- final int rotation)
604
- {
605
- if (rotation == 0) return yuv;
606
- if (rotation % 90 != 0 || rotation < 0 || rotation > 270) {
607
- throw new IllegalArgumentException("0 <= rotation < 360, rotation % 90 == 0");
668
+
669
+ public void setOpacity(final float opacity) {
670
+ Log.d(TAG, "set opacity:" + opacity);
671
+ this.opacity = opacity;
672
+ mPreview.setOpacity(opacity);
608
673
  }
609
674
 
610
- final byte[] output = new byte[yuv.length];
611
- final int frameSize = width * height;
612
- final boolean swap = rotation % 180 != 0;
613
- final boolean xflip = rotation % 270 != 0;
614
- final boolean yflip = rotation >= 180;
615
-
616
- for (int j = 0; j < height; j++) {
617
- for (int i = 0; i < width; i++) {
618
- final int yIn = j * width + i;
619
- final int uIn = frameSize + (j >> 1) * width + (i & ~1);
620
- final int vIn = uIn + 1;
621
-
622
- final int wOut = swap ? height : width;
623
- final int hOut = swap ? width : height;
624
- final int iSwapped = swap ? j : i;
625
- final int jSwapped = swap ? i : j;
626
- final int iOut = xflip ? wOut - iSwapped - 1 : iSwapped;
627
- final int jOut = yflip ? hOut - jSwapped - 1 : jSwapped;
628
-
629
- final int yOut = jOut * wOut + iOut;
630
- final int uOut = frameSize + (jOut >> 1) * wOut + (iOut & ~1);
631
- final int vOut = uOut + 1;
632
-
633
- output[yOut] = (byte)(0xff & yuv[yIn]);
634
- output[uOut] = (byte)(0xff & yuv[uIn]);
635
- output[vOut] = (byte)(0xff & yuv[vIn]);
636
- }
675
+ public void takeSnapshot(final int quality) {
676
+ mCamera.setPreviewCallback(
677
+ new Camera.PreviewCallback() {
678
+ @Override
679
+ public void onPreviewFrame(byte[] bytes, Camera camera) {
680
+ try {
681
+ Camera.Parameters parameters = camera.getParameters();
682
+ Camera.Size size = parameters.getPreviewSize();
683
+ int orientation = mPreview.getDisplayOrientation();
684
+ if (mPreview.getCameraFacing() == Camera.CameraInfo.CAMERA_FACING_FRONT) {
685
+ bytes = rotateNV21(bytes, size.width, size.height, (360 - orientation) % 360);
686
+ } else {
687
+ bytes = rotateNV21(bytes, size.width, size.height, orientation);
688
+ }
689
+ // switch width/height when rotating 90/270 deg
690
+ Rect rect = orientation == 90 || orientation == 270
691
+ ? new Rect(0, 0, size.height, size.width)
692
+ : new Rect(0, 0, size.width, size.height);
693
+ YuvImage yuvImage = new YuvImage(bytes, parameters.getPreviewFormat(), rect.width(), rect.height(), null);
694
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
695
+ yuvImage.compressToJpeg(rect, quality, byteArrayOutputStream);
696
+ byte[] data = byteArrayOutputStream.toByteArray();
697
+ byteArrayOutputStream.close();
698
+ eventListener.onSnapshotTaken(Base64.encodeToString(data, Base64.NO_WRAP));
699
+ } catch (IOException e) {
700
+ Log.d(TAG, "CameraPreview IOException");
701
+ eventListener.onSnapshotTakenError("IO Error");
702
+ } finally {
703
+ mCamera.setPreviewCallback(null);
704
+ }
705
+ }
706
+ }
707
+ );
708
+ }
709
+
710
+ public void takePicture(final int width, final int height, final int quality) {
711
+ Log.d(TAG, "CameraPreview takePicture width: " + width + ", height: " + height + ", quality: " + quality);
712
+
713
+ if (mPreview != null) {
714
+ if (!canTakePicture) {
715
+ return;
716
+ }
717
+
718
+ canTakePicture = false;
719
+
720
+ new Thread() {
721
+ public void run() {
722
+ Camera.Parameters params = mCamera.getParameters();
723
+
724
+ Camera.Size size = getOptimalPictureSize(width, height, params.getPreviewSize(), params.getSupportedPictureSizes());
725
+ params.setPictureSize(size.width, size.height);
726
+ currentQuality = quality;
727
+
728
+ if (cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT && !storeToFile) {
729
+ // The image will be recompressed in the callback
730
+ params.setJpegQuality(99);
731
+ } else {
732
+ params.setJpegQuality(quality);
733
+ }
734
+
735
+ if (cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT && disableExifHeaderStripping) {
736
+ Activity activity = getActivity();
737
+ int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
738
+ int degrees = 0;
739
+ switch (rotation) {
740
+ case Surface.ROTATION_0:
741
+ degrees = 0;
742
+ break;
743
+ case Surface.ROTATION_90:
744
+ degrees = 180;
745
+ break;
746
+ case Surface.ROTATION_180:
747
+ degrees = 270;
748
+ break;
749
+ case Surface.ROTATION_270:
750
+ degrees = 0;
751
+ break;
752
+ }
753
+ int orientation;
754
+ Camera.CameraInfo info = new Camera.CameraInfo();
755
+ if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
756
+ orientation = (info.orientation + degrees) % 360;
757
+ if (degrees != 0) {
758
+ orientation = (360 - orientation) % 360;
759
+ }
760
+ } else {
761
+ orientation = (info.orientation - degrees + 360) % 360;
762
+ }
763
+ params.setRotation(orientation);
764
+ } else {
765
+ params.setRotation(mPreview.getDisplayOrientation());
766
+ }
767
+
768
+ mCamera.setParameters(params);
769
+ mCamera.takePicture(shutterCallback, null, jpegPictureCallback);
770
+ }
771
+ }
772
+ .start();
773
+ } else {
774
+ canTakePicture = true;
775
+ }
637
776
  }
638
- return output;
639
- }
640
-
641
- public void setOpacity(final float opacity) {
642
- Log.d(TAG, "set opacity:" + opacity);
643
- this.opacity = opacity;
644
- mPreview.setOpacity(opacity);
645
- }
646
- public void takeSnapshot(final int quality) {
647
- mCamera.setPreviewCallback(new Camera.PreviewCallback() {
648
- @Override
649
- public void onPreviewFrame(byte[] bytes, Camera camera) {
777
+
778
+ public void startRecord(
779
+ final String filePath,
780
+ final String camera,
781
+ final int width,
782
+ final int height,
783
+ final int quality,
784
+ final boolean withFlash,
785
+ final int maxDuration
786
+ ) {
787
+ Log.d(TAG, "CameraPreview startRecord camera: " + camera + " width: " + width + ", height: " + height + ", quality: " + quality);
788
+ Activity activity = getActivity();
789
+ muteStream(true, activity);
790
+ if (this.mRecordingState == RecordingState.STARTED) {
791
+ Log.d(TAG, "Already Recording");
792
+ return;
793
+ }
794
+
795
+ this.recordFilePath = filePath;
796
+ int mOrientationHint = calculateOrientationHint();
797
+ int videoWidth = 0; //set whatever
798
+ int videoHeight = 0; //set whatever
799
+
800
+ Camera.Parameters cameraParams = mCamera.getParameters();
801
+ if (withFlash) {
802
+ cameraParams.setFlashMode(withFlash ? Camera.Parameters.FLASH_MODE_TORCH : Camera.Parameters.FLASH_MODE_OFF);
803
+ mCamera.setParameters(cameraParams);
804
+ mCamera.startPreview();
805
+ }
806
+
807
+ mCamera.unlock();
808
+ mRecorder = new MediaRecorder();
809
+
650
810
  try {
651
- Camera.Parameters parameters = camera.getParameters();
652
- Camera.Size size = parameters.getPreviewSize();
653
- int orientation = mPreview.getDisplayOrientation();
654
- if (mPreview.getCameraFacing() == Camera.CameraInfo.CAMERA_FACING_FRONT) {
655
- bytes = rotateNV21(bytes, size.width, size.height, (360 - orientation) % 360);
656
- } else {
657
- bytes = rotateNV21(bytes, size.width, size.height, orientation);
658
- }
659
- // switch width/height when rotating 90/270 deg
660
- Rect rect = orientation == 90 || orientation == 270 ?
661
- new Rect(0, 0, size.height, size.width) :
662
- new Rect(0, 0, size.width, size.height);
663
- YuvImage yuvImage = new YuvImage(bytes, parameters.getPreviewFormat(), rect.width(), rect.height(), null);
664
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
665
- yuvImage.compressToJpeg(rect, quality, byteArrayOutputStream);
666
- byte[] data = byteArrayOutputStream.toByteArray();
667
- byteArrayOutputStream.close();
668
- eventListener.onSnapshotTaken(Base64.encodeToString(data, Base64.NO_WRAP));
669
- } catch (IOException e) {
670
- Log.d(TAG, "CameraPreview IOException");
671
- eventListener.onSnapshotTakenError("IO Error");
672
- } finally {
811
+ mRecorder.setCamera(mCamera);
673
812
 
674
- mCamera.setPreviewCallback(null);
813
+ CamcorderProfile profile;
814
+ if (CamcorderProfile.hasProfile(defaultCameraId, CamcorderProfile.QUALITY_HIGH)) {
815
+ profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_HIGH);
816
+ } else {
817
+ if (CamcorderProfile.hasProfile(defaultCameraId, CamcorderProfile.QUALITY_480P)) {
818
+ profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_480P);
819
+ } else {
820
+ if (CamcorderProfile.hasProfile(defaultCameraId, CamcorderProfile.QUALITY_720P)) {
821
+ profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_720P);
822
+ } else {
823
+ if (CamcorderProfile.hasProfile(defaultCameraId, CamcorderProfile.QUALITY_1080P)) {
824
+ profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_1080P);
825
+ } else {
826
+ profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_LOW);
827
+ }
828
+ }
829
+ }
830
+ }
831
+
832
+ mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION);
833
+ mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
834
+ mRecorder.setProfile(profile);
835
+ mRecorder.setOutputFile(filePath);
836
+ mRecorder.setOrientationHint(mOrientationHint);
837
+ mRecorder.setMaxDuration(maxDuration);
838
+
839
+ mRecorder.prepare();
840
+ Log.d(TAG, "Starting recording");
841
+ mRecorder.start();
842
+ eventListener.onStartRecordVideo();
843
+ } catch (IOException e) {
844
+ eventListener.onStartRecordVideoError(e.getMessage());
675
845
  }
676
- }
677
- });
678
- }
679
-
680
- public void takePicture(final int width, final int height, final int quality){
681
- Log.d(TAG, "CameraPreview takePicture width: " + width + ", height: " + height + ", quality: " + quality);
682
-
683
- if(mPreview != null) {
684
- if(!canTakePicture){
685
- return;
686
- }
687
-
688
- canTakePicture = false;
689
-
690
- new Thread() {
691
- public void run() {
692
- Camera.Parameters params = mCamera.getParameters();
693
-
694
- Camera.Size size = getOptimalPictureSize(width, height, params.getPreviewSize(), params.getSupportedPictureSizes());
695
- params.setPictureSize(size.width, size.height);
696
- currentQuality = quality;
697
-
698
- if(cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT && !storeToFile) {
699
- // The image will be recompressed in the callback
700
- params.setJpegQuality(99);
701
- } else {
702
- params.setJpegQuality(quality);
703
- }
704
-
705
- if(cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT && disableExifHeaderStripping) {
706
- Activity activity = getActivity();
707
- int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
708
- int degrees = 0;
709
- switch (rotation) {
710
- case Surface.ROTATION_0:
846
+ }
847
+
848
+ public int calculateOrientationHint() {
849
+ DisplayMetrics dm = new DisplayMetrics();
850
+ Camera.CameraInfo info = new Camera.CameraInfo();
851
+ Camera.getCameraInfo(defaultCameraId, info);
852
+ int cameraRotationOffset = info.orientation;
853
+ Activity activity = getActivity();
854
+
855
+ activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
856
+ int currentScreenRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
857
+
858
+ int degrees = 0;
859
+ switch (currentScreenRotation) {
860
+ case Surface.ROTATION_0:
711
861
  degrees = 0;
712
862
  break;
713
- case Surface.ROTATION_90:
863
+ case Surface.ROTATION_90:
864
+ degrees = 90;
865
+ break;
866
+ case Surface.ROTATION_180:
714
867
  degrees = 180;
715
868
  break;
716
- case Surface.ROTATION_180:
869
+ case Surface.ROTATION_270:
717
870
  degrees = 270;
718
871
  break;
719
- case Surface.ROTATION_270:
720
- degrees = 0;
721
- break;
722
- }
723
- int orientation;
724
- Camera.CameraInfo info = new Camera.CameraInfo();
725
- if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
726
- orientation = (info.orientation + degrees) % 360;
727
- if (degrees != 0) {
872
+ }
873
+
874
+ int orientation;
875
+ if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
876
+ orientation = (cameraRotationOffset + degrees) % 360;
877
+ if (degrees != 0) {
728
878
  orientation = (360 - orientation) % 360;
729
- }
730
- } else {
731
- orientation = (info.orientation - degrees + 360) % 360;
732
879
  }
733
- params.setRotation(orientation);
734
- } else {
735
- params.setRotation(mPreview.getDisplayOrientation());
736
- }
737
-
738
- mCamera.setParameters(params);
739
- mCamera.takePicture(shutterCallback, null, jpegPictureCallback);
880
+ } else {
881
+ orientation = (cameraRotationOffset - degrees + 360) % 360;
740
882
  }
741
- }.start();
742
- } else {
743
- canTakePicture = true;
744
- }
745
- }
746
-
747
- public void startRecord(final String filePath, final String camera, final int width, final int height, final int quality, final boolean withFlash, final int maxDuration){
748
- Log.d(TAG, "CameraPreview startRecord camera: " + camera + " width: " + width + ", height: " + height + ", quality: " + quality);
749
- Activity activity = getActivity();
750
- muteStream(true, activity);
751
- if (this.mRecordingState == RecordingState.STARTED) {
752
- Log.d(TAG, "Already Recording");
753
- return;
754
- }
883
+ Log.w(TAG, "************orientationHint ***********= " + orientation);
755
884
 
756
- this.recordFilePath = filePath;
757
- int mOrientationHint = calculateOrientationHint();
758
- int videoWidth = 0;//set whatever
759
- int videoHeight = 0;//set whatever
760
-
761
- Camera.Parameters cameraParams = mCamera.getParameters();
762
- if (withFlash) {
763
- cameraParams.setFlashMode(withFlash ? Camera.Parameters.FLASH_MODE_TORCH : Camera.Parameters.FLASH_MODE_OFF);
764
- mCamera.setParameters(cameraParams);
765
- mCamera.startPreview();
885
+ return orientation;
766
886
  }
767
887
 
768
- mCamera.unlock();
769
- mRecorder = new MediaRecorder();
770
-
771
- try {
772
- mRecorder.setCamera(mCamera);
888
+ public void stopRecord() {
889
+ Log.d(TAG, "stopRecord");
773
890
 
774
- CamcorderProfile profile;
775
- if (CamcorderProfile.hasProfile(defaultCameraId, CamcorderProfile.QUALITY_HIGH)) {
776
- profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_HIGH);
777
- } else {
778
- if (CamcorderProfile.hasProfile(defaultCameraId, CamcorderProfile.QUALITY_480P)) {
779
- profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_480P);
780
- } else {
781
- if (CamcorderProfile.hasProfile(defaultCameraId, CamcorderProfile.QUALITY_720P)) {
782
- profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_720P);
783
- } else {
784
- if (CamcorderProfile.hasProfile(defaultCameraId, CamcorderProfile.QUALITY_1080P)) {
785
- profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_1080P);
786
- } else {
787
- profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_LOW);
788
- }
789
- }
891
+ try {
892
+ mRecorder.stop();
893
+ mRecorder.reset(); // clear recorder configuration
894
+ mRecorder.release(); // release the recorder object
895
+ mRecorder = null;
896
+ mCamera.lock();
897
+ Camera.Parameters cameraParams = mCamera.getParameters();
898
+ cameraParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
899
+ mCamera.setParameters(cameraParams);
900
+ mCamera.startPreview();
901
+ eventListener.onStopRecordVideo(this.recordFilePath);
902
+ } catch (Exception e) {
903
+ eventListener.onStopRecordVideoError(e.getMessage());
790
904
  }
791
- }
792
-
793
-
794
- mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION);
795
- mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
796
- mRecorder.setProfile(profile);
797
- mRecorder.setOutputFile(filePath);
798
- mRecorder.setOrientationHint(mOrientationHint);
799
- mRecorder.setMaxDuration(maxDuration);
800
-
801
- mRecorder.prepare();
802
- Log.d(TAG, "Starting recording");
803
- mRecorder.start();
804
- eventListener.onStartRecordVideo();
805
- } catch (IOException e) {
806
- eventListener.onStartRecordVideoError(e.getMessage());
807
- }
808
- }
809
-
810
- public int calculateOrientationHint() {
811
- DisplayMetrics dm = new DisplayMetrics();
812
- Camera.CameraInfo info = new Camera.CameraInfo();
813
- Camera.getCameraInfo(defaultCameraId, info);
814
- int cameraRotationOffset = info.orientation;
815
- Activity activity = getActivity();
816
-
817
- activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
818
- int currentScreenRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
819
-
820
- int degrees = 0;
821
- switch (currentScreenRotation) {
822
- case Surface.ROTATION_0:
823
- degrees = 0;
824
- break;
825
- case Surface.ROTATION_90:
826
- degrees = 90;
827
- break;
828
- case Surface.ROTATION_180:
829
- degrees = 180;
830
- break;
831
- case Surface.ROTATION_270:
832
- degrees = 270;
833
- break;
834
905
  }
835
906
 
836
- int orientation;
837
- if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
838
- orientation = (cameraRotationOffset + degrees) % 360;
839
- if (degrees != 0) {
840
- orientation = (360 - orientation) % 360;
841
- }
842
- } else {
843
- orientation = (cameraRotationOffset - degrees + 360) % 360;
907
+ public void muteStream(boolean mute, Activity activity) {
908
+ AudioManager audioManager = ((AudioManager) activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE));
909
+ int direction = mute ? audioManager.ADJUST_MUTE : audioManager.ADJUST_UNMUTE;
844
910
  }
845
- Log.w(TAG, "************orientationHint ***********= " + orientation);
846
-
847
- return orientation;
848
- }
849
-
850
- public void stopRecord() {
851
- Log.d(TAG, "stopRecord");
852
-
853
- try {
854
- mRecorder.stop();
855
- mRecorder.reset(); // clear recorder configuration
856
- mRecorder.release(); // release the recorder object
857
- mRecorder = null;
858
- mCamera.lock();
859
- Camera.Parameters cameraParams = mCamera.getParameters();
860
- cameraParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
861
- mCamera.setParameters(cameraParams);
862
- mCamera.startPreview();
863
- eventListener.onStopRecordVideo(this.recordFilePath);
864
- } catch (Exception e) {
865
- eventListener.onStopRecordVideoError(e.getMessage());
866
- }
867
- }
868
-
869
- public void muteStream(boolean mute, Activity activity) {
870
- AudioManager audioManager = ((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE));
871
- int direction = mute ? audioManager.ADJUST_MUTE : audioManager.ADJUST_UNMUTE;
872
- }
873
911
 
874
- public void setFocusArea(final int pointX, final int pointY, final Camera.AutoFocusCallback callback) {
875
- if (mCamera != null) {
912
+ public void setFocusArea(final int pointX, final int pointY, final Camera.AutoFocusCallback callback) {
913
+ if (mCamera != null) {
914
+ mCamera.cancelAutoFocus();
876
915
 
877
- mCamera.cancelAutoFocus();
916
+ Camera.Parameters parameters = mCamera.getParameters();
878
917
 
879
- Camera.Parameters parameters = mCamera.getParameters();
918
+ Rect focusRect = calculateTapArea(pointX, pointY, 1f);
919
+ parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
920
+ parameters.setFocusAreas(Arrays.asList(new Camera.Area(focusRect, 1000)));
880
921
 
881
- Rect focusRect = calculateTapArea(pointX, pointY, 1f);
882
- parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
883
- parameters.setFocusAreas(Arrays.asList(new Camera.Area(focusRect, 1000)));
884
-
885
- if (parameters.getMaxNumMeteringAreas() > 0) {
886
- Rect meteringRect = calculateTapArea(pointX, pointY, 1.5f);
887
- parameters.setMeteringAreas(Arrays.asList(new Camera.Area(meteringRect, 1000)));
888
- }
922
+ if (parameters.getMaxNumMeteringAreas() > 0) {
923
+ Rect meteringRect = calculateTapArea(pointX, pointY, 1.5f);
924
+ parameters.setMeteringAreas(Arrays.asList(new Camera.Area(meteringRect, 1000)));
925
+ }
889
926
 
890
- try {
891
- setCameraParameters(parameters);
892
- mCamera.autoFocus(callback);
893
- } catch (Exception e) {
894
- Log.d(TAG, e.getMessage());
895
- callback.onAutoFocus(false, this.mCamera);
896
- }
927
+ try {
928
+ setCameraParameters(parameters);
929
+ mCamera.autoFocus(callback);
930
+ } catch (Exception e) {
931
+ Log.d(TAG, e.getMessage());
932
+ callback.onAutoFocus(false, this.mCamera);
933
+ }
934
+ }
897
935
  }
898
- }
899
936
 
900
- private Rect calculateTapArea(float x, float y, float coefficient) {
901
- if (x < 100) {
902
- x = 100;
903
- }
904
- if (x > width - 100) {
905
- x = width - 100;
906
- }
907
- if (y < 100) {
908
- y = 100;
909
- }
910
- if (y > height - 100) {
911
- y = height - 100;
937
+ private Rect calculateTapArea(float x, float y, float coefficient) {
938
+ if (x < 100) {
939
+ x = 100;
940
+ }
941
+ if (x > width - 100) {
942
+ x = width - 100;
943
+ }
944
+ if (y < 100) {
945
+ y = 100;
946
+ }
947
+ if (y > height - 100) {
948
+ y = height - 100;
949
+ }
950
+ return new Rect(
951
+ Math.round((x - 100) * 2000 / width - 1000),
952
+ Math.round((y - 100) * 2000 / height - 1000),
953
+ Math.round((x + 100) * 2000 / width - 1000),
954
+ Math.round((y + 100) * 2000 / height - 1000)
955
+ );
912
956
  }
913
- return new Rect(
914
- Math.round((x - 100) * 2000 / width - 1000),
915
- Math.round((y - 100) * 2000 / height - 1000),
916
- Math.round((x + 100) * 2000 / width - 1000),
917
- Math.round((y + 100) * 2000 / height - 1000)
918
- );
919
- }
920
-
921
- /**
922
- * Determine the space between the first two fingers
923
- */
924
- private static float getFingerSpacing(MotionEvent event) {
925
- // ...
926
- float x = event.getX(0) - event.getX(1);
927
- float y = event.getY(0) - event.getY(1);
928
- return (float) Math.sqrt(x * x + y * y);
929
- }
930
957
 
958
+ /**
959
+ * Determine the space between the first two fingers
960
+ */
961
+ private static float getFingerSpacing(MotionEvent event) {
962
+ // ...
963
+ float x = event.getX(0) - event.getX(1);
964
+ float y = event.getY(0) - event.getY(1);
965
+ return (float) Math.sqrt(x * x + y * y);
966
+ }
931
967
  }