@capgo/camera-preview 8.11.5 → 8.11.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.
- package/android/build.gradle +6 -1
- package/android/src/main/java/app/capgo/capacitor/camera/preview/CameraPreview.java +27 -20
- package/android/src/main/java/app/capgo/capacitor/camera/preview/LocationPermissionHelper.java +32 -0
- package/android/src/test/java/app/capgo/capacitor/camera/preview/LocationPermissionHelperContextTest.java +38 -0
- package/android/src/test/java/app/capgo/capacitor/camera/preview/LocationPermissionHelperTest.java +25 -0
- package/ios/Sources/CapgoCameraPreviewPlugin/Plugin.swift +1 -1
- package/package.json +1 -1
package/android/build.gradle
CHANGED
|
@@ -40,6 +40,9 @@ android {
|
|
|
40
40
|
lintOptions {
|
|
41
41
|
abortOnError = false
|
|
42
42
|
}
|
|
43
|
+
testOptions {
|
|
44
|
+
unitTests.includeAndroidResources = true
|
|
45
|
+
}
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
repositories {
|
|
@@ -65,10 +68,12 @@ dependencies {
|
|
|
65
68
|
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
|
|
66
69
|
implementation "androidx.camera:camera-view:${camerax_version}"
|
|
67
70
|
implementation "androidx.camera:camera-extensions:${camerax_version}"
|
|
68
|
-
implementation 'com.google.guava:guava:33.
|
|
71
|
+
implementation 'com.google.guava:guava:33.7.2-android'
|
|
69
72
|
implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1'
|
|
70
73
|
|
|
71
74
|
testImplementation "junit:junit:$junitVersion"
|
|
75
|
+
testImplementation 'org.robolectric:robolectric:4.14.1'
|
|
76
|
+
testImplementation 'androidx.test:core:1.7.0'
|
|
72
77
|
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
73
78
|
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
74
79
|
}
|
|
@@ -29,7 +29,6 @@ import android.view.ViewGroup;
|
|
|
29
29
|
import android.webkit.WebView;
|
|
30
30
|
import androidx.annotation.RequiresPermission;
|
|
31
31
|
import androidx.appcompat.app.AlertDialog;
|
|
32
|
-
import androidx.core.app.ActivityCompat;
|
|
33
32
|
import androidx.core.graphics.Insets;
|
|
34
33
|
import androidx.core.view.ViewCompat;
|
|
35
34
|
import androidx.core.view.WindowInsetsCompat;
|
|
@@ -456,10 +455,13 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
456
455
|
final boolean withExifLocation = Boolean.TRUE.equals(call.getBoolean("withExifLocation", false));
|
|
457
456
|
|
|
458
457
|
if (withExifLocation) {
|
|
459
|
-
if (
|
|
458
|
+
if (LocationPermissionHelper.canCaptureWithExifLocation(getContext())) {
|
|
459
|
+
getLocationAndCapture(call);
|
|
460
|
+
} else if (getPermissionState(CAMERA_WITH_LOCATION_PERMISSION_ALIAS) != PermissionState.GRANTED) {
|
|
460
461
|
requestPermissionForAlias(CAMERA_WITH_LOCATION_PERMISSION_ALIAS, call, "captureWithLocationPermission");
|
|
461
462
|
} else {
|
|
462
|
-
|
|
463
|
+
Logger.warn("Location permission unavailable. Capturing photo without location data.");
|
|
464
|
+
captureWithoutLocation(call);
|
|
463
465
|
}
|
|
464
466
|
} else {
|
|
465
467
|
captureWithoutLocation(call);
|
|
@@ -469,35 +471,40 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
469
471
|
@SuppressLint("MissingPermission")
|
|
470
472
|
@PermissionCallback
|
|
471
473
|
private void captureWithLocationPermission(PluginCall call) {
|
|
472
|
-
if (
|
|
473
|
-
if (
|
|
474
|
-
ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) !=
|
|
475
|
-
PackageManager.PERMISSION_GRANTED ||
|
|
476
|
-
ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) !=
|
|
477
|
-
PackageManager.PERMISSION_GRANTED
|
|
478
|
-
) {
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
474
|
+
if (LocationPermissionHelper.canCaptureWithExifLocation(getContext())) {
|
|
481
475
|
getLocationAndCapture(call);
|
|
482
476
|
} else {
|
|
483
|
-
Logger.warn("Location permission denied. Capturing photo without location data.");
|
|
477
|
+
Logger.warn("Location permission denied or unavailable. Capturing photo without location data.");
|
|
484
478
|
captureWithoutLocation(call);
|
|
485
479
|
}
|
|
486
480
|
}
|
|
487
481
|
|
|
488
|
-
@RequiresPermission(
|
|
482
|
+
@RequiresPermission(anyOf = { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION })
|
|
489
483
|
private void getLocationAndCapture(PluginCall call) {
|
|
484
|
+
if (getActivity() == null) {
|
|
485
|
+
Logger.warn("Activity unavailable for location lookup. Capturing photo without location data.");
|
|
486
|
+
captureWithoutLocation(call);
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
490
|
if (fusedLocationClient == null) {
|
|
491
491
|
fusedLocationClient = LocationServices.getFusedLocationProviderClient(getContext());
|
|
492
492
|
}
|
|
493
493
|
fusedLocationClient
|
|
494
494
|
.getLastLocation()
|
|
495
|
-
.
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
495
|
+
.addOnCompleteListener((task) -> {
|
|
496
|
+
if (task.isCanceled()) {
|
|
497
|
+
Logger.warn("Location lookup cancelled. Capturing photo without location data.");
|
|
498
|
+
proceedWithCapture(call, null);
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
if (task.isSuccessful()) {
|
|
502
|
+
lastLocation = task.getResult();
|
|
503
|
+
proceedWithCapture(call, lastLocation);
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
Exception error = task.getException();
|
|
507
|
+
Logger.error("Failed to get location: " + (error != null ? error.getMessage() : "unknown error"));
|
|
501
508
|
proceedWithCapture(call, null);
|
|
502
509
|
});
|
|
503
510
|
}
|
package/android/src/main/java/app/capgo/capacitor/camera/preview/LocationPermissionHelper.java
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
package app.capgo.capacitor.camera.preview;
|
|
2
|
+
|
|
3
|
+
import android.Manifest;
|
|
4
|
+
import android.content.Context;
|
|
5
|
+
import android.content.pm.PackageManager;
|
|
6
|
+
import androidx.core.app.ActivityCompat;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Runtime location permission checks for EXIF capture.
|
|
10
|
+
* <p>
|
|
11
|
+
* Capacitor's cached {@link PermissionState} can diverge from the OS grant state; always
|
|
12
|
+
* verify both before requesting location and before settling a capture call.
|
|
13
|
+
*/
|
|
14
|
+
public final class LocationPermissionHelper {
|
|
15
|
+
|
|
16
|
+
private LocationPermissionHelper() {}
|
|
17
|
+
|
|
18
|
+
public static boolean hasRuntimeLocationPermissions(Context context) {
|
|
19
|
+
return (
|
|
20
|
+
ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ||
|
|
21
|
+
ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public static boolean canCaptureWithExifLocation(Context context) {
|
|
26
|
+
return canCaptureWithExifLocation(hasRuntimeLocationPermissions(context));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static boolean canCaptureWithExifLocation(boolean hasRuntimeLocationPermissions) {
|
|
30
|
+
return hasRuntimeLocationPermissions;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
package app.capgo.capacitor.camera.preview;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertFalse;
|
|
4
|
+
import static org.junit.Assert.assertTrue;
|
|
5
|
+
import static org.robolectric.Shadows.shadowOf;
|
|
6
|
+
|
|
7
|
+
import android.Manifest;
|
|
8
|
+
import android.app.Application;
|
|
9
|
+
import androidx.test.core.app.ApplicationProvider;
|
|
10
|
+
import org.junit.Test;
|
|
11
|
+
import org.junit.runner.RunWith;
|
|
12
|
+
import org.robolectric.RobolectricTestRunner;
|
|
13
|
+
import org.robolectric.annotation.Config;
|
|
14
|
+
|
|
15
|
+
@RunWith(RobolectricTestRunner.class)
|
|
16
|
+
@Config(sdk = 31)
|
|
17
|
+
public class LocationPermissionHelperContextTest {
|
|
18
|
+
|
|
19
|
+
@Test
|
|
20
|
+
public void canCaptureWithExifLocationContextOverloadAllowsFineOnly() {
|
|
21
|
+
Application application = (Application) ApplicationProvider.getApplicationContext();
|
|
22
|
+
shadowOf(application).grantPermissions(Manifest.permission.ACCESS_FINE_LOCATION);
|
|
23
|
+
assertTrue(LocationPermissionHelper.canCaptureWithExifLocation(application));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@Test
|
|
27
|
+
public void canCaptureWithExifLocationContextOverloadAllowsCoarseOnly() {
|
|
28
|
+
Application application = (Application) ApplicationProvider.getApplicationContext();
|
|
29
|
+
shadowOf(application).grantPermissions(Manifest.permission.ACCESS_COARSE_LOCATION);
|
|
30
|
+
assertTrue(LocationPermissionHelper.canCaptureWithExifLocation(application));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@Test
|
|
34
|
+
public void canCaptureWithExifLocationContextOverloadDeniesWhenNeitherGranted() {
|
|
35
|
+
Application application = (Application) ApplicationProvider.getApplicationContext();
|
|
36
|
+
assertFalse(LocationPermissionHelper.canCaptureWithExifLocation(application));
|
|
37
|
+
}
|
|
38
|
+
}
|
package/android/src/test/java/app/capgo/capacitor/camera/preview/LocationPermissionHelperTest.java
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package app.capgo.capacitor.camera.preview;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertFalse;
|
|
4
|
+
import static org.junit.Assert.assertTrue;
|
|
5
|
+
|
|
6
|
+
import org.junit.Test;
|
|
7
|
+
|
|
8
|
+
public class LocationPermissionHelperTest {
|
|
9
|
+
|
|
10
|
+
@Test
|
|
11
|
+
public void canCaptureWithExifLocationUsesRuntimePermissionOnly() {
|
|
12
|
+
assertTrue(LocationPermissionHelper.canCaptureWithExifLocation(true));
|
|
13
|
+
assertFalse(LocationPermissionHelper.canCaptureWithExifLocation(false));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@Test
|
|
17
|
+
public void runtimeAccessAllowsExifCaptureRegardlessOfCapacitorCache() {
|
|
18
|
+
assertTrue(LocationPermissionHelper.canCaptureWithExifLocation(true));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@Test
|
|
22
|
+
public void missingRuntimePermissionsFallsBackToGpsLessCapture() {
|
|
23
|
+
assertFalse(LocationPermissionHelper.canCaptureWithExifLocation(false));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -35,7 +35,7 @@ extension UIWindow {
|
|
|
35
35
|
*/
|
|
36
36
|
@objc(CameraPreview)
|
|
37
37
|
public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelegate {
|
|
38
|
-
private let pluginVersion: String = "8.11.
|
|
38
|
+
private let pluginVersion: String = "8.11.8"
|
|
39
39
|
public let identifier = "CameraPreviewPlugin"
|
|
40
40
|
public let jsName = "CameraPreview"
|
|
41
41
|
public let pluginMethods: [CAPPluginMethod] = [
|