cordova.plugins.diagnostic 7.2.4 → 7.2.6

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,12 @@
1
1
  # CHANGELOG
2
2
 
3
+ **v7.2.6**
4
+ * (ios) fix: Local Network status check now accepts a configurable timeout, detects permission denials via NWBrowser errors/NSNetService failures, and returns `UNKNOWN` instead of `DENIED_ALWAYS` when the probe times out. This works around an issue where, if the network stack is under load, local network permission may be falsely reported as denied because iOS fails to resolve the Bonjour service within the default timeout period.
5
+
6
+ **v7.2.5**
7
+ * (ios) feat: add check/request local network authorization to Wifi module
8
+ * Resolves [#524](https://github.com/dpa99c/cordova-diagnostic-plugin/issues/524)
9
+
3
10
  **v7.2.4**
4
11
  * (android & ios) feat: add `isCompassAvailable()` to detect availability of compass for device heading.
5
12
  * (doc) update getCameraRollAuthorizationStatus example to include accessLevel parameter
package/README.md CHANGED
@@ -206,145 +206,154 @@ Cordova diagnostic plugin [![Latest Stable Version](https://img.shields.io/npm/v
206
206
  - [isWifiEnabled()](#iswifienabled)
207
207
  - [Parameters](#parameters-51)
208
208
  - [Example usage](#example-usage-51)
209
- - [setWifiState()](#setwifistate)
209
+ - [isLocalNetworkAuthorized()](#islocalnetworkauthorized)
210
210
  - [Parameters](#parameters-52)
211
211
  - [Example usage](#example-usage-52)
212
- - [switchToWifiSettings()](#switchtowifisettings)
213
- - [Camera module](#camera-module)
214
- - [isCameraPresent()](#iscamerapresent)
212
+ - [getLocalNetworkAuthorizationStatus()](#getlocalnetworkauthorizationstatus)
215
213
  - [Parameters](#parameters-53)
216
214
  - [Example usage](#example-usage-53)
217
- - [isCameraAvailable()](#iscameraavailable)
215
+ - [requestLocalNetworkAuthorization()](#requestlocalnetworkauthorization)
218
216
  - [Parameters](#parameters-54)
219
217
  - [Example usage](#example-usage-54)
220
- - [isCameraAuthorized()](#iscameraauthorized)
218
+ - [setWifiState()](#setwifistate)
221
219
  - [Parameters](#parameters-55)
222
220
  - [Example usage](#example-usage-55)
223
- - [getCameraAuthorizationStatus()](#getcameraauthorizationstatus)
221
+ - [switchToWifiSettings()](#switchtowifisettings)
222
+ - [Camera module](#camera-module)
223
+ - [isCameraPresent()](#iscamerapresent)
224
224
  - [Parameters](#parameters-56)
225
225
  - [Example usage](#example-usage-56)
226
- - [getCameraAuthorizationStatuses()](#getcameraauthorizationstatuses)
226
+ - [isCameraAvailable()](#iscameraavailable)
227
227
  - [Parameters](#parameters-57)
228
228
  - [Example usage](#example-usage-57)
229
- - [requestCameraAuthorization()](#requestcameraauthorization)
229
+ - [isCameraAuthorized()](#iscameraauthorized)
230
230
  - [Parameters](#parameters-58)
231
231
  - [Example usage](#example-usage-58)
232
- - [isCameraRollAuthorized()](#iscamerarollauthorized)
232
+ - [getCameraAuthorizationStatus()](#getcameraauthorizationstatus)
233
233
  - [Parameters](#parameters-59)
234
234
  - [Example usage](#example-usage-59)
235
- - [getCameraRollAuthorizationStatus()](#getcamerarollauthorizationstatus)
235
+ - [getCameraAuthorizationStatuses()](#getcameraauthorizationstatuses)
236
236
  - [Parameters](#parameters-60)
237
237
  - [Example usage](#example-usage-60)
238
- - [requestCameraRollAuthorization()](#requestcamerarollauthorization)
238
+ - [requestCameraAuthorization()](#requestcameraauthorization)
239
239
  - [Parameters](#parameters-61)
240
240
  - [Example usage](#example-usage-61)
241
- - [presentLimitedLibraryPicker()](#presentlimitedlibrarypicker)
241
+ - [isCameraRollAuthorized()](#iscamerarollauthorized)
242
242
  - [Parameters](#parameters-62)
243
243
  - [Example usage](#example-usage-62)
244
- - [Notifications module](#notifications-module)
245
- - [remoteNotificationType constants](#remotenotificationtype-constants)
246
- - [Example](#example-4)
247
- - [isRemoteNotificationsEnabled()](#isremotenotificationsenabled)
244
+ - [getCameraRollAuthorizationStatus()](#getcamerarollauthorizationstatus)
248
245
  - [Parameters](#parameters-63)
249
246
  - [Example usage](#example-usage-63)
250
- - [isRegisteredForRemoteNotifications()](#isregisteredforremotenotifications)
247
+ - [requestCameraRollAuthorization()](#requestcamerarollauthorization)
251
248
  - [Parameters](#parameters-64)
252
249
  - [Example usage](#example-usage-64)
253
- - [getRemoteNotificationTypes()](#getremotenotificationtypes)
250
+ - [presentLimitedLibraryPicker()](#presentlimitedlibrarypicker)
254
251
  - [Parameters](#parameters-65)
255
252
  - [Example usage](#example-usage-65)
256
- - [getRemoteNotificationsAuthorizationStatus()](#getremotenotificationsauthorizationstatus)
253
+ - [Notifications module](#notifications-module)
254
+ - [remoteNotificationType constants](#remotenotificationtype-constants)
255
+ - [Example](#example-4)
256
+ - [isRemoteNotificationsEnabled()](#isremotenotificationsenabled)
257
257
  - [Parameters](#parameters-66)
258
258
  - [Example usage](#example-usage-66)
259
- - [requestRemoteNotificationsAuthorization()](#requestremotenotificationsauthorization)
259
+ - [isRegisteredForRemoteNotifications()](#isregisteredforremotenotifications)
260
260
  - [Parameters](#parameters-67)
261
261
  - [Example usage](#example-usage-67)
262
- - [switchToNotificationSettings()](#switchtonotificationsettings)
263
- - [Microphone module](#microphone-module)
264
- - [isMicrophoneAuthorized()](#ismicrophoneauthorized)
262
+ - [getRemoteNotificationTypes()](#getremotenotificationtypes)
265
263
  - [Parameters](#parameters-68)
266
264
  - [Example usage](#example-usage-68)
267
- - [getMicrophoneAuthorizationStatus()](#getmicrophoneauthorizationstatus)
265
+ - [getRemoteNotificationsAuthorizationStatus()](#getremotenotificationsauthorizationstatus)
268
266
  - [Parameters](#parameters-69)
269
267
  - [Example usage](#example-usage-69)
270
- - [requestMicrophoneAuthorization()](#requestmicrophoneauthorization)
268
+ - [requestRemoteNotificationsAuthorization()](#requestremotenotificationsauthorization)
271
269
  - [Parameters](#parameters-70)
272
270
  - [Example usage](#example-usage-70)
273
- - [Contacts module](#contacts-module)
274
- - [isContactsAuthorized()](#iscontactsauthorized)
271
+ - [switchToNotificationSettings()](#switchtonotificationsettings)
272
+ - [Microphone module](#microphone-module)
273
+ - [isMicrophoneAuthorized()](#ismicrophoneauthorized)
275
274
  - [Parameters](#parameters-71)
276
275
  - [Example usage](#example-usage-71)
277
- - [getContactsAuthorizationStatus()](#getcontactsauthorizationstatus)
276
+ - [getMicrophoneAuthorizationStatus()](#getmicrophoneauthorizationstatus)
278
277
  - [Parameters](#parameters-72)
279
278
  - [Example usage](#example-usage-72)
280
- - [requestContactsAuthorization()](#requestcontactsauthorization)
279
+ - [requestMicrophoneAuthorization()](#requestmicrophoneauthorization)
281
280
  - [Parameters](#parameters-73)
282
281
  - [Example usage](#example-usage-73)
283
- - [Calendar module](#calendar-module)
284
- - [isCalendarAuthorized()](#iscalendarauthorized)
282
+ - [Contacts module](#contacts-module)
283
+ - [isContactsAuthorized()](#iscontactsauthorized)
285
284
  - [Parameters](#parameters-74)
286
285
  - [Example usage](#example-usage-74)
287
- - [getCalendarAuthorizationStatus()](#getcalendarauthorizationstatus)
286
+ - [getContactsAuthorizationStatus()](#getcontactsauthorizationstatus)
288
287
  - [Parameters](#parameters-75)
289
288
  - [Example usage](#example-usage-75)
290
- - [requestCalendarAuthorization()](#requestcalendarauthorization)
289
+ - [requestContactsAuthorization()](#requestcontactsauthorization)
291
290
  - [Parameters](#parameters-76)
292
291
  - [Example usage](#example-usage-76)
293
- - [Reminders module](#reminders-module)
294
- - [isRemindersAuthorized()](#isremindersauthorized)
292
+ - [Calendar module](#calendar-module)
293
+ - [isCalendarAuthorized()](#iscalendarauthorized)
295
294
  - [Parameters](#parameters-77)
296
295
  - [Example usage](#example-usage-77)
297
- - [getRemindersAuthorizationStatus()](#getremindersauthorizationstatus)
296
+ - [getCalendarAuthorizationStatus()](#getcalendarauthorizationstatus)
298
297
  - [Parameters](#parameters-78)
299
298
  - [Example usage](#example-usage-78)
300
- - [requestRemindersAuthorization()](#requestremindersauthorization)
299
+ - [requestCalendarAuthorization()](#requestcalendarauthorization)
301
300
  - [Parameters](#parameters-79)
302
301
  - [Example usage](#example-usage-79)
303
- - [Motion module](#motion-module)
304
- - [motionStatus constants](#motionstatus-constants)
305
- - [Example](#example-5)
306
- - [isMotionAvailable()](#ismotionavailable)
302
+ - [Reminders module](#reminders-module)
303
+ - [isRemindersAuthorized()](#isremindersauthorized)
307
304
  - [Parameters](#parameters-80)
308
305
  - [Example usage](#example-usage-80)
309
- - [isMotionRequestOutcomeAvailable()](#ismotionrequestoutcomeavailable)
306
+ - [getRemindersAuthorizationStatus()](#getremindersauthorizationstatus)
310
307
  - [Parameters](#parameters-81)
311
308
  - [Example usage](#example-usage-81)
312
- - [requestMotionAuthorization()](#requestmotionauthorization)
309
+ - [requestRemindersAuthorization()](#requestremindersauthorization)
313
310
  - [Parameters](#parameters-82)
314
311
  - [Example usage](#example-usage-82)
315
- - [getMotionAuthorizationStatus()](#getmotionauthorizationstatus)
312
+ - [Motion module](#motion-module)
313
+ - [motionStatus constants](#motionstatus-constants)
314
+ - [Example](#example-5)
315
+ - [isMotionAvailable()](#ismotionavailable)
316
316
  - [Parameters](#parameters-83)
317
317
  - [Example usage](#example-usage-83)
318
- - [NFC module](#nfc-module)
319
- - [NFCState constants](#nfcstate-constants)
320
- - [Values](#values-3)
321
- - [Example](#example-6)
322
- - [isNFCPresent()](#isnfcpresent)
318
+ - [isMotionRequestOutcomeAvailable()](#ismotionrequestoutcomeavailable)
323
319
  - [Parameters](#parameters-84)
324
320
  - [Example usage](#example-usage-84)
325
- - [isNFCEnabled()](#isnfcenabled)
321
+ - [requestMotionAuthorization()](#requestmotionauthorization)
326
322
  - [Parameters](#parameters-85)
327
323
  - [Example usage](#example-usage-85)
328
- - [isNFCAvailable()](#isnfcavailable)
324
+ - [getMotionAuthorizationStatus()](#getmotionauthorizationstatus)
329
325
  - [Parameters](#parameters-86)
330
326
  - [Example usage](#example-usage-86)
331
- - [registerNFCStateChangeHandler()](#registernfcstatechangehandler)
327
+ - [NFC module](#nfc-module)
328
+ - [NFCState constants](#nfcstate-constants)
329
+ - [Values](#values-3)
330
+ - [Example](#example-6)
331
+ - [isNFCPresent()](#isnfcpresent)
332
332
  - [Parameters](#parameters-87)
333
333
  - [Example usage](#example-usage-87)
334
- - [switchToNFCSettings()](#switchtonfcsettings)
335
- - [External storage module](#external-storage-module)
336
- - [isExternalStorageAuthorized()](#isexternalstorageauthorized)
334
+ - [isNFCEnabled()](#isnfcenabled)
337
335
  - [Parameters](#parameters-88)
338
336
  - [Example usage](#example-usage-88)
339
- - [getExternalStorageAuthorizationStatus()](#getexternalstorageauthorizationstatus)
337
+ - [isNFCAvailable()](#isnfcavailable)
340
338
  - [Parameters](#parameters-89)
341
339
  - [Example usage](#example-usage-89)
342
- - [requestExternalStorageAuthorization()](#requestexternalstorageauthorization)
340
+ - [registerNFCStateChangeHandler()](#registernfcstatechangehandler)
343
341
  - [Parameters](#parameters-90)
344
342
  - [Example usage](#example-usage-90)
345
- - [getExternalSdCardDetails()](#getexternalsdcarddetails)
343
+ - [switchToNFCSettings()](#switchtonfcsettings)
344
+ - [External storage module](#external-storage-module)
345
+ - [isExternalStorageAuthorized()](#isexternalstorageauthorized)
346
346
  - [Parameters](#parameters-91)
347
347
  - [Example usage](#example-usage-91)
348
+ - [getExternalStorageAuthorizationStatus()](#getexternalstorageauthorizationstatus)
349
+ - [Parameters](#parameters-92)
350
+ - [Example usage](#example-usage-92)
351
+ - [requestExternalStorageAuthorization()](#requestexternalstorageauthorization)
352
+ - [Parameters](#parameters-93)
353
+ - [Example usage](#example-usage-93)
354
+ - [getExternalSdCardDetails()](#getexternalsdcarddetails)
355
+ - [Parameters](#parameters-94)
356
+ - [Example usage](#example-usage-94)
348
357
  - [Platform Notes](#platform-notes)
349
358
  - [Android](#android-3)
350
359
  - [Android permissions](#android-permissions)
@@ -630,14 +639,17 @@ App can never ask for permission again.
630
639
  The only way around this is to instruct the user to manually change the permission in Settings.
631
640
  - `RESTRICTED` - Permission is unavailable and user cannot enable it.
632
641
  For example, when parental controls are in effect for the current user.
633
- - `GRANTED` - User granted access to this permission.
634
- For location permission, this indicates the user has granted access to the permission "always" (when app is both in foreground and background).
635
- - `GRANTED_WHEN_IN_USE` - Used only for location permission.
636
- Indicates the user has granted access to the permission "when in use" (only when the app is in the foreground).
637
-
638
- Addtionally, for notifications permissions:
639
- - `PROVISIONAL` - The app is provisionally authorized to post non-interruptive user notifications.
640
- - `EPHEMERAL` - The app is authorized to schedule or receive notifications for a limited amount of time.
642
+ - `GRANTED` - User granted access to this permission.
643
+ For location permission, this indicates the user has granted access to the permission "always" (when app is both in foreground and background).
644
+ - `GRANTED_WHEN_IN_USE` - Used only for location permission.
645
+ Indicates the user has granted access to the permission "when in use" (only when the app is in the foreground).
646
+
647
+ Addtionally, for notifications permissions:
648
+ - `PROVISIONAL` - The app is provisionally authorized to post non-interruptive user notifications.
649
+ - `EPHEMERAL` - The app is authorized to schedule or receive notifications for a limited amount of time.
650
+
651
+ For cases where the platform cannot return a definitive answer, the plugin also exposes:
652
+ - `UNKNOWN` (Android and iOS) - Returned when the underlying OS has not yet provided a concrete status (for example, if an iOS Local Network probe timed out). Treat this as a transient state and retry before surfacing a denial to the user.
641
653
 
642
654
  #### Example
643
655
 
@@ -2442,6 +2454,120 @@ The function is passed a single string parameter containing the error message.
2442
2454
  console.error("The following error occurred: "+error);
2443
2455
  });
2444
2456
 
2457
+ ### isLocalNetworkAuthorized()
2458
+
2459
+ Platforms: iOS
2460
+
2461
+ Checks if the app is authorised to access devices on the local network (iOS 14+).
2462
+ On iOS versions prior to 14 this will always return TRUE as no local network authorization is required.
2463
+ An optional third argument allows you to override the fallback timeout (defaults to 2 seconds) by passing `{ timeoutMs: <number> }`.
2464
+
2465
+ cordova.plugins.diagnostic.isLocalNetworkAuthorized(successCallback, errorCallback);
2466
+
2467
+ #### Parameters
2468
+
2469
+ - {Function} successCallback - The callback which will be called when operation is successful.
2470
+ The function is passed a single boolean parameter which is TRUE if the app is authorised to use the Local Network.
2471
+ - {Function} errorCallback - The callback which will be called when operation encounters an error.
2472
+ The function is passed a single string parameter containing the error message.
2473
+ - {Object} [options] - Optional timeout control object. Provide `timeoutMs` (milliseconds) to override the default 2000 ms timeout.
2474
+
2475
+
2476
+ #### Example usage
2477
+
2478
+ cordova.plugins.diagnostic.isLocalNetworkAuthorized(function(authorized){
2479
+ console.log("Local Network is " + (authorized ? "authorized" : "unauthorised"));
2480
+ }, function(error){
2481
+ console.error("The following error occurred: "+error);
2482
+ });
2483
+
2484
+ To wait longer before treating a slow response as indeterminate:
2485
+
2486
+ ```
2487
+ cordova.plugins.diagnostic.isLocalNetworkAuthorized(
2488
+ function(authorized){
2489
+ console.log("Local Network authorized? " + authorized);
2490
+ },
2491
+ console.error,
2492
+ { timeoutMs: 8000 }
2493
+ );
2494
+ ```
2495
+
2496
+ ### getLocalNetworkAuthorizationStatus()
2497
+
2498
+ Platforms: iOS
2499
+
2500
+ Returns the app's Local Network authorization status.
2501
+ On iOS 14+ this returns one of the values in `cordova.plugins.diagnostic.permissionStatus`: `NOT_REQUESTED`, `GRANTED`, `DENIED_ALWAYS`, `UNKNOWN`.
2502
+ `UNKNOWN` indicates that iOS did not return a definitive answer before the timeout elapsed, so the app can retry before warning the user.
2503
+ On iOS versions prior to 14 this will always return `GRANTED` as no authorization is required.
2504
+
2505
+ cordova.plugins.diagnostic.getLocalNetworkAuthorizationStatus(successCallback, errorCallback);
2506
+
2507
+ #### Parameters
2508
+
2509
+ - {Function} successCallback - The callback which will be called when operation is successful.
2510
+ The function is passed a single string parameter which is one of the values in `cordova.plugins.diagnostic.permissionStatus`:
2511
+ `NOT_REQUESTED`, `GRANTED`, `DENIED_ALWAYS`, `UNKNOWN`.
2512
+ - {Function} errorCallback - The callback which will be called when operation encounters an error.
2513
+ The function is passed a single string parameter containing the error message.
2514
+ - {Object} [options] - Optional timeout override (defaults to 2 seconds). Provide `timeoutMs` (milliseconds) to customize the fallback duration.
2515
+
2516
+
2517
+ #### Example usage
2518
+
2519
+ cordova.plugins.diagnostic.getLocalNetworkAuthorizationStatus(function(status){
2520
+ switch(status){
2521
+ case cordova.plugins.diagnostic.permissionStatus.NOT_REQUESTED:
2522
+ console.log("Local Network permission not requested");
2523
+ break;
2524
+ case cordova.plugins.diagnostic.permissionStatus.DENIED_ALWAYS:
2525
+ console.log("Local Network permission denied");
2526
+ break;
2527
+ case cordova.plugins.diagnostic.permissionStatus.UNKNOWN:
2528
+ console.log("Local Network permission could not be determined (retry recommended)");
2529
+ break;
2530
+ case cordova.plugins.diagnostic.permissionStatus.GRANTED:
2531
+ console.log("Local Network permission granted");
2532
+ break;
2533
+ }
2534
+ }, function(error){
2535
+ console.error("The following error occurred: "+error);
2536
+ });
2537
+
2538
+ ### requestLocalNetworkAuthorization()
2539
+
2540
+ Platforms: iOS
2541
+
2542
+ Requests the user to authorise the app to access devices on the local network (iOS 14+).
2543
+ On iOS versions prior to 14 this does nothing and will return success as no authorization is required.
2544
+ May return `UNKNOWN` if iOS does not respond before the native APIs time out, allowing the app to retry.
2545
+
2546
+ cordova.plugins.diagnostic.requestLocalNetworkAuthorization(successCallback, errorCallback);
2547
+
2548
+ #### Parameters
2549
+
2550
+ - {Function} successCallback - The callback which will be called when operation is successful.
2551
+ The function is passed a single string parameter which is one of the values in `cordova.plugins.diagnostic.permissionStatus`:
2552
+ `NOT_REQUESTED`, `GRANTED`, `DENIED_ALWAYS`, `UNKNOWN`.
2553
+ - {Function} errorCallback - The callback which will be called when operation encounters an error.
2554
+ The function is passed a single string parameter containing the error message.
2555
+
2556
+
2557
+ #### Example usage
2558
+
2559
+ cordova.plugins.diagnostic.requestLocalNetworkAuthorization(function(status){
2560
+ if(status === cordova.plugins.diagnostic.permissionStatus.GRANTED){
2561
+ console.log("Local Network access granted");
2562
+ }else if(status === cordova.plugins.diagnostic.permissionStatus.UNKNOWN){
2563
+ console.log("Local Network status could not be determined, retrying may succeed");
2564
+ }else{
2565
+ console.log("Local Network access not granted: " + status);
2566
+ }
2567
+ }, function(error){
2568
+ console.error("The following error occurred: "+error);
2569
+ });
2570
+
2445
2571
  ### setWifiState()
2446
2572
 
2447
2573
  Platforms: Android
@@ -78,6 +78,7 @@ interface Diagnostic {
78
78
  "GRANTED_WHEN_IN_USE": "authorized_when_in_use";
79
79
  "NOT_REQUESTED": "not_determined"|"NOT_REQUESTED";
80
80
  "DENIED_ALWAYS": "denied_always"|"DENIED_ALWAYS";
81
+ "UNKNOWN": "unknown"|"UNKNOWN";
81
82
  };
82
83
 
83
84
  /**
@@ -1263,6 +1264,45 @@ interface Diagnostic {
1263
1264
  successCallback: (status: string) => void,
1264
1265
  errorCallback: (error: string) => void
1265
1266
  ) => void;
1267
+
1268
+ /**
1269
+ * iOS ONLY
1270
+ * Checks if the application is authorized to use local network.
1271
+ * @param successCallback
1272
+ * @param errorCallback
1273
+ */
1274
+ isLocalNetworkAuthorized?: (
1275
+ successCallback: (authorized: boolean) => void,
1276
+ errorCallback: (error: string) => void,
1277
+ options?: {
1278
+ timeoutMs?: number;
1279
+ }
1280
+ ) => void;
1281
+
1282
+ /**
1283
+ * iOS ONLY
1284
+ * Returns the local network authorization status for the application.
1285
+ * @param successCallback
1286
+ * @param errorCallback
1287
+ */
1288
+ getLocalNetworkAuthorizationStatus?: (
1289
+ successCallback: (status: string) => void,
1290
+ errorCallback: (error: string) => void,
1291
+ options?: {
1292
+ timeoutMs?: number;
1293
+ }
1294
+ ) => void;
1295
+
1296
+ /**
1297
+ * iOS ONLY
1298
+ * Requests local network authorization for the application.
1299
+ * @param successCallback
1300
+ * @param errorCallback
1301
+ */
1302
+ requestLocalNetworkAuthorization?: (
1303
+ successCallback: (status: string) => void,
1304
+ errorCallback: (error: string) => void
1305
+ ) => void;
1266
1306
  }
1267
1307
 
1268
1308
  interface CordovaPlugins {
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "7.2.4",
2
+ "version": "7.2.6",
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.2.4">
5
+ version="7.2.6">
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>
@@ -104,6 +104,17 @@
104
104
 
105
105
  <header-file src="src/ios/Diagnostic_Wifi.h" />
106
106
  <source-file src="src/ios/Diagnostic_Wifi.m" />
107
+
108
+ <config-file parent="NSLocalNetworkUsageDescription" platform="ios" target="*-Info.plist">
109
+ <string>This app requires access to your local network in order to discover and connect to devices on the same network.</string>
110
+ </config-file>
111
+
112
+ <config-file parent="NSBonjourServices" platform="ios" target="*-Info.plist">
113
+ <array>
114
+ <string>_lnp._tcp.</string>
115
+ <string>_bonjour._tcp.</string>
116
+ </array>
117
+ </config-file>
107
118
  <!--END_MODULE WIFI-->
108
119
 
109
120
  <!--BEGIN_MODULE CAMERA-->
@@ -47,6 +47,8 @@ extern NSString*const AUTHORIZATION_LIMITED;
47
47
  - (void) sendPluginResultSuccess:(CDVInvokedUrlCommand*)command;
48
48
  - (void) sendPluginNoResultAndKeepCallback:(CDVInvokedUrlCommand*)command;
49
49
  - (void) sendPluginResultBool: (BOOL)result :(CDVInvokedUrlCommand*)command;
50
+ - (void) sendPluginResultInt: (int)result :(CDVInvokedUrlCommand*)command;
51
+ - (void) sendPluginResultObject: (NSDictionary*)result :(CDVInvokedUrlCommand*)command;
50
52
  - (void) sendPluginResultString: (NSString*)result :(CDVInvokedUrlCommand*)command;
51
53
  - (void) sendPluginError: (NSString*) errorMessage :(CDVInvokedUrlCommand*)command;
52
54
  - (void) handlePluginException: (NSException*) exception :(CDVInvokedUrlCommand*)command;
@@ -10,10 +10,11 @@
10
10
  #import <Cordova/CDVPlugin.h>
11
11
  #import "Diagnostic.h"
12
12
 
13
-
14
- @interface Diagnostic_Wifi : CDVPlugin
13
+ @interface Diagnostic_Wifi : CDVPlugin <NSNetServiceDelegate>
15
14
 
16
15
  - (void) isWifiAvailable: (CDVInvokedUrlCommand*)command;
17
16
  - (void) isWifiEnabled: (CDVInvokedUrlCommand*)command;
17
+ - (void) requestLocalNetworkAuthorization: (CDVInvokedUrlCommand*)command;
18
+ - (void) getLocalNetworkAuthorizationStatus: (CDVInvokedUrlCommand*)command;
18
19
 
19
20
  @end
@@ -11,24 +11,331 @@
11
11
  #import <arpa/inet.h> // For AF_INET, etc.
12
12
  #import <ifaddrs.h> // For getifaddrs()
13
13
  #import <net/if.h> // For IFF_LOOPBACK
14
+ #import <Network/Network.h>
15
+ #import <Network/browser.h>
16
+ #import <errno.h>
14
17
 
15
- @implementation Diagnostic_Wifi
18
+ // UserDefaults key for caching local network permission
19
+ static NSString*const kLocalNetworkPermissionKey = @"Diagnostic_LocalNetworkPermission";
20
+
21
+ typedef NS_ENUM(NSInteger, LocalNetworkPermissionState) {
22
+ LocalNetworkPermissionStateUnknown = 0,
23
+ LocalNetworkPermissionStateGranted = 1,
24
+ LocalNetworkPermissionStateDenied = -1,
25
+ LocalNetworkPermissionStateIndeterminate = -2,
26
+ };
27
+ @implementation Diagnostic_Wifi {
28
+ nw_browser_t _browser;
29
+ NSNetService *_netService;
30
+ // Completion callbacks stored as CDV callbacks (we'll send results to all when done)
31
+ NSMutableArray<CDVInvokedUrlCommand*> *_localNetworkCommands;
32
+ NSTimer* _localNetworkTimer;
33
+
34
+ // If we have a cached granted/denied value, fall through to the normal path which will verify current status
35
+ // (this may trigger a prompt only if requestLocalNetworkAuthorization was previously called).
36
+ BOOL _isPublishing;
37
+
38
+ BOOL _isRequesting;
39
+ }
16
40
 
17
41
  // Internal reference to Diagnostic singleton instance
18
42
  static Diagnostic* diagnostic;
19
43
 
20
44
  // Internal constants
21
45
  static NSString*const LOG_TAG = @"Diagnostic_Wifi[native]";
46
+ static NSTimeInterval const kLocalNetworkDefaultTimeoutSeconds = 2.0;
22
47
 
23
48
  - (void)pluginInitialize {
24
49
 
25
50
  [super pluginInitialize];
26
51
 
27
52
  diagnostic = [Diagnostic getInstance];
53
+ // initialize commands array
54
+ _localNetworkCommands = [NSMutableArray new];
55
+ }
56
+
57
+ /**************************************/
58
+ #pragma mark - Local Network Plugin API
59
+ /**************************************/
60
+
61
+ - (void) getLocalNetworkAuthorizationStatus: (CDVInvokedUrlCommand*)command
62
+ {
63
+ [self.commandDelegate runInBackground:^{
64
+ @try {
65
+
66
+ // Read cached permission state first
67
+ NSInteger cached = [[NSUserDefaults standardUserDefaults] integerForKey:kLocalNetworkPermissionKey];
68
+ LocalNetworkPermissionState state = (LocalNetworkPermissionState)cached;
69
+
70
+ if (state == LocalNetworkPermissionStateUnknown) {
71
+ // If unknown, do not attempt to start browsing/publishing (that would trigger the system prompt).
72
+ // respond with NO (unauthorized) when never requested.
73
+ [diagnostic sendPluginResultInt:LocalNetworkPermissionStateUnknown :command];
74
+ [diagnostic logDebug:@"Local network permission status is NOT_REQUESTED"];
75
+ return;
76
+ }
77
+
78
+ // Store command so we can send the result later
79
+ @synchronized(self->_localNetworkCommands) {
80
+ [self->_localNetworkCommands addObject:command];
81
+ }
82
+
83
+ if(self->_isRequesting){
84
+ // A request is already in progress so await the result
85
+ [diagnostic logDebug:@"A request is already in progress, will return result when done"];
86
+ return;
87
+ }
88
+
89
+ NSTimeInterval timeoutSeconds = [self resolveLocalNetworkTimeoutFromCommand:command];
90
+
91
+ // Create parameters, and allow browsing over peer-to-peer link.
92
+ if (@available(iOS 14.0, *)) {
93
+ // Create parameters, and allow browsing over peer-to-peer link.
94
+ nw_parameters_t parameters = nw_parameters_create_secure_tcp(NW_PARAMETERS_DISABLE_PROTOCOL, NW_PARAMETERS_DEFAULT_CONFIGURATION);
95
+ nw_parameters_set_include_peer_to_peer(parameters, true);
96
+
97
+ // Browse for a custom service type.
98
+ nw_browse_descriptor_t descriptor =
99
+ nw_browse_descriptor_create_bonjour_service("_bonjour._tcp", NULL);
100
+ self->_browser = nw_browser_create(descriptor, parameters);
101
+
102
+ nw_browser_set_queue(self->_browser, dispatch_get_main_queue());
103
+
104
+ self->_netService = [[NSNetService alloc] initWithDomain:@"local." type:@"_lnp._tcp." name:@"LocalNetworkPrivacy" port:1100];
105
+
106
+ self->_isRequesting = YES;
107
+ self->_isPublishing = NO;
108
+
109
+ [diagnostic logDebug:[NSString stringWithFormat:@"Starting local network permission status check (timeout %.2fs)", timeoutSeconds]];
110
+ // Start the browsing/publish flow on the main queue immediately and create a single-shot timeout.
111
+ dispatch_async(dispatch_get_main_queue(), ^{
112
+ __weak __typeof__(self) weakSelf = self;
113
+
114
+ __strong __typeof__(weakSelf) strongSelf = weakSelf;
115
+ if (!strongSelf) return;
116
+
117
+ // Ensure we only start once for this check
118
+ if (strongSelf->_isPublishing) {
119
+ [diagnostic logDebug:@"Local network permission request already publishing, skipping start"];
120
+ return;
121
+ }
122
+
123
+ strongSelf->_isPublishing = YES;
124
+ strongSelf->_netService.delegate = strongSelf;
125
+
126
+ // Install a state handler so the browser emits state changes (silences the warning about missing handlers)
127
+ if (strongSelf->_browser) {
128
+ nw_browser_set_state_changed_handler(strongSelf->_browser, ^(nw_browser_state_t newState, nw_error_t error) {
129
+ __strong __typeof__(weakSelf) innerSelf = weakSelf;
130
+ if (!innerSelf) {
131
+ return;
132
+ }
133
+ [innerSelf handleBrowserState:newState error:error context:@"status check"];
134
+ });
135
+
136
+ nw_browser_start(strongSelf->_browser);
137
+ } else {
138
+ [diagnostic logDebug:@"Attempted to start browser but browser is null"];
139
+ }
140
+
141
+ [strongSelf->_netService publish];
142
+ [strongSelf->_netService scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
143
+
144
+ if (timeoutSeconds > 0) {
145
+ strongSelf->_localNetworkTimer = [NSTimer scheduledTimerWithTimeInterval:timeoutSeconds
146
+ repeats:NO
147
+ block:^(NSTimer * _Nonnull timer) {
148
+ __strong __typeof__(weakSelf) innerSelf = weakSelf;
149
+ if (!innerSelf) return;
150
+
151
+ [diagnostic logDebug:[NSString stringWithFormat:@"Local network permission status check timed out after %.2fs", timeoutSeconds]];
152
+ [innerSelf completeLocalNetworkFlowWithState:LocalNetworkPermissionStateIndeterminate shouldCache:NO];
153
+ }];
154
+ }
155
+ });
156
+ }else{
157
+ [diagnostic logDebug:@"iOS version < 14.0, so local network permission is not required"];
158
+ [self callLocalNetworkCallbacks:LocalNetworkPermissionStateGranted];
159
+ }
160
+ }
161
+ @catch (NSException *exception) {
162
+ [diagnostic handlePluginException:exception :command];
163
+ }
164
+ }];
165
+ }
166
+
167
+ // This code is based on https://stackoverflow.com/a/67758105/2618437 with slight modifications
168
+ - (void) requestLocalNetworkAuthorization: (CDVInvokedUrlCommand*)command
169
+ {
170
+ [self.commandDelegate runInBackground:^{
171
+ @try {
172
+ if(self->_isRequesting){
173
+ // A request is already in progress
174
+ [diagnostic sendPluginError:@"A request is already in progress" :command];
175
+ return;
176
+ }
177
+ self->_isRequesting = YES;
178
+
179
+ // Store command so we can send the result later
180
+ @synchronized(self->_localNetworkCommands) {
181
+ [self->_localNetworkCommands addObject:command];
182
+ }
183
+
184
+ if (@available(iOS 14.0, *)) {
185
+ // Create parameters, and allow browsing over peer-to-peer link.
186
+ nw_parameters_t parameters = nw_parameters_create_secure_tcp(NW_PARAMETERS_DISABLE_PROTOCOL, NW_PARAMETERS_DEFAULT_CONFIGURATION);
187
+ nw_parameters_set_include_peer_to_peer(parameters, true);
188
+
189
+ // Browse for a custom service type.
190
+ nw_browse_descriptor_t descriptor =
191
+ nw_browse_descriptor_create_bonjour_service("_bonjour._tcp", NULL);
192
+ self->_browser = nw_browser_create(descriptor, parameters);
193
+
194
+ nw_browser_set_queue(self->_browser, dispatch_get_main_queue());
195
+
196
+ __weak __typeof__(self) weakSelf = self;
197
+ nw_browser_set_state_changed_handler(self->_browser, ^(nw_browser_state_t newState, nw_error_t error) {
198
+ __strong __typeof__(weakSelf) strongSelf = weakSelf;
199
+ if (!strongSelf) {
200
+ return;
201
+ }
202
+ [strongSelf handleBrowserState:newState error:error context:@"authorization request"];
203
+ });
204
+
205
+ self->_netService = [[NSNetService alloc] initWithDomain:@"local." type:@"_lnp._tcp." name:@"LocalNetworkPrivacy" port:1100];
206
+ self->_netService.delegate = self;
207
+
208
+ // Start browsing on main queue
209
+ nw_browser_start(self->_browser);
210
+ [self->_netService publish];
211
+ // the netService needs to be scheduled on a run loop, in this case the main runloop
212
+ [self->_netService scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
213
+ }else{
214
+ // iOS version < 14.0, so local network permission is not required
215
+ [self callLocalNetworkCallbacks:LocalNetworkPermissionStateGranted];
216
+ }
217
+ } @catch (NSException *exception) {
218
+ [diagnostic handlePluginException:exception :command];
219
+ }
220
+ }];
221
+ }
222
+
223
+ - (void) resetLocalNetwork
224
+ {
225
+ [diagnostic logDebug:@"resetting"];
226
+ // stop the timer if active so it doesn't keep firing
227
+ if (_localNetworkTimer) {
228
+ [_localNetworkTimer invalidate];
229
+ _localNetworkTimer = nil;
230
+ }
231
+
232
+ // reset state flags
233
+ self->_isPublishing = NO;
234
+ self->_isRequesting = NO;
235
+
236
+ if (_browser) {
237
+ if (@available(iOS 13.0, *)) {
238
+ nw_browser_cancel(_browser);
239
+ }
240
+ _browser = nil;
241
+ }
242
+ if (_netService) {
243
+ [_netService stop];
244
+ _netService = nil;
245
+ }
246
+ }
247
+
248
+ - (void) callLocalNetworkCallbacks:(LocalNetworkPermissionState)result
249
+ {
250
+ @synchronized(self->_localNetworkCommands) {
251
+ for (CDVInvokedUrlCommand *c in self->_localNetworkCommands) {
252
+ [diagnostic sendPluginResultInt:(int)result :c];
253
+ }
254
+ [self->_localNetworkCommands removeAllObjects];
255
+ }
256
+ }
257
+
258
+ - (void)completeLocalNetworkFlowWithState:(LocalNetworkPermissionState)state shouldCache:(BOOL)shouldCache
259
+ {
260
+ dispatch_block_t completion = ^{
261
+ [self resetLocalNetwork];
262
+ if (shouldCache && (state == LocalNetworkPermissionStateGranted || state == LocalNetworkPermissionStateDenied)) {
263
+ [[NSUserDefaults standardUserDefaults] setInteger:state forKey:kLocalNetworkPermissionKey];
264
+ [[NSUserDefaults standardUserDefaults] synchronize];
265
+ }
266
+ [self callLocalNetworkCallbacks:state];
267
+ };
268
+
269
+ if ([NSThread isMainThread]) {
270
+ completion();
271
+ } else {
272
+ dispatch_async(dispatch_get_main_queue(), completion);
273
+ }
274
+ }
275
+
276
+ - (NSTimeInterval)resolveLocalNetworkTimeoutFromCommand:(CDVInvokedUrlCommand*)command
277
+ {
278
+ NSTimeInterval timeout = kLocalNetworkDefaultTimeoutSeconds;
279
+ if (!command || !command.arguments || command.arguments.count == 0) {
280
+ return timeout;
281
+ }
282
+
283
+ id rawValue = command.arguments[0];
284
+ if (![rawValue isKindOfClass:[NSDictionary class]]) {
285
+ return timeout;
286
+ }
287
+
288
+ NSDictionary *dict = (NSDictionary *)rawValue;
289
+ id timeoutMsValue = dict[@"timeoutMs"];
290
+ if ([timeoutMsValue isKindOfClass:[NSNumber class]]) {
291
+ double milliseconds = [timeoutMsValue doubleValue];
292
+ if (milliseconds < 0) {
293
+ milliseconds = 0;
294
+ }
295
+ return milliseconds / 1000.0;
296
+ }
297
+
298
+ return timeout;
299
+ }
300
+
301
+ - (BOOL)isPermissionDeniedError:(nw_error_t)error
302
+ {
303
+ if (!error) {
304
+ return NO;
305
+ }
306
+
307
+ nw_error_domain_t errorDomain = nw_error_get_error_domain(error);
308
+ int errorCode = (int)nw_error_get_error_code(error);
309
+ return (errorDomain == nw_error_domain_posix && errorCode == EPERM);
310
+ }
311
+
312
+ - (void)handleBrowserState:(nw_browser_state_t)newState error:(nw_error_t)error context:(NSString *)context
313
+ {
314
+ if (newState == nw_browser_state_waiting || newState == nw_browser_state_failed) {
315
+ if ([self isPermissionDeniedError:error]) {
316
+ nw_error_domain_t domain = nw_error_get_error_domain(error);
317
+ int code = (int)nw_error_get_error_code(error);
318
+ [diagnostic logDebug:[NSString stringWithFormat:@"Local network permission denied during %@ (domain=%d, code=%d)", context, (int)domain, code]];
319
+ [self completeLocalNetworkFlowWithState:LocalNetworkPermissionStateDenied shouldCache:YES];
320
+ return;
321
+ }
322
+
323
+ if (error) {
324
+ nw_error_domain_t domain = nw_error_get_error_domain(error);
325
+ int code = (int)nw_error_get_error_code(error);
326
+ [diagnostic logDebug:[NSString stringWithFormat:@"Local network browser %@ state %ld error domain=%d code=%d", context, (long)newState, (int)domain, code]];
327
+ } else {
328
+ [diagnostic logDebug:[NSString stringWithFormat:@"Local network browser %@ entered state %ld without error", context, (long)newState]];
329
+ }
330
+
331
+ if (newState == nw_browser_state_failed) {
332
+ [self completeLocalNetworkFlowWithState:LocalNetworkPermissionStateIndeterminate shouldCache:NO];
333
+ }
334
+ }
28
335
  }
29
336
 
30
337
  /********************************/
31
- #pragma mark - Plugin API
338
+ #pragma mark - Wifi Plugin API
32
339
  /********************************/
33
340
 
34
341
  - (void) isWifiAvailable: (CDVInvokedUrlCommand*)command
@@ -105,4 +412,19 @@ static NSString*const LOG_TAG = @"Diagnostic_Wifi[native]";
105
412
  }
106
413
 
107
414
 
415
+ /********************************/
416
+ #pragma mark - NetServiceDelegate
417
+ /********************************/
418
+
419
+ - (void)netServiceDidPublish:(NSNetService *)sender {
420
+ [diagnostic logDebug:@"netServiceDidPublish: Local network permission has been granted"];
421
+ [self completeLocalNetworkFlowWithState:LocalNetworkPermissionStateGranted shouldCache:YES];
422
+ }
423
+
424
+ - (void)netService:(NSNetService *)sender didNotPublish:(NSDictionary<NSString *,NSNumber *> *)errorDict {
425
+ NSNumber *errorDomain = errorDict[NSNetServicesErrorDomain];
426
+ NSNumber *errorCode = errorDict[NSNetServicesErrorCode];
427
+ [diagnostic logDebug:[NSString stringWithFormat:@"netService didNotPublish (domain=%@, code=%@)", errorDomain, errorCode]];
428
+ [self completeLocalNetworkFlowWithState:LocalNetworkPermissionStateDenied shouldCache:YES];
429
+ }
108
430
  @end
@@ -89,6 +89,8 @@ var Diagnostic = (function(){
89
89
  "DENIED_ALWAYS": "DENIED_ALWAYS",
90
90
  // App has not yet requested access to this permission.
91
91
  "NOT_REQUESTED": "NOT_REQUESTED",
92
+ // Platform has not provided a definitive status (e.g. timeout/indeterminate)
93
+ "UNKNOWN": "unknown",
92
94
  // Limited access to the photo library on Android 14 (API 34) and above
93
95
  "LIMITED": "LIMITED"
94
96
  };
@@ -22,6 +22,7 @@ var Diagnostic = (function(){
22
22
  */
23
23
  Diagnostic.permissionStatus = {
24
24
  "NOT_REQUESTED": "not_determined", // App has not yet requested this permission
25
+ "UNKNOWN": "unknown", // Platform has not provided a definitive status (e.g. timeout/indeterminate)
25
26
  "DENIED_ALWAYS": "denied_always", // User denied access to this permission
26
27
  "RESTRICTED": "restricted", // Permission is unavailable and user cannot enable it. For example, when parental controls are in effect for the current user.
27
28
  "GRANTED": "authorized", // User granted access to this permission
@@ -647,6 +648,65 @@ var Diagnostic = (function(){
647
648
  }
648
649
  };
649
650
 
651
+ /**
652
+ * Checks if the app is authorized to use Local Network.
653
+ * On iOS 14+ this returns true if the user has authorized the app to access devices on the local network.
654
+ * On iOS versions prior to 14, this always returns true as no authorization is required.
655
+ *
656
+ * @param {Function} successCallback - The callback which will be called when operation is successful.
657
+ * This callback function is passed a single boolean parameter which is TRUE if the app is authorized to use Local Network.
658
+ * @param {Function} errorCallback - The callback which will be called when operation encounters an error.
659
+ * This callback function is passed a single string parameter containing the error message.
660
+ * @param {Object} [options] - Optional timeout control object containing an optional `timeoutMs` number, matching the options accepted by `getLocalNetworkAuthorizationStatus()`.
661
+ */
662
+ Diagnostic.isLocalNetworkAuthorized = function(successCallback, errorCallback, options) {
663
+ if(cordova.plugins.diagnostic.wifi){
664
+ cordova.plugins.diagnostic.wifi.isLocalNetworkAuthorized.apply(this, arguments);
665
+ }else{
666
+ throw "Diagnostic Wifi module is not installed";
667
+ }
668
+ };
669
+
670
+ /**
671
+ * Returns the app's Local Network authorization status.
672
+ * On iOS 14+ this returns one of the values in Diagnostic.permissionStatus: NOT_REQUESTED, GRANTED, DENIED_ALWAYS, UNKNOWN.
673
+ * On iOS versions prior to 14, this always returns GRANTED as no authorization is required.
674
+ *
675
+ * @param {Function} successCallback - The callback which will be called when operation is successful.
676
+ * This callback function is passed a single string parameter which is one of the values in Diagnostic.permissionStatus:
677
+ * NOT_REQUESTED, GRANTED, DENIED_ALWAYS, UNKNOWN.
678
+ * @param {Function} errorCallback - The callback which will be called when operation encounters an error.
679
+ * This callback function is passed a single string parameter containing the error message.
680
+ * @param {Object} [options] - Optional control over the timeout (defaults to 2 seconds) used when inferring the permission state.
681
+ * Provide `{ timeoutMs: <number> }` to override the timeout in milliseconds.
682
+ */
683
+ Diagnostic.getLocalNetworkAuthorizationStatus = function(successCallback, errorCallback, options) {
684
+ if(cordova.plugins.diagnostic.wifi){
685
+ cordova.plugins.diagnostic.wifi.getLocalNetworkAuthorizationStatus.apply(this, arguments);
686
+ }else{
687
+ throw "Diagnostic Wifi module is not installed";
688
+ }
689
+ };
690
+
691
+ /**
692
+ * Requests the user to authorize the app to use Local Network.
693
+ * On iOS 14+ this will prompt the user to authorize the app to access devices on the local network.
694
+ * On iOS versions prior to 14, this does nothing as no authorization is required and will return success.
695
+ *
696
+ * @param {Function} successCallback - The callback which will be called when operation is successful.
697
+ * This callback function is passed a single string parameter which is one of the values in Diagnostic.permissionStatus:
698
+ * NOT_REQUESTED, GRANTED, DENIED_ALWAYS, UNKNOWN.
699
+ * @param {Function} errorCallback - The callback which will be called when operation encounters an error.
700
+ * This callback function is passed a single string parameter containing the error message.
701
+ */
702
+ Diagnostic.requestLocalNetworkAuthorization = function(successCallback, errorCallback) {
703
+ if(cordova.plugins.diagnostic.wifi){
704
+ cordova.plugins.diagnostic.wifi.requestLocalNetworkAuthorization.apply(this, arguments);
705
+ }else{
706
+ throw "Diagnostic Wifi module is not installed";
707
+ }
708
+ };
709
+
650
710
  /***************
651
711
  * Bluetooth *
652
712
  ***************/
@@ -27,6 +27,37 @@ var Diagnostic_Wifi = (function(){
27
27
  * Internal functions
28
28
  *
29
29
  ********************/
30
+ function processLocalNetworkStatus(nativeStatus, successCallback) {
31
+ let status;
32
+ switch (nativeStatus) {
33
+ case 1: // LocalNetworkPermissionStateGranted
34
+ status = Diagnostic.permissionStatus.GRANTED;
35
+ break;
36
+ case -1: // LocalNetworkPermissionStateDenied
37
+ status = Diagnostic.permissionStatus.DENIED_ALWAYS;
38
+ break;
39
+ case -2: // LocalNetworkPermissionStateIndeterminate
40
+ status = Diagnostic.permissionStatus.UNKNOWN;
41
+ break;
42
+ case 0: // LocalNetworkPermissionStateUnknown
43
+ default:
44
+ status = Diagnostic.permissionStatus.NOT_REQUESTED;
45
+ break;
46
+ }
47
+ successCallback(status);
48
+ }
49
+
50
+ function buildLocalNetworkArgs(options) {
51
+ if (options && typeof options === "object" && options.timeoutMs != null) {
52
+ var timeoutMs = Number(options.timeoutMs);
53
+ if (isFinite(timeoutMs)) {
54
+ return [{
55
+ timeoutMs: Math.max(0, timeoutMs)
56
+ }];
57
+ }
58
+ }
59
+ return [];
60
+ }
30
61
 
31
62
  /*****************************
32
63
  *
@@ -75,6 +106,75 @@ var Diagnostic_Wifi = (function(){
75
106
  []);
76
107
  };
77
108
 
109
+ /**
110
+ * Checks if the app is authorized to use Local Network.
111
+ * On iOS 14+ this returns true if the user has authorized the app to access devices on the local network.
112
+ * On iOS versions prior to 14, this always returns true as no authorization is required.
113
+ *
114
+ * @param {Function} successCallback - The callback which will be called when operation is successful.
115
+ * This callback function is passed a single boolean parameter which is TRUE if the app is authorized to use Local Network.
116
+ * @param {Function} errorCallback - The callback which will be called when operation encounters an error.
117
+ * This callback function is passed a single string parameter containing the error message.
118
+ * @param {Object} [options] - Optional timeout control object containing an optional `timeoutMs` number.
119
+ */
120
+ Diagnostic_Wifi.isLocalNetworkAuthorized = function(successCallback, errorCallback, options) {
121
+ var args = buildLocalNetworkArgs(options);
122
+ return cordova.exec(function(status) {
123
+ var authorized = (status === 1); // LocalNetworkPermissionStateAuthorized
124
+ successCallback(authorized);
125
+ },
126
+ errorCallback,
127
+ 'Diagnostic_Wifi',
128
+ 'getLocalNetworkAuthorizationStatus',
129
+ args);
130
+ };
131
+
132
+
133
+ /**
134
+ * Returns the app's Local Network authorization status.
135
+ * On iOS 14+ this returns one of the values in Diagnostic.permissionStatus: NOT_REQUESTED, GRANTED, DENIED_ALWAYS, UNKNOWN.
136
+ * On iOS versions prior to 14, this always returns GRANTED as no authorization is required.
137
+ *
138
+ * @param {Function} successCallback - The callback which will be called when operation is successful.
139
+ * This callback function is passed a single string parameter which is one of the values in Diagnostic.permissionStatus:
140
+ * NOT_REQUESTED, GRANTED, DENIED_ALWAYS, UNKNOWN.
141
+ * @param {Function} errorCallback - The callback which will be called when operation encounters an error.
142
+ * This callback function is passed a single string parameter containing the error message.
143
+ * @param {Object} [options] - Optional control over the timeout used when inferring the permission state.
144
+ * Defaults to 2 seconds when omitted. Provide `{ timeoutMs: <number> }` to override the timeout in milliseconds.
145
+ */
146
+ Diagnostic_Wifi.getLocalNetworkAuthorizationStatus = function(successCallback, errorCallback, options) {
147
+ var args = buildLocalNetworkArgs(options);
148
+ return cordova.exec(function(nativeStatus) {
149
+ processLocalNetworkStatus(nativeStatus, successCallback);
150
+ },
151
+ errorCallback,
152
+ 'Diagnostic_Wifi',
153
+ 'getLocalNetworkAuthorizationStatus',
154
+ args);
155
+ };
156
+
157
+ /**
158
+ * Requests the user to authorize the app to use Local Network.
159
+ * On iOS 14+ this will prompt the user to authorize the app to access devices on the local network.
160
+ * On iOS versions prior to 14, this does nothing as no authorization is required and will return success.
161
+ *
162
+ * @param {Function} successCallback - The callback which will be called when operation is successful.
163
+ * This callback function is passed a single string parameter which is one of the values in Diagnostic.permissionStatus:
164
+ * NOT_REQUESTED, GRANTED, DENIED_ALWAYS, UNKNOWN.
165
+ * @param {Function} errorCallback - The callback which will be called when operation encounters an error.
166
+ * This callback function is passed a single string parameter containing the error message.
167
+ */
168
+ Diagnostic_Wifi.requestLocalNetworkAuthorization = function(successCallback, errorCallback) {
169
+ return cordova.exec(function(nativeStatus) {
170
+ processLocalNetworkStatus(nativeStatus, successCallback);
171
+ },
172
+ errorCallback,
173
+ 'Diagnostic_Wifi',
174
+ 'requestLocalNetworkAuthorization',
175
+ []);
176
+ };
177
+
78
178
  return Diagnostic_Wifi;
79
179
  });
80
- module.exports = new Diagnostic_Wifi();
180
+ module.exports = new Diagnostic_Wifi();