capacitor-community-multilens-camerapreview 0.0.7 → 0.0.8

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 (37) hide show
  1. package/CapacitorCommunityMultilensCamerapreview.podspec +17 -17
  2. package/README.md +16 -16
  3. package/android/build.gradle +55 -55
  4. package/android/src/main/AndroidManifest.xml +4 -4
  5. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraActivity.java +1008 -1008
  6. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java +544 -544
  7. package/android/src/main/java/com/ahm/capacitor/camera/preview/CustomSurfaceView.java +23 -23
  8. package/android/src/main/java/com/ahm/capacitor/camera/preview/CustomTextureView.java +29 -29
  9. package/android/src/main/java/com/ahm/capacitor/camera/preview/Preview.java +386 -386
  10. package/android/src/main/java/com/ahm/capacitor/camera/preview/TapGestureDetector.java +24 -24
  11. package/android/src/main/res/layout/bridge_layout_main.xml +15 -15
  12. package/android/src/main/res/layout/camera_activity.xml +68 -68
  13. package/android/src/main/res/values/camera_ids.xml +4 -4
  14. package/android/src/main/res/values/camera_theme.xml +9 -9
  15. package/android/src/main/res/values/colors.xml +3 -3
  16. package/android/src/main/res/values/strings.xml +3 -3
  17. package/android/src/main/res/values/styles.xml +3 -3
  18. package/dist/docs.json +1 -1
  19. package/dist/esm/definitions.d.ts +80 -80
  20. package/dist/esm/definitions.js +1 -1
  21. package/dist/esm/definitions.js.map +1 -1
  22. package/dist/esm/index.d.ts +4 -4
  23. package/dist/esm/index.js +6 -6
  24. package/dist/esm/index.js.map +1 -1
  25. package/dist/esm/web.d.ts +28 -28
  26. package/dist/esm/web.js +155 -155
  27. package/dist/esm/web.js.map +1 -1
  28. package/dist/plugin.cjs.js +149 -149
  29. package/dist/plugin.cjs.js.map +1 -1
  30. package/dist/plugin.js +149 -149
  31. package/dist/plugin.js.map +1 -1
  32. package/ios/Plugin/CameraController.swift +720 -716
  33. package/ios/Plugin/Info.plist +24 -24
  34. package/ios/Plugin/Plugin.h +10 -10
  35. package/ios/Plugin/Plugin.m +18 -18
  36. package/ios/Plugin/Plugin.swift +308 -300
  37. package/package.json +78 -78
@@ -1,544 +1,544 @@
1
- package com.ahm.capacitor.camera.preview;
2
-
3
- import static android.Manifest.permission.CAMERA;
4
-
5
- import android.app.FragmentManager;
6
- import android.app.FragmentTransaction;
7
- import android.content.pm.ActivityInfo;
8
- import android.graphics.Color;
9
- import android.graphics.Point;
10
- import android.hardware.Camera;
11
- import android.content.Context;
12
- import android.hardware.camera2.*;
13
- import android.hardware.camera2.params.OutputConfiguration;
14
- import android.util.DisplayMetrics;
15
- import android.util.TypedValue;
16
- import android.view.Display;
17
- import android.view.MotionEvent;
18
- import android.view.View;
19
- import android.view.ViewGroup;
20
- import android.widget.FrameLayout;
21
- import com.getcapacitor.JSObject;
22
- import com.getcapacitor.Logger;
23
- import com.getcapacitor.PermissionState;
24
- import com.getcapacitor.Plugin;
25
- import com.getcapacitor.PluginCall;
26
- import com.getcapacitor.PluginMethod;
27
- import com.getcapacitor.annotation.CapacitorPlugin;
28
- import com.getcapacitor.annotation.Permission;
29
- import com.getcapacitor.annotation.PermissionCallback;
30
- import java.io.File;
31
- import java.util.List;
32
- import java.util.Set;
33
- import org.json.JSONArray;
34
-
35
- @CapacitorPlugin(name = "CameraPreview", permissions = { @Permission(strings = { CAMERA }, alias = CameraPreview.CAMERA_PERMISSION_ALIAS) })
36
- public class CameraPreview extends Plugin implements CameraActivity.CameraPreviewListener {
37
-
38
- static final String CAMERA_PERMISSION_ALIAS = "camera";
39
-
40
- private static String VIDEO_FILE_PATH = "";
41
- private static String VIDEO_FILE_EXTENSION = ".mp4";
42
-
43
- private String captureCallbackId = "";
44
- private String snapshotCallbackId = "";
45
- private String recordCallbackId = "";
46
- private String cameraStartCallbackId = "";
47
-
48
- // keep track of previously specified orientation to support locking orientation:
49
- private int previousOrientationRequest = -1;
50
-
51
- private static CameraActivity fragment;
52
- private int containerViewId = 20;
53
- private int zoomLevel = 0;
54
-
55
- @PluginMethod
56
- public void echo(PluginCall call) {
57
- String value = call.getString("value");
58
-
59
- JSObject ret = new JSObject();
60
- ret.put("value", value);
61
- call.resolve(ret);
62
- }
63
-
64
- @PluginMethod
65
- public void start(PluginCall call) {
66
- if (PermissionState.GRANTED.equals(getPermissionState(CAMERA_PERMISSION_ALIAS))) {
67
- startCamera(call);
68
- } else {
69
- requestPermissionForAlias(CAMERA_PERMISSION_ALIAS, call, "handleCameraPermissionResult");
70
- }
71
- }
72
-
73
- @PluginMethod
74
- public void flip(PluginCall call) {
75
- try {
76
- fragment.switchCamera();
77
- call.resolve();
78
- } catch (Exception e) {
79
- Logger.debug(getLogTag(), "Camera flip exception: " + e);
80
- call.reject("failed to flip camera");
81
- }
82
- }
83
-
84
- @PluginMethod
85
- public void setOpacity(PluginCall call) {
86
- if (this.hasCamera(call) == false) {
87
- call.error("Camera is not running");
88
- return;
89
- }
90
-
91
- bridge.saveCall(call);
92
- Float opacity = call.getFloat("opacity", 1F);
93
- fragment.setOpacity(opacity);
94
- }
95
-
96
- @PluginMethod
97
- public void capture(PluginCall call) {
98
- if (this.hasCamera(call) == false) {
99
- call.reject("Camera is not running");
100
- return;
101
- }
102
- bridge.saveCall(call);
103
- captureCallbackId = call.getCallbackId();
104
-
105
- Integer quality = call.getInt("quality", 85);
106
- // Image Dimensions - Optional
107
- Integer width = call.getInt("width", 0);
108
- Integer height = call.getInt("height", 0);
109
- fragment.takePicture(width, height, quality);
110
- }
111
-
112
- @PluginMethod
113
- public void captureSample(PluginCall call) {
114
- if (this.hasCamera(call) == false) {
115
- call.reject("Camera is not running");
116
- return;
117
- }
118
- bridge.saveCall(call);
119
- snapshotCallbackId = call.getCallbackId();
120
-
121
- Integer quality = call.getInt("quality", 85);
122
- fragment.takeSnapshot(quality);
123
- }
124
-
125
- @PluginMethod
126
- public void stop(final PluginCall call) {
127
- bridge
128
- .getActivity()
129
- .runOnUiThread(
130
- new Runnable() {
131
- @Override
132
- public void run() {
133
- FrameLayout containerView = getBridge().getActivity().findViewById(containerViewId);
134
-
135
- // allow orientation changes after closing camera:
136
- getBridge().getActivity().setRequestedOrientation(previousOrientationRequest);
137
-
138
- if (containerView != null) {
139
- ((ViewGroup) getBridge().getWebView().getParent()).removeView(containerView);
140
- getBridge().getWebView().setBackgroundColor(Color.WHITE);
141
- FragmentManager fragmentManager = getActivity().getFragmentManager();
142
- FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
143
- fragmentTransaction.remove(fragment);
144
- fragmentTransaction.commit();
145
- fragment = null;
146
-
147
- call.resolve();
148
- } else {
149
- call.reject("camera already stopped");
150
- }
151
- }
152
- }
153
- );
154
- }
155
-
156
- @PluginMethod
157
- public void getSupportedFlashModes(PluginCall call) {
158
- if (this.hasCamera(call) == false) {
159
- call.reject("Camera is not running");
160
- return;
161
- }
162
-
163
- Camera camera = fragment.getCamera();
164
- Camera.Parameters params = camera.getParameters();
165
- List<String> supportedFlashModes;
166
- supportedFlashModes = params.getSupportedFlashModes();
167
- JSONArray jsonFlashModes = new JSONArray();
168
-
169
- if (supportedFlashModes != null) {
170
- for (int i = 0; i < supportedFlashModes.size(); i++) {
171
- jsonFlashModes.put(new String(supportedFlashModes.get(i)));
172
- }
173
- }
174
-
175
- JSObject jsObject = new JSObject();
176
- jsObject.put("result", jsonFlashModes);
177
- call.resolve(jsObject);
178
- }
179
- @PluginMethod
180
- public void getSupportedZoomLevels(PluginCall call) {
181
-
182
- try {
183
- JSONArray jsonZoomLevels = new JSONArray();
184
- Context context = getContext();
185
- CameraManager cameraManager = (CameraManager)context.getSystemService(Context.CAMERA_SERVICE);
186
- String[] cameraIdList = cameraManager.getCameraIdList(); // may be empty
187
- // iterate over available camera devices
188
- for (String cameraId : cameraIdList) {
189
- CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
190
- Set<String> physicalIds = characteristics.getPhysicalCameraIds();
191
- System.out.println(physicalIds);
192
- for(String id : physicalIds){
193
- jsonZoomLevels.put(id);
194
- }
195
- }
196
- JSObject jsObject = new JSObject();
197
- jsObject.put("result", jsonZoomLevels);
198
- call.resolve(jsObject);
199
- } catch (CameraAccessException e) {
200
- call.reject("Can't get Camera Id's");
201
- }
202
- }
203
- @PluginMethod
204
- public void setZoom(PluginCall call) {
205
- int zoomFactor = call.getInt("zoomFactor", 0);
206
- //this does nothing in android
207
- call.resolve();
208
- }
209
-
210
- @PluginMethod
211
- public void setFlashMode(PluginCall call) {
212
- if (this.hasCamera(call) == false) {
213
- call.reject("Camera is not running");
214
- return;
215
- }
216
-
217
- String flashMode = call.getString("flashMode");
218
- if (flashMode == null || flashMode.isEmpty() == true) {
219
- call.reject("flashMode required parameter is missing");
220
- return;
221
- }
222
-
223
- Camera camera = fragment.getCamera();
224
- Camera.Parameters params = camera.getParameters();
225
-
226
- List<String> supportedFlashModes;
227
- supportedFlashModes = camera.getParameters().getSupportedFlashModes();
228
- if (supportedFlashModes.indexOf(flashMode) > -1) {
229
- params.setFlashMode(flashMode);
230
- } else {
231
- call.reject("Flash mode not recognised: " + flashMode);
232
- return;
233
- }
234
-
235
- fragment.setCameraParameters(params);
236
-
237
- call.resolve();
238
- }
239
-
240
- @PluginMethod
241
- public void startRecordVideo(final PluginCall call) {
242
- if (this.hasCamera(call) == false) {
243
- call.reject("Camera is not running");
244
- return;
245
- }
246
- final String filename = "videoTmp";
247
- VIDEO_FILE_PATH = getActivity().getCacheDir().toString() + "/";
248
-
249
- final String position = call.getString("position", "front");
250
- final Integer width = call.getInt("width", 0);
251
- final Integer height = call.getInt("height", 0);
252
- final Boolean withFlash = call.getBoolean("withFlash", false);
253
- final Integer maxDuration = call.getInt("maxDuration", 0);
254
- final String lens = call.getString("zoomFactor", "0");
255
- // final Integer quality = call.getInt("quality", 0);
256
- bridge.saveCall(call);
257
- recordCallbackId = call.getCallbackId();
258
-
259
- bridge
260
- .getActivity()
261
- .runOnUiThread(
262
- new Runnable() {
263
- @Override
264
- public void run() {
265
- // fragment.startRecord(getFilePath(filename), position, width, height, quality, withFlash);
266
- fragment.startRecord(getFilePath(filename), position, width, height, 70, withFlash, maxDuration, lens);
267
- }
268
- }
269
- );
270
-
271
- call.resolve();
272
- }
273
-
274
- @PluginMethod
275
- public void stopRecordVideo(PluginCall call) {
276
- if (this.hasCamera(call) == false) {
277
- call.reject("Camera is not running");
278
- return;
279
- }
280
-
281
- System.out.println("stopRecordVideo - Callbackid=" + call.getCallbackId());
282
-
283
- bridge.saveCall(call);
284
- recordCallbackId = call.getCallbackId();
285
-
286
- // bridge.getActivity().runOnUiThread(new Runnable() {
287
- // @Override
288
- // public void run() {
289
- // fragment.stopRecord();
290
- // }
291
- // });
292
-
293
- fragment.stopRecord();
294
- // call.resolve();
295
- }
296
-
297
- @PermissionCallback
298
- private void handleCameraPermissionResult(PluginCall call) {
299
- if (PermissionState.GRANTED.equals(getPermissionState(CAMERA_PERMISSION_ALIAS))) {
300
- startCamera(call);
301
- } else {
302
- Logger.debug(getLogTag(), "User denied camera permission: " + getPermissionState(CAMERA_PERMISSION_ALIAS).toString());
303
- call.reject("Permission failed: user denied access to camera.");
304
- }
305
- }
306
-
307
-
308
- private void startCamera(final PluginCall call) {
309
- String position = call.getString("position");
310
- //int zoomFactor = call.getInt("zoomFactor", 0);
311
-
312
- if (position == null || position.isEmpty() || "rear".equals(position)) {
313
- position = "back";
314
- } else {
315
- position = "front";
316
- }
317
-
318
- final Integer x = call.getInt("x", 0);
319
- final Integer y = call.getInt("y", 0);
320
- final Integer width = call.getInt("width", 0);
321
- final Integer height = call.getInt("height", 0);
322
- final Integer paddingBottom = call.getInt("paddingBottom", 0);
323
- final Boolean toBack = call.getBoolean("toBack", false);
324
- final Boolean storeToFile = call.getBoolean("storeToFile", false);
325
- final Boolean enableOpacity = call.getBoolean("enableOpacity", false);
326
- final Boolean enableZoom = call.getBoolean("enableZoom", false);
327
- final Boolean disableExifHeaderStripping = call.getBoolean("disableExifHeaderStripping", true);
328
- final Boolean lockOrientation = call.getBoolean("lockAndroidOrientation", false);
329
- previousOrientationRequest = getBridge().getActivity().getRequestedOrientation();
330
-
331
- fragment = new CameraActivity();
332
- fragment.setEventListener(this);
333
- fragment.defaultCamera = position;
334
- fragment.tapToTakePicture = false;
335
- fragment.dragEnabled = false;
336
- fragment.tapToFocus = true;
337
- fragment.disableExifHeaderStripping = disableExifHeaderStripping;
338
- fragment.storeToFile = storeToFile;
339
- fragment.toBack = toBack;
340
- fragment.enableOpacity = enableOpacity;
341
- fragment.enableZoom = enableZoom;
342
- bridge
343
- .getActivity()
344
- .runOnUiThread(
345
- new Runnable() {
346
- @Override
347
- public void run() {
348
- DisplayMetrics metrics = getBridge().getActivity().getResources().getDisplayMetrics();
349
- // lock orientation if specified in options:
350
- if (lockOrientation) {
351
- getBridge().getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
352
- }
353
-
354
- // offset
355
- int computedX = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, x, metrics);
356
- int computedY = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, y, metrics);
357
-
358
- // size
359
- int computedWidth;
360
- int computedHeight;
361
- int computedPaddingBottom;
362
-
363
- if (paddingBottom != 0) {
364
- computedPaddingBottom = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, paddingBottom, metrics);
365
- } else {
366
- computedPaddingBottom = 0;
367
- }
368
-
369
- if (width != 0) {
370
- computedWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, metrics);
371
- } else {
372
- Display defaultDisplay = getBridge().getActivity().getWindowManager().getDefaultDisplay();
373
- final Point size = new Point();
374
- defaultDisplay.getSize(size);
375
-
376
- computedWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, size.x, metrics);
377
- }
378
-
379
- if (height != 0) {
380
- computedHeight =
381
- (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, metrics) - computedPaddingBottom;
382
- } else {
383
- Display defaultDisplay = getBridge().getActivity().getWindowManager().getDefaultDisplay();
384
- final Point size = new Point();
385
- defaultDisplay.getSize(size);
386
-
387
- computedHeight =
388
- (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, size.y, metrics) - computedPaddingBottom;
389
- }
390
-
391
- fragment.setRect(computedX, computedY, computedWidth, computedHeight);
392
-
393
- FrameLayout containerView = getBridge().getActivity().findViewById(containerViewId);
394
- if (containerView == null) {
395
- containerView = new FrameLayout(getActivity().getApplicationContext());
396
- containerView.setId(containerViewId);
397
-
398
- getBridge().getWebView().setBackgroundColor(Color.TRANSPARENT);
399
- ((ViewGroup) getBridge().getWebView().getParent()).addView(containerView);
400
- if (toBack == true) {
401
- getBridge().getWebView().getParent().bringChildToFront(getBridge().getWebView());
402
- setupBroadcast();
403
- }
404
-
405
- FragmentManager fragmentManager = getBridge().getActivity().getFragmentManager();
406
- FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
407
- fragmentTransaction.add(containerView.getId(), fragment);
408
- fragmentTransaction.commit();
409
-
410
- // NOTE: we don't return invoke call.resolve here because it must be invoked in onCameraStarted
411
- // otherwise the plugin start method might resolve/return before the camera is actually set in CameraActivity
412
- // onResume method (see this line mCamera = Camera.open(defaultCameraId);) and the next subsequent plugin
413
- // method invocations (for example, getSupportedFlashModes) might fails with "Camera is not running" error
414
- // because camera is not available yet and hasCamera method will return false
415
- // Please also see https://developer.android.com/reference/android/hardware/Camera.html#open%28int%29
416
- bridge.saveCall(call);
417
- cameraStartCallbackId = call.getCallbackId();
418
- } else {
419
- call.reject("camera already started");
420
- }
421
- }
422
- }
423
- );
424
- }
425
-
426
- @Override
427
- protected void handleOnResume() {
428
- super.handleOnResume();
429
- }
430
-
431
- @Override
432
- public void onPictureTaken(String originalPicture) {
433
- JSObject jsObject = new JSObject();
434
- jsObject.put("value", originalPicture);
435
- bridge.getSavedCall(captureCallbackId).resolve(jsObject);
436
- }
437
-
438
- @Override
439
- public void onPictureTakenError(String message) {
440
- bridge.getSavedCall(captureCallbackId).reject(message);
441
- }
442
-
443
- @Override
444
- public void onSnapshotTaken(String originalPicture) {
445
- JSObject jsObject = new JSObject();
446
- jsObject.put("value", originalPicture);
447
- bridge.getSavedCall(snapshotCallbackId).resolve(jsObject);
448
- }
449
-
450
- @Override
451
- public void onSnapshotTakenError(String message) {
452
- bridge.getSavedCall(snapshotCallbackId).reject(message);
453
- }
454
-
455
- @Override
456
- public void onFocusSet(int pointX, int pointY) {}
457
-
458
- @Override
459
- public void onFocusSetError(String message) {}
460
-
461
- @Override
462
- public void onBackButton() {}
463
-
464
- @Override
465
- public void onCameraStarted() {
466
- PluginCall pluginCall = bridge.getSavedCall(cameraStartCallbackId);
467
- pluginCall.resolve();
468
- bridge.releaseCall(pluginCall);
469
- }
470
-
471
- @Override
472
- public void onStartRecordVideo() {}
473
-
474
- @Override
475
- public void onStartRecordVideoError(String message) {
476
- bridge.getSavedCall(recordCallbackId).reject(message);
477
- }
478
-
479
- @Override
480
- public void onStopRecordVideo(String file) {
481
- PluginCall pluginCall = bridge.getSavedCall(recordCallbackId);
482
- JSObject jsObject = new JSObject();
483
- jsObject.put("videoFilePath", file);
484
- pluginCall.resolve(jsObject);
485
- }
486
-
487
- @Override
488
- public void onStopRecordVideoError(String error) {
489
- bridge.getSavedCall(recordCallbackId).reject(error);
490
- }
491
-
492
- private boolean hasView(PluginCall call) {
493
- if (fragment == null) {
494
- return false;
495
- }
496
-
497
- return true;
498
- }
499
-
500
- private boolean hasCamera(PluginCall call) {
501
- if (this.hasView(call) == false) {
502
- return false;
503
- }
504
-
505
- if (fragment.getCamera() == null) {
506
- return false;
507
- }
508
-
509
- return true;
510
- }
511
-
512
- private String getFilePath(String filename) {
513
- String fileName = filename;
514
-
515
- int i = 1;
516
-
517
- while (new File(VIDEO_FILE_PATH + fileName + VIDEO_FILE_EXTENSION).exists()) {
518
- // Add number suffix if file exists
519
- fileName = filename + '_' + i;
520
- i++;
521
- }
522
-
523
- return VIDEO_FILE_PATH + fileName + VIDEO_FILE_EXTENSION;
524
- }
525
-
526
- private void setupBroadcast() {
527
- /** When touch event is triggered, relay it to camera view if needed so it can support pinch zoom */
528
-
529
- getBridge().getWebView().setClickable(true);
530
- getBridge()
531
- .getWebView()
532
- .setOnTouchListener(
533
- new View.OnTouchListener() {
534
- @Override
535
- public boolean onTouch(View v, MotionEvent event) {
536
- if ((null != fragment) && (fragment.toBack == true)) {
537
- fragment.frameContainerLayout.dispatchTouchEvent(event);
538
- }
539
- return false;
540
- }
541
- }
542
- );
543
- }
544
- }
1
+ package com.ahm.capacitor.camera.preview;
2
+
3
+ import static android.Manifest.permission.CAMERA;
4
+
5
+ import android.app.FragmentManager;
6
+ import android.app.FragmentTransaction;
7
+ import android.content.pm.ActivityInfo;
8
+ import android.graphics.Color;
9
+ import android.graphics.Point;
10
+ import android.hardware.Camera;
11
+ import android.content.Context;
12
+ import android.hardware.camera2.*;
13
+ import android.hardware.camera2.params.OutputConfiguration;
14
+ import android.util.DisplayMetrics;
15
+ import android.util.TypedValue;
16
+ import android.view.Display;
17
+ import android.view.MotionEvent;
18
+ import android.view.View;
19
+ import android.view.ViewGroup;
20
+ import android.widget.FrameLayout;
21
+ import com.getcapacitor.JSObject;
22
+ import com.getcapacitor.Logger;
23
+ import com.getcapacitor.PermissionState;
24
+ import com.getcapacitor.Plugin;
25
+ import com.getcapacitor.PluginCall;
26
+ import com.getcapacitor.PluginMethod;
27
+ import com.getcapacitor.annotation.CapacitorPlugin;
28
+ import com.getcapacitor.annotation.Permission;
29
+ import com.getcapacitor.annotation.PermissionCallback;
30
+ import java.io.File;
31
+ import java.util.List;
32
+ import java.util.Set;
33
+ import org.json.JSONArray;
34
+
35
+ @CapacitorPlugin(name = "CameraPreview", permissions = { @Permission(strings = { CAMERA }, alias = CameraPreview.CAMERA_PERMISSION_ALIAS) })
36
+ public class CameraPreview extends Plugin implements CameraActivity.CameraPreviewListener {
37
+
38
+ static final String CAMERA_PERMISSION_ALIAS = "camera";
39
+
40
+ private static String VIDEO_FILE_PATH = "";
41
+ private static String VIDEO_FILE_EXTENSION = ".mp4";
42
+
43
+ private String captureCallbackId = "";
44
+ private String snapshotCallbackId = "";
45
+ private String recordCallbackId = "";
46
+ private String cameraStartCallbackId = "";
47
+
48
+ // keep track of previously specified orientation to support locking orientation:
49
+ private int previousOrientationRequest = -1;
50
+
51
+ private static CameraActivity fragment;
52
+ private int containerViewId = 20;
53
+ private int zoomLevel = 0;
54
+
55
+ @PluginMethod
56
+ public void echo(PluginCall call) {
57
+ String value = call.getString("value");
58
+
59
+ JSObject ret = new JSObject();
60
+ ret.put("value", value);
61
+ call.resolve(ret);
62
+ }
63
+
64
+ @PluginMethod
65
+ public void start(PluginCall call) {
66
+ if (PermissionState.GRANTED.equals(getPermissionState(CAMERA_PERMISSION_ALIAS))) {
67
+ startCamera(call);
68
+ } else {
69
+ requestPermissionForAlias(CAMERA_PERMISSION_ALIAS, call, "handleCameraPermissionResult");
70
+ }
71
+ }
72
+
73
+ @PluginMethod
74
+ public void flip(PluginCall call) {
75
+ try {
76
+ fragment.switchCamera();
77
+ call.resolve();
78
+ } catch (Exception e) {
79
+ Logger.debug(getLogTag(), "Camera flip exception: " + e);
80
+ call.reject("failed to flip camera");
81
+ }
82
+ }
83
+
84
+ @PluginMethod
85
+ public void setOpacity(PluginCall call) {
86
+ if (this.hasCamera(call) == false) {
87
+ call.error("Camera is not running");
88
+ return;
89
+ }
90
+
91
+ bridge.saveCall(call);
92
+ Float opacity = call.getFloat("opacity", 1F);
93
+ fragment.setOpacity(opacity);
94
+ }
95
+
96
+ @PluginMethod
97
+ public void capture(PluginCall call) {
98
+ if (this.hasCamera(call) == false) {
99
+ call.reject("Camera is not running");
100
+ return;
101
+ }
102
+ bridge.saveCall(call);
103
+ captureCallbackId = call.getCallbackId();
104
+
105
+ Integer quality = call.getInt("quality", 85);
106
+ // Image Dimensions - Optional
107
+ Integer width = call.getInt("width", 0);
108
+ Integer height = call.getInt("height", 0);
109
+ fragment.takePicture(width, height, quality);
110
+ }
111
+
112
+ @PluginMethod
113
+ public void captureSample(PluginCall call) {
114
+ if (this.hasCamera(call) == false) {
115
+ call.reject("Camera is not running");
116
+ return;
117
+ }
118
+ bridge.saveCall(call);
119
+ snapshotCallbackId = call.getCallbackId();
120
+
121
+ Integer quality = call.getInt("quality", 85);
122
+ fragment.takeSnapshot(quality);
123
+ }
124
+
125
+ @PluginMethod
126
+ public void stop(final PluginCall call) {
127
+ bridge
128
+ .getActivity()
129
+ .runOnUiThread(
130
+ new Runnable() {
131
+ @Override
132
+ public void run() {
133
+ FrameLayout containerView = getBridge().getActivity().findViewById(containerViewId);
134
+
135
+ // allow orientation changes after closing camera:
136
+ getBridge().getActivity().setRequestedOrientation(previousOrientationRequest);
137
+
138
+ if (containerView != null) {
139
+ ((ViewGroup) getBridge().getWebView().getParent()).removeView(containerView);
140
+ getBridge().getWebView().setBackgroundColor(Color.WHITE);
141
+ FragmentManager fragmentManager = getActivity().getFragmentManager();
142
+ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
143
+ fragmentTransaction.remove(fragment);
144
+ fragmentTransaction.commit();
145
+ fragment = null;
146
+
147
+ call.resolve();
148
+ } else {
149
+ call.reject("camera already stopped");
150
+ }
151
+ }
152
+ }
153
+ );
154
+ }
155
+
156
+ @PluginMethod
157
+ public void getSupportedFlashModes(PluginCall call) {
158
+ if (this.hasCamera(call) == false) {
159
+ call.reject("Camera is not running");
160
+ return;
161
+ }
162
+
163
+ Camera camera = fragment.getCamera();
164
+ Camera.Parameters params = camera.getParameters();
165
+ List<String> supportedFlashModes;
166
+ supportedFlashModes = params.getSupportedFlashModes();
167
+ JSONArray jsonFlashModes = new JSONArray();
168
+
169
+ if (supportedFlashModes != null) {
170
+ for (int i = 0; i < supportedFlashModes.size(); i++) {
171
+ jsonFlashModes.put(new String(supportedFlashModes.get(i)));
172
+ }
173
+ }
174
+
175
+ JSObject jsObject = new JSObject();
176
+ jsObject.put("result", jsonFlashModes);
177
+ call.resolve(jsObject);
178
+ }
179
+ @PluginMethod
180
+ public void getSupportedZoomLevels(PluginCall call) {
181
+
182
+ try {
183
+ JSONArray jsonZoomLevels = new JSONArray();
184
+ Context context = getContext();
185
+ CameraManager cameraManager = (CameraManager)context.getSystemService(Context.CAMERA_SERVICE);
186
+ String[] cameraIdList = cameraManager.getCameraIdList(); // may be empty
187
+ // iterate over available camera devices
188
+ for (String cameraId : cameraIdList) {
189
+ CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
190
+ Set<String> physicalIds = characteristics.getPhysicalCameraIds();
191
+ System.out.println(physicalIds);
192
+ for(String id : physicalIds){
193
+ jsonZoomLevels.put(id);
194
+ }
195
+ }
196
+ JSObject jsObject = new JSObject();
197
+ jsObject.put("result", jsonZoomLevels);
198
+ call.resolve(jsObject);
199
+ } catch (CameraAccessException e) {
200
+ call.reject("Can't get Camera Id's");
201
+ }
202
+ }
203
+ @PluginMethod
204
+ public void setZoom(PluginCall call) {
205
+ int zoomFactor = call.getInt("zoomFactor", 0);
206
+ //this does nothing in android
207
+ call.resolve();
208
+ }
209
+
210
+ @PluginMethod
211
+ public void setFlashMode(PluginCall call) {
212
+ if (this.hasCamera(call) == false) {
213
+ call.reject("Camera is not running");
214
+ return;
215
+ }
216
+
217
+ String flashMode = call.getString("flashMode");
218
+ if (flashMode == null || flashMode.isEmpty() == true) {
219
+ call.reject("flashMode required parameter is missing");
220
+ return;
221
+ }
222
+
223
+ Camera camera = fragment.getCamera();
224
+ Camera.Parameters params = camera.getParameters();
225
+
226
+ List<String> supportedFlashModes;
227
+ supportedFlashModes = camera.getParameters().getSupportedFlashModes();
228
+ if (supportedFlashModes.indexOf(flashMode) > -1) {
229
+ params.setFlashMode(flashMode);
230
+ } else {
231
+ call.reject("Flash mode not recognised: " + flashMode);
232
+ return;
233
+ }
234
+
235
+ fragment.setCameraParameters(params);
236
+
237
+ call.resolve();
238
+ }
239
+
240
+ @PluginMethod
241
+ public void startRecordVideo(final PluginCall call) {
242
+ if (this.hasCamera(call) == false) {
243
+ call.reject("Camera is not running");
244
+ return;
245
+ }
246
+ final String filename = "videoTmp";
247
+ VIDEO_FILE_PATH = getActivity().getCacheDir().toString() + "/";
248
+
249
+ final String position = call.getString("position", "front");
250
+ final Integer width = call.getInt("width", 0);
251
+ final Integer height = call.getInt("height", 0);
252
+ final Boolean withFlash = call.getBoolean("withFlash", false);
253
+ final Integer maxDuration = call.getInt("maxDuration", 0);
254
+ final String lens = call.getString("zoomFactor", "0");
255
+ // final Integer quality = call.getInt("quality", 0);
256
+ bridge.saveCall(call);
257
+ recordCallbackId = call.getCallbackId();
258
+
259
+ bridge
260
+ .getActivity()
261
+ .runOnUiThread(
262
+ new Runnable() {
263
+ @Override
264
+ public void run() {
265
+ // fragment.startRecord(getFilePath(filename), position, width, height, quality, withFlash);
266
+ fragment.startRecord(getFilePath(filename), position, width, height, 70, withFlash, maxDuration, lens);
267
+ }
268
+ }
269
+ );
270
+
271
+ call.resolve();
272
+ }
273
+
274
+ @PluginMethod
275
+ public void stopRecordVideo(PluginCall call) {
276
+ if (this.hasCamera(call) == false) {
277
+ call.reject("Camera is not running");
278
+ return;
279
+ }
280
+
281
+ System.out.println("stopRecordVideo - Callbackid=" + call.getCallbackId());
282
+
283
+ bridge.saveCall(call);
284
+ recordCallbackId = call.getCallbackId();
285
+
286
+ // bridge.getActivity().runOnUiThread(new Runnable() {
287
+ // @Override
288
+ // public void run() {
289
+ // fragment.stopRecord();
290
+ // }
291
+ // });
292
+
293
+ fragment.stopRecord();
294
+ // call.resolve();
295
+ }
296
+
297
+ @PermissionCallback
298
+ private void handleCameraPermissionResult(PluginCall call) {
299
+ if (PermissionState.GRANTED.equals(getPermissionState(CAMERA_PERMISSION_ALIAS))) {
300
+ startCamera(call);
301
+ } else {
302
+ Logger.debug(getLogTag(), "User denied camera permission: " + getPermissionState(CAMERA_PERMISSION_ALIAS).toString());
303
+ call.reject("Permission failed: user denied access to camera.");
304
+ }
305
+ }
306
+
307
+
308
+ private void startCamera(final PluginCall call) {
309
+ String position = call.getString("position");
310
+ //int zoomFactor = call.getInt("zoomFactor", 0);
311
+
312
+ if (position == null || position.isEmpty() || "rear".equals(position)) {
313
+ position = "back";
314
+ } else {
315
+ position = "front";
316
+ }
317
+
318
+ final Integer x = call.getInt("x", 0);
319
+ final Integer y = call.getInt("y", 0);
320
+ final Integer width = call.getInt("width", 0);
321
+ final Integer height = call.getInt("height", 0);
322
+ final Integer paddingBottom = call.getInt("paddingBottom", 0);
323
+ final Boolean toBack = call.getBoolean("toBack", false);
324
+ final Boolean storeToFile = call.getBoolean("storeToFile", false);
325
+ final Boolean enableOpacity = call.getBoolean("enableOpacity", false);
326
+ final Boolean enableZoom = call.getBoolean("enableZoom", false);
327
+ final Boolean disableExifHeaderStripping = call.getBoolean("disableExifHeaderStripping", true);
328
+ final Boolean lockOrientation = call.getBoolean("lockAndroidOrientation", false);
329
+ previousOrientationRequest = getBridge().getActivity().getRequestedOrientation();
330
+
331
+ fragment = new CameraActivity();
332
+ fragment.setEventListener(this);
333
+ fragment.defaultCamera = position;
334
+ fragment.tapToTakePicture = false;
335
+ fragment.dragEnabled = false;
336
+ fragment.tapToFocus = true;
337
+ fragment.disableExifHeaderStripping = disableExifHeaderStripping;
338
+ fragment.storeToFile = storeToFile;
339
+ fragment.toBack = toBack;
340
+ fragment.enableOpacity = enableOpacity;
341
+ fragment.enableZoom = enableZoom;
342
+ bridge
343
+ .getActivity()
344
+ .runOnUiThread(
345
+ new Runnable() {
346
+ @Override
347
+ public void run() {
348
+ DisplayMetrics metrics = getBridge().getActivity().getResources().getDisplayMetrics();
349
+ // lock orientation if specified in options:
350
+ if (lockOrientation) {
351
+ getBridge().getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
352
+ }
353
+
354
+ // offset
355
+ int computedX = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, x, metrics);
356
+ int computedY = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, y, metrics);
357
+
358
+ // size
359
+ int computedWidth;
360
+ int computedHeight;
361
+ int computedPaddingBottom;
362
+
363
+ if (paddingBottom != 0) {
364
+ computedPaddingBottom = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, paddingBottom, metrics);
365
+ } else {
366
+ computedPaddingBottom = 0;
367
+ }
368
+
369
+ if (width != 0) {
370
+ computedWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, metrics);
371
+ } else {
372
+ Display defaultDisplay = getBridge().getActivity().getWindowManager().getDefaultDisplay();
373
+ final Point size = new Point();
374
+ defaultDisplay.getSize(size);
375
+
376
+ computedWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, size.x, metrics);
377
+ }
378
+
379
+ if (height != 0) {
380
+ computedHeight =
381
+ (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, metrics) - computedPaddingBottom;
382
+ } else {
383
+ Display defaultDisplay = getBridge().getActivity().getWindowManager().getDefaultDisplay();
384
+ final Point size = new Point();
385
+ defaultDisplay.getSize(size);
386
+
387
+ computedHeight =
388
+ (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, size.y, metrics) - computedPaddingBottom;
389
+ }
390
+
391
+ fragment.setRect(computedX, computedY, computedWidth, computedHeight);
392
+
393
+ FrameLayout containerView = getBridge().getActivity().findViewById(containerViewId);
394
+ if (containerView == null) {
395
+ containerView = new FrameLayout(getActivity().getApplicationContext());
396
+ containerView.setId(containerViewId);
397
+
398
+ getBridge().getWebView().setBackgroundColor(Color.TRANSPARENT);
399
+ ((ViewGroup) getBridge().getWebView().getParent()).addView(containerView);
400
+ if (toBack == true) {
401
+ getBridge().getWebView().getParent().bringChildToFront(getBridge().getWebView());
402
+ setupBroadcast();
403
+ }
404
+
405
+ FragmentManager fragmentManager = getBridge().getActivity().getFragmentManager();
406
+ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
407
+ fragmentTransaction.add(containerView.getId(), fragment);
408
+ fragmentTransaction.commit();
409
+
410
+ // NOTE: we don't return invoke call.resolve here because it must be invoked in onCameraStarted
411
+ // otherwise the plugin start method might resolve/return before the camera is actually set in CameraActivity
412
+ // onResume method (see this line mCamera = Camera.open(defaultCameraId);) and the next subsequent plugin
413
+ // method invocations (for example, getSupportedFlashModes) might fails with "Camera is not running" error
414
+ // because camera is not available yet and hasCamera method will return false
415
+ // Please also see https://developer.android.com/reference/android/hardware/Camera.html#open%28int%29
416
+ bridge.saveCall(call);
417
+ cameraStartCallbackId = call.getCallbackId();
418
+ } else {
419
+ call.reject("camera already started");
420
+ }
421
+ }
422
+ }
423
+ );
424
+ }
425
+
426
+ @Override
427
+ protected void handleOnResume() {
428
+ super.handleOnResume();
429
+ }
430
+
431
+ @Override
432
+ public void onPictureTaken(String originalPicture) {
433
+ JSObject jsObject = new JSObject();
434
+ jsObject.put("value", originalPicture);
435
+ bridge.getSavedCall(captureCallbackId).resolve(jsObject);
436
+ }
437
+
438
+ @Override
439
+ public void onPictureTakenError(String message) {
440
+ bridge.getSavedCall(captureCallbackId).reject(message);
441
+ }
442
+
443
+ @Override
444
+ public void onSnapshotTaken(String originalPicture) {
445
+ JSObject jsObject = new JSObject();
446
+ jsObject.put("value", originalPicture);
447
+ bridge.getSavedCall(snapshotCallbackId).resolve(jsObject);
448
+ }
449
+
450
+ @Override
451
+ public void onSnapshotTakenError(String message) {
452
+ bridge.getSavedCall(snapshotCallbackId).reject(message);
453
+ }
454
+
455
+ @Override
456
+ public void onFocusSet(int pointX, int pointY) {}
457
+
458
+ @Override
459
+ public void onFocusSetError(String message) {}
460
+
461
+ @Override
462
+ public void onBackButton() {}
463
+
464
+ @Override
465
+ public void onCameraStarted() {
466
+ PluginCall pluginCall = bridge.getSavedCall(cameraStartCallbackId);
467
+ pluginCall.resolve();
468
+ bridge.releaseCall(pluginCall);
469
+ }
470
+
471
+ @Override
472
+ public void onStartRecordVideo() {}
473
+
474
+ @Override
475
+ public void onStartRecordVideoError(String message) {
476
+ bridge.getSavedCall(recordCallbackId).reject(message);
477
+ }
478
+
479
+ @Override
480
+ public void onStopRecordVideo(String file) {
481
+ PluginCall pluginCall = bridge.getSavedCall(recordCallbackId);
482
+ JSObject jsObject = new JSObject();
483
+ jsObject.put("videoFilePath", file);
484
+ pluginCall.resolve(jsObject);
485
+ }
486
+
487
+ @Override
488
+ public void onStopRecordVideoError(String error) {
489
+ bridge.getSavedCall(recordCallbackId).reject(error);
490
+ }
491
+
492
+ private boolean hasView(PluginCall call) {
493
+ if (fragment == null) {
494
+ return false;
495
+ }
496
+
497
+ return true;
498
+ }
499
+
500
+ private boolean hasCamera(PluginCall call) {
501
+ if (this.hasView(call) == false) {
502
+ return false;
503
+ }
504
+
505
+ if (fragment.getCamera() == null) {
506
+ return false;
507
+ }
508
+
509
+ return true;
510
+ }
511
+
512
+ private String getFilePath(String filename) {
513
+ String fileName = filename;
514
+
515
+ int i = 1;
516
+
517
+ while (new File(VIDEO_FILE_PATH + fileName + VIDEO_FILE_EXTENSION).exists()) {
518
+ // Add number suffix if file exists
519
+ fileName = filename + '_' + i;
520
+ i++;
521
+ }
522
+
523
+ return VIDEO_FILE_PATH + fileName + VIDEO_FILE_EXTENSION;
524
+ }
525
+
526
+ private void setupBroadcast() {
527
+ /** When touch event is triggered, relay it to camera view if needed so it can support pinch zoom */
528
+
529
+ getBridge().getWebView().setClickable(true);
530
+ getBridge()
531
+ .getWebView()
532
+ .setOnTouchListener(
533
+ new View.OnTouchListener() {
534
+ @Override
535
+ public boolean onTouch(View v, MotionEvent event) {
536
+ if ((null != fragment) && (fragment.toBack == true)) {
537
+ fragment.frameContainerLayout.dispatchTouchEvent(event);
538
+ }
539
+ return false;
540
+ }
541
+ }
542
+ );
543
+ }
544
+ }