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 +7 -0
- package/README.md +193 -67
- package/cordova.plugins.diagnostic.d.ts +40 -0
- package/package.json +1 -1
- package/plugin.xml +12 -1
- package/src/ios/Diagnostic.h +2 -0
- package/src/ios/Diagnostic_Wifi.h +3 -2
- package/src/ios/Diagnostic_Wifi.m +324 -2
- package/www/android/diagnostic.js +2 -0
- package/www/ios/diagnostic.js +60 -0
- package/www/ios/diagnostic.wifi.js +101 -1
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 [](#iswifienabled)
|
|
207
207
|
- [Parameters](#parameters-51)
|
|
208
208
|
- [Example usage](#example-usage-51)
|
|
209
|
-
- [
|
|
209
|
+
- [isLocalNetworkAuthorized()](#islocalnetworkauthorized)
|
|
210
210
|
- [Parameters](#parameters-52)
|
|
211
211
|
- [Example usage](#example-usage-52)
|
|
212
|
-
- [
|
|
213
|
-
- [Camera module](#camera-module)
|
|
214
|
-
- [isCameraPresent()](#iscamerapresent)
|
|
212
|
+
- [getLocalNetworkAuthorizationStatus()](#getlocalnetworkauthorizationstatus)
|
|
215
213
|
- [Parameters](#parameters-53)
|
|
216
214
|
- [Example usage](#example-usage-53)
|
|
217
|
-
- [
|
|
215
|
+
- [requestLocalNetworkAuthorization()](#requestlocalnetworkauthorization)
|
|
218
216
|
- [Parameters](#parameters-54)
|
|
219
217
|
- [Example usage](#example-usage-54)
|
|
220
|
-
- [
|
|
218
|
+
- [setWifiState()](#setwifistate)
|
|
221
219
|
- [Parameters](#parameters-55)
|
|
222
220
|
- [Example usage](#example-usage-55)
|
|
223
|
-
- [
|
|
221
|
+
- [switchToWifiSettings()](#switchtowifisettings)
|
|
222
|
+
- [Camera module](#camera-module)
|
|
223
|
+
- [isCameraPresent()](#iscamerapresent)
|
|
224
224
|
- [Parameters](#parameters-56)
|
|
225
225
|
- [Example usage](#example-usage-56)
|
|
226
|
-
- [
|
|
226
|
+
- [isCameraAvailable()](#iscameraavailable)
|
|
227
227
|
- [Parameters](#parameters-57)
|
|
228
228
|
- [Example usage](#example-usage-57)
|
|
229
|
-
- [
|
|
229
|
+
- [isCameraAuthorized()](#iscameraauthorized)
|
|
230
230
|
- [Parameters](#parameters-58)
|
|
231
231
|
- [Example usage](#example-usage-58)
|
|
232
|
-
- [
|
|
232
|
+
- [getCameraAuthorizationStatus()](#getcameraauthorizationstatus)
|
|
233
233
|
- [Parameters](#parameters-59)
|
|
234
234
|
- [Example usage](#example-usage-59)
|
|
235
|
-
- [
|
|
235
|
+
- [getCameraAuthorizationStatuses()](#getcameraauthorizationstatuses)
|
|
236
236
|
- [Parameters](#parameters-60)
|
|
237
237
|
- [Example usage](#example-usage-60)
|
|
238
|
-
- [
|
|
238
|
+
- [requestCameraAuthorization()](#requestcameraauthorization)
|
|
239
239
|
- [Parameters](#parameters-61)
|
|
240
240
|
- [Example usage](#example-usage-61)
|
|
241
|
-
- [
|
|
241
|
+
- [isCameraRollAuthorized()](#iscamerarollauthorized)
|
|
242
242
|
- [Parameters](#parameters-62)
|
|
243
243
|
- [Example usage](#example-usage-62)
|
|
244
|
-
|
|
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
|
-
- [
|
|
247
|
+
- [requestCameraRollAuthorization()](#requestcamerarollauthorization)
|
|
251
248
|
- [Parameters](#parameters-64)
|
|
252
249
|
- [Example usage](#example-usage-64)
|
|
253
|
-
- [
|
|
250
|
+
- [presentLimitedLibraryPicker()](#presentlimitedlibrarypicker)
|
|
254
251
|
- [Parameters](#parameters-65)
|
|
255
252
|
- [Example usage](#example-usage-65)
|
|
256
|
-
|
|
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
|
-
- [
|
|
259
|
+
- [isRegisteredForRemoteNotifications()](#isregisteredforremotenotifications)
|
|
260
260
|
- [Parameters](#parameters-67)
|
|
261
261
|
- [Example usage](#example-usage-67)
|
|
262
|
-
- [
|
|
263
|
-
- [Microphone module](#microphone-module)
|
|
264
|
-
- [isMicrophoneAuthorized()](#ismicrophoneauthorized)
|
|
262
|
+
- [getRemoteNotificationTypes()](#getremotenotificationtypes)
|
|
265
263
|
- [Parameters](#parameters-68)
|
|
266
264
|
- [Example usage](#example-usage-68)
|
|
267
|
-
- [
|
|
265
|
+
- [getRemoteNotificationsAuthorizationStatus()](#getremotenotificationsauthorizationstatus)
|
|
268
266
|
- [Parameters](#parameters-69)
|
|
269
267
|
- [Example usage](#example-usage-69)
|
|
270
|
-
- [
|
|
268
|
+
- [requestRemoteNotificationsAuthorization()](#requestremotenotificationsauthorization)
|
|
271
269
|
- [Parameters](#parameters-70)
|
|
272
270
|
- [Example usage](#example-usage-70)
|
|
273
|
-
|
|
274
|
-
|
|
271
|
+
- [switchToNotificationSettings()](#switchtonotificationsettings)
|
|
272
|
+
- [Microphone module](#microphone-module)
|
|
273
|
+
- [isMicrophoneAuthorized()](#ismicrophoneauthorized)
|
|
275
274
|
- [Parameters](#parameters-71)
|
|
276
275
|
- [Example usage](#example-usage-71)
|
|
277
|
-
- [
|
|
276
|
+
- [getMicrophoneAuthorizationStatus()](#getmicrophoneauthorizationstatus)
|
|
278
277
|
- [Parameters](#parameters-72)
|
|
279
278
|
- [Example usage](#example-usage-72)
|
|
280
|
-
- [
|
|
279
|
+
- [requestMicrophoneAuthorization()](#requestmicrophoneauthorization)
|
|
281
280
|
- [Parameters](#parameters-73)
|
|
282
281
|
- [Example usage](#example-usage-73)
|
|
283
|
-
- [
|
|
284
|
-
- [
|
|
282
|
+
- [Contacts module](#contacts-module)
|
|
283
|
+
- [isContactsAuthorized()](#iscontactsauthorized)
|
|
285
284
|
- [Parameters](#parameters-74)
|
|
286
285
|
- [Example usage](#example-usage-74)
|
|
287
|
-
- [
|
|
286
|
+
- [getContactsAuthorizationStatus()](#getcontactsauthorizationstatus)
|
|
288
287
|
- [Parameters](#parameters-75)
|
|
289
288
|
- [Example usage](#example-usage-75)
|
|
290
|
-
- [
|
|
289
|
+
- [requestContactsAuthorization()](#requestcontactsauthorization)
|
|
291
290
|
- [Parameters](#parameters-76)
|
|
292
291
|
- [Example usage](#example-usage-76)
|
|
293
|
-
- [
|
|
294
|
-
- [
|
|
292
|
+
- [Calendar module](#calendar-module)
|
|
293
|
+
- [isCalendarAuthorized()](#iscalendarauthorized)
|
|
295
294
|
- [Parameters](#parameters-77)
|
|
296
295
|
- [Example usage](#example-usage-77)
|
|
297
|
-
- [
|
|
296
|
+
- [getCalendarAuthorizationStatus()](#getcalendarauthorizationstatus)
|
|
298
297
|
- [Parameters](#parameters-78)
|
|
299
298
|
- [Example usage](#example-usage-78)
|
|
300
|
-
- [
|
|
299
|
+
- [requestCalendarAuthorization()](#requestcalendarauthorization)
|
|
301
300
|
- [Parameters](#parameters-79)
|
|
302
301
|
- [Example usage](#example-usage-79)
|
|
303
|
-
- [
|
|
304
|
-
- [
|
|
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
|
-
- [
|
|
306
|
+
- [getRemindersAuthorizationStatus()](#getremindersauthorizationstatus)
|
|
310
307
|
- [Parameters](#parameters-81)
|
|
311
308
|
- [Example usage](#example-usage-81)
|
|
312
|
-
- [
|
|
309
|
+
- [requestRemindersAuthorization()](#requestremindersauthorization)
|
|
313
310
|
- [Parameters](#parameters-82)
|
|
314
311
|
- [Example usage](#example-usage-82)
|
|
315
|
-
|
|
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
|
-
|
|
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
|
-
- [
|
|
321
|
+
- [requestMotionAuthorization()](#requestmotionauthorization)
|
|
326
322
|
- [Parameters](#parameters-85)
|
|
327
323
|
- [Example usage](#example-usage-85)
|
|
328
|
-
- [
|
|
324
|
+
- [getMotionAuthorizationStatus()](#getmotionauthorizationstatus)
|
|
329
325
|
- [Parameters](#parameters-86)
|
|
330
326
|
- [Example usage](#example-usage-86)
|
|
331
|
-
|
|
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
|
-
- [
|
|
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
|
-
- [
|
|
337
|
+
- [isNFCAvailable()](#isnfcavailable)
|
|
340
338
|
- [Parameters](#parameters-89)
|
|
341
339
|
- [Example usage](#example-usage-89)
|
|
342
|
-
- [
|
|
340
|
+
- [registerNFCStateChangeHandler()](#registernfcstatechangehandler)
|
|
343
341
|
- [Parameters](#parameters-90)
|
|
344
342
|
- [Example usage](#example-usage-90)
|
|
345
|
-
- [
|
|
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
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.
|
|
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-->
|
package/src/ios/Diagnostic.h
CHANGED
|
@@ -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
|
-
|
|
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
|
};
|
package/www/ios/diagnostic.js
CHANGED
|
@@ -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();
|