cordova-plugin-mserviceinterface-2.0 1.0.106 → 1.0.108
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 +1 -1
- package/plugin.xml +5 -1
- package/src/android/AttachmentFileIO.java +59 -59
- package/src/android/CameraActivity.java +142 -142
- package/src/android/GeofenceBroadcastReceiver.java +99 -19
- package/src/android/mInterface.java +308 -674
- package/src/android/mInterfaceUtil.java +42 -85
- package/src/android/res/layout/activity_camera.xml +16 -16
- package/src/ios/mInterface.m +15 -23
package/package.json
CHANGED
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.
|
|
3
|
+
xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-mserviceinterface-2.0" version="1.0.108">
|
|
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>
|
|
@@ -48,11 +48,15 @@
|
|
|
48
48
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
|
49
49
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
50
50
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
|
51
|
+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
|
|
52
|
+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
|
51
53
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
52
54
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
53
55
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
|
54
56
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
|
55
57
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
58
|
+
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
|
59
|
+
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
|
|
56
60
|
<queries>
|
|
57
61
|
<intent>
|
|
58
62
|
<action android:name="android.media.action.IMAGE_CAPTURE" />
|
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
package com.selfservit.util;
|
|
2
|
-
|
|
3
|
-
import java.io.File;
|
|
4
|
-
import java.io.FileOutputStream;
|
|
5
|
-
import java.io.IOException;
|
|
6
|
-
import java.io.InputStream;
|
|
7
|
-
import java.io.OutputStream;
|
|
8
|
-
|
|
9
|
-
/** Copies a provider stream into an app-owned file without assuming a filesystem URI. */
|
|
10
|
-
final class AttachmentFileIO {
|
|
11
|
-
private AttachmentFileIO() { }
|
|
12
|
-
|
|
13
|
-
static File copy(InputStream input, File directory, String displayName) throws IOException {
|
|
14
|
-
File outputFile = null;
|
|
15
|
-
boolean complete = false;
|
|
16
|
-
try {
|
|
17
|
-
try (InputStream source = input) {
|
|
18
|
-
if (source == null) {
|
|
19
|
-
throw new IOException("The selected file is no longer available");
|
|
20
|
-
}
|
|
21
|
-
if (!directory.isDirectory() && !directory.mkdirs()) {
|
|
22
|
-
throw new IOException("Cannot create attachment directory");
|
|
23
|
-
}
|
|
24
|
-
String name = displayName == null ? "attachment" : displayName;
|
|
25
|
-
// Provider display names are labels, never paths.
|
|
26
|
-
name = name.replaceAll("[\\\\/\\p{Cntrl}:*?\"<>|]", "_").trim();
|
|
27
|
-
if (name.isEmpty() || name.equals(".") || name.equals("..")) {
|
|
28
|
-
name = "attachment";
|
|
29
|
-
}
|
|
30
|
-
int dot = name.lastIndexOf('.');
|
|
31
|
-
String stem = dot > 0 ? name.substring(0, dot) : name;
|
|
32
|
-
String suffix = dot > 0 ? name.substring(dot) : "";
|
|
33
|
-
// Bound provider-supplied names, retaining normal filename extensions.
|
|
34
|
-
stem = stem.substring(0, Math.min(stem.length(), 80));
|
|
35
|
-
suffix = suffix.substring(0, Math.min(suffix.length(), 20));
|
|
36
|
-
outputFile = File.createTempFile(stem + "_attachment_", suffix, directory);
|
|
37
|
-
try (OutputStream output = new FileOutputStream(outputFile)) {
|
|
38
|
-
byte[] buffer = new byte[8192];
|
|
39
|
-
int count;
|
|
40
|
-
while ((count = source.read(buffer)) != -1) {
|
|
41
|
-
if (count == 0) {
|
|
42
|
-
int next = source.read();
|
|
43
|
-
if (next == -1) break;
|
|
44
|
-
output.write(next);
|
|
45
|
-
} else {
|
|
46
|
-
output.write(buffer, 0, count);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
complete = true;
|
|
52
|
-
} finally {
|
|
53
|
-
if (!complete && outputFile != null && outputFile.exists()) {
|
|
54
|
-
outputFile.delete();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return outputFile;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
1
|
+
package com.selfservit.util;
|
|
2
|
+
|
|
3
|
+
import java.io.File;
|
|
4
|
+
import java.io.FileOutputStream;
|
|
5
|
+
import java.io.IOException;
|
|
6
|
+
import java.io.InputStream;
|
|
7
|
+
import java.io.OutputStream;
|
|
8
|
+
|
|
9
|
+
/** Copies a provider stream into an app-owned file without assuming a filesystem URI. */
|
|
10
|
+
final class AttachmentFileIO {
|
|
11
|
+
private AttachmentFileIO() { }
|
|
12
|
+
|
|
13
|
+
static File copy(InputStream input, File directory, String displayName) throws IOException {
|
|
14
|
+
File outputFile = null;
|
|
15
|
+
boolean complete = false;
|
|
16
|
+
try {
|
|
17
|
+
try (InputStream source = input) {
|
|
18
|
+
if (source == null) {
|
|
19
|
+
throw new IOException("The selected file is no longer available");
|
|
20
|
+
}
|
|
21
|
+
if (!directory.isDirectory() && !directory.mkdirs()) {
|
|
22
|
+
throw new IOException("Cannot create attachment directory");
|
|
23
|
+
}
|
|
24
|
+
String name = displayName == null ? "attachment" : displayName;
|
|
25
|
+
// Provider display names are labels, never paths.
|
|
26
|
+
name = name.replaceAll("[\\\\/\\p{Cntrl}:*?\"<>|]", "_").trim();
|
|
27
|
+
if (name.isEmpty() || name.equals(".") || name.equals("..")) {
|
|
28
|
+
name = "attachment";
|
|
29
|
+
}
|
|
30
|
+
int dot = name.lastIndexOf('.');
|
|
31
|
+
String stem = dot > 0 ? name.substring(0, dot) : name;
|
|
32
|
+
String suffix = dot > 0 ? name.substring(dot) : "";
|
|
33
|
+
// Bound provider-supplied names, retaining normal filename extensions.
|
|
34
|
+
stem = stem.substring(0, Math.min(stem.length(), 80));
|
|
35
|
+
suffix = suffix.substring(0, Math.min(suffix.length(), 20));
|
|
36
|
+
outputFile = File.createTempFile(stem + "_attachment_", suffix, directory);
|
|
37
|
+
try (OutputStream output = new FileOutputStream(outputFile)) {
|
|
38
|
+
byte[] buffer = new byte[8192];
|
|
39
|
+
int count;
|
|
40
|
+
while ((count = source.read(buffer)) != -1) {
|
|
41
|
+
if (count == 0) {
|
|
42
|
+
int next = source.read();
|
|
43
|
+
if (next == -1) break;
|
|
44
|
+
output.write(next);
|
|
45
|
+
} else {
|
|
46
|
+
output.write(buffer, 0, count);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
complete = true;
|
|
52
|
+
} finally {
|
|
53
|
+
if (!complete && outputFile != null && outputFile.exists()) {
|
|
54
|
+
outputFile.delete();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return outputFile;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -2,21 +2,21 @@ package com.selfservit.util;
|
|
|
2
2
|
|
|
3
3
|
import android.Manifest;
|
|
4
4
|
import android.annotation.SuppressLint;
|
|
5
|
-
import android.app.Activity;
|
|
6
|
-
import android.content.Context;
|
|
7
|
-
import android.content.Intent;
|
|
8
|
-
import android.content.pm.PackageManager;
|
|
9
|
-
import android.content.res.Configuration;
|
|
10
|
-
import android.hardware.display.DisplayManager;
|
|
11
|
-
import android.os.Bundle;
|
|
12
|
-
import android.os.Handler;
|
|
13
|
-
import android.os.Looper;
|
|
14
|
-
import android.util.Log;
|
|
15
|
-
import android.view.Display;
|
|
16
|
-
import android.view.MotionEvent;
|
|
17
|
-
import android.view.ScaleGestureDetector;
|
|
18
|
-
import android.view.Surface;
|
|
19
|
-
import android.view.View;
|
|
5
|
+
import android.app.Activity;
|
|
6
|
+
import android.content.Context;
|
|
7
|
+
import android.content.Intent;
|
|
8
|
+
import android.content.pm.PackageManager;
|
|
9
|
+
import android.content.res.Configuration;
|
|
10
|
+
import android.hardware.display.DisplayManager;
|
|
11
|
+
import android.os.Bundle;
|
|
12
|
+
import android.os.Handler;
|
|
13
|
+
import android.os.Looper;
|
|
14
|
+
import android.util.Log;
|
|
15
|
+
import android.view.Display;
|
|
16
|
+
import android.view.MotionEvent;
|
|
17
|
+
import android.view.ScaleGestureDetector;
|
|
18
|
+
import android.view.Surface;
|
|
19
|
+
import android.view.View;
|
|
20
20
|
import android.widget.ImageButton;
|
|
21
21
|
import android.widget.Toast;
|
|
22
22
|
|
|
@@ -32,11 +32,11 @@ import androidx.camera.core.Preview;
|
|
|
32
32
|
import androidx.camera.lifecycle.ProcessCameraProvider;
|
|
33
33
|
import androidx.camera.view.PreviewView;
|
|
34
34
|
import androidx.core.app.ActivityCompat;
|
|
35
|
-
import androidx.core.content.ContextCompat;
|
|
36
|
-
import androidx.core.graphics.Insets;
|
|
37
|
-
import androidx.core.view.ViewCompat;
|
|
38
|
-
import androidx.core.view.WindowCompat;
|
|
39
|
-
import androidx.core.view.WindowInsetsCompat;
|
|
35
|
+
import androidx.core.content.ContextCompat;
|
|
36
|
+
import androidx.core.graphics.Insets;
|
|
37
|
+
import androidx.core.view.ViewCompat;
|
|
38
|
+
import androidx.core.view.WindowCompat;
|
|
39
|
+
import androidx.core.view.WindowInsetsCompat;
|
|
40
40
|
|
|
41
41
|
import com.google.common.util.concurrent.ListenableFuture;
|
|
42
42
|
|
|
@@ -55,27 +55,27 @@ public class CameraActivity extends AppCompatActivity {
|
|
|
55
55
|
private ImageCapture imageCapture;
|
|
56
56
|
private ImageButton torchButton;
|
|
57
57
|
private ProcessCameraProvider cameraProvider;
|
|
58
|
-
private Camera camera;
|
|
59
|
-
private View cameraControls;
|
|
60
|
-
private DisplayManager displayManager;
|
|
61
|
-
private int torchOnDrawable;
|
|
62
|
-
private int torchOffDrawable;
|
|
63
|
-
|
|
64
|
-
private final DisplayManager.DisplayListener displayListener = new DisplayManager.DisplayListener() {
|
|
65
|
-
@Override
|
|
66
|
-
public void onDisplayAdded(int displayId) {}
|
|
67
|
-
|
|
68
|
-
@Override
|
|
69
|
-
public void onDisplayRemoved(int displayId) {}
|
|
70
|
-
|
|
71
|
-
@Override
|
|
72
|
-
public void onDisplayChanged(int displayId) {
|
|
73
|
-
Display display = previewView == null ? null : previewView.getDisplay();
|
|
74
|
-
if (display != null && display.getDisplayId() == displayId) {
|
|
75
|
-
updateCaptureRotation();
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
};
|
|
58
|
+
private Camera camera;
|
|
59
|
+
private View cameraControls;
|
|
60
|
+
private DisplayManager displayManager;
|
|
61
|
+
private int torchOnDrawable;
|
|
62
|
+
private int torchOffDrawable;
|
|
63
|
+
|
|
64
|
+
private final DisplayManager.DisplayListener displayListener = new DisplayManager.DisplayListener() {
|
|
65
|
+
@Override
|
|
66
|
+
public void onDisplayAdded(int displayId) {}
|
|
67
|
+
|
|
68
|
+
@Override
|
|
69
|
+
public void onDisplayRemoved(int displayId) {}
|
|
70
|
+
|
|
71
|
+
@Override
|
|
72
|
+
public void onDisplayChanged(int displayId) {
|
|
73
|
+
Display display = previewView == null ? null : previewView.getDisplay();
|
|
74
|
+
if (display != null && display.getDisplayId() == displayId) {
|
|
75
|
+
updateCaptureRotation();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
79
|
|
|
80
80
|
private int lensFacing = CameraSelector.LENS_FACING_BACK;
|
|
81
81
|
private boolean isTorchOn = false;
|
|
@@ -85,18 +85,18 @@ public class CameraActivity extends AppCompatActivity {
|
|
|
85
85
|
@SuppressLint("ClickableViewAccessibility")
|
|
86
86
|
@Override
|
|
87
87
|
protected void onCreate(Bundle savedInstanceState) {
|
|
88
|
-
super.onCreate(savedInstanceState);
|
|
89
|
-
|
|
90
|
-
// Let the system handle predictive Back while preserving the plugin's cancellation result.
|
|
91
|
-
Intent cancelled = new Intent();
|
|
92
|
-
cancelled.putExtra("result", "cancelled");
|
|
93
|
-
setResult(Activity.RESULT_CANCELED, cancelled);
|
|
94
|
-
if (savedInstanceState != null) {
|
|
95
|
-
lensFacing = savedInstanceState.getInt("lensFacing", CameraSelector.LENS_FACING_BACK);
|
|
96
|
-
isTorchOn = savedInstanceState.getBoolean("isTorchOn", false);
|
|
97
|
-
}
|
|
98
|
-
displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
|
|
99
|
-
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
|
88
|
+
super.onCreate(savedInstanceState);
|
|
89
|
+
|
|
90
|
+
// Let the system handle predictive Back while preserving the plugin's cancellation result.
|
|
91
|
+
Intent cancelled = new Intent();
|
|
92
|
+
cancelled.putExtra("result", "cancelled");
|
|
93
|
+
setResult(Activity.RESULT_CANCELED, cancelled);
|
|
94
|
+
if (savedInstanceState != null) {
|
|
95
|
+
lensFacing = savedInstanceState.getInt("lensFacing", CameraSelector.LENS_FACING_BACK);
|
|
96
|
+
isTorchOn = savedInstanceState.getBoolean("isTorchOn", false);
|
|
97
|
+
}
|
|
98
|
+
displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
|
|
99
|
+
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
|
100
100
|
|
|
101
101
|
// Dynamically inflate layout
|
|
102
102
|
String pkg = getPackageName();
|
|
@@ -108,22 +108,22 @@ public class CameraActivity extends AppCompatActivity {
|
|
|
108
108
|
int captureId = getResources().getIdentifier("captureButton", "id", pkg);
|
|
109
109
|
int switchId = getResources().getIdentifier("switchCamera", "id", pkg);
|
|
110
110
|
int torchId = getResources().getIdentifier("torchButton", "id", pkg);
|
|
111
|
-
int focusViewId = getResources().getIdentifier("focusView", "id", pkg);
|
|
112
|
-
int controlsId = getResources().getIdentifier("cameraControls", "id", pkg);
|
|
111
|
+
int focusViewId = getResources().getIdentifier("focusView", "id", pkg);
|
|
112
|
+
int controlsId = getResources().getIdentifier("cameraControls", "id", pkg);
|
|
113
113
|
|
|
114
114
|
// Resolve drawable IDs
|
|
115
|
-
torchOnDrawable = getResources().getIdentifier("ic_flashlight_on", "drawable", pkg);
|
|
116
|
-
torchOffDrawable = getResources().getIdentifier("ic_flashlight_off", "drawable", pkg);
|
|
115
|
+
torchOnDrawable = getResources().getIdentifier("ic_flashlight_on", "drawable", pkg);
|
|
116
|
+
torchOffDrawable = getResources().getIdentifier("ic_flashlight_off", "drawable", pkg);
|
|
117
117
|
|
|
118
118
|
// Bind views to fields
|
|
119
119
|
previewView = findViewById(previewId);
|
|
120
120
|
ImageButton captureButton = findViewById(captureId);
|
|
121
121
|
ImageButton switchButton = findViewById(switchId);
|
|
122
122
|
torchButton = findViewById(torchId);
|
|
123
|
-
focusView = findViewById(focusViewId);
|
|
124
|
-
cameraControls = findViewById(controlsId);
|
|
125
|
-
applyControlInsets();
|
|
126
|
-
previewView.post(this::updateCaptureRotation);
|
|
123
|
+
focusView = findViewById(focusViewId);
|
|
124
|
+
cameraControls = findViewById(controlsId);
|
|
125
|
+
applyControlInsets();
|
|
126
|
+
previewView.post(this::updateCaptureRotation);
|
|
127
127
|
|
|
128
128
|
// Utility to add press animation to any view
|
|
129
129
|
View.OnTouchListener pressAnim = (v, e) -> {
|
|
@@ -227,11 +227,11 @@ public class CameraActivity extends AppCompatActivity {
|
|
|
227
227
|
|
|
228
228
|
// Switch front/back
|
|
229
229
|
switchButton.setOnClickListener(v -> {
|
|
230
|
-
lensFacing = (lensFacing == CameraSelector.LENS_FACING_BACK)
|
|
231
|
-
? CameraSelector.LENS_FACING_FRONT
|
|
232
|
-
: CameraSelector.LENS_FACING_BACK;
|
|
233
|
-
isTorchOn = false;
|
|
234
|
-
bindUseCases();
|
|
230
|
+
lensFacing = (lensFacing == CameraSelector.LENS_FACING_BACK)
|
|
231
|
+
? CameraSelector.LENS_FACING_FRONT
|
|
232
|
+
: CameraSelector.LENS_FACING_BACK;
|
|
233
|
+
isTorchOn = false;
|
|
234
|
+
bindUseCases();
|
|
235
235
|
});
|
|
236
236
|
|
|
237
237
|
// Torch toggle
|
|
@@ -242,72 +242,72 @@ public class CameraActivity extends AppCompatActivity {
|
|
|
242
242
|
torchButton.setImageResource(isTorchOn ? torchOnDrawable : torchOffDrawable);
|
|
243
243
|
}
|
|
244
244
|
});
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
private void applyControlInsets() {
|
|
248
|
-
final int left = cameraControls.getPaddingLeft();
|
|
249
|
-
final int top = cameraControls.getPaddingTop();
|
|
250
|
-
final int right = cameraControls.getPaddingRight();
|
|
251
|
-
final int bottom = cameraControls.getPaddingBottom();
|
|
252
|
-
ViewCompat.setOnApplyWindowInsetsListener(cameraControls, (view, windowInsets) -> {
|
|
253
|
-
Insets safeInsets = windowInsets.getInsets(
|
|
254
|
-
WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
|
|
255
|
-
view.setPadding(left + safeInsets.left, top + safeInsets.top,
|
|
256
|
-
right + safeInsets.right, bottom + safeInsets.bottom);
|
|
257
|
-
return windowInsets;
|
|
258
|
-
});
|
|
259
|
-
cameraControls.post(() -> ViewCompat.requestApplyInsets(cameraControls));
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
@Override
|
|
263
|
-
protected void onStart() {
|
|
264
|
-
super.onStart();
|
|
265
|
-
if (displayManager != null) {
|
|
266
|
-
displayManager.registerDisplayListener(displayListener, new Handler(Looper.getMainLooper()));
|
|
267
|
-
}
|
|
268
|
-
previewView.post(this::updateCaptureRotation);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
@Override
|
|
272
|
-
protected void onStop() {
|
|
273
|
-
if (displayManager != null) {
|
|
274
|
-
displayManager.unregisterDisplayListener(displayListener);
|
|
275
|
-
}
|
|
276
|
-
super.onStop();
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
@Override
|
|
280
|
-
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
|
281
|
-
super.onConfigurationChanged(newConfig);
|
|
282
|
-
previewView.post(this::updateCaptureRotation);
|
|
283
|
-
ViewCompat.requestApplyInsets(cameraControls);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
@Override
|
|
287
|
-
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
|
288
|
-
outState.putInt("lensFacing", lensFacing);
|
|
289
|
-
outState.putBoolean("isTorchOn", isTorchOn);
|
|
290
|
-
super.onSaveInstanceState(outState);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
private int getCaptureRotation() {
|
|
294
|
-
Display display = previewView == null ? null : previewView.getDisplay();
|
|
295
|
-
return display == null ? Surface.ROTATION_0 : display.getRotation();
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
private void updateCaptureRotation() {
|
|
299
|
-
if (imageCapture != null && previewView.getDisplay() != null) {
|
|
300
|
-
imageCapture.setTargetRotation(getCaptureRotation());
|
|
301
|
-
}
|
|
302
|
-
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
private void applyControlInsets() {
|
|
248
|
+
final int left = cameraControls.getPaddingLeft();
|
|
249
|
+
final int top = cameraControls.getPaddingTop();
|
|
250
|
+
final int right = cameraControls.getPaddingRight();
|
|
251
|
+
final int bottom = cameraControls.getPaddingBottom();
|
|
252
|
+
ViewCompat.setOnApplyWindowInsetsListener(cameraControls, (view, windowInsets) -> {
|
|
253
|
+
Insets safeInsets = windowInsets.getInsets(
|
|
254
|
+
WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
|
|
255
|
+
view.setPadding(left + safeInsets.left, top + safeInsets.top,
|
|
256
|
+
right + safeInsets.right, bottom + safeInsets.bottom);
|
|
257
|
+
return windowInsets;
|
|
258
|
+
});
|
|
259
|
+
cameraControls.post(() -> ViewCompat.requestApplyInsets(cameraControls));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
@Override
|
|
263
|
+
protected void onStart() {
|
|
264
|
+
super.onStart();
|
|
265
|
+
if (displayManager != null) {
|
|
266
|
+
displayManager.registerDisplayListener(displayListener, new Handler(Looper.getMainLooper()));
|
|
267
|
+
}
|
|
268
|
+
previewView.post(this::updateCaptureRotation);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
@Override
|
|
272
|
+
protected void onStop() {
|
|
273
|
+
if (displayManager != null) {
|
|
274
|
+
displayManager.unregisterDisplayListener(displayListener);
|
|
275
|
+
}
|
|
276
|
+
super.onStop();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
@Override
|
|
280
|
+
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
|
281
|
+
super.onConfigurationChanged(newConfig);
|
|
282
|
+
previewView.post(this::updateCaptureRotation);
|
|
283
|
+
ViewCompat.requestApplyInsets(cameraControls);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
@Override
|
|
287
|
+
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
|
288
|
+
outState.putInt("lensFacing", lensFacing);
|
|
289
|
+
outState.putBoolean("isTorchOn", isTorchOn);
|
|
290
|
+
super.onSaveInstanceState(outState);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private int getCaptureRotation() {
|
|
294
|
+
Display display = previewView == null ? null : previewView.getDisplay();
|
|
295
|
+
return display == null ? Surface.ROTATION_0 : display.getRotation();
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
private void updateCaptureRotation() {
|
|
299
|
+
if (imageCapture != null && previewView.getDisplay() != null) {
|
|
300
|
+
imageCapture.setTargetRotation(getCaptureRotation());
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
303
|
|
|
304
304
|
private void startCamera() {
|
|
305
305
|
ListenableFuture<ProcessCameraProvider> future =
|
|
306
306
|
ProcessCameraProvider.getInstance(this);
|
|
307
|
-
future.addListener(() -> {
|
|
308
|
-
try {
|
|
309
|
-
if (isFinishing() || isDestroyed()) return;
|
|
310
|
-
cameraProvider = future.get();
|
|
307
|
+
future.addListener(() -> {
|
|
308
|
+
try {
|
|
309
|
+
if (isFinishing() || isDestroyed()) return;
|
|
310
|
+
cameraProvider = future.get();
|
|
311
311
|
bindUseCases();
|
|
312
312
|
} catch (ExecutionException | InterruptedException e) {
|
|
313
313
|
Log.e("CameraActivity", "CameraProvider init failed", e);
|
|
@@ -326,10 +326,10 @@ public class CameraActivity extends AppCompatActivity {
|
|
|
326
326
|
preview.setSurfaceProvider(previewView.getSurfaceProvider());
|
|
327
327
|
|
|
328
328
|
// Image capture use-case
|
|
329
|
-
imageCapture = new ImageCapture.Builder()
|
|
330
|
-
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
|
331
|
-
.setTargetRotation(getCaptureRotation())
|
|
332
|
-
.build();
|
|
329
|
+
imageCapture = new ImageCapture.Builder()
|
|
330
|
+
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
|
331
|
+
.setTargetRotation(getCaptureRotation())
|
|
332
|
+
.build();
|
|
333
333
|
|
|
334
334
|
// Select camera
|
|
335
335
|
CameraSelector selector = new CameraSelector.Builder()
|
|
@@ -341,19 +341,19 @@ public class CameraActivity extends AppCompatActivity {
|
|
|
341
341
|
this, selector, preview, imageCapture
|
|
342
342
|
);
|
|
343
343
|
boolean hasFlash = camera.getCameraInfo().hasFlashUnit();
|
|
344
|
-
if (hasFlash) {
|
|
345
|
-
torchButton.setVisibility(View.VISIBLE);
|
|
346
|
-
camera.getCameraControl().enableTorch(isTorchOn);
|
|
344
|
+
if (hasFlash) {
|
|
345
|
+
torchButton.setVisibility(View.VISIBLE);
|
|
346
|
+
camera.getCameraControl().enableTorch(isTorchOn);
|
|
347
347
|
} else {
|
|
348
348
|
torchButton.setVisibility(View.GONE);
|
|
349
349
|
// reset state in case you were mid-toggle
|
|
350
|
-
isTorchOn = false;
|
|
351
|
-
}
|
|
352
|
-
torchButton.setImageResource(isTorchOn ? torchOnDrawable : torchOffDrawable);
|
|
353
|
-
}
|
|
354
|
-
private void takePhoto() {
|
|
355
|
-
if (imageCapture == null) return;
|
|
356
|
-
updateCaptureRotation();
|
|
350
|
+
isTorchOn = false;
|
|
351
|
+
}
|
|
352
|
+
torchButton.setImageResource(isTorchOn ? torchOnDrawable : torchOffDrawable);
|
|
353
|
+
}
|
|
354
|
+
private void takePhoto() {
|
|
355
|
+
if (imageCapture == null) return;
|
|
356
|
+
updateCaptureRotation();
|
|
357
357
|
|
|
358
358
|
// Prepare output file
|
|
359
359
|
File photoFile = new File(getCacheDir(),
|