cordova.plugins.diagnostic 7.1.2 → 7.1.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # CHANGELOG
2
2
 
3
+ **v7.1.4**
4
+ * (android) bugfix: decide if a permission is implicitly granted by checking if the device runtime is less than, but the build SDK used for the app is greater is or equal than, the SDK version in which the permission was added.
5
+ * Resolves [#508](https://github.com/dpa99c/cordova-diagnostic-plugin/issues/508)
6
+ * (android) tweak: throw error if a requested runtime permission is not supported by the build SDK version
7
+ * (android) bugfix: when requesting camera permission, storage permission should also be requested by default if not specified but is currently not being
8
+
9
+
10
+ **v7.1.3**
11
+ * (android) update camera module to support READ_MEDIA permissions on Android 13+
12
+ * (android): For new runtime permissions added in API 33, consider them implicitly granted if the build SDK >= 33 and device runtime is < 33.
13
+ * Resolves [#493](https://github.com/dpa99c/cordova-diagnostic-plugin/issues/493)
14
+ * (android) fix: Return error if attempting to change Bluetooth state when build SDK >= API 33 as this is no longer support.
15
+ * Resolves [#496](https://github.com/dpa99c/cordova-diagnostic-plugin/issues/496)
16
+ * (android) fix: getExternalSdCardDetails on API 33
17
+ * Merged from PR [#495](https://github.com/dpa99c/cordova-diagnostic-plugin/pull/495)
18
+ * (types) Using unlimited arrays in the TypeScript definition
19
+ * Merged from PR [#497](https://github.com/dpa99c/cordova-diagnostic-plugin/pull/497)
20
+
21
+
3
22
  **v7.1.2**
4
23
  * (Android) fix: Data roaming setting not available on API 32+
5
24
  * (Android) Support new media storage permissions on Android 13 / API 33.
package/README.md CHANGED
@@ -2194,13 +2194,11 @@ Notes:
2194
2194
  - On Android & iOS this returns true if the device has a camera AND the application is authorized to use it.
2195
2195
 
2196
2196
  Notes for Android:
2197
- - On Android by default this checks run-time permission for both `READ_EXTERNAL_STORAGE` and `CAMERA` because [cordova-plugin-camera@2.2+](https://github.com/apache/cordova-plugin-camera) requires both of these permissions.
2198
- - The call signature `cordova.plugins.diagnostic.isCameraAvailable(successCallback, errorCallback, externalStorage)` is also supported for benefit of the [ionic-native Promise API wrapper](https://github.com/driftyco/ionic-native/blob/master/src/%40ionic-native/plugins/diagnostic/index.ts).
2197
+ - By default this also checks run-time storage permissions in addition to `CAMERA` permission because [cordova-plugin-camera](https://github.com/apache/cordova-plugin-camera) requires both of these permission sets.
2198
+ - On Android 13+, storage permissions are `READ_MEDIA_IMAGES` and `READ_MEDIA_VIDEO`. On Android 12 and below, storage permissions are `READ_EXTERNAL_STORAGE` and `WRITE_EXTERNAL_STORAGE`.
2199
2199
 
2200
2200
  ```
2201
- cordova.plugins.diagnostic.isCameraAvailable(params);
2202
- cordova.plugins.diagnostic.isCameraAvailable(successCallback, errorCallback, params)
2203
- cordova.plugins.diagnostic.isCameraAvailable(successCallback, errorCallback, externalStorage)
2201
+ cordova.plugins.diagnostic.isCameraAvailable(successCallback, errorCallback, storage)
2204
2202
  ```
2205
2203
 
2206
2204
  #### Parameters
@@ -2209,32 +2207,11 @@ cordova.plugins.diagnostic.isCameraAvailable(successCallback, errorCallback, ext
2209
2207
  The function is passed a single boolean parameter which is TRUE if camera is present and authorized for use.
2210
2208
  - {Function} errorCallback - The callback which will be called when operation encounters an error.
2211
2209
  The function is passed a single string parameter containing the error message.
2212
- - {Boolean} externalStorage - (Android only) If true, checks permission for `READ_EXTERNAL_STORAGE` in addition to `CAMERA` run-time permission.
2213
- Defaults to true.
2210
+ - {Boolean} storage - (Android only) If true, requests storage permissions in addition to `CAMERA` run-time permission. Defaults to true.
2214
2211
 
2215
2212
 
2216
2213
  #### Example usage
2217
2214
 
2218
- cordova.plugins.diagnostic.isCameraAvailable({
2219
- successCallback: function(available){
2220
- console.log("Camera is " + (available ? "available" : "not available"));
2221
- },
2222
- errorCallback: function(error){
2223
- console.error("The following error occurred: "+error);
2224
- },
2225
- externalStorage: false
2226
- });
2227
-
2228
- cordova.plugins.diagnostic.isCameraAvailable(
2229
- function(available){
2230
- console.log("Camera is " + (available ? "available" : "not available"));
2231
- }, function(error){
2232
- console.error("The following error occurred: "+error);
2233
- }, {
2234
- externalStorage: false
2235
- }
2236
- );
2237
-
2238
2215
  cordova.plugins.diagnostic.isCameraAvailable(
2239
2216
  function(available){
2240
2217
  console.log("Camera is " + (available ? "available" : "not available"));
@@ -2251,13 +2228,11 @@ Checks if the application is authorized to use the camera.
2251
2228
 
2252
2229
  Notes for Android:
2253
2230
  - This is intended for Android 6 / API 23 and above. Calling on Android 5.1 / API 22 and below will always return TRUE as permissions are already granted at installation time.
2254
- - By default this checks run-time permission for both `READ_EXTERNAL_STORAGE` and `CAMERA` because [cordova-plugin-camera@2.2+](https://github.com/apache/cordova-plugin-camera) requires both of these permissions.
2255
- - The call signature `cordova.plugins.diagnostic.isCameraAuthorized(successCallback, errorCallback, externalStorage)` is also supported for benefit of the [ionic-native Promise API wrapper](https://github.com/driftyco/ionic-native/blob/master/src/%40ionic-native/plugins/diagnostic/index.ts).
2231
+ - By default this also checks run-time storage permissions in addition to `CAMERA` permission because [cordova-plugin-camera](https://github.com/apache/cordova-plugin-camera) requires both of these permission sets.
2232
+ - On Android 13+, storage permissions are `READ_MEDIA_IMAGES` and `READ_MEDIA_VIDEO`. On Android 12 and below, storage permissions are `READ_EXTERNAL_STORAGE` and `WRITE_EXTERNAL_STORAGE`.
2256
2233
 
2257
2234
  ```
2258
- cordova.plugins.diagnostic.isCameraAuthorized(params);
2259
- cordova.plugins.diagnostic.isCameraAuthorized(successCallback, errorCallback, params)
2260
- cordova.plugins.diagnostic.isCameraAuthorized(successCallback, errorCallback, externalStorage)
2235
+ cordova.plugins.diagnostic.isCameraAuthorized(successCallback, errorCallback, storage)
2261
2236
  ```
2262
2237
 
2263
2238
  #### Parameters
@@ -2266,31 +2241,10 @@ cordova.plugins.diagnostic.isCameraAuthorized(successCallback, errorCallback, ex
2266
2241
  The function is passed a single boolean parameter which is TRUE if camera is authorized for use.
2267
2242
  - {Function} errorCallback - The callback which will be called when operation encounters an error.
2268
2243
  The function is passed a single string parameter containing the error message.
2269
- - {Boolean} externalStorage - (Android only) If true, checks permission for `READ_EXTERNAL_STORAGE` in addition to `CAMERA` run-time permission.
2270
- Defaults to true.
2244
+ - {Boolean} storage - (Android only) If true, requests storage permissions in addition to `CAMERA` run-time permission. Defaults to true.
2271
2245
 
2272
2246
  #### Example usage
2273
2247
 
2274
- cordova.plugins.diagnostic.isCameraAuthorized({
2275
- successCallback: function(authorized){
2276
- console.log("App is " + (authorized ? "authorized" : "denied") + " access to the camera");
2277
- },
2278
- errorCallback: function(error){
2279
- console.error("The following error occurred: "+error);
2280
- },
2281
- externalStorage: false
2282
- });
2283
-
2284
- cordova.plugins.diagnostic.isCameraAuthorized(
2285
- function(authorized){
2286
- console.log("App is " + (authorized ? "authorized" : "denied") + " access to the camera");
2287
- }, function(error){
2288
- console.error("The following error occurred: "+error);
2289
- }, {
2290
- externalStorage: false
2291
- }
2292
- );
2293
-
2294
2248
  cordova.plugins.diagnostic.isCameraAuthorized(
2295
2249
  function(authorized){
2296
2250
  console.log("App is " + (authorized ? "authorized" : "denied") + " access to the camera");
@@ -2307,13 +2261,11 @@ Returns the camera authorization status for the application.
2307
2261
 
2308
2262
  Notes for Android:
2309
2263
  - This is intended for Android 6 / API 23 and above. Calling on Android 5.1 / API 22 and below will always return GRANTED status as permissions are already granted at installation time.
2310
- - By default this checks run-time permission for both `READ_EXTERNAL_STORAGE` and `CAMERA` because [cordova-plugin-camera@2.2+](https://github.com/apache/cordova-plugin-camera) requires both of these permissions.
2311
- - The call signature `cordova.plugins.diagnostic.getCameraAuthorizationStatus(successCallback, errorCallback, externalStorage)` is also supported for benefit of the [ionic-native Promise API wrapper](https://github.com/driftyco/ionic-native/blob/master/src/%40ionic-native/plugins/diagnostic/index.ts).
2264
+ - By default this also checks run-time storage permissions in addition to `CAMERA` permission because [cordova-plugin-camera](https://github.com/apache/cordova-plugin-camera) requires both of these permission sets.
2265
+ - On Android 13+, storage permissions are `READ_MEDIA_IMAGES` and `READ_MEDIA_VIDEO`. On Android 12 and below, storage permissions are `READ_EXTERNAL_STORAGE` and `WRITE_EXTERNAL_STORAGE`.
2312
2266
 
2313
2267
  ```
2314
- cordova.plugins.diagnostic.getCameraAuthorizationStatus(params);
2315
- cordova.plugins.diagnostic.getCameraAuthorizationStatus(successCallback, errorCallback, params)
2316
- cordova.plugins.diagnostic.getCameraAuthorizationStatus(successCallback, errorCallback, externalStorage)
2268
+ cordova.plugins.diagnostic.getCameraAuthorizationStatus(successCallback, errorCallback, storage)
2317
2269
  ```
2318
2270
 
2319
2271
  #### Parameters
@@ -2322,36 +2274,11 @@ cordova.plugins.diagnostic.getCameraAuthorizationStatus(successCallback, errorCa
2322
2274
  The function is passed a single string parameter which indicates the authorization status as a [permissionStatus constant](#permissionstatus-constants).
2323
2275
  - {Function} errorCallback - The callback which will be called when operation encounters an error.
2324
2276
  The function is passed a single string parameter containing the error message.
2325
- - {Boolean} externalStorage - (Android only) If true, checks permission for `READ_EXTERNAL_STORAGE` in addition to `CAMERA` run-time permission.
2326
- Defaults to true.
2277
+ - {Boolean} storage - (Android only) If true, requests storage permissions in addition to `CAMERA` run-time permission. Defaults to true.
2327
2278
 
2328
2279
 
2329
2280
  #### Example usage
2330
2281
 
2331
- cordova.plugins.diagnostic.getCameraAuthorizationStatus({
2332
- successCallback: function(status){
2333
- if(status === cordova.plugins.diagnostic.permissionStatus.GRANTED){
2334
- console.log("Camera use is authorized");
2335
- }
2336
- },
2337
- errorCallback: function(error){
2338
- console.error("The following error occurred: "+error);
2339
- },
2340
- externalStorage: false
2341
- });
2342
-
2343
- cordova.plugins.diagnostic.getCameraAuthorizationStatus(
2344
- function(status){
2345
- if(status === cordova.plugins.diagnostic.permissionStatus.GRANTED){
2346
- console.log("Camera use is authorized");
2347
- }
2348
- }, function(error){
2349
- console.error("The following error occurred: "+error);
2350
- }, {
2351
- externalStorage: false
2352
- }
2353
- );
2354
-
2355
2282
  cordova.plugins.diagnostic.getCameraAuthorizationStatus(
2356
2283
  function(status){
2357
2284
  if(status === cordova.plugins.diagnostic.permissionStatus.GRANTED){
@@ -2376,49 +2303,25 @@ this plugin provides a default message, but you should override this with your s
2376
2303
 
2377
2304
  Notes for Android:
2378
2305
  - This is intended for Android 6 / API 23 and above. Calling on Android 5.1 / API 22 and below will have no effect as the permissions are already granted at installation time.
2379
- - By default this requests run-time permission for both `READ_EXTERNAL_STORAGE` and `CAMERA` because [cordova-plugin-camera@2.2+](https://github.com/apache/cordova-plugin-camera) requires both of these permissions.
2306
+ - By default this requests run-time storage permissions in addition to `CAMERA` permission because [cordova-plugin-camera](https://github.com/apache/cordova-plugin-camera) requires both of these permission sets.
2307
+ - On Android 13+, storage permissions are `READ_MEDIA_IMAGES` and `READ_MEDIA_VIDEO`. On Android 12 and below, storage permissions are `READ_EXTERNAL_STORAGE` and `WRITE_EXTERNAL_STORAGE`.
2380
2308
  - Requested run-time permissions which must be added to `AndroidManifest.xml` - see [Android camera permissions](#android-camera-permissions).
2381
- - The call signature `cordova.plugins.diagnostic.requestCameraAuthorization(successCallback, errorCallback, externalStorage)` is also supported for benefit of the [ionic-native Promise API wrapper](https://github.com/driftyco/ionic-native/blob/master/src/%40ionic-native/plugins/diagnostic/index.ts).
2382
2309
 
2383
2310
  ```
2384
- cordova.plugins.diagnostic.requestCameraAuthorization(params);
2385
- cordova.plugins.diagnostic.requestCameraAuthorization(successCallback, errorCallback, params)
2386
- cordova.plugins.diagnostic.requestCameraAuthorization(successCallback, errorCallback, externalStorage)
2311
+ cordova.plugins.diagnostic.requestCameraAuthorization(successCallback, errorCallback, storage)
2387
2312
  ```
2388
2313
 
2389
2314
  #### Parameters
2390
2315
 
2391
2316
  - {Object} params - (optional) parameters:
2392
2317
  - {Function} successCallback - The callback which will be called when operation is successful.
2393
- The function is passed a single string parameter indicating whether access to the camera was granted or denied:
2394
- `cordova.plugins.diagnostic.permissionStatus.GRANTED` or `cordova.plugins.diagnostic.permissionStatus.DENIED_ALWAYS`
2318
+ The function is passed a single string parameter indicating the resulting permission status.
2395
2319
  - {Function} errorCallback - The callback which will be called when operation encounters an error.
2396
2320
  The function is passed a single string parameter containing the error message.
2397
- - {Boolean} externalStorage - (Android only) If true, requests permission for `READ_EXTERNAL_STORAGE` in addition to `CAMERA` run-time permission.
2398
- Defaults to true.
2321
+ - {Boolean} storage - (Android only) If true, requests storage permissions in addition to `CAMERA` run-time permission. Defaults to true.
2399
2322
 
2400
2323
  #### Example usage
2401
2324
 
2402
- cordova.plugins.diagnostic.requestCameraAuthorization({
2403
- successCallback: function(status){
2404
- console.log("Authorization request for camera use was " + (status == cordova.plugins.diagnostic.permissionStatus.GRANTED ? "granted" : "denied"));
2405
- },
2406
- errorCallback: function(error){
2407
- console.error(error);
2408
- },
2409
- externalStorage: false
2410
- });
2411
-
2412
- cordova.plugins.diagnostic.requestCameraAuthorization(
2413
- function(status){
2414
- console.log("Authorization request for camera use was " + (status == cordova.plugins.diagnostic.permissionStatus.GRANTED ? "granted" : "denied"));
2415
- }, function(error){
2416
- console.error("The following error occurred: "+error);
2417
- }, {
2418
- externalStorage: false
2419
- }
2420
- );
2421
-
2422
2325
  cordova.plugins.diagnostic.requestCameraAuthorization(
2423
2326
  function(status){
2424
2327
  console.log("Authorization request for camera use was " + (status == cordova.plugins.diagnostic.permissionStatus.GRANTED ? "granted" : "denied"));
@@ -1001,7 +1001,7 @@ interface Diagnostic {
1001
1001
  * @param errorCallback
1002
1002
  */
1003
1003
  presentLimitedLibraryPicker?: (
1004
- successCallback: (identifiers?: [string]) => void,
1004
+ successCallback: (identifiers?: string[]) => void,
1005
1005
  errorCallback: (error: string) => void
1006
1006
  ) => void;
1007
1007
 
@@ -1149,7 +1149,7 @@ interface Diagnostic {
1149
1149
  requestBluetoothAuthorization?: (
1150
1150
  successCallback: () => void,
1151
1151
  errorCallback: (error: string) => void,
1152
- permissions?: ([string])
1152
+ permissions?: (string[])
1153
1153
  ) => void;
1154
1154
 
1155
1155
  /**
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "7.1.2",
2
+ "version": "7.1.4",
3
3
  "name": "cordova.plugins.diagnostic",
4
4
  "cordova_name": "Diagnostic",
5
5
  "description": "Cordova/Phonegap plugin to check the state of Location/WiFi/Camera/Bluetooth device settings.",
package/plugin.xml CHANGED
@@ -2,7 +2,7 @@
2
2
  <plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
3
3
  xmlns:android="http://schemas.android.com/apk/res/android"
4
4
  id="cordova.plugins.diagnostic"
5
- version="7.1.2">
5
+ version="7.1.4">
6
6
 
7
7
  <name>Diagnostic</name>
8
8
  <description>Cordova/Phonegap plugin to check the state of Location/WiFi/Camera/Bluetooth device settings.</description>
@@ -143,6 +143,55 @@ public class Diagnostic extends CordovaPlugin{
143
143
  permissionsMap = Collections.unmodifiableMap(_permissionsMap);
144
144
  }
145
145
 
146
+ /**
147
+ * Map of minimum build SDK version supported by defined permissions
148
+ */
149
+ protected static final Map<String, Integer> minSdkPermissionMap;
150
+ static {
151
+ Map<String, Integer> _permissionsMap = new HashMap <String, Integer>();
152
+
153
+ // API 26+
154
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "ANSWER_PHONE_CALLS", 26);
155
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "READ_PHONE_NUMBERS", 26);
156
+
157
+ // API 28+
158
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "ACCEPT_HANDOVER", 28);
159
+
160
+ // API 29+
161
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "ACCESS_BACKGROUND_LOCATION", 29);
162
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "ACCESS_MEDIA_LOCATION", 29);
163
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "ACTIVITY_RECOGNITION", 29);
164
+
165
+ // API 31+
166
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "BLUETOOTH_ADVERTISE", 31);
167
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "BLUETOOTH_CONNECT", 31);
168
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "BLUETOOTH_SCAN", 31);
169
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "UWB_RANGING", 31);
170
+
171
+ // API 33+
172
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "BODY_SENSORS_BACKGROUND", 33);
173
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "NEARBY_WIFI_DEVICES", 33);
174
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "POST_NOTIFICATIONS", 33);
175
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "READ_MEDIA_AUDIO", 33);
176
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "READ_MEDIA_IMAGES", 33);
177
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "READ_MEDIA_VIDEO", 33);
178
+
179
+ minSdkPermissionMap = Collections.unmodifiableMap(_permissionsMap);
180
+ }
181
+
182
+ /**
183
+ * Map of maximum build SDK version supported by defined permissions
184
+ */
185
+ protected static final Map<String, Integer> maxSdkPermissionMap;
186
+ static {
187
+ Map<String, Integer> _permissionsMap = new HashMap <String, Integer>();
188
+
189
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "READ_EXTERNAL_STORAGE", 32);
190
+ Diagnostic.addBiDirMapEntry(_permissionsMap, "WRITE_EXTERNAL_STORAGE", 29);
191
+
192
+ maxSdkPermissionMap = Collections.unmodifiableMap(_permissionsMap);
193
+ }
194
+
146
195
 
147
196
  /*
148
197
  * Map of permission request code to callback context
@@ -553,18 +602,10 @@ public class Diagnostic extends CordovaPlugin{
553
602
  if(!permissionsMap.containsKey(permission)){
554
603
  throw new Exception("Permission name '"+permission+"' is not a valid permission");
555
604
  }
556
- if(Build.VERSION.SDK_INT < 29 && permission.equals("ACCESS_BACKGROUND_LOCATION")){
557
- // This version of Android doesn't support background location permission so check for standard coarse location permission
558
- permission = "ACCESS_COARSE_LOCATION";
559
- }
560
- if(Build.VERSION.SDK_INT < 29 && permission.equals("ACTIVITY_RECOGNITION")){
561
- // This version of Android doesn't support activity recognition permission so check for body sensors permission
562
- permission = "BODY_SENSORS";
563
- }
564
605
  String androidPermission = permissionsMap.get(permission);
565
606
  Log.v(TAG, "Get authorisation status for "+androidPermission);
566
607
  boolean granted = hasRuntimePermission(androidPermission);
567
- if(granted){
608
+ if(granted || isPermissionImplicitlyGranted(permission)){
568
609
  statuses.put(permission, Diagnostic.STATUS_GRANTED);
569
610
  }else{
570
611
  boolean showRationale = shouldShowRequestPermissionRationale(this.cordova.getActivity(), androidPermission);
@@ -587,13 +628,27 @@ public class Diagnostic extends CordovaPlugin{
587
628
  JSONArray permissionsToRequest = new JSONArray();
588
629
  for(int i = 0; i<currentPermissionsStatuses.names().length(); i++){
589
630
  String permission = currentPermissionsStatuses.names().getString(i);
631
+
632
+ if(!permissionsMap.containsKey(permission)){
633
+ throw new Exception("Permission name '"+permission+"' is not a supported permission");
634
+ }
635
+
590
636
  boolean granted = currentPermissionsStatuses.getString(permission) == Diagnostic.STATUS_GRANTED;
591
- if(granted){
637
+ if(granted || isPermissionImplicitlyGranted(permission)){
592
638
  Log.d(TAG, "Permission already granted for "+permission);
593
639
  JSONObject requestStatuses = permissionStatuses.get(String.valueOf(requestId));
594
640
  requestStatuses.put(permission, Diagnostic.STATUS_GRANTED);
595
641
  permissionStatuses.put(String.valueOf(requestId), requestStatuses);
596
642
  }else{
643
+
644
+ if(minSdkPermissionMap.containsKey(permission) && getDeviceRuntimeSdkVersion() < minSdkPermissionMap.get(permission)){
645
+ throw new Exception("Permission "+permission+" not supported for build SDK version "+getDeviceRuntimeSdkVersion());
646
+ }
647
+
648
+ if(maxSdkPermissionMap.containsKey(permission) && getDeviceRuntimeSdkVersion() > maxSdkPermissionMap.get(permission)){
649
+ throw new Exception("Permission "+permission+" not supported for build SDK version "+getDeviceRuntimeSdkVersion());
650
+ }
651
+
597
652
  String androidPermission = permissionsMap.get(permission);
598
653
  Log.d(TAG, "Requesting permission for "+androidPermission);
599
654
  permissionsToRequest.put(androidPermission);
@@ -609,6 +664,22 @@ public class Diagnostic extends CordovaPlugin{
609
664
  }
610
665
  }
611
666
 
667
+ protected boolean isPermissionImplicitlyGranted(String permission) throws Exception{
668
+ boolean isImplicitlyGranted = false;
669
+ int buildTargetSdkVersion = getBuildTargetSdkVersion();
670
+ int deviceRuntimeSdkVersion = getDeviceRuntimeSdkVersion();
671
+
672
+ if(minSdkPermissionMap.containsKey(permission)){
673
+ int minSDKForPermission = minSdkPermissionMap.get(permission);
674
+ if(buildTargetSdkVersion >= minSDKForPermission && deviceRuntimeSdkVersion < minSDKForPermission) {
675
+ isImplicitlyGranted = true;
676
+ Log.v(TAG, "Permission "+permission+" is implicitly granted because while it's defined in build SDK version "+buildTargetSdkVersion+", the device runtime SDK version "+deviceRuntimeSdkVersion+" does not support it.");
677
+ }
678
+ }
679
+
680
+ return isImplicitlyGranted;
681
+ }
682
+
612
683
  protected void sendRuntimeRequestResult(int requestId){
613
684
  String sRequestId = String.valueOf(requestId);
614
685
  CallbackContext context = callbackContexts.get(sRequestId);
@@ -863,31 +934,51 @@ public class Diagnostic extends CordovaPlugin{
863
934
  public JSONObject getDeviceOSVersion() throws Exception{
864
935
  JSONObject details = new JSONObject();
865
936
  details.put("version", Build.VERSION.RELEASE);
866
- details.put("apiLevel", Build.VERSION.SDK_INT);
867
- details.put("apiName", getNameForApiLevel(Build.VERSION.SDK_INT));
937
+ int buildVersion = getDeviceRuntimeSdkVersion();
938
+ details.put("apiLevel", buildVersion);
939
+ details.put("apiName", getNameForApiLevel(buildVersion));
868
940
  return details;
869
941
  }
870
942
 
943
+ protected int getDeviceRuntimeSdkVersion() {
944
+ return Build.VERSION.SDK_INT;
945
+ }
946
+
871
947
  public JSONObject getBuildOSVersion() throws Exception{
872
948
  JSONObject details = new JSONObject();
949
+ int targetVersion = getBuildTargetSdkVersion();
950
+ int minVersion = getBuildMinimumSdkVersion();
951
+
952
+ details.put("targetApiLevel", targetVersion);
953
+ details.put("targetApiName", getNameForApiLevel(targetVersion));
954
+ details.put("minApiLevel", minVersion);
955
+ details.put("minApiName", getNameForApiLevel(minVersion));
956
+ return details;
957
+ }
958
+
959
+ protected int getBuildTargetSdkVersion() throws Exception{
873
960
  int targetVersion = 0;
874
- int minVersion = 0;
875
961
  Activity activity = instance.cordova.getActivity();
876
962
  ApplicationInfo applicationInfo = activity.getPackageManager().getApplicationInfo(activity.getPackageName(), 0);
877
963
  if (applicationInfo != null) {
878
964
  targetVersion = applicationInfo.targetSdkVersion;
965
+ }
966
+ return targetVersion;
967
+ }
968
+
969
+ protected int getBuildMinimumSdkVersion() throws Exception{
970
+ int minVersion = 0;
971
+ Activity activity = instance.cordova.getActivity();
972
+ ApplicationInfo applicationInfo = activity.getPackageManager().getApplicationInfo(activity.getPackageName(), 0);
973
+ if (applicationInfo != null) {
879
974
  if(Build.VERSION.SDK_INT >= 24){
880
975
  minVersion = applicationInfo.minSdkVersion;
881
976
  }
882
977
  }
883
-
884
- details.put("targetApiLevel", targetVersion);
885
- details.put("targetApiName", getNameForApiLevel(targetVersion));
886
- details.put("minApiLevel", minVersion);
887
- details.put("minApiName", getNameForApiLevel(minVersion));
888
- return details;
978
+ return minVersion;
889
979
  }
890
980
 
981
+
891
982
  // https://stackoverflow.com/a/55946200/777265
892
983
  protected String getNameForApiLevel(int apiLevel) throws Exception{
893
984
  Field[] fields = Build.VERSION_CODES.class.getFields();
@@ -244,6 +244,10 @@ public class Diagnostic_Bluetooth extends CordovaPlugin {
244
244
  callbackContext.error("Cannot change Bluetooth state as device does not support Bluetooth");
245
245
  return;
246
246
  }
247
+ if(Build.VERSION.SDK_INT >= 33){ // TIRAMISU / Android 13
248
+ callbackContext.error("Cannot change Bluetooth state on Android 13+ as this is no longer supported");
249
+ return;
250
+ }
247
251
 
248
252
  BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
249
253
  boolean isEnabled = bluetoothAdapter.isEnabled();
@@ -252,9 +256,11 @@ public class Diagnostic_Bluetooth extends CordovaPlugin {
252
256
 
253
257
  if (statuses.getString("BLUETOOTH_CONNECT").equals(Diagnostic.STATUS_GRANTED)) {
254
258
  if (enable && !isEnabled) {
259
+ https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#enable()
255
260
  bluetoothAdapter.enable();
256
261
  }
257
262
  else if(!enable && isEnabled) {
263
+ https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#disable()
258
264
  bluetoothAdapter.disable();
259
265
  }
260
266
  callbackContext.success();
@@ -149,24 +149,24 @@ public class Diagnostic_Camera extends CordovaPlugin{
149
149
  * Internals
150
150
  ***********/
151
151
 
152
- private String[] getPermissions(boolean externalStorage){
152
+ private String[] getPermissions(boolean storage){
153
153
  String[] permissions = {cameraPermission};
154
- if(externalStorage){
154
+ if(storage){
155
155
  permissions = Diagnostic.instance.concatStrings(permissions, storagePermissions);
156
156
  }
157
157
  return permissions;
158
158
  }
159
159
 
160
160
  private void requestCameraAuthorization(JSONArray args, CallbackContext callbackContext) throws Exception{
161
- boolean externalStorage = args.getBoolean(0);
162
- String[] permissions = getPermissions(externalStorage);
161
+ boolean storage = args.getBoolean(0);
162
+ String[] permissions = getPermissions(storage);
163
163
  int requestId = Diagnostic.instance.storeContextByRequestId(callbackContext);
164
164
  Diagnostic.instance._requestRuntimePermissions(Diagnostic.instance.stringArrayToJsonArray(permissions), requestId);
165
165
  }
166
166
 
167
167
  private void getCameraAuthorizationStatus(JSONArray args, CallbackContext callbackContext) throws Exception{
168
- boolean externalStorage = args.getBoolean(0);
169
- String[] permissions = getPermissions(externalStorage);
168
+ boolean storage = args.getBoolean(0);
169
+ String[] permissions = getPermissions(storage);
170
170
  JSONObject statuses = Diagnostic.instance._getPermissionsAuthorizationStatus(permissions);
171
171
  callbackContext.success(statuses);
172
172
  }
@@ -136,11 +136,15 @@ public class Diagnostic_External_Storage extends CordovaPlugin{
136
136
  ***********/
137
137
 
138
138
  protected void getExternalSdCardDetails() throws Exception{
139
- String permission = diagnostic.permissionsMap.get(externalStoragePermission);
140
- if (diagnostic.hasRuntimePermission(permission)) {
139
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
141
140
  _getExternalSdCardDetails();
142
141
  } else {
143
- diagnostic.requestRuntimePermission(permission, Diagnostic.GET_EXTERNAL_SD_CARD_DETAILS_PERMISSION_REQUEST);
142
+ String permission = diagnostic.permissionsMap.get(externalStoragePermission);
143
+ if (diagnostic.hasRuntimePermission(permission)) {
144
+ _getExternalSdCardDetails();
145
+ } else {
146
+ diagnostic.requestRuntimePermission(permission, Diagnostic.GET_EXTERNAL_SD_CARD_DETAILS_PERMISSION_REQUEST);
147
+ }
144
148
  }
145
149
  }
146
150
 
@@ -28,23 +28,6 @@ var Diagnostic_Camera = (function(){
28
28
  *
29
29
  ********************/
30
30
 
31
- function combineCameraStatuses(statuses){
32
- var cameraStatus = statuses[Diagnostic.permission.CAMERA],
33
- storageStatus = statuses[Diagnostic.permission.READ_EXTERNAL_STORAGE] || statuses[Diagnostic.permission.READ_MEDIA_IMAGES],
34
- status;
35
-
36
- if(cameraStatus === Diagnostic.permissionStatus.DENIED_ALWAYS || storageStatus === Diagnostic.permissionStatus.DENIED_ALWAYS){
37
- status = Diagnostic.permissionStatus.DENIED_ALWAYS;
38
- }else if(cameraStatus === Diagnostic.permissionStatus.DENIED_ONCE || storageStatus === Diagnostic.permissionStatus.DENIED_ONCE){
39
- status = Diagnostic.permissionStatus.DENIED_ONCE;
40
- }else if(cameraStatus === Diagnostic.permissionStatus.NOT_REQUESTED || storageStatus === Diagnostic.permissionStatus.NOT_REQUESTED){
41
- status = Diagnostic.permissionStatus.NOT_REQUESTED;
42
- }else{
43
- status = Diagnostic.permissionStatus.GRANTED;
44
- }
45
- return status;
46
- }
47
-
48
31
  function mapFromLegacyCameraApi() {
49
32
  var params;
50
33
  if (typeof arguments[0] === "function") {
@@ -54,11 +37,12 @@ var Diagnostic_Camera = (function(){
54
37
  params.errorCallback = arguments[1];
55
38
  }
56
39
  if(arguments.length > 2 && arguments[2] === false) {
57
- params.externalStorage = arguments[2];
40
+ params.storage = arguments[2];
58
41
  }
59
42
  }else { // if (typeof arguments[0] === "object")
60
43
  params = arguments[0];
61
44
  }
45
+ if(typeof params.storage === 'undefined') params.storage = true; // default to true
62
46
  return params;
63
47
  }
64
48
 
@@ -91,8 +75,10 @@ var Diagnostic_Camera = (function(){
91
75
  * This callback function is passed a single boolean parameter which is TRUE if camera is present and authorized for use.
92
76
  * - {Function} errorCallback - The callback which will be called when the operation encounters an error.
93
77
  * This callback function is passed a single string parameter containing the error message.
94
- * - {Boolean} externalStorage - (Android only) If true, checks permission for READ_EXTERNAL_STORAGE in addition to CAMERA run-time permission.
95
- * cordova-plugin-camera@2.2+ requires both of these permissions. Defaults to true.
78
+ * - {Boolean} storage - (Android only) If true, requests storage permissions in addition to CAMERA run-time permission.
79
+ * On Android 13+, storage permissions are READ_MEDIA_IMAGES and READ_MEDIA_VIDEO. On Android 9-12, storage permission is READ_EXTERNAL_STORAGE.
80
+ * cordova-plugin-camera requires both storage and camera permissions.
81
+ * Defaults to true.
96
82
  */
97
83
  Diagnostic_Camera.isCameraAvailable = function(params) {
98
84
  params = mapFromLegacyCameraApi.apply(this, arguments);
@@ -130,7 +116,9 @@ var Diagnostic_Camera = (function(){
130
116
  * - {Function} successCallback - function to call on successful request for runtime permissions.
131
117
  * This callback function is passed a single string parameter which defines the resulting authorisation status as a value in cordova.plugins.diagnostic.permissionStatus.
132
118
  * - {Function} errorCallback - function to call on failure to request authorisation.
133
- * - {Boolean} externalStorage - (Android only) If true, requests storage permissions for in addition to CAMERA run-time permission.
119
+ * - {Boolean} storage - (Android only) If true, requests storage permissions in addition to CAMERA run-time permission.
120
+ * On Android 13+, storage permissions are READ_MEDIA_IMAGES and READ_MEDIA_VIDEO. On Android 9-12, storage permission is READ_EXTERNAL_STORAGE.
121
+ * cordova-plugin-camera requires both storage and camera permissions.
134
122
  * Defaults to true.
135
123
  */
136
124
  Diagnostic_Camera.requestCameraAuthorization = function(params){
@@ -138,39 +126,41 @@ var Diagnostic_Camera = (function(){
138
126
 
139
127
  params.successCallback = params.successCallback || function(){};
140
128
  var onSuccess = function(statuses){
141
- params.successCallback(numberOfKeys(statuses) > 1 ? combineCameraStatuses(statuses): statuses[Diagnostic.permission.CAMERA]);
129
+ params.successCallback(numberOfKeys(statuses) > 1 ? cordova.plugins.diagnostic._combinePermissionStatuses(statuses): statuses[Diagnostic.permission.CAMERA]);
142
130
  };
143
131
 
144
132
  return cordova.exec(onSuccess,
145
133
  params.errorCallback,
146
134
  'Diagnostic_Camera',
147
135
  'requestCameraAuthorization',
148
- [!!params.externalStorage]);
136
+ [!!params.storage]);
149
137
  };
150
138
 
151
139
  /**
152
140
  * Returns the authorisation status for runtime permissions to use the camera.
153
141
  * Note: this is intended for Android 6 / API 23 and above. Calling on Android 5 / API 22 and below will always return GRANTED status as permissions are already granted at installation time.
154
142
  * @param {Object} params - (optional) parameters:
155
- * - {Function} successCallback - function to call on successful request for runtime permissions status.
143
+ * - {Function} successCallback - function to call on successful request for runtime permission status.
156
144
  * This callback function is passed a single string parameter which defines the current authorisation status as a value in cordova.plugins.diagnostic.permissionStatus.
157
145
  * - {Function} errorCallback - function to call on failure to request authorisation status.
158
- * - {Boolean} externalStorage - (Android only) If true, checks permission for READ_EXTERNAL_STORAGE in addition to CAMERA run-time permission.
159
- * cordova-plugin-camera@2.2+ requires both of these permissions. Defaults to true.
146
+ * - {Boolean} storage - (Android only) If true, requests storage permissions in addition to CAMERA run-time permission.
147
+ * On Android 13+, storage permissions are READ_MEDIA_IMAGES and READ_MEDIA_VIDEO. On Android 9-12, storage permission is READ_EXTERNAL_STORAGE.
148
+ * cordova-plugin-camera requires both storage and camera permissions.
149
+ * Defaults to true.
160
150
  */
161
151
  Diagnostic_Camera.getCameraAuthorizationStatus = function(params){
162
152
  params = mapFromLegacyCameraApi.apply(this, arguments);
163
153
 
164
154
  params.successCallback = params.successCallback || function(){};
165
155
  var onSuccess = function(statuses){
166
- params.successCallback(numberOfKeys(statuses) > 1 ? combineCameraStatuses(statuses): statuses[Diagnostic.permission.CAMERA]);
156
+ params.successCallback(numberOfKeys(statuses) > 1 ? cordova.plugins.diagnostic._combinePermissionStatuses(statuses): statuses[Diagnostic.permission.CAMERA]);
167
157
  };
168
158
 
169
159
  return cordova.exec(onSuccess,
170
160
  params.errorCallback,
171
161
  'Diagnostic_Camera',
172
162
  'getCameraAuthorizationStatus',
173
- [!!params.externalStorage]);
163
+ [!!params.storage]);
174
164
  };
175
165
 
176
166
  /**
@@ -180,8 +170,10 @@ var Diagnostic_Camera = (function(){
180
170
  * - {Function} successCallback - function to call on successful request for runtime permissions status.
181
171
  * This callback function is passed a single boolean parameter which is TRUE if the app currently has runtime authorisation to use location.
182
172
  * - {Function} errorCallback - function to call on failure to request authorisation status.
183
- * - {Boolean} externalStorage - (Android only) If true, checks permission for READ_EXTERNAL_STORAGE in addition to CAMERA run-time permission.
184
- * cordova-plugin-camera@2.2+ requires both of these permissions. Defaults to true.
173
+ * - {Boolean} storage - (Android only) If true, requests storage permissions in addition to CAMERA run-time permission.
174
+ * On Android 13+, storage permissions are READ_MEDIA_IMAGES and READ_MEDIA_VIDEO. On Android 9-12, storage permission is READ_EXTERNAL_STORAGE.
175
+ * cordova-plugin-camera requires both storage and camera permissions.
176
+ * Defaults to true.
185
177
  */
186
178
  Diagnostic_Camera.isCameraAuthorized = function(params){
187
179
  params = mapFromLegacyCameraApi.apply(this, arguments);
@@ -194,7 +186,7 @@ var Diagnostic_Camera = (function(){
194
186
  Diagnostic_Camera.getCameraAuthorizationStatus({
195
187
  successCallback: onSuccess,
196
188
  errorCallback: params.errorCallback,
197
- externalStorage: params.externalStorage
189
+ storage: params.storage
198
190
  });
199
191
  };
200
192
 
@@ -111,12 +111,35 @@ var Diagnostic = (function(){
111
111
  Diagnostic._onNFCStateChange =
112
112
  Diagnostic._onPermissionRequestComplete = function(){};
113
113
 
114
+ Diagnostic._combinePermissionStatuses = function(statuses){
115
+ var status = Diagnostic.permissionStatus.NOT_REQUESTED;
116
+ if(anyStatusIs(statuses, Diagnostic.permissionStatus.DENIED_ALWAYS)){
117
+ status = Diagnostic.permissionStatus.DENIED_ALWAYS;
118
+ }else if(anyStatusIs(statuses, Diagnostic.permissionStatus.DENIED_ONCE)){
119
+ status = Diagnostic.permissionStatus.DENIED_ONCE;
120
+ }else if(anyStatusIs(statuses, Diagnostic.permissionStatus.GRANTED)){
121
+ status = Diagnostic.permissionStatus.GRANTED;
122
+ }
123
+ return status;
124
+ };
125
+
114
126
  /********************
115
127
  *
116
128
  * Internal functions
117
129
  *
118
130
  ********************/
119
131
 
132
+ function anyStatusIs(statuses, status){
133
+ var anyStatus = false;
134
+ for(var permission in statuses){
135
+ if(statuses[permission] === status){
136
+ anyStatus = true;
137
+ break;
138
+ }
139
+ }
140
+ return anyStatus;
141
+ }
142
+
120
143
  function checkForInvalidPermissions(permissions, errorCallback){
121
144
  if(typeof(permissions) !== "object") permissions = [permissions];
122
145
  var valid = true, invalidPermissions = [];
@@ -49,20 +49,13 @@ var Diagnostic_Location = (function(){
49
49
  function combineLocationStatuses(statuses){
50
50
  var coarseStatus = statuses[Diagnostic.permission.ACCESS_COARSE_LOCATION],
51
51
  fineStatus = statuses[Diagnostic.permission.ACCESS_FINE_LOCATION],
52
- backgroundStatus = typeof statuses[Diagnostic.permission.ACCESS_BACKGROUND_LOCATION] !== "undefined" ? statuses[Diagnostic.permission.ACCESS_BACKGROUND_LOCATION] : true
53
- status;
52
+ backgroundStatus = typeof statuses[Diagnostic.permission.ACCESS_BACKGROUND_LOCATION] !== "undefined" ? statuses[Diagnostic.permission.ACCESS_BACKGROUND_LOCATION] : true;
54
53
 
55
- var GRANTED = backgroundStatus === Diagnostic.permissionStatus.GRANTED ? Diagnostic.permissionStatus.GRANTED : Diagnostic.permissionStatus.GRANTED_WHEN_IN_USE;
56
-
57
- if(coarseStatus === Diagnostic.permissionStatus.GRANTED || fineStatus === Diagnostic.permissionStatus.GRANTED){
58
- status = GRANTED;
59
- }else if(coarseStatus === Diagnostic.permissionStatus.DENIED_ONCE || fineStatus === Diagnostic.permissionStatus.DENIED_ONCE){
60
- status = Diagnostic.permissionStatus.DENIED_ONCE;
61
- }else if(coarseStatus === Diagnostic.permissionStatus.DENIED_ALWAYS || fineStatus === Diagnostic.permissionStatus.DENIED_ALWAYS){
62
- status = Diagnostic.permissionStatus.DENIED_ALWAYS;
63
- }else if(coarseStatus === Diagnostic.permissionStatus.NOT_REQUESTED || fineStatus === Diagnostic.permissionStatus.NOT_REQUESTED){
64
- status = Diagnostic.permissionStatus.NOT_REQUESTED;
54
+ var status = cordova.plugins.diagnostic._combinePermissionStatuses([coarseStatus, fineStatus]);
55
+ if(status === Diagnostic.permissionStatus.GRANTED && backgroundStatus !== Diagnostic.permissionStatus.GRANTED){
56
+ status = Diagnostic.permissionStatus.GRANTED_WHEN_IN_USE;
65
57
  }
58
+
66
59
  return status;
67
60
  }
68
61