@capgo/camera-preview 3.6.23 → 4.0.0

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.
Files changed (42) hide show
  1. package/README.md +67 -405
  2. package/android/build.gradle +8 -7
  3. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  4. package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  5. package/android/gradle.properties +1 -1
  6. package/android/gradlew +2 -2
  7. package/android/src/androidTest/java/com/getcapacitor/android/ExampleInstrumentedTest.java +6 -6
  8. package/android/src/main/AndroidManifest.xml +1 -1
  9. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraActivity.java +1105 -854
  10. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java +543 -428
  11. package/android/src/main/java/com/ahm/capacitor/camera/preview/CustomSurfaceView.java +15 -10
  12. package/android/src/main/java/com/ahm/capacitor/camera/preview/CustomTextureView.java +31 -21
  13. package/android/src/main/java/com/ahm/capacitor/camera/preview/Preview.java +386 -332
  14. package/android/src/main/java/com/ahm/capacitor/camera/preview/TapGestureDetector.java +13 -13
  15. package/android/src/test/java/com/getcapacitor/ExampleUnitTest.java +4 -4
  16. package/dist/docs.json +208 -37
  17. package/dist/esm/definitions.d.ts +76 -3
  18. package/dist/esm/index.d.ts +2 -2
  19. package/dist/esm/index.js +4 -4
  20. package/dist/esm/web.d.ts +2 -2
  21. package/dist/esm/web.js +39 -36
  22. package/dist/esm/web.js.map +1 -1
  23. package/dist/plugin.cjs.js +39 -36
  24. package/dist/plugin.cjs.js.map +1 -1
  25. package/dist/plugin.js +39 -36
  26. package/dist/plugin.js.map +1 -1
  27. package/ios/Plugin/CameraController.swift +1 -1
  28. package/ios/Plugin/Plugin.swift +1 -1
  29. package/ios/Podfile.lock +3 -3
  30. package/package.json +22 -22
  31. package/android/.gradle/7.6/checksums/checksums.lock +0 -0
  32. package/android/.gradle/7.6/checksums/md5-checksums.bin +0 -0
  33. package/android/.gradle/7.6/checksums/sha1-checksums.bin +0 -0
  34. package/android/.gradle/7.6/dependencies-accessors/dependencies-accessors.lock +0 -0
  35. package/android/.gradle/7.6/dependencies-accessors/gc.properties +0 -0
  36. package/android/.gradle/7.6/executionHistory/executionHistory.lock +0 -0
  37. package/android/.gradle/7.6/fileChanges/last-build.bin +0 -0
  38. package/android/.gradle/7.6/fileHashes/fileHashes.lock +0 -0
  39. package/android/.gradle/7.6/gc.properties +0 -0
  40. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  41. package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
  42. package/android/.gradle/vcs-1/gc.properties +0 -0
@@ -48,953 +48,1204 @@ import java.util.UUID;
48
48
 
49
49
  public class CameraActivity extends Fragment {
50
50
 
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
-
81
- private enum RecordingState {
82
- INITIALIZING,
83
- STARTED,
84
- STOPPED
85
- }
86
-
87
- private RecordingState mRecordingState = RecordingState.INITIALIZING;
88
- private MediaRecorder mRecorder = null;
89
- private String recordFilePath;
90
- private float opacity;
91
-
92
- // The first rear facing camera
93
- private int defaultCameraId;
94
- public String defaultCamera;
95
- public boolean tapToTakePicture;
96
- public boolean dragEnabled;
97
- public boolean tapToFocus;
98
- public boolean disableExifHeaderStripping;
99
- public boolean storeToFile;
100
- public boolean toBack;
101
- public boolean enableOpacity = false;
102
- public boolean enableZoom = false;
103
-
104
- public int width;
105
- public int height;
106
- public int x;
107
- public int y;
108
-
109
- public void setEventListener(CameraPreviewListener listener) {
110
- eventListener = listener;
111
- }
112
-
113
- private String appResourcesPackage;
114
-
115
- @Override
116
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
117
- appResourcesPackage = getActivity().getPackageName();
118
-
119
- // Inflate the layout for this fragment
120
- view = inflater.inflate(getResources().getIdentifier("camera_activity", "layout", appResourcesPackage), container, false);
121
- createCameraPreview();
122
- return view;
123
- }
124
-
125
- public void setRect(int x, int y, int width, int height) {
126
- this.x = x;
127
- this.y = y;
128
- this.width = width;
129
- this.height = height;
130
- }
131
-
132
- private void createCameraPreview() {
133
- if (mPreview == null) {
134
- setDefaultCameraId();
135
-
136
- //set box position and size
137
- FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(width, height);
138
- layoutParams.setMargins(x, y, 0, 0);
139
- frameContainerLayout =
140
- (FrameLayout) view.findViewById(getResources().getIdentifier("frame_container", "id", appResourcesPackage));
141
- frameContainerLayout.setLayoutParams(layoutParams);
142
-
143
- //video view
144
- mPreview = new Preview(getActivity(), enableOpacity);
145
- mainLayout = (FrameLayout) view.findViewById(getResources().getIdentifier("video_view", "id", appResourcesPackage));
146
- mainLayout.setLayoutParams(
147
- new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)
148
- );
149
- mainLayout.addView(mPreview);
150
- mainLayout.setEnabled(false);
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
+
81
+ private enum RecordingState {
82
+ INITIALIZING,
83
+ STARTED,
84
+ STOPPED,
85
+ }
86
+
87
+ private RecordingState mRecordingState = RecordingState.INITIALIZING;
88
+ private MediaRecorder mRecorder = null;
89
+ private String recordFilePath;
90
+ private float opacity;
91
+
92
+ // The first rear facing camera
93
+ private int defaultCameraId;
94
+ public String defaultCamera;
95
+ public boolean tapToTakePicture;
96
+ public boolean dragEnabled;
97
+ public boolean tapToFocus;
98
+ public boolean disableExifHeaderStripping;
99
+ public boolean storeToFile;
100
+ public boolean toBack;
101
+ public boolean enableOpacity = false;
102
+ public boolean enableZoom = false;
103
+
104
+ public int width;
105
+ public int height;
106
+ public int x;
107
+ public int y;
108
+
109
+ public void setEventListener(CameraPreviewListener listener) {
110
+ eventListener = listener;
111
+ }
112
+
113
+ private String appResourcesPackage;
114
+
115
+ @Override
116
+ public View onCreateView(
117
+ LayoutInflater inflater,
118
+ ViewGroup container,
119
+ Bundle savedInstanceState
120
+ ) {
121
+ appResourcesPackage = getActivity().getPackageName();
122
+
123
+ // Inflate the layout for this fragment
124
+ view =
125
+ inflater.inflate(
126
+ getResources()
127
+ .getIdentifier("camera_activity", "layout", appResourcesPackage),
128
+ container,
129
+ false
130
+ );
131
+ createCameraPreview();
132
+ return view;
133
+ }
134
+
135
+ public void setRect(int x, int y, int width, int height) {
136
+ this.x = x;
137
+ this.y = y;
138
+ this.width = width;
139
+ this.height = height;
140
+ }
141
+
142
+ private void createCameraPreview() {
143
+ if (mPreview == null) {
144
+ setDefaultCameraId();
145
+
146
+ //set box position and size
147
+ FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
148
+ width,
149
+ height
150
+ );
151
+ layoutParams.setMargins(x, y, 0, 0);
152
+ frameContainerLayout =
153
+ (FrameLayout) view.findViewById(
154
+ getResources()
155
+ .getIdentifier("frame_container", "id", appResourcesPackage)
156
+ );
157
+ frameContainerLayout.setLayoutParams(layoutParams);
151
158
 
152
- if (enableZoom) {
153
- this.setupTouchAndBackButton();
154
- }
155
- }
159
+ //video view
160
+ mPreview = new Preview(getActivity(), enableOpacity);
161
+ mainLayout =
162
+ (FrameLayout) view.findViewById(
163
+ getResources().getIdentifier("video_view", "id", appResourcesPackage)
164
+ );
165
+ mainLayout.setLayoutParams(
166
+ new RelativeLayout.LayoutParams(
167
+ RelativeLayout.LayoutParams.MATCH_PARENT,
168
+ RelativeLayout.LayoutParams.MATCH_PARENT
169
+ )
170
+ );
171
+ mainLayout.addView(mPreview);
172
+ mainLayout.setEnabled(false);
173
+
174
+ if (enableZoom) {
175
+ this.setupTouchAndBackButton();
176
+ }
156
177
  }
178
+ }
179
+
180
+ private void setupTouchAndBackButton() {
181
+ final GestureDetector gestureDetector = new GestureDetector(
182
+ getActivity().getApplicationContext(),
183
+ new TapGestureDetector()
184
+ );
185
+
186
+ getActivity()
187
+ .runOnUiThread(
188
+ new Runnable() {
189
+ @Override
190
+ public void run() {
191
+ frameContainerLayout.setClickable(true);
192
+ frameContainerLayout.setOnTouchListener(
193
+ new View.OnTouchListener() {
194
+ private int mLastTouchX;
195
+ private int mLastTouchY;
196
+ private int mPosX = 0;
197
+ private int mPosY = 0;
157
198
 
158
- private void setupTouchAndBackButton() {
159
- final GestureDetector gestureDetector = new GestureDetector(getActivity().getApplicationContext(), new TapGestureDetector());
160
-
161
- getActivity()
162
- .runOnUiThread(
163
- new Runnable() {
164
- @Override
165
- public void run() {
166
- frameContainerLayout.setClickable(true);
167
- frameContainerLayout.setOnTouchListener(
168
- new View.OnTouchListener() {
169
- private int mLastTouchX;
170
- private int mLastTouchY;
171
- private int mPosX = 0;
172
- private int mPosY = 0;
173
-
174
- @Override
175
- public boolean onTouch(View v, MotionEvent event) {
176
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) frameContainerLayout.getLayoutParams();
177
-
178
- boolean isSingleTapTouch = gestureDetector.onTouchEvent(event);
179
- int action = event.getAction();
180
- int eventCount = event.getPointerCount();
181
- Log.d(TAG, "onTouch event, action, count: " + event + ", " + action + ", " + eventCount);
182
- if (eventCount > 1) {
183
- // handle multi-touch events
184
- Camera.Parameters params = mCamera.getParameters();
185
- if (action == MotionEvent.ACTION_POINTER_DOWN) {
186
- mDist = getFingerSpacing(event);
187
- } else if (action == MotionEvent.ACTION_MOVE && params.isZoomSupported()) {
188
- handleZoom(event, params);
189
- }
190
- } else {
191
- if (action != MotionEvent.ACTION_MOVE && isSingleTapTouch) {
192
- if (tapToTakePicture && tapToFocus) {
193
- setFocusArea(
194
- (int) event.getX(0),
195
- (int) event.getY(0),
196
- new Camera.AutoFocusCallback() {
197
- public void onAutoFocus(boolean success, Camera camera) {
198
- if (success) {
199
- takePicture(0, 0, 85);
200
- } else {
201
- Log.d(TAG, "onTouch:" + " setFocusArea() did not suceed");
202
- }
203
- }
204
- }
205
- );
206
- } else if (tapToTakePicture) {
207
- takePicture(0, 0, 85);
208
- } else if (tapToFocus) {
209
- setFocusArea(
210
- (int) event.getX(0),
211
- (int) event.getY(0),
212
- new Camera.AutoFocusCallback() {
213
- public void onAutoFocus(boolean success, Camera camera) {
214
- if (success) {
215
- // A callback to JS might make sense here.
216
- } else {
217
- Log.d(TAG, "onTouch:" + " setFocusArea() did not suceed");
218
- }
219
- }
220
- }
221
- );
222
- }
223
- return true;
224
- } else {
225
- if (dragEnabled) {
226
- int x;
227
- int y;
228
-
229
- switch (event.getAction()) {
230
- case MotionEvent.ACTION_DOWN:
231
- if (mLastTouchX == 0 || mLastTouchY == 0) {
232
- mLastTouchX = (int) event.getRawX() - layoutParams.leftMargin;
233
- mLastTouchY = (int) event.getRawY() - layoutParams.topMargin;
234
- } else {
235
- mLastTouchX = (int) event.getRawX();
236
- mLastTouchY = (int) event.getRawY();
237
- }
238
- break;
239
- case MotionEvent.ACTION_MOVE:
240
- x = (int) event.getRawX();
241
- y = (int) event.getRawY();
242
-
243
- final float dx = x - mLastTouchX;
244
- final float dy = y - mLastTouchY;
245
-
246
- mPosX += dx;
247
- mPosY += dy;
248
-
249
- layoutParams.leftMargin = mPosX;
250
- layoutParams.topMargin = mPosY;
251
-
252
- frameContainerLayout.setLayoutParams(layoutParams);
253
-
254
- // Remember this touch position for the next move event
255
- mLastTouchX = x;
256
- mLastTouchY = y;
257
-
258
- break;
259
- default:
260
- break;
261
- }
262
- }
263
- }
264
- }
265
- return true;
266
- }
199
+ @Override
200
+ public boolean onTouch(View v, MotionEvent event) {
201
+ FrameLayout.LayoutParams layoutParams =
202
+ (FrameLayout.LayoutParams) frameContainerLayout.getLayoutParams();
203
+
204
+ boolean isSingleTapTouch = gestureDetector.onTouchEvent(
205
+ event
206
+ );
207
+ int action = event.getAction();
208
+ int eventCount = event.getPointerCount();
209
+ Log.d(
210
+ TAG,
211
+ "onTouch event, action, count: " +
212
+ event +
213
+ ", " +
214
+ action +
215
+ ", " +
216
+ eventCount
217
+ );
218
+ if (eventCount > 1) {
219
+ // handle multi-touch events
220
+ Camera.Parameters params = mCamera.getParameters();
221
+ if (action == MotionEvent.ACTION_POINTER_DOWN) {
222
+ mDist = getFingerSpacing(event);
223
+ } else if (
224
+ action == MotionEvent.ACTION_MOVE &&
225
+ params.isZoomSupported()
226
+ ) {
227
+ handleZoom(event, params);
228
+ }
229
+ } else {
230
+ if (action != MotionEvent.ACTION_MOVE && isSingleTapTouch) {
231
+ if (tapToTakePicture && tapToFocus) {
232
+ setFocusArea(
233
+ (int) event.getX(0),
234
+ (int) event.getY(0),
235
+ new Camera.AutoFocusCallback() {
236
+ public void onAutoFocus(
237
+ boolean success,
238
+ Camera camera
239
+ ) {
240
+ if (success) {
241
+ takePicture(0, 0, 85);
242
+ } else {
243
+ Log.d(
244
+ TAG,
245
+ "onTouch:" + " setFocusArea() did not suceed"
246
+ );
247
+ }
267
248
  }
249
+ }
268
250
  );
269
- frameContainerLayout.setFocusableInTouchMode(true);
270
- frameContainerLayout.requestFocus();
271
- frameContainerLayout.setOnKeyListener(
272
- new View.OnKeyListener() {
273
- @Override
274
- public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
275
- if (keyCode == android.view.KeyEvent.KEYCODE_BACK) {
276
- eventListener.onBackButton();
277
- return true;
278
- }
279
- return false;
280
- }
251
+ } else if (tapToTakePicture) {
252
+ takePicture(0, 0, 85);
253
+ } else if (tapToFocus) {
254
+ setFocusArea(
255
+ (int) event.getX(0),
256
+ (int) event.getY(0),
257
+ new Camera.AutoFocusCallback() {
258
+ public void onAutoFocus(
259
+ boolean success,
260
+ Camera camera
261
+ ) {
262
+ if (success) {
263
+ // A callback to JS might make sense here.
264
+ } else {
265
+ Log.d(
266
+ TAG,
267
+ "onTouch:" + " setFocusArea() did not suceed"
268
+ );
269
+ }
281
270
  }
271
+ }
282
272
  );
283
- }
284
-
285
- private float mDist = 0F;
286
-
287
- private void handleZoom(MotionEvent event, Camera.Parameters params) {
288
- if (mCamera != null) {
289
- mCamera.cancelAutoFocus();
290
- int maxZoom = params.getMaxZoom();
291
- int zoom = params.getZoom();
292
- float newDist = getFingerSpacing(event);
293
- if (newDist > mDist) {
294
- //zoom in
295
- if (zoom < maxZoom) zoom++;
296
- } else if (newDist < mDist) {
297
- //zoom out
298
- if (zoom > 0) zoom--;
273
+ }
274
+ return true;
275
+ } else {
276
+ if (dragEnabled) {
277
+ int x;
278
+ int y;
279
+
280
+ switch (event.getAction()) {
281
+ case MotionEvent.ACTION_DOWN:
282
+ if (mLastTouchX == 0 || mLastTouchY == 0) {
283
+ mLastTouchX =
284
+ (int) event.getRawX() - layoutParams.leftMargin;
285
+ mLastTouchY =
286
+ (int) event.getRawY() - layoutParams.topMargin;
287
+ } else {
288
+ mLastTouchX = (int) event.getRawX();
289
+ mLastTouchY = (int) event.getRawY();
299
290
  }
300
- mDist = newDist;
301
- params.setZoom(zoom);
302
- mCamera.setParameters(params);
303
- }
304
- }
305
- }
306
- );
307
- }
291
+ break;
292
+ case MotionEvent.ACTION_MOVE:
293
+ x = (int) event.getRawX();
294
+ y = (int) event.getRawY();
308
295
 
309
- private void setDefaultCameraId() {
310
- // Find the total number of cameras available
311
- numberOfCameras = Camera.getNumberOfCameras();
296
+ final float dx = x - mLastTouchX;
297
+ final float dy = y - mLastTouchY;
312
298
 
313
- int facing = "front".equals(defaultCamera) ? Camera.CameraInfo.CAMERA_FACING_FRONT : Camera.CameraInfo.CAMERA_FACING_BACK;
299
+ mPosX += dx;
300
+ mPosY += dy;
314
301
 
315
- // Find the ID of the default camera
316
- Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
317
- for (int i = 0; i < numberOfCameras; i++) {
318
- Camera.getCameraInfo(i, cameraInfo);
319
- if (cameraInfo.facing == facing) {
320
- defaultCameraId = i;
321
- break;
322
- }
323
- }
324
- }
325
-
326
- @Override
327
- public void onResume() {
328
- super.onResume();
329
-
330
- mCamera = Camera.open(defaultCameraId);
302
+ layoutParams.leftMargin = mPosX;
303
+ layoutParams.topMargin = mPosY;
331
304
 
332
- if (cameraParameters != null) {
333
- mCamera.setParameters(cameraParameters);
334
- }
305
+ frameContainerLayout.setLayoutParams(layoutParams);
335
306
 
336
- cameraCurrentlyLocked = defaultCameraId;
307
+ // Remember this touch position for the next move event
308
+ mLastTouchX = x;
309
+ mLastTouchY = y;
337
310
 
338
- if (mPreview.mPreviewSize == null) {
339
- mPreview.setCamera(mCamera, cameraCurrentlyLocked);
340
- eventListener.onCameraStarted();
341
- } else {
342
- mPreview.switchCamera(mCamera, cameraCurrentlyLocked);
343
- mCamera.startPreview();
344
- }
345
-
346
- Log.d(TAG, "cameraCurrentlyLocked:" + cameraCurrentlyLocked);
347
-
348
- final FrameLayout frameContainerLayout = (FrameLayout) view.findViewById(
349
- getResources().getIdentifier("frame_container", "id", appResourcesPackage)
350
- );
351
-
352
- ViewTreeObserver viewTreeObserver = frameContainerLayout.getViewTreeObserver();
353
-
354
- if (viewTreeObserver.isAlive()) {
355
- viewTreeObserver.addOnGlobalLayoutListener(
356
- new ViewTreeObserver.OnGlobalLayoutListener() {
357
- @Override
358
- public void onGlobalLayout() {
359
- frameContainerLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
360
- frameContainerLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
361
- Activity activity = getActivity();
362
- if (isAdded() && activity != null) {
363
- final RelativeLayout frameCamContainerLayout = (RelativeLayout) view.findViewById(
364
- getResources().getIdentifier("frame_camera_cont", "id", appResourcesPackage)
365
- );
366
-
367
- FrameLayout.LayoutParams camViewLayout = new FrameLayout.LayoutParams(
368
- frameContainerLayout.getWidth(),
369
- frameContainerLayout.getHeight()
370
- );
371
- camViewLayout.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
372
- frameCamContainerLayout.setLayoutParams(camViewLayout);
311
+ break;
312
+ default:
313
+ break;
373
314
  }
315
+ }
374
316
  }
317
+ }
318
+ return true;
375
319
  }
320
+ }
376
321
  );
377
- }
378
- }
322
+ frameContainerLayout.setFocusableInTouchMode(true);
323
+ frameContainerLayout.requestFocus();
324
+ frameContainerLayout.setOnKeyListener(
325
+ new View.OnKeyListener() {
326
+ @Override
327
+ public boolean onKey(
328
+ View v,
329
+ int keyCode,
330
+ android.view.KeyEvent event
331
+ ) {
332
+ if (keyCode == android.view.KeyEvent.KEYCODE_BACK) {
333
+ eventListener.onBackButton();
334
+ return true;
335
+ }
336
+ return false;
337
+ }
338
+ }
339
+ );
340
+ }
379
341
 
380
- @Override
381
- public void onPause() {
382
- super.onPause();
342
+ private float mDist = 0F;
383
343
 
384
- // Because the Camera object is a shared resource, it's very important to release it when the activity is paused.
385
- if (mCamera != null) {
386
- setDefaultCameraId();
387
- mPreview.setCamera(null, -1);
388
- mCamera.setPreviewCallback(null);
389
- mCamera.release();
390
- mCamera = null;
344
+ private void handleZoom(MotionEvent event, Camera.Parameters params) {
345
+ if (mCamera != null) {
346
+ mCamera.cancelAutoFocus();
347
+ int maxZoom = params.getMaxZoom();
348
+ int zoom = params.getZoom();
349
+ float newDist = getFingerSpacing(event);
350
+ if (newDist > mDist) {
351
+ //zoom in
352
+ if (zoom < maxZoom) zoom++;
353
+ } else if (newDist < mDist) {
354
+ //zoom out
355
+ if (zoom > 0) zoom--;
356
+ }
357
+ mDist = newDist;
358
+ params.setZoom(zoom);
359
+ mCamera.setParameters(params);
360
+ }
361
+ }
391
362
  }
363
+ );
364
+ }
365
+
366
+ private void setDefaultCameraId() {
367
+ // Find the total number of cameras available
368
+ numberOfCameras = Camera.getNumberOfCameras();
369
+
370
+ int facing = "front".equals(defaultCamera)
371
+ ? Camera.CameraInfo.CAMERA_FACING_FRONT
372
+ : Camera.CameraInfo.CAMERA_FACING_BACK;
373
+
374
+ // Find the ID of the default camera
375
+ Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
376
+ for (int i = 0; i < numberOfCameras; i++) {
377
+ Camera.getCameraInfo(i, cameraInfo);
378
+ if (cameraInfo.facing == facing) {
379
+ defaultCameraId = i;
380
+ break;
381
+ }
392
382
  }
383
+ }
393
384
 
394
- @Override
395
- public void onConfigurationChanged(Configuration newConfig) {
396
- super.onConfigurationChanged(newConfig);
385
+ @Override
386
+ public void onResume() {
387
+ super.onResume();
397
388
 
398
- final FrameLayout frameContainerLayout = (FrameLayout) view.findViewById(
399
- getResources().getIdentifier("frame_container", "id", appResourcesPackage)
400
- );
401
-
402
- final int previousOrientation = frameContainerLayout.getHeight() > frameContainerLayout.getWidth()
403
- ? Configuration.ORIENTATION_PORTRAIT
404
- : Configuration.ORIENTATION_LANDSCAPE;
405
- // Checks if the orientation of the screen has changed
406
- if (newConfig.orientation != previousOrientation) {
407
- final RelativeLayout frameCamContainerLayout = (RelativeLayout) view.findViewById(
408
- getResources().getIdentifier("frame_camera_cont", "id", appResourcesPackage)
409
- );
410
-
411
- frameContainerLayout.getLayoutParams().width = frameCamContainerLayout.getHeight();
412
- frameContainerLayout.getLayoutParams().height = frameCamContainerLayout.getWidth();
389
+ mCamera = Camera.open(defaultCameraId);
413
390
 
414
- frameCamContainerLayout.getLayoutParams().width = frameCamContainerLayout.getHeight();
415
- frameCamContainerLayout.getLayoutParams().height = frameCamContainerLayout.getWidth();
391
+ if (cameraParameters != null) {
392
+ mCamera.setParameters(cameraParameters);
393
+ }
416
394
 
417
- frameContainerLayout.invalidate();
418
- frameContainerLayout.requestLayout();
395
+ cameraCurrentlyLocked = defaultCameraId;
419
396
 
420
- frameCamContainerLayout.forceLayout();
397
+ if (mPreview.mPreviewSize == null) {
398
+ mPreview.setCamera(mCamera, cameraCurrentlyLocked);
399
+ eventListener.onCameraStarted();
400
+ } else {
401
+ mPreview.switchCamera(mCamera, cameraCurrentlyLocked);
402
+ mCamera.startPreview();
403
+ }
421
404
 
422
- mPreview.setCameraDisplayOrientation();
405
+ Log.d(TAG, "cameraCurrentlyLocked:" + cameraCurrentlyLocked);
406
+
407
+ final FrameLayout frameContainerLayout = (FrameLayout) view.findViewById(
408
+ getResources().getIdentifier("frame_container", "id", appResourcesPackage)
409
+ );
410
+
411
+ ViewTreeObserver viewTreeObserver =
412
+ frameContainerLayout.getViewTreeObserver();
413
+
414
+ if (viewTreeObserver.isAlive()) {
415
+ viewTreeObserver.addOnGlobalLayoutListener(
416
+ new ViewTreeObserver.OnGlobalLayoutListener() {
417
+ @Override
418
+ public void onGlobalLayout() {
419
+ frameContainerLayout
420
+ .getViewTreeObserver()
421
+ .removeGlobalOnLayoutListener(this);
422
+ frameContainerLayout.measure(
423
+ View.MeasureSpec.UNSPECIFIED,
424
+ View.MeasureSpec.UNSPECIFIED
425
+ );
426
+ Activity activity = getActivity();
427
+ if (isAdded() && activity != null) {
428
+ final RelativeLayout frameCamContainerLayout =
429
+ (RelativeLayout) view.findViewById(
430
+ getResources()
431
+ .getIdentifier(
432
+ "frame_camera_cont",
433
+ "id",
434
+ appResourcesPackage
435
+ )
436
+ );
437
+
438
+ FrameLayout.LayoutParams camViewLayout =
439
+ new FrameLayout.LayoutParams(
440
+ frameContainerLayout.getWidth(),
441
+ frameContainerLayout.getHeight()
442
+ );
443
+ camViewLayout.gravity =
444
+ Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
445
+ frameCamContainerLayout.setLayoutParams(camViewLayout);
446
+ }
447
+ }
423
448
  }
449
+ );
424
450
  }
425
-
426
- public Camera getCamera() {
427
- return mCamera;
451
+ }
452
+
453
+ @Override
454
+ public void onPause() {
455
+ super.onPause();
456
+
457
+ // Because the Camera object is a shared resource, it's very important to release it when the activity is paused.
458
+ if (mCamera != null) {
459
+ setDefaultCameraId();
460
+ mPreview.setCamera(null, -1);
461
+ mCamera.setPreviewCallback(null);
462
+ mCamera.release();
463
+ mCamera = null;
428
464
  }
465
+ }
466
+
467
+ @Override
468
+ public void onConfigurationChanged(Configuration newConfig) {
469
+ super.onConfigurationChanged(newConfig);
470
+
471
+ final FrameLayout frameContainerLayout = (FrameLayout) view.findViewById(
472
+ getResources().getIdentifier("frame_container", "id", appResourcesPackage)
473
+ );
474
+
475
+ final int previousOrientation = frameContainerLayout.getHeight() >
476
+ frameContainerLayout.getWidth()
477
+ ? Configuration.ORIENTATION_PORTRAIT
478
+ : Configuration.ORIENTATION_LANDSCAPE;
479
+ // Checks if the orientation of the screen has changed
480
+ if (newConfig.orientation != previousOrientation) {
481
+ final RelativeLayout frameCamContainerLayout =
482
+ (RelativeLayout) view.findViewById(
483
+ getResources()
484
+ .getIdentifier("frame_camera_cont", "id", appResourcesPackage)
485
+ );
429
486
 
430
- public void switchCamera() {
431
- // check for availability of multiple cameras
432
- if (numberOfCameras == 1) {
433
- //There is only one camera available
434
- } else {
435
- Log.d(TAG, "numberOfCameras: " + numberOfCameras);
487
+ frameContainerLayout.getLayoutParams().width =
488
+ frameCamContainerLayout.getHeight();
489
+ frameContainerLayout.getLayoutParams().height =
490
+ frameCamContainerLayout.getWidth();
436
491
 
437
- // OK, we have multiple cameras. Release this camera -> cameraCurrentlyLocked
438
- if (mCamera != null) {
439
- mCamera.stopPreview();
440
- mPreview.setCamera(null, -1);
441
- mCamera.release();
442
- mCamera = null;
443
- }
492
+ frameCamContainerLayout.getLayoutParams().width =
493
+ frameCamContainerLayout.getHeight();
494
+ frameCamContainerLayout.getLayoutParams().height =
495
+ frameCamContainerLayout.getWidth();
444
496
 
445
- Log.d(TAG, "cameraCurrentlyLocked := " + Integer.toString(cameraCurrentlyLocked));
446
- try {
447
- cameraCurrentlyLocked = (cameraCurrentlyLocked + 1) % numberOfCameras;
448
- Log.d(TAG, "cameraCurrentlyLocked new: " + cameraCurrentlyLocked);
449
- } catch (Exception exception) {
450
- Log.d(TAG, exception.getMessage());
451
- }
452
-
453
- // Acquire the next camera and request Preview to reconfigure parameters.
454
- mCamera = Camera.open(cameraCurrentlyLocked);
497
+ frameContainerLayout.invalidate();
498
+ frameContainerLayout.requestLayout();
455
499
 
456
- if (cameraParameters != null) {
457
- Log.d(TAG, "camera parameter not null");
500
+ frameCamContainerLayout.forceLayout();
458
501
 
459
- // Check for flashMode as well to prevent error on frontward facing camera.
460
- List<String> supportedFlashModesNewCamera = mCamera.getParameters().getSupportedFlashModes();
461
- String currentFlashModePreviousCamera = cameraParameters.getFlashMode();
462
- if (supportedFlashModesNewCamera != null && supportedFlashModesNewCamera.contains(currentFlashModePreviousCamera)) {
463
- Log.d(TAG, "current flash mode supported on new camera. setting params");
464
- /* mCamera.setParameters(cameraParameters);
502
+ mPreview.setCameraDisplayOrientation();
503
+ }
504
+ }
505
+
506
+ public Camera getCamera() {
507
+ return mCamera;
508
+ }
509
+
510
+ public void switchCamera() {
511
+ // check for availability of multiple cameras
512
+ if (numberOfCameras == 1) {
513
+ //There is only one camera available
514
+ } else {
515
+ Log.d(TAG, "numberOfCameras: " + numberOfCameras);
516
+
517
+ // OK, we have multiple cameras. Release this camera -> cameraCurrentlyLocked
518
+ if (mCamera != null) {
519
+ mCamera.stopPreview();
520
+ mPreview.setCamera(null, -1);
521
+ mCamera.release();
522
+ mCamera = null;
523
+ }
524
+
525
+ Log.d(
526
+ TAG,
527
+ "cameraCurrentlyLocked := " + Integer.toString(cameraCurrentlyLocked)
528
+ );
529
+ try {
530
+ cameraCurrentlyLocked = (cameraCurrentlyLocked + 1) % numberOfCameras;
531
+ Log.d(TAG, "cameraCurrentlyLocked new: " + cameraCurrentlyLocked);
532
+ } catch (Exception exception) {
533
+ Log.d(TAG, exception.getMessage());
534
+ }
535
+
536
+ // Acquire the next camera and request Preview to reconfigure parameters.
537
+ mCamera = Camera.open(cameraCurrentlyLocked);
538
+
539
+ if (cameraParameters != null) {
540
+ Log.d(TAG, "camera parameter not null");
541
+
542
+ // Check for flashMode as well to prevent error on frontward facing camera.
543
+ List<String> supportedFlashModesNewCamera = mCamera
544
+ .getParameters()
545
+ .getSupportedFlashModes();
546
+ String currentFlashModePreviousCamera = cameraParameters.getFlashMode();
547
+ if (
548
+ supportedFlashModesNewCamera != null &&
549
+ supportedFlashModesNewCamera.contains(currentFlashModePreviousCamera)
550
+ ) {
551
+ Log.d(
552
+ TAG,
553
+ "current flash mode supported on new camera. setting params"
554
+ );
555
+ /* mCamera.setParameters(cameraParameters);
465
556
  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.
466
557
  */
467
- } else {
468
- Log.d(TAG, "current flash mode NOT supported on new camera");
469
- }
470
- } else {
471
- Log.d(TAG, "camera parameter NULL");
472
- }
473
-
474
- mPreview.switchCamera(mCamera, cameraCurrentlyLocked);
475
-
476
- mCamera.startPreview();
558
+ } else {
559
+ Log.d(TAG, "current flash mode NOT supported on new camera");
477
560
  }
478
- }
561
+ } else {
562
+ Log.d(TAG, "camera parameter NULL");
563
+ }
479
564
 
480
- public void setCameraParameters(Camera.Parameters params) {
481
- cameraParameters = params;
565
+ mPreview.switchCamera(mCamera, cameraCurrentlyLocked);
482
566
 
483
- if (mCamera != null && cameraParameters != null) {
484
- mCamera.setParameters(cameraParameters);
485
- }
567
+ mCamera.startPreview();
486
568
  }
569
+ }
487
570
 
488
- public boolean hasFrontCamera() {
489
- return getActivity().getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
490
- }
571
+ public void setCameraParameters(Camera.Parameters params) {
572
+ cameraParameters = params;
491
573
 
492
- public static Bitmap applyMatrix(Bitmap source, Matrix matrix) {
493
- return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
574
+ if (mCamera != null && cameraParameters != null) {
575
+ mCamera.setParameters(cameraParameters);
494
576
  }
495
-
496
- ShutterCallback shutterCallback = new ShutterCallback() {
497
- public void onShutter() {
498
- // do nothing, availabilty of this callback causes default system shutter sound to work
499
- }
500
- };
501
-
502
- private static int exifToDegrees(int exifOrientation) {
503
- if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
504
- return 90;
505
- } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
506
- return 180;
507
- } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
508
- return 270;
509
- }
510
- return 0;
511
- }
512
-
513
- private String getTempDirectoryPath() {
514
- File cache = null;
515
-
516
- // Use internal storage
517
- cache = getActivity().getCacheDir();
518
-
519
- // Create the cache directory if it doesn't exist
520
- cache.mkdirs();
521
- return cache.getAbsolutePath();
577
+ }
578
+
579
+ public boolean hasFrontCamera() {
580
+ return getActivity()
581
+ .getApplicationContext()
582
+ .getPackageManager()
583
+ .hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
584
+ }
585
+
586
+ public static Bitmap applyMatrix(Bitmap source, Matrix matrix) {
587
+ return Bitmap.createBitmap(
588
+ source,
589
+ 0,
590
+ 0,
591
+ source.getWidth(),
592
+ source.getHeight(),
593
+ matrix,
594
+ true
595
+ );
596
+ }
597
+
598
+ ShutterCallback shutterCallback = new ShutterCallback() {
599
+ public void onShutter() {
600
+ // do nothing, availabilty of this callback causes default system shutter sound to work
522
601
  }
523
-
524
- private String getTempFilePath() {
525
- return getTempDirectoryPath() + "/cpcp_capture_" + UUID.randomUUID().toString().replace("-", "").substring(0, 8) + ".jpg";
602
+ };
603
+
604
+ private static int exifToDegrees(int exifOrientation) {
605
+ if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
606
+ return 90;
607
+ } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
608
+ return 180;
609
+ } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
610
+ return 270;
526
611
  }
612
+ return 0;
613
+ }
614
+
615
+ private String getTempDirectoryPath() {
616
+ File cache = null;
617
+
618
+ // Use internal storage
619
+ cache = getActivity().getCacheDir();
620
+
621
+ // Create the cache directory if it doesn't exist
622
+ cache.mkdirs();
623
+ return cache.getAbsolutePath();
624
+ }
625
+
626
+ private String getTempFilePath() {
627
+ return (
628
+ getTempDirectoryPath() +
629
+ "/cpcp_capture_" +
630
+ UUID.randomUUID().toString().replace("-", "").substring(0, 8) +
631
+ ".jpg"
632
+ );
633
+ }
634
+
635
+ PictureCallback jpegPictureCallback = new PictureCallback() {
636
+ public void onPictureTaken(byte[] data, Camera arg1) {
637
+ Log.d(TAG, "CameraPreview jpegPictureCallback");
638
+
639
+ try {
640
+ if (!disableExifHeaderStripping) {
641
+ Matrix matrix = new Matrix();
642
+ if (cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT) {
643
+ matrix.preScale(1.0f, -1.0f);
644
+ }
645
+
646
+ ExifInterface exifInterface = new ExifInterface(
647
+ new ByteArrayInputStream(data)
648
+ );
649
+ int rotation = exifInterface.getAttributeInt(
650
+ ExifInterface.TAG_ORIENTATION,
651
+ ExifInterface.ORIENTATION_NORMAL
652
+ );
653
+ int rotationInDegrees = exifToDegrees(rotation);
654
+
655
+ if (rotation != 0f) {
656
+ matrix.preRotate(rotationInDegrees);
657
+ }
658
+
659
+ // Check if matrix has changed. In that case, apply matrix and override data
660
+ if (!matrix.isIdentity()) {
661
+ Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
662
+ bitmap = applyMatrix(bitmap, matrix);
663
+
664
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
665
+ bitmap.compress(CompressFormat.JPEG, currentQuality, outputStream);
666
+ data = outputStream.toByteArray();
667
+ }
668
+ }
527
669
 
528
- PictureCallback jpegPictureCallback = new PictureCallback() {
529
- public void onPictureTaken(byte[] data, Camera arg1) {
530
- Log.d(TAG, "CameraPreview jpegPictureCallback");
531
-
532
- try {
533
- if (!disableExifHeaderStripping) {
534
- Matrix matrix = new Matrix();
535
- if (cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT) {
536
- matrix.preScale(1.0f, -1.0f);
537
- }
538
-
539
- ExifInterface exifInterface = new ExifInterface(new ByteArrayInputStream(data));
540
- int rotation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
541
- int rotationInDegrees = exifToDegrees(rotation);
542
-
543
- if (rotation != 0f) {
544
- matrix.preRotate(rotationInDegrees);
545
- }
546
-
547
- // Check if matrix has changed. In that case, apply matrix and override data
548
- if (!matrix.isIdentity()) {
549
- Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
550
- bitmap = applyMatrix(bitmap, matrix);
551
-
552
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
553
- bitmap.compress(CompressFormat.JPEG, currentQuality, outputStream);
554
- data = outputStream.toByteArray();
555
- }
556
- }
557
-
558
- if (!storeToFile) {
559
- String encodedImage = Base64.encodeToString(data, Base64.NO_WRAP);
670
+ if (!storeToFile) {
671
+ String encodedImage = Base64.encodeToString(data, Base64.NO_WRAP);
560
672
 
561
- eventListener.onPictureTaken(encodedImage);
562
- } else {
563
- String path = getTempFilePath();
564
- FileOutputStream out = new FileOutputStream(path);
565
- out.write(data);
566
- out.close();
567
- eventListener.onPictureTaken(path);
568
- }
569
- Log.d(TAG, "CameraPreview pictureTakenHandler called back");
570
- } catch (OutOfMemoryError e) {
571
- // most likely failed to allocate memory for rotateBitmap
572
- Log.d(TAG, "CameraPreview OutOfMemoryError");
573
- // failed to allocate memory
574
- eventListener.onPictureTakenError("Picture too large (memory)");
575
- } catch (IOException e) {
576
- Log.d(TAG, "CameraPreview IOException");
577
- eventListener.onPictureTakenError("IO Error when extracting exif");
578
- } catch (Exception e) {
579
- Log.d(TAG, "CameraPreview onPictureTaken general exception");
580
- } finally {
581
- canTakePicture = true;
582
- mCamera.startPreview();
583
- }
673
+ eventListener.onPictureTaken(encodedImage);
674
+ } else {
675
+ String path = getTempFilePath();
676
+ FileOutputStream out = new FileOutputStream(path);
677
+ out.write(data);
678
+ out.close();
679
+ eventListener.onPictureTaken(path);
584
680
  }
585
- };
586
-
587
- private Camera.Size getOptimalPictureSize(
588
- final int width,
589
- final int height,
590
- final Camera.Size previewSize,
591
- final List<Camera.Size> supportedSizes
592
- ) {
593
- /*
681
+ Log.d(TAG, "CameraPreview pictureTakenHandler called back");
682
+ } catch (OutOfMemoryError e) {
683
+ // most likely failed to allocate memory for rotateBitmap
684
+ Log.d(TAG, "CameraPreview OutOfMemoryError");
685
+ // failed to allocate memory
686
+ eventListener.onPictureTakenError("Picture too large (memory)");
687
+ } catch (IOException e) {
688
+ Log.d(TAG, "CameraPreview IOException");
689
+ eventListener.onPictureTakenError("IO Error when extracting exif");
690
+ } catch (Exception e) {
691
+ Log.d(TAG, "CameraPreview onPictureTaken general exception");
692
+ } finally {
693
+ canTakePicture = true;
694
+ mCamera.startPreview();
695
+ }
696
+ }
697
+ };
698
+
699
+ private Camera.Size getOptimalPictureSize(
700
+ final int width,
701
+ final int height,
702
+ final Camera.Size previewSize,
703
+ final List<Camera.Size> supportedSizes
704
+ ) {
705
+ /*
594
706
  get the supportedPictureSize that:
595
707
  - matches exactly width and height
596
708
  - has the closest aspect ratio to the preview aspect ratio
597
709
  - has picture.width and picture.height closest to width and height
598
710
  - has the highest supported picture width and height up to 2 Megapixel if width == 0 || height == 0
599
711
  */
600
- Camera.Size size = mCamera.new Size(width, height);
712
+ Camera.Size size = mCamera.new Size(width, height);
601
713
 
602
- // convert to landscape if necessary
603
- if (size.width < size.height) {
604
- int temp = size.width;
605
- size.width = size.height;
606
- size.height = temp;
607
- }
608
-
609
- Camera.Size requestedSize = mCamera.new Size(size.width, size.height);
610
-
611
- double previewAspectRatio = (double) previewSize.width / (double) previewSize.height;
612
-
613
- if (previewAspectRatio < 1.0) {
614
- // reset ratio to landscape
615
- previewAspectRatio = 1.0 / previewAspectRatio;
616
- }
617
-
618
- Log.d(TAG, "CameraPreview previewAspectRatio " + previewAspectRatio);
619
-
620
- double aspectTolerance = 0.1;
621
- double bestDifference = Double.MAX_VALUE;
622
-
623
- for (int i = 0; i < supportedSizes.size(); i++) {
624
- Camera.Size supportedSize = supportedSizes.get(i);
625
-
626
- // Perfect match
627
- if (supportedSize.equals(requestedSize)) {
628
- Log.d(TAG, "CameraPreview optimalPictureSize " + supportedSize.width + 'x' + supportedSize.height);
629
- return supportedSize;
630
- }
631
-
632
- double difference = Math.abs(previewAspectRatio - ((double) supportedSize.width / (double) supportedSize.height));
633
-
634
- if (difference < bestDifference - aspectTolerance) {
635
- // better aspectRatio found
636
- if ((width != 0 && height != 0) || (supportedSize.width * supportedSize.height < 2048 * 1024)) {
637
- size.width = supportedSize.width;
638
- size.height = supportedSize.height;
639
- bestDifference = difference;
640
- }
641
- } else if (difference < bestDifference + aspectTolerance) {
642
- // same aspectRatio found (within tolerance)
643
- if (width == 0 || height == 0) {
644
- // set highest supported resolution below 2 Megapixel
645
- if ((size.width < supportedSize.width) && (supportedSize.width * supportedSize.height < 2048 * 1024)) {
646
- size.width = supportedSize.width;
647
- size.height = supportedSize.height;
648
- }
649
- } else {
650
- // check if this pictureSize closer to requested width and height
651
- if (
652
- Math.abs(width * height - supportedSize.width * supportedSize.height) <
653
- Math.abs(width * height - size.width * size.height)
654
- ) {
655
- size.width = supportedSize.width;
656
- size.height = supportedSize.height;
657
- }
658
- }
659
- }
660
- }
661
- Log.d(TAG, "CameraPreview optimalPictureSize " + size.width + 'x' + size.height);
662
- return size;
714
+ // convert to landscape if necessary
715
+ if (size.width < size.height) {
716
+ int temp = size.width;
717
+ size.width = size.height;
718
+ size.height = temp;
663
719
  }
664
720
 
665
- static byte[] rotateNV21(final byte[] yuv, final int width, final int height, final int rotation) {
666
- if (rotation == 0) return yuv;
667
- if (rotation % 90 != 0 || rotation < 0 || rotation > 270) {
668
- throw new IllegalArgumentException("0 <= rotation < 360, rotation % 90 == 0");
669
- }
721
+ Camera.Size requestedSize = mCamera.new Size(size.width, size.height);
670
722
 
671
- final byte[] output = new byte[yuv.length];
672
- final int frameSize = width * height;
673
- final boolean swap = rotation % 180 != 0;
674
- final boolean xflip = rotation % 270 != 0;
675
- final boolean yflip = rotation >= 180;
676
-
677
- for (int j = 0; j < height; j++) {
678
- for (int i = 0; i < width; i++) {
679
- final int yIn = j * width + i;
680
- final int uIn = frameSize + (j >> 1) * width + (i & ~1);
681
- final int vIn = uIn + 1;
682
-
683
- final int wOut = swap ? height : width;
684
- final int hOut = swap ? width : height;
685
- final int iSwapped = swap ? j : i;
686
- final int jSwapped = swap ? i : j;
687
- final int iOut = xflip ? wOut - iSwapped - 1 : iSwapped;
688
- final int jOut = yflip ? hOut - jSwapped - 1 : jSwapped;
689
-
690
- final int yOut = jOut * wOut + iOut;
691
- final int uOut = frameSize + (jOut >> 1) * wOut + (iOut & ~1);
692
- final int vOut = uOut + 1;
693
-
694
- output[yOut] = (byte) (0xff & yuv[yIn]);
695
- output[uOut] = (byte) (0xff & yuv[uIn]);
696
- output[vOut] = (byte) (0xff & yuv[vIn]);
697
- }
698
- }
699
- return output;
700
- }
723
+ double previewAspectRatio = (double) previewSize.width /
724
+ (double) previewSize.height;
701
725
 
702
- public void setOpacity(final float opacity) {
703
- Log.d(TAG, "set opacity:" + opacity);
704
- this.opacity = opacity;
705
- mPreview.setOpacity(opacity);
726
+ if (previewAspectRatio < 1.0) {
727
+ // reset ratio to landscape
728
+ previewAspectRatio = 1.0 / previewAspectRatio;
706
729
  }
707
730
 
708
- public void takeSnapshot(final int quality) {
709
- mCamera.setPreviewCallback(
710
- new Camera.PreviewCallback() {
711
- @Override
712
- public void onPreviewFrame(byte[] bytes, Camera camera) {
713
- try {
714
- Camera.Parameters parameters = camera.getParameters();
715
- Camera.Size size = parameters.getPreviewSize();
716
- int orientation = mPreview.getDisplayOrientation();
717
- if (mPreview.getCameraFacing() == Camera.CameraInfo.CAMERA_FACING_FRONT) {
718
- bytes = rotateNV21(bytes, size.width, size.height, (360 - orientation) % 360);
719
- } else {
720
- bytes = rotateNV21(bytes, size.width, size.height, orientation);
721
- }
722
- // switch width/height when rotating 90/270 deg
723
- Rect rect = orientation == 90 || orientation == 270
724
- ? new Rect(0, 0, size.height, size.width)
725
- : new Rect(0, 0, size.width, size.height);
726
- YuvImage yuvImage = new YuvImage(bytes, parameters.getPreviewFormat(), rect.width(), rect.height(), null);
727
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
728
- yuvImage.compressToJpeg(rect, quality, byteArrayOutputStream);
729
- byte[] data = byteArrayOutputStream.toByteArray();
730
- byteArrayOutputStream.close();
731
- eventListener.onSnapshotTaken(Base64.encodeToString(data, Base64.NO_WRAP));
732
- } catch (IOException e) {
733
- Log.d(TAG, "CameraPreview IOException");
734
- eventListener.onSnapshotTakenError("IO Error");
735
- } finally {
736
- mCamera.setPreviewCallback(null);
737
- }
738
- }
739
- }
740
- );
741
- }
742
-
743
- public void takePicture(final int width, final int height, final int quality) {
744
- Log.d(TAG, "CameraPreview takePicture width: " + width + ", height: " + height + ", quality: " + quality);
745
-
746
- if (mPreview != null) {
747
- if (!canTakePicture) {
748
- return;
749
- }
750
-
751
- canTakePicture = false;
752
-
753
- new Thread() {
754
- public void run() {
755
- Camera.Parameters params = mCamera.getParameters();
756
-
757
- Camera.Size size = getOptimalPictureSize(width, height, params.getPreviewSize(), params.getSupportedPictureSizes());
758
- params.setPictureSize(size.width, size.height);
759
- currentQuality = quality;
731
+ Log.d(TAG, "CameraPreview previewAspectRatio " + previewAspectRatio);
760
732
 
761
- if (cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT && !storeToFile) {
762
- // The image will be recompressed in the callback
763
- params.setJpegQuality(99);
764
- } else {
765
- params.setJpegQuality(quality);
766
- }
733
+ double aspectTolerance = 0.1;
734
+ double bestDifference = Double.MAX_VALUE;
767
735
 
768
- if (cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT && disableExifHeaderStripping) {
769
- Activity activity = getActivity();
770
- int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
771
- int degrees = 0;
772
- switch (rotation) {
773
- case Surface.ROTATION_0:
774
- degrees = 0;
775
- break;
776
- case Surface.ROTATION_90:
777
- degrees = 180;
778
- break;
779
- case Surface.ROTATION_180:
780
- degrees = 270;
781
- break;
782
- case Surface.ROTATION_270:
783
- degrees = 0;
784
- break;
785
- }
786
- int orientation;
787
- Camera.CameraInfo info = new Camera.CameraInfo();
788
- if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
789
- orientation = (info.orientation + degrees) % 360;
790
- if (degrees != 0) {
791
- orientation = (360 - orientation) % 360;
792
- }
793
- } else {
794
- orientation = (info.orientation - degrees + 360) % 360;
795
- }
796
- params.setRotation(orientation);
797
- } else {
798
- params.setRotation(mPreview.getDisplayOrientation());
799
- }
736
+ for (int i = 0; i < supportedSizes.size(); i++) {
737
+ Camera.Size supportedSize = supportedSizes.get(i);
800
738
 
801
- mCamera.setParameters(params);
802
- mCamera.takePicture(shutterCallback, null, jpegPictureCallback);
803
- }
804
- }
805
- .start();
739
+ // Perfect match
740
+ if (supportedSize.equals(requestedSize)) {
741
+ Log.d(
742
+ TAG,
743
+ "CameraPreview optimalPictureSize " +
744
+ supportedSize.width +
745
+ 'x' +
746
+ supportedSize.height
747
+ );
748
+ return supportedSize;
749
+ }
750
+
751
+ double difference = Math.abs(
752
+ previewAspectRatio -
753
+ ((double) supportedSize.width / (double) supportedSize.height)
754
+ );
755
+
756
+ if (difference < bestDifference - aspectTolerance) {
757
+ // better aspectRatio found
758
+ if (
759
+ (width != 0 && height != 0) ||
760
+ (supportedSize.width * supportedSize.height < 2048 * 1024)
761
+ ) {
762
+ size.width = supportedSize.width;
763
+ size.height = supportedSize.height;
764
+ bestDifference = difference;
765
+ }
766
+ } else if (difference < bestDifference + aspectTolerance) {
767
+ // same aspectRatio found (within tolerance)
768
+ if (width == 0 || height == 0) {
769
+ // set highest supported resolution below 2 Megapixel
770
+ if (
771
+ (size.width < supportedSize.width) &&
772
+ (supportedSize.width * supportedSize.height < 2048 * 1024)
773
+ ) {
774
+ size.width = supportedSize.width;
775
+ size.height = supportedSize.height;
776
+ }
806
777
  } else {
807
- canTakePicture = true;
778
+ // check if this pictureSize closer to requested width and height
779
+ if (
780
+ Math.abs(
781
+ width * height - supportedSize.width * supportedSize.height
782
+ ) <
783
+ Math.abs(width * height - size.width * size.height)
784
+ ) {
785
+ size.width = supportedSize.width;
786
+ size.height = supportedSize.height;
787
+ }
808
788
  }
789
+ }
790
+ }
791
+ Log.d(
792
+ TAG,
793
+ "CameraPreview optimalPictureSize " + size.width + 'x' + size.height
794
+ );
795
+ return size;
796
+ }
797
+
798
+ static byte[] rotateNV21(
799
+ final byte[] yuv,
800
+ final int width,
801
+ final int height,
802
+ final int rotation
803
+ ) {
804
+ if (rotation == 0) return yuv;
805
+ if (rotation % 90 != 0 || rotation < 0 || rotation > 270) {
806
+ throw new IllegalArgumentException(
807
+ "0 <= rotation < 360, rotation % 90 == 0"
808
+ );
809
809
  }
810
810
 
811
- public void startRecord(
812
- final String filePath,
813
- final String camera,
814
- final int width,
815
- final int height,
816
- final int quality,
817
- final boolean withFlash,
818
- final int maxDuration
819
- ) {
820
- Log.d(TAG, "CameraPreview startRecord camera: " + camera + " width: " + width + ", height: " + height + ", quality: " + quality);
821
- Activity activity = getActivity();
822
- muteStream(true, activity);
823
- if (this.mRecordingState == RecordingState.STARTED) {
824
- Log.d(TAG, "Already Recording");
825
- return;
826
- }
827
-
828
- this.recordFilePath = filePath;
829
- int mOrientationHint = calculateOrientationHint();
830
- int videoWidth = 0; //set whatever
831
- int videoHeight = 0; //set whatever
832
-
833
- Camera.Parameters cameraParams = mCamera.getParameters();
834
- if (withFlash) {
835
- cameraParams.setFlashMode(withFlash ? Camera.Parameters.FLASH_MODE_TORCH : Camera.Parameters.FLASH_MODE_OFF);
836
- mCamera.setParameters(cameraParams);
837
- mCamera.startPreview();
838
- }
839
-
840
- mCamera.unlock();
841
- mRecorder = new MediaRecorder();
842
-
843
- try {
844
- mRecorder.setCamera(mCamera);
845
-
846
- CamcorderProfile profile;
847
- if (CamcorderProfile.hasProfile(defaultCameraId, CamcorderProfile.QUALITY_HIGH)) {
848
- profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_HIGH);
811
+ final byte[] output = new byte[yuv.length];
812
+ final int frameSize = width * height;
813
+ final boolean swap = rotation % 180 != 0;
814
+ final boolean xflip = rotation % 270 != 0;
815
+ final boolean yflip = rotation >= 180;
816
+
817
+ for (int j = 0; j < height; j++) {
818
+ for (int i = 0; i < width; i++) {
819
+ final int yIn = j * width + i;
820
+ final int uIn = frameSize + (j >> 1) * width + (i & ~1);
821
+ final int vIn = uIn + 1;
822
+
823
+ final int wOut = swap ? height : width;
824
+ final int hOut = swap ? width : height;
825
+ final int iSwapped = swap ? j : i;
826
+ final int jSwapped = swap ? i : j;
827
+ final int iOut = xflip ? wOut - iSwapped - 1 : iSwapped;
828
+ final int jOut = yflip ? hOut - jSwapped - 1 : jSwapped;
829
+
830
+ final int yOut = jOut * wOut + iOut;
831
+ final int uOut = frameSize + (jOut >> 1) * wOut + (iOut & ~1);
832
+ final int vOut = uOut + 1;
833
+
834
+ output[yOut] = (byte) (0xff & yuv[yIn]);
835
+ output[uOut] = (byte) (0xff & yuv[uIn]);
836
+ output[vOut] = (byte) (0xff & yuv[vIn]);
837
+ }
838
+ }
839
+ return output;
840
+ }
841
+
842
+ public void setOpacity(final float opacity) {
843
+ Log.d(TAG, "set opacity:" + opacity);
844
+ this.opacity = opacity;
845
+ mPreview.setOpacity(opacity);
846
+ }
847
+
848
+ public void takeSnapshot(final int quality) {
849
+ mCamera.setPreviewCallback(
850
+ new Camera.PreviewCallback() {
851
+ @Override
852
+ public void onPreviewFrame(byte[] bytes, Camera camera) {
853
+ try {
854
+ Camera.Parameters parameters = camera.getParameters();
855
+ Camera.Size size = parameters.getPreviewSize();
856
+ int orientation = mPreview.getDisplayOrientation();
857
+ if (
858
+ mPreview.getCameraFacing() ==
859
+ Camera.CameraInfo.CAMERA_FACING_FRONT
860
+ ) {
861
+ bytes =
862
+ rotateNV21(
863
+ bytes,
864
+ size.width,
865
+ size.height,
866
+ (360 - orientation) % 360
867
+ );
849
868
  } else {
850
- if (CamcorderProfile.hasProfile(defaultCameraId, CamcorderProfile.QUALITY_480P)) {
851
- profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_480P);
852
- } else {
853
- if (CamcorderProfile.hasProfile(defaultCameraId, CamcorderProfile.QUALITY_720P)) {
854
- profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_720P);
855
- } else {
856
- if (CamcorderProfile.hasProfile(defaultCameraId, CamcorderProfile.QUALITY_1080P)) {
857
- profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_1080P);
858
- } else {
859
- profile = CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_LOW);
860
- }
861
- }
862
- }
869
+ bytes = rotateNV21(bytes, size.width, size.height, orientation);
863
870
  }
864
-
865
- mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION);
866
- mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
867
- mRecorder.setProfile(profile);
868
- mRecorder.setOutputFile(filePath);
869
- mRecorder.setOrientationHint(mOrientationHint);
870
- mRecorder.setMaxDuration(maxDuration);
871
-
872
- mRecorder.prepare();
873
- Log.d(TAG, "Starting recording");
874
- mRecorder.start();
875
- eventListener.onStartRecordVideo();
876
- } catch (IOException e) {
877
- eventListener.onStartRecordVideoError(e.getMessage());
871
+ // switch width/height when rotating 90/270 deg
872
+ Rect rect = orientation == 90 || orientation == 270
873
+ ? new Rect(0, 0, size.height, size.width)
874
+ : new Rect(0, 0, size.width, size.height);
875
+ YuvImage yuvImage = new YuvImage(
876
+ bytes,
877
+ parameters.getPreviewFormat(),
878
+ rect.width(),
879
+ rect.height(),
880
+ null
881
+ );
882
+ ByteArrayOutputStream byteArrayOutputStream =
883
+ new ByteArrayOutputStream();
884
+ yuvImage.compressToJpeg(rect, quality, byteArrayOutputStream);
885
+ byte[] data = byteArrayOutputStream.toByteArray();
886
+ byteArrayOutputStream.close();
887
+ eventListener.onSnapshotTaken(
888
+ Base64.encodeToString(data, Base64.NO_WRAP)
889
+ );
890
+ } catch (IOException e) {
891
+ Log.d(TAG, "CameraPreview IOException");
892
+ eventListener.onSnapshotTakenError("IO Error");
893
+ } finally {
894
+ mCamera.setPreviewCallback(null);
895
+ }
878
896
  }
879
- }
880
-
881
- public int calculateOrientationHint() {
882
- DisplayMetrics dm = new DisplayMetrics();
883
- Camera.CameraInfo info = new Camera.CameraInfo();
884
- Camera.getCameraInfo(defaultCameraId, info);
885
- int cameraRotationOffset = info.orientation;
886
- Activity activity = getActivity();
887
-
888
- activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
889
- int currentScreenRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
890
-
891
- int degrees = 0;
892
- switch (currentScreenRotation) {
893
- case Surface.ROTATION_0:
897
+ }
898
+ );
899
+ }
900
+
901
+ public void takePicture(
902
+ final int width,
903
+ final int height,
904
+ final int quality
905
+ ) {
906
+ Log.d(
907
+ TAG,
908
+ "CameraPreview takePicture width: " +
909
+ width +
910
+ ", height: " +
911
+ height +
912
+ ", quality: " +
913
+ quality
914
+ );
915
+
916
+ if (mPreview != null) {
917
+ if (!canTakePicture) {
918
+ return;
919
+ }
920
+
921
+ canTakePicture = false;
922
+
923
+ new Thread() {
924
+ public void run() {
925
+ Camera.Parameters params = mCamera.getParameters();
926
+
927
+ Camera.Size size = getOptimalPictureSize(
928
+ width,
929
+ height,
930
+ params.getPreviewSize(),
931
+ params.getSupportedPictureSizes()
932
+ );
933
+ params.setPictureSize(size.width, size.height);
934
+ currentQuality = quality;
935
+
936
+ if (
937
+ cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT &&
938
+ !storeToFile
939
+ ) {
940
+ // The image will be recompressed in the callback
941
+ params.setJpegQuality(99);
942
+ } else {
943
+ params.setJpegQuality(quality);
944
+ }
945
+
946
+ if (
947
+ cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT &&
948
+ disableExifHeaderStripping
949
+ ) {
950
+ Activity activity = getActivity();
951
+ int rotation = activity
952
+ .getWindowManager()
953
+ .getDefaultDisplay()
954
+ .getRotation();
955
+ int degrees = 0;
956
+ switch (rotation) {
957
+ case Surface.ROTATION_0:
894
958
  degrees = 0;
895
959
  break;
896
- case Surface.ROTATION_90:
897
- degrees = 90;
898
- break;
899
- case Surface.ROTATION_180:
960
+ case Surface.ROTATION_90:
900
961
  degrees = 180;
901
962
  break;
902
- case Surface.ROTATION_270:
963
+ case Surface.ROTATION_180:
903
964
  degrees = 270;
904
965
  break;
905
- }
906
-
907
- int orientation;
908
- if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
909
- orientation = (cameraRotationOffset + degrees) % 360;
910
- if (degrees != 0) {
966
+ case Surface.ROTATION_270:
967
+ degrees = 0;
968
+ break;
969
+ }
970
+ int orientation;
971
+ Camera.CameraInfo info = new Camera.CameraInfo();
972
+ if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
973
+ orientation = (info.orientation + degrees) % 360;
974
+ if (degrees != 0) {
911
975
  orientation = (360 - orientation) % 360;
976
+ }
977
+ } else {
978
+ orientation = (info.orientation - degrees + 360) % 360;
912
979
  }
913
- } else {
914
- orientation = (cameraRotationOffset - degrees + 360) % 360;
915
- }
916
- Log.w(TAG, "************orientationHint ***********= " + orientation);
980
+ params.setRotation(orientation);
981
+ } else {
982
+ params.setRotation(mPreview.getDisplayOrientation());
983
+ }
917
984
 
918
- return orientation;
919
- }
920
-
921
- public void stopRecord() {
922
- Log.d(TAG, "stopRecord");
923
-
924
- try {
925
- mRecorder.stop();
926
- mRecorder.reset(); // clear recorder configuration
927
- mRecorder.release(); // release the recorder object
928
- mRecorder = null;
929
- mCamera.lock();
930
- Camera.Parameters cameraParams = mCamera.getParameters();
931
- cameraParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
932
- mCamera.setParameters(cameraParams);
933
- mCamera.startPreview();
934
- eventListener.onStopRecordVideo(this.recordFilePath);
935
- } catch (Exception e) {
936
- eventListener.onStopRecordVideoError(e.getMessage());
985
+ mCamera.setParameters(params);
986
+ mCamera.takePicture(shutterCallback, null, jpegPictureCallback);
937
987
  }
988
+ }
989
+ .start();
990
+ } else {
991
+ canTakePicture = true;
938
992
  }
939
-
940
- public void muteStream(boolean mute, Activity activity) {
941
- AudioManager audioManager = ((AudioManager) activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE));
942
- int direction = mute ? audioManager.ADJUST_MUTE : audioManager.ADJUST_UNMUTE;
993
+ }
994
+
995
+ public void startRecord(
996
+ final String filePath,
997
+ final String camera,
998
+ final int width,
999
+ final int height,
1000
+ final int quality,
1001
+ final boolean withFlash,
1002
+ final int maxDuration
1003
+ ) {
1004
+ Log.d(
1005
+ TAG,
1006
+ "CameraPreview startRecord camera: " +
1007
+ camera +
1008
+ " width: " +
1009
+ width +
1010
+ ", height: " +
1011
+ height +
1012
+ ", quality: " +
1013
+ quality
1014
+ );
1015
+ Activity activity = getActivity();
1016
+ muteStream(true, activity);
1017
+ if (this.mRecordingState == RecordingState.STARTED) {
1018
+ Log.d(TAG, "Already Recording");
1019
+ return;
943
1020
  }
944
1021
 
945
- public void setFocusArea(final int pointX, final int pointY, final Camera.AutoFocusCallback callback) {
946
- if (mCamera != null) {
947
- mCamera.cancelAutoFocus();
948
-
949
- Camera.Parameters parameters = mCamera.getParameters();
950
-
951
- Rect focusRect = calculateTapArea(pointX, pointY, 1f);
952
- parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
953
- parameters.setFocusAreas(Arrays.asList(new Camera.Area(focusRect, 1000)));
954
-
955
- if (parameters.getMaxNumMeteringAreas() > 0) {
956
- Rect meteringRect = calculateTapArea(pointX, pointY, 1.5f);
957
- parameters.setMeteringAreas(Arrays.asList(new Camera.Area(meteringRect, 1000)));
958
- }
1022
+ this.recordFilePath = filePath;
1023
+ int mOrientationHint = calculateOrientationHint();
1024
+ int videoWidth = 0; //set whatever
1025
+ int videoHeight = 0; //set whatever
1026
+
1027
+ Camera.Parameters cameraParams = mCamera.getParameters();
1028
+ if (withFlash) {
1029
+ cameraParams.setFlashMode(
1030
+ withFlash
1031
+ ? Camera.Parameters.FLASH_MODE_TORCH
1032
+ : Camera.Parameters.FLASH_MODE_OFF
1033
+ );
1034
+ mCamera.setParameters(cameraParams);
1035
+ mCamera.startPreview();
1036
+ }
959
1037
 
960
- try {
961
- setCameraParameters(parameters);
962
- mCamera.autoFocus(callback);
963
- } catch (Exception e) {
964
- Log.d(TAG, e.getMessage());
965
- callback.onAutoFocus(false, this.mCamera);
1038
+ mCamera.unlock();
1039
+ mRecorder = new MediaRecorder();
1040
+
1041
+ try {
1042
+ mRecorder.setCamera(mCamera);
1043
+
1044
+ CamcorderProfile profile;
1045
+ if (
1046
+ CamcorderProfile.hasProfile(
1047
+ defaultCameraId,
1048
+ CamcorderProfile.QUALITY_HIGH
1049
+ )
1050
+ ) {
1051
+ profile =
1052
+ CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_HIGH);
1053
+ } else {
1054
+ if (
1055
+ CamcorderProfile.hasProfile(
1056
+ defaultCameraId,
1057
+ CamcorderProfile.QUALITY_480P
1058
+ )
1059
+ ) {
1060
+ profile =
1061
+ CamcorderProfile.get(
1062
+ defaultCameraId,
1063
+ CamcorderProfile.QUALITY_480P
1064
+ );
1065
+ } else {
1066
+ if (
1067
+ CamcorderProfile.hasProfile(
1068
+ defaultCameraId,
1069
+ CamcorderProfile.QUALITY_720P
1070
+ )
1071
+ ) {
1072
+ profile =
1073
+ CamcorderProfile.get(
1074
+ defaultCameraId,
1075
+ CamcorderProfile.QUALITY_720P
1076
+ );
1077
+ } else {
1078
+ if (
1079
+ CamcorderProfile.hasProfile(
1080
+ defaultCameraId,
1081
+ CamcorderProfile.QUALITY_1080P
1082
+ )
1083
+ ) {
1084
+ profile =
1085
+ CamcorderProfile.get(
1086
+ defaultCameraId,
1087
+ CamcorderProfile.QUALITY_1080P
1088
+ );
1089
+ } else {
1090
+ profile =
1091
+ CamcorderProfile.get(
1092
+ defaultCameraId,
1093
+ CamcorderProfile.QUALITY_LOW
1094
+ );
966
1095
  }
1096
+ }
967
1097
  }
1098
+ }
1099
+
1100
+ mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION);
1101
+ mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
1102
+ mRecorder.setProfile(profile);
1103
+ mRecorder.setOutputFile(filePath);
1104
+ mRecorder.setOrientationHint(mOrientationHint);
1105
+ mRecorder.setMaxDuration(maxDuration);
1106
+
1107
+ mRecorder.prepare();
1108
+ Log.d(TAG, "Starting recording");
1109
+ mRecorder.start();
1110
+ eventListener.onStartRecordVideo();
1111
+ } catch (IOException e) {
1112
+ eventListener.onStartRecordVideoError(e.getMessage());
1113
+ }
1114
+ }
1115
+
1116
+ public int calculateOrientationHint() {
1117
+ DisplayMetrics dm = new DisplayMetrics();
1118
+ Camera.CameraInfo info = new Camera.CameraInfo();
1119
+ Camera.getCameraInfo(defaultCameraId, info);
1120
+ int cameraRotationOffset = info.orientation;
1121
+ Activity activity = getActivity();
1122
+
1123
+ activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
1124
+ int currentScreenRotation = activity
1125
+ .getWindowManager()
1126
+ .getDefaultDisplay()
1127
+ .getRotation();
1128
+
1129
+ int degrees = 0;
1130
+ switch (currentScreenRotation) {
1131
+ case Surface.ROTATION_0:
1132
+ degrees = 0;
1133
+ break;
1134
+ case Surface.ROTATION_90:
1135
+ degrees = 90;
1136
+ break;
1137
+ case Surface.ROTATION_180:
1138
+ degrees = 180;
1139
+ break;
1140
+ case Surface.ROTATION_270:
1141
+ degrees = 270;
1142
+ break;
968
1143
  }
969
1144
 
970
- private Rect calculateTapArea(float x, float y, float coefficient) {
971
- if (x < 100) {
972
- x = 100;
973
- }
974
- if (x > width - 100) {
975
- x = width - 100;
976
- }
977
- if (y < 100) {
978
- y = 100;
979
- }
980
- if (y > height - 100) {
981
- y = height - 100;
982
- }
983
- return new Rect(
984
- Math.round((x - 100) * 2000 / width - 1000),
985
- Math.round((y - 100) * 2000 / height - 1000),
986
- Math.round((x + 100) * 2000 / width - 1000),
987
- Math.round((y + 100) * 2000 / height - 1000)
1145
+ int orientation;
1146
+ if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
1147
+ orientation = (cameraRotationOffset + degrees) % 360;
1148
+ if (degrees != 0) {
1149
+ orientation = (360 - orientation) % 360;
1150
+ }
1151
+ } else {
1152
+ orientation = (cameraRotationOffset - degrees + 360) % 360;
1153
+ }
1154
+ Log.w(TAG, "************orientationHint ***********= " + orientation);
1155
+
1156
+ return orientation;
1157
+ }
1158
+
1159
+ public void stopRecord() {
1160
+ Log.d(TAG, "stopRecord");
1161
+
1162
+ try {
1163
+ mRecorder.stop();
1164
+ mRecorder.reset(); // clear recorder configuration
1165
+ mRecorder.release(); // release the recorder object
1166
+ mRecorder = null;
1167
+ mCamera.lock();
1168
+ Camera.Parameters cameraParams = mCamera.getParameters();
1169
+ cameraParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
1170
+ mCamera.setParameters(cameraParams);
1171
+ mCamera.startPreview();
1172
+ eventListener.onStopRecordVideo(this.recordFilePath);
1173
+ } catch (Exception e) {
1174
+ eventListener.onStopRecordVideoError(e.getMessage());
1175
+ }
1176
+ }
1177
+
1178
+ public void muteStream(boolean mute, Activity activity) {
1179
+ AudioManager audioManager =
1180
+ (
1181
+ (AudioManager) activity
1182
+ .getApplicationContext()
1183
+ .getSystemService(Context.AUDIO_SERVICE)
1184
+ );
1185
+ int direction = mute
1186
+ ? audioManager.ADJUST_MUTE
1187
+ : audioManager.ADJUST_UNMUTE;
1188
+ }
1189
+
1190
+ public void setFocusArea(
1191
+ final int pointX,
1192
+ final int pointY,
1193
+ final Camera.AutoFocusCallback callback
1194
+ ) {
1195
+ if (mCamera != null) {
1196
+ mCamera.cancelAutoFocus();
1197
+
1198
+ Camera.Parameters parameters = mCamera.getParameters();
1199
+
1200
+ Rect focusRect = calculateTapArea(pointX, pointY, 1f);
1201
+ parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
1202
+ parameters.setFocusAreas(Arrays.asList(new Camera.Area(focusRect, 1000)));
1203
+
1204
+ if (parameters.getMaxNumMeteringAreas() > 0) {
1205
+ Rect meteringRect = calculateTapArea(pointX, pointY, 1.5f);
1206
+ parameters.setMeteringAreas(
1207
+ Arrays.asList(new Camera.Area(meteringRect, 1000))
988
1208
  );
1209
+ }
1210
+
1211
+ try {
1212
+ setCameraParameters(parameters);
1213
+ mCamera.autoFocus(callback);
1214
+ } catch (Exception e) {
1215
+ Log.d(TAG, e.getMessage());
1216
+ callback.onAutoFocus(false, this.mCamera);
1217
+ }
989
1218
  }
1219
+ }
990
1220
 
991
- /**
992
- * Determine the space between the first two fingers
993
- */
994
- private static float getFingerSpacing(MotionEvent event) {
995
- // ...
996
- float x = event.getX(0) - event.getX(1);
997
- float y = event.getY(0) - event.getY(1);
998
- return (float) Math.sqrt(x * x + y * y);
1221
+ private Rect calculateTapArea(float x, float y, float coefficient) {
1222
+ if (x < 100) {
1223
+ x = 100;
1224
+ }
1225
+ if (x > width - 100) {
1226
+ x = width - 100;
1227
+ }
1228
+ if (y < 100) {
1229
+ y = 100;
1230
+ }
1231
+ if (y > height - 100) {
1232
+ y = height - 100;
999
1233
  }
1234
+ return new Rect(
1235
+ Math.round((x - 100) * 2000 / width - 1000),
1236
+ Math.round((y - 100) * 2000 / height - 1000),
1237
+ Math.round((x + 100) * 2000 / width - 1000),
1238
+ Math.round((y + 100) * 2000 / height - 1000)
1239
+ );
1240
+ }
1241
+
1242
+ /**
1243
+ * Determine the space between the first two fingers
1244
+ */
1245
+ private static float getFingerSpacing(MotionEvent event) {
1246
+ // ...
1247
+ float x = event.getX(0) - event.getX(1);
1248
+ float y = event.getY(0) - event.getY(1);
1249
+ return (float) Math.sqrt(x * x + y * y);
1250
+ }
1000
1251
  }