cordova-plugin-mserviceinterface-2.0 1.0.84 → 1.0.86

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cordova-plugin-mserviceinterface-2.0",
3
- "version": "1.0.84",
3
+ "version": "1.0.86",
4
4
  "description": "This plugin establishes the connection to the native interface and performs the requested task.",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/plugin.xml CHANGED
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
3
- xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-mserviceinterface-2.0" version="1.0.84">
3
+ xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-mserviceinterface-2.0" version="1.0.86">
4
4
  <name>mserviceinterface-2.0</name>
5
5
  <description>This plugin establishes the connection to the native interface and performs the requested task.</description>
6
6
  <author>selfservit@gmail.com</author>
@@ -17,6 +17,11 @@
17
17
  </js-module>
18
18
  <platform name="android">
19
19
  <framework src="src/android/doubleogradle.gradle" custom="true" type="gradleReference"/>
20
+ <framework src="androidx.camera:camera-core:1.2.0" />
21
+ <framework src="androidx.camera:camera-camera2:1.2.0" />
22
+ <framework src="androidx.camera:camera-lifecycle:1.2.0" />
23
+ <framework src="androidx.camera:camera-view:1.2.0" />
24
+ <framework src="androidx.constraintlayout:constraintlayout:2.1.4" />
20
25
  <framework src="com.google.android.gms:play-services-location:21.0.1" />
21
26
  <framework src="androidx.exifinterface:exifinterface:1.3.5" />
22
27
  <framework src="com.android.support:support-v4:28.0.0" />
@@ -50,8 +55,14 @@
50
55
  <uses-permission android:name="android.permission.READ_PHONE_STATE" />
51
56
  <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
52
57
  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
58
+ <queries>
59
+ <intent>
60
+ <action android:name="android.media.action.IMAGE_CAPTURE" />
61
+ </intent>
62
+ </queries>
53
63
  </config-file>
54
64
  <config-file target="AndroidManifest.xml" parent="/manifest/application">
65
+ <activity android:name="com.selfservit.util.CameraActivity" android:configChanges="orientation|screenSize" android:screenOrientation="portrait" android:exported="true" android:theme="@style/CameraTheme" />
55
66
  <service android:name="com.selfservit.util.mInterfaceService" android:foregroundServiceType="location" android:enabled="true" android:exported="true"/>
56
67
  <receiver android:name="com.selfservit.util.mInterfaceReceiver" android:enabled="true" android:exported="true">
57
68
  <intent-filter>
@@ -69,7 +80,6 @@
69
80
  </provider>
70
81
  </config-file>
71
82
  <source-file src="src/android/mInterfaceService.java" target-dir="src/com/selfservit/util/" />
72
- <source-file src="src/android/backgroundNotification.java" target-dir="src/com/selfservit/util/" />
73
83
  <source-file src="src/android/mInterfaceReceiver.java" target-dir="src/com/selfservit/util/" />
74
84
  <source-file src="src/android/mInterface.java" target-dir="src/com/selfservit/util/" />
75
85
  <source-file src="src/android/GeofenceBroadcastReceiver.java" target-dir="src/com/selfservit/util/" />
@@ -79,6 +89,13 @@
79
89
  <source-file src="src/android/res/xml/opener_paths.xml" target-dir="res/xml" />
80
90
  <source-file src="src/android/res/xml/network_security_config.xml" target-dir="res/xml" />
81
91
  <source-file src="src/android/res/xml/my_backup_rules.xml" target-dir="res/xml" />
92
+ <resource-file src="src/android/src/main/res/layout/activity_camera.xml" target="app/src/main/res/layout/activity_camera.xml" />
93
+ <resource-file src="src/android/src/main/res/drawable/focus_box.xml" target="app/src/main/res/drawable/focus_box.xml" />
94
+ <resource-file src="src/android/src/main/res/drawable/ic_flip_camera.xml" target="app/src/main/res/drawable/ic_flip_camera.xml" />
95
+ <resource-file src="src/android/src/main/res/drawable/circle_button.xml" target="app/src/main/res/drawable/circle_button.xml" />
96
+ <resource-file src="src/android/src/main/res/drawable/ic_flashlight_on.xml" target="app/src/main/res/drawable/ic_flashlight_on.xml" />
97
+ <resource-file src="src/android/src/main/res/drawable/ic_flashlight_off.xml" target="app/src/main/res/drawable/ic_flashlight_off.xml" />
98
+ <resource-file src="src/android/src/main/res/values/styles.xml" target="app/src/main/res/values/styles.xml" />
82
99
  </platform>
83
100
  <platform name="ios">
84
101
  <config-file target="*-Info.plist" parent="NSCameraUsageDescription">
@@ -0,0 +1,334 @@
1
+ package com.selfservit.util;
2
+
3
+ import android.Manifest;
4
+ import android.annotation.SuppressLint;
5
+ import android.app.Activity;
6
+ import android.content.Intent;
7
+ import android.content.pm.PackageManager;
8
+ import android.os.Bundle;
9
+ import android.util.Log;
10
+ import android.view.MotionEvent;
11
+ import android.view.ScaleGestureDetector;
12
+ import android.view.View;
13
+ import android.view.ViewGroup;
14
+ import android.widget.ImageButton;
15
+ import android.widget.Toast;
16
+
17
+ import androidx.annotation.NonNull;
18
+ import androidx.appcompat.app.AppCompatActivity;
19
+ import androidx.camera.core.Camera;
20
+ import androidx.camera.core.CameraSelector;
21
+ import androidx.camera.core.FocusMeteringAction;
22
+ import androidx.camera.core.ImageCapture;
23
+ import androidx.camera.core.ImageCaptureException;
24
+ import androidx.camera.core.MeteringPoint;
25
+ import androidx.camera.core.Preview;
26
+ import androidx.camera.lifecycle.ProcessCameraProvider;
27
+ import androidx.camera.view.PreviewView;
28
+ import androidx.core.app.ActivityCompat;
29
+ import androidx.core.content.ContextCompat;
30
+
31
+ import com.google.common.util.concurrent.ListenableFuture;
32
+
33
+ import java.io.File;
34
+ import java.text.SimpleDateFormat;
35
+ import java.util.Locale;
36
+ import java.util.Objects;
37
+ import java.util.concurrent.ExecutionException;
38
+ import java.util.concurrent.TimeUnit;
39
+
40
+ public class CameraActivity extends AppCompatActivity {
41
+ private static final int REQUEST_CODE_PERMISSIONS = 10;
42
+ private final String[] REQUIRED_PERMISSIONS = new String[]{ Manifest.permission.CAMERA };
43
+
44
+ private PreviewView previewView;
45
+ private ImageCapture imageCapture;
46
+ private ImageButton torchButton;
47
+ private ProcessCameraProvider cameraProvider;
48
+ private Camera camera;
49
+
50
+ private int lensFacing = CameraSelector.LENS_FACING_BACK;
51
+ private boolean isTorchOn = false;
52
+ private ScaleGestureDetector scaleGestureDetector;
53
+ private View focusView;
54
+ private ScaleGestureDetector scaleDetector;
55
+ @SuppressLint("ClickableViewAccessibility")
56
+ @Override
57
+ protected void onCreate(Bundle savedInstanceState) {
58
+ super.onCreate(savedInstanceState);
59
+
60
+ // Dynamically inflate layout
61
+ String pkg = getPackageName();
62
+ int layoutId = getResources().getIdentifier("activity_camera", "layout", pkg);
63
+ setContentView(layoutId);
64
+
65
+ // Resolve view IDs
66
+ int previewId = getResources().getIdentifier("previewView", "id", pkg);
67
+ int captureId = getResources().getIdentifier("captureButton", "id", pkg);
68
+ int switchId = getResources().getIdentifier("switchCamera", "id", pkg);
69
+ int torchId = getResources().getIdentifier("torchButton", "id", pkg);
70
+ int focusViewId = getResources().getIdentifier("focusView", "id", pkg);
71
+
72
+ // Resolve drawable IDs
73
+ final int torchOnDrawable = getResources().getIdentifier("ic_flashlight_on", "drawable", pkg);
74
+ final int torchOffDrawable = getResources().getIdentifier("ic_flashlight_off", "drawable", pkg);
75
+
76
+ // Bind views to fields
77
+ previewView = findViewById(previewId);
78
+ ImageButton captureButton = findViewById(captureId);
79
+ ImageButton switchButton = findViewById(switchId);
80
+ torchButton = findViewById(torchId);
81
+ focusView = findViewById(focusViewId);
82
+
83
+ // Utility to add press animation to any view
84
+ View.OnTouchListener pressAnim = (v, e) -> {
85
+ switch (e.getAction()) {
86
+ case MotionEvent.ACTION_DOWN:
87
+ v.animate()
88
+ .scaleX(0.9f)
89
+ .scaleY(0.9f)
90
+ .setDuration(100)
91
+ .start();
92
+ break;
93
+ case MotionEvent.ACTION_UP:
94
+ case MotionEvent.ACTION_CANCEL:
95
+ v.animate()
96
+ .scaleX(1f)
97
+ .scaleY(1f)
98
+ .setDuration(100)
99
+ .start();
100
+ break;
101
+ }
102
+ // return false so the click event still fires
103
+ return false;
104
+ };
105
+
106
+ // Apply it to your buttons
107
+ captureButton.setOnTouchListener(pressAnim);
108
+ switchButton .setOnTouchListener(pressAnim);
109
+ torchButton .setOnTouchListener(pressAnim);
110
+ // Pinch-to-zoom & tap-to-focus
111
+ scaleGestureDetector = new ScaleGestureDetector(this,
112
+ new ScaleGestureDetector.SimpleOnScaleGestureListener() {
113
+ @Override
114
+ public boolean onScale(@NonNull ScaleGestureDetector detector) {
115
+ if (camera != null) {
116
+ float current = Objects.requireNonNull(camera.getCameraInfo()
117
+ .getZoomState().getValue()).getZoomRatio();
118
+ camera.getCameraControl()
119
+ .setZoomRatio(current * detector.getScaleFactor());
120
+ }
121
+ return true;
122
+ }
123
+ });
124
+ previewView.setOnTouchListener((v, e) -> {
125
+ scaleGestureDetector.onTouchEvent(e);
126
+ if (e.getAction() == MotionEvent.ACTION_UP && camera != null) {
127
+ MeteringPoint point = previewView.getMeteringPointFactory()
128
+ .createPoint(e.getX(), e.getY());
129
+ camera.getCameraControl()
130
+ .startFocusAndMetering(new FocusMeteringAction.Builder(point).build());
131
+ }
132
+ return true;
133
+ });
134
+ scaleDetector = new ScaleGestureDetector(this,
135
+ new ScaleGestureDetector.SimpleOnScaleGestureListener() {
136
+ @Override
137
+ public boolean onScale(ScaleGestureDetector detector) {
138
+ if (camera != null) {
139
+ float current = camera.getCameraInfo()
140
+ .getZoomState().getValue().getZoomRatio();
141
+ camera.getCameraControl().setZoomRatio(current * detector.getScaleFactor());
142
+ }
143
+ return true;
144
+ }
145
+ });
146
+ // Touch listener: zoom + focus box + CameraX focus
147
+ previewView.setOnTouchListener((v, e) -> {
148
+ scaleDetector.onTouchEvent(e);
149
+ if (e.getAction() == MotionEvent.ACTION_UP && camera != null) {
150
+ float x = e.getX(), y = e.getY();
151
+
152
+ // 1) Show & animate focus box
153
+ focusView.setX(x - (float) focusView.getWidth() /2);
154
+ focusView.setY(y - (float) focusView.getHeight() /2);
155
+ focusView.setAlpha(1f);
156
+ focusView.setVisibility(View.VISIBLE);
157
+ focusView.animate()
158
+ .alpha(0f)
159
+ .setDuration(800)
160
+ .withEndAction(() -> focusView.setVisibility(View.GONE));
161
+
162
+ // 2) Tell CameraX to focus there
163
+ MeteringPoint point = previewView.getMeteringPointFactory()
164
+ .createPoint(x, y);
165
+ FocusMeteringAction action = new FocusMeteringAction.Builder(point)
166
+ .setAutoCancelDuration(3, TimeUnit.SECONDS)
167
+ .build();
168
+ camera.getCameraControl().startFocusAndMetering(action);
169
+ }
170
+ return true;
171
+ });
172
+
173
+ // Permissions and start
174
+ if (allPermissionsGranted()) {
175
+ startCamera();
176
+ } else {
177
+ ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS);
178
+ }
179
+
180
+ // Capture
181
+ captureButton.setOnClickListener(v -> takePhoto());
182
+
183
+ // Switch front/back
184
+ switchButton.setOnClickListener(v -> {
185
+ lensFacing = (lensFacing == CameraSelector.LENS_FACING_BACK)
186
+ ? CameraSelector.LENS_FACING_FRONT
187
+ : CameraSelector.LENS_FACING_BACK;
188
+ bindUseCases();
189
+ });
190
+
191
+ // Torch toggle
192
+ torchButton.setOnClickListener(v -> {
193
+ if (camera != null) {
194
+ isTorchOn = !isTorchOn;
195
+ camera.getCameraControl().enableTorch(isTorchOn);
196
+ torchButton.setImageResource(isTorchOn ? torchOnDrawable : torchOffDrawable);
197
+ }
198
+ });
199
+ }
200
+
201
+ private void startCamera() {
202
+ ListenableFuture<ProcessCameraProvider> future =
203
+ ProcessCameraProvider.getInstance(this);
204
+ future.addListener(() -> {
205
+ try {
206
+ cameraProvider = future.get();
207
+ bindUseCases();
208
+ } catch (ExecutionException | InterruptedException e) {
209
+ Log.e("CameraActivity", "CameraProvider init failed", e);
210
+ }
211
+ }, ContextCompat.getMainExecutor(this));
212
+ }
213
+
214
+ private void bindUseCases() {
215
+ if (cameraProvider == null || previewView == null) return;
216
+
217
+ // Unbind old before rebinding
218
+ cameraProvider.unbindAll();
219
+
220
+ // Preview use-case
221
+ Preview preview = new Preview.Builder().build();
222
+ preview.setSurfaceProvider(previewView.getSurfaceProvider());
223
+
224
+ // Image capture use-case
225
+ imageCapture = new ImageCapture.Builder()
226
+ .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
227
+ .build();
228
+
229
+ // Select camera
230
+ CameraSelector selector = new CameraSelector.Builder()
231
+ .requireLensFacing(lensFacing)
232
+ .build();
233
+
234
+ // Bind lifecycle
235
+ camera = cameraProvider.bindToLifecycle(
236
+ this, selector, preview, imageCapture
237
+ );
238
+ boolean hasFlash = camera.getCameraInfo().hasFlashUnit();
239
+ if (hasFlash) {
240
+ torchButton.setVisibility(View.VISIBLE);
241
+ } else {
242
+ torchButton.setVisibility(View.GONE);
243
+ // reset state in case you were mid-toggle
244
+ isTorchOn = false;
245
+ }
246
+ }
247
+ private void takePhoto() {
248
+ if (imageCapture == null) return;
249
+
250
+ // Prepare output file
251
+ File photoFile = new File(getCacheDir(),
252
+ new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.US)
253
+ .format(System.currentTimeMillis()) + ".jpg"
254
+ );
255
+ ImageCapture.OutputFileOptions options =
256
+ new ImageCapture.OutputFileOptions.Builder(photoFile).build();
257
+
258
+ // Take picture
259
+ imageCapture.takePicture(options,
260
+ ContextCompat.getMainExecutor(this),
261
+ new ImageCapture.OnImageSavedCallback() {
262
+ @Override
263
+ public void onImageSaved(@NonNull ImageCapture.OutputFileResults result) {
264
+ // Return path to Cordova plugin
265
+ Intent out = new Intent();
266
+ out.putExtra("imagePath", photoFile.getAbsolutePath());
267
+ setResult(Activity.RESULT_OK, out);
268
+ finish();
269
+ }
270
+ @Override
271
+ public void onError(@NonNull ImageCaptureException exc) {
272
+ Intent out = new Intent();
273
+ out.putExtra("error", exc.getMessage());
274
+ setResult(Activity.RESULT_CANCELED, out);
275
+ finish();
276
+ }
277
+ }
278
+ );
279
+ }
280
+ private void takePhoto1() {
281
+ if (imageCapture == null) return;
282
+
283
+ File file = new File(getCacheDir(),
284
+ new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.US)
285
+ .format(System.currentTimeMillis()) + ".jpg"
286
+ );
287
+ ImageCapture.OutputFileOptions opts =
288
+ new ImageCapture.OutputFileOptions.Builder(file).build();
289
+
290
+ imageCapture.takePicture(
291
+ opts,
292
+ ContextCompat.getMainExecutor(this),
293
+ new ImageCapture.OnImageSavedCallback() {
294
+ @Override
295
+ public void onImageSaved(@NonNull ImageCapture.OutputFileResults result) {
296
+ Toast.makeText(CameraActivity.this,
297
+ "Saved: " + file.getAbsolutePath(),
298
+ Toast.LENGTH_SHORT).show();
299
+ // TODO: return path via Intent to Cordova side
300
+ }
301
+ @Override
302
+ public void onError(@NonNull ImageCaptureException exc) {
303
+ Toast.makeText(CameraActivity.this,
304
+ "Error: " + exc.getMessage(),
305
+ Toast.LENGTH_SHORT).show();
306
+ }
307
+ }
308
+ );
309
+ }
310
+
311
+ private boolean allPermissionsGranted() {
312
+ for (String p : REQUIRED_PERMISSIONS) {
313
+ if (ContextCompat.checkSelfPermission(this, p)
314
+ != PackageManager.PERMISSION_GRANTED) return false;
315
+ }
316
+ return true;
317
+ }
318
+
319
+ @Override
320
+ public void onRequestPermissionsResult(int rc, @NonNull String[] perms,
321
+ @NonNull int[] results) {
322
+ super.onRequestPermissionsResult(rc, perms, results);
323
+ if (rc == REQUEST_CODE_PERMISSIONS) {
324
+ if (allPermissionsGranted()) {
325
+ startCamera();
326
+ } else {
327
+ Toast.makeText(this,
328
+ "Camera permission required", Toast.LENGTH_SHORT).show();
329
+ setResult(Activity.RESULT_CANCELED);
330
+ finish();
331
+ }
332
+ }
333
+ }
334
+ }
@@ -194,9 +194,6 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
194
194
  boolean appInfoUpdated = new mInterfaceUtil().updateAppInfo(args);
195
195
  System.out.println("appInfoUpdated: " + appInfoUpdated);
196
196
  //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
197
- if (!isServiceRunning(backgroundNotification.class)) {
198
- cordova.getActivity().startService(new Intent(cordova.getActivity().getApplicationContext(), backgroundNotification.class));
199
- }
200
197
  if (!isServiceRunning(mInterfaceService.class)) {
201
198
  cordova.getActivity().startService(new Intent(cordova.getActivity().getApplicationContext(), mInterfaceService.class));
202
199
  } else {
@@ -0,0 +1,14 @@
1
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
2
+ android:width="60dp"
3
+ android:height="60dp"
4
+ android:viewportWidth="60"
5
+ android:viewportHeight="60">
6
+ <path
7
+ android:fillColor="#FFFFFFFF"
8
+ android:pathData="M0 30c0-16.57 13.43-30 30-30h0c16.57 0 30 13.43 30 30v0c0 16.57-13.43 30-30 30h0c-16.57 0-30-13.43-30-30z"/>
9
+ <path
10
+ android:fillColor="#FFFFFFFF"
11
+ android:strokeColor="#FF000000"
12
+ android:strokeWidth="1.3"
13
+ android:pathData="M29.5 4.65c13.71 0 24.85 11.34 24.85 25.35 0 14.01-11.14 25.35-24.85 25.35S4.65 44.01 4.65 30c0-14.01 11.14-25.35 24.85-25.35Z"/>
14
+ </vector>
@@ -0,0 +1,11 @@
1
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
2
+ android:width="80dp"
3
+ android:height="80dp"
4
+ android:viewportWidth="80"
5
+ android:viewportHeight="80">
6
+ <group>
7
+ <path
8
+ android:fillColor="#FFFFFFFF"
9
+ android:pathData="M14.33 65.67V50.1h2v13.56H29.9v2H14.33Zm35.78 0v-2h13.56V50.1h2v15.56H50.1ZM14.33 29.89V14.33H29.9v2H16.33V29.9h-2Zm49.34 0V16.33H50.1v-2h15.56V29.9h-2Z"/>
10
+ </group>
11
+ </vector>
@@ -0,0 +1,17 @@
1
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
2
+ android:width="45dp"
3
+ android:height="45dp"
4
+ android:viewportWidth="45"
5
+ android:viewportHeight="45">
6
+ <path
7
+ android:fillColor="#54151515"
8
+ android:pathData="M0 22.5c0-12.43 10.07-22.5 22.5-22.5h0c12.43 0 22.5 10.07 22.5 22.5v0c0 12.43-10.07 22.5-22.5 22.5h0c-12.43 0-22.5-10.07-22.5-22.5z"/>
9
+ <path
10
+ android:fillColor="#FFFFFFFF"
11
+ android:pathData="M20.7 36.9h-1.8l1.8-11.2h-6.3c-1.05 0-1.03-0.51-0.7-1.06 0.35-0.54 0.1-0.12 0.14-0.19 2.32-3.65 5.8-9.09 10.45-16.35h1.8l-1.8 11.2h6.3c0.89 0 1.01 0.53 0.85 0.82l-0.13 0.24C24.22 31.38 20.7 36.9 20.7 36.9Z"/>
12
+ <path
13
+ android:fillColor="#FFFFFFFF"
14
+ android:strokeColor="#FF000000"
15
+ android:strokeWidth="0.1"
16
+ android:pathData="M14.33 13.24l0.85-0.71 15.82 19-0.85 0.72z"/>
17
+ </vector>
@@ -0,0 +1,12 @@
1
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
2
+ android:width="45dp"
3
+ android:height="45dp"
4
+ android:viewportWidth="45"
5
+ android:viewportHeight="45">
6
+ <path
7
+ android:fillColor="#54151515"
8
+ android:pathData="M0 22.5c0-12.43 10.07-22.5 22.5-22.5h0c12.43 0 22.5 10.07 22.5 22.5v0c0 12.43-10.07 22.5-22.5 22.5h0c-12.43 0-22.5-10.07-22.5-22.5z"/>
9
+ <path
10
+ android:fillColor="#FFFFFFFF"
11
+ android:pathData="M20.7 36.9h-1.8l1.8-11.2h-6.3c-1.05 0-1.03-0.51-0.7-1.06 0.35-0.54 0.1-0.12 0.14-0.19 2.32-3.65 5.8-9.09 10.45-16.35h1.8l-1.8 11.2h6.3c0.89 0 1.01 0.53 0.85 0.82l-0.13 0.24C24.22 31.38 20.7 36.9 20.7 36.9Z"/>
12
+ </vector>
@@ -0,0 +1,14 @@
1
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
2
+ android:width="45dp"
3
+ android:height="45dp"
4
+ android:viewportWidth="45"
5
+ android:viewportHeight="45">
6
+ <path
7
+ android:fillColor="#54151515"
8
+ android:pathData="M0 22.5c0-12.43 10.07-22.5 22.5-22.5h0c12.43 0 22.5 10.07 22.5 22.5v0c0 12.43-10.07 22.5-22.5 22.5h0c-12.43 0-22.5-10.07-22.5-22.5z"/>
9
+ <group>
10
+ <path
11
+ android:fillColor="#FFFFFFFF"
12
+ android:pathData="M12.07 19.63l6.45 3.72-3.81 1.02c1.12 4.2 5.46 6.7 9.66 5.58 1.28-0.34 2.42-0.99 3.32-1.84l2.35 1.35c-1.3 1.41-3 2.5-4.99 3.03-5.61 1.5-11.38-1.83-12.88-7.44l-3.82 1.02 3.72-6.44Zm17.88 0.66c-1.13-4.2-5.46-6.71-9.66-5.58-1.29 0.34-2.42 0.98-3.32 1.84l-2.35-1.36c1.3-1.4 2.99-2.49 4.98-3.02 5.62-1.5 11.39 1.82 12.89 7.43l3.81-1.02-3.72 6.45-6.44-3.72 3.8-1.02Z"/>
13
+ </group>
14
+ </vector>
@@ -0,0 +1,64 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <androidx.constraintlayout.widget.ConstraintLayout
3
+ xmlns:android="http://schemas.android.com/apk/res/android"
4
+ xmlns:app="http://schemas.android.com/apk/res-auto"
5
+ android:layout_width="match_parent"
6
+ android:layout_height="match_parent">
7
+
8
+ <androidx.camera.view.PreviewView
9
+ android:id="@+id/previewView"
10
+ android:layout_width="0dp"
11
+ android:layout_height="0dp"
12
+ app:layout_constraintTop_toTopOf="parent"
13
+ app:layout_constraintBottom_toBottomOf="parent"
14
+ app:layout_constraintStart_toStartOf="parent"
15
+ app:layout_constraintEnd_toEndOf="parent"/>
16
+ <View
17
+ android:id="@+id/focusView"
18
+ android:layout_width="80dp"
19
+ android:layout_height="80dp"
20
+ android:background="@drawable/focus_box"
21
+ android:visibility="gone"
22
+ app:layout_constraintTop_toTopOf="parent"
23
+ app:layout_constraintStart_toStartOf="parent"/>
24
+
25
+ <ImageButton
26
+ android:id="@+id/torchButton"
27
+ android:layout_width="56dp"
28
+ android:layout_height="56dp"
29
+ android:layout_marginStart="8dp"
30
+ android:layout_marginEnd="24dp"
31
+ android:layout_marginBottom="32dp"
32
+ android:background="?attr/selectableItemBackgroundBorderless"
33
+ android:contentDescription="Toggle flash"
34
+ android:src="@drawable/ic_flashlight_off"
35
+ app:layout_constraintBottom_toBottomOf="parent"
36
+ app:layout_constraintEnd_toStartOf="@id/captureButton"
37
+ app:layout_constraintStart_toStartOf="parent" />
38
+
39
+ <ImageButton
40
+ android:id="@+id/captureButton"
41
+ android:layout_width="72dp"
42
+ android:layout_height="72dp"
43
+ android:layout_marginBottom="32dp"
44
+ android:background="@drawable/circle_button"
45
+ android:contentDescription="Capture"
46
+ app:layout_constraintBottom_toBottomOf="parent"
47
+ app:layout_constraintEnd_toEndOf="parent"
48
+ app:layout_constraintStart_toStartOf="parent" />
49
+
50
+ <ImageButton
51
+ android:id="@+id/switchCamera"
52
+ android:layout_width="56dp"
53
+ android:layout_height="56dp"
54
+ android:layout_marginStart="24dp"
55
+ android:layout_marginEnd="8dp"
56
+ android:layout_marginBottom="32dp"
57
+ android:background="?attr/selectableItemBackgroundBorderless"
58
+ android:contentDescription="Switch camera"
59
+ android:src="@drawable/ic_flip_camera"
60
+ app:layout_constraintBottom_toBottomOf="parent"
61
+ app:layout_constraintEnd_toEndOf="parent"
62
+ app:layout_constraintStart_toEndOf="@+id/captureButton" />
63
+
64
+ </androidx.constraintlayout.widget.ConstraintLayout>
@@ -0,0 +1,8 @@
1
+ <!-- src/main/res/values/styles.xml -->
2
+ <resources>
3
+ <!-- A no-action-bar theme for your camera -->
4
+ <style name="CameraTheme" parent="Theme.AppCompat.Light.NoActionBar">
5
+ <!-- if you want full-screen preview, you can add -->
6
+ <item name="android:windowFullscreen">true</item>
7
+ </style>
8
+ </resources>