diff --git a/plugin.xml b/plugin.xml
index c665eae..9202320 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -29,6 +29,7 @@
+
diff --git a/src/android/wifiwizard2/WifiWizard2.java b/src/android/wifiwizard2/WifiWizard2.java
index f3c57b8..9132aed 100644
--- a/src/android/wifiwizard2/WifiWizard2.java
+++ b/src/android/wifiwizard2/WifiWizard2.java
@@ -17,13 +17,15 @@
import org.apache.cordova.*;
import java.util.List;
-import java.util.concurrent.Future;
+import java.util.concurrent.Future;
import java.lang.InterruptedException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import android.Manifest;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.content.BroadcastReceiver;
import android.content.Intent;
@@ -36,6 +38,10 @@
import android.net.DhcpInfo;
import android.net.wifi.WifiManager;
+import android.net.wifi.rtt.RangingResult;
+import android.net.wifi.rtt.WifiRttManager;
+import android.net.wifi.rtt.RangingRequest;
+import android.net.wifi.rtt.RangingResultCallback;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.ScanResult;
@@ -46,12 +52,13 @@
import android.net.ConnectivityManager.NetworkCallback;
import android.net.NetworkSpecifier;
-import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.os.Build.VERSION;
import android.os.PatternMatcher;
+import androidx.core.app.ActivityCompat;
+
import java.net.URL;
import java.net.InetAddress;
import java.net.Inet4Address;
@@ -80,6 +87,7 @@ public class WifiWizard2 extends CordovaPlugin {
private static final String IS_WIFI_ENABLED = "isWifiEnabled";
private static final String SET_WIFI_ENABLED = "setWifiEnabled";
private static final String SCAN = "scan";
+ private static final String SCAN_RTT = "scanWithRTT";
private static final String ENABLE_NETWORK = "enable";
private static final String DISABLE_NETWORK = "disable";
private static final String GET_SSID_NET_ID = "getSSIDNetworkID";
@@ -110,6 +118,7 @@ public class WifiWizard2 extends CordovaPlugin {
private static boolean bssidRequested = false;
private WifiManager wifiManager;
+ private WifiRttManager rttWifiManager;
private CallbackContext callbackContext;
private JSONArray passedData;
@@ -154,12 +163,13 @@ private static boolean getHexKey(String s) {
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
this.wifiManager = (WifiManager) cordova.getActivity().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ this.rttWifiManager = (WifiRttManager) cordova.getActivity().getApplicationContext().getSystemService(Context.WIFI_RTT_RANGING_SERVICE);
this.connectivityManager = (ConnectivityManager) cordova.getActivity().getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
}
@Override
public boolean execute(String action, JSONArray data, CallbackContext callbackContext)
- throws JSONException {
+ throws JSONException {
this.callbackContext = callbackContext;
this.passedData = data;
@@ -196,7 +206,7 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackCo
}
// Return only IP address
- if( action.equals( GET_WIFI_IP_ADDRESS ) ){
+ if (action.equals(GET_WIFI_IP_ADDRESS)) {
callbackContext.success(ip);
return true;
}
@@ -240,6 +250,8 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackCo
this.reconnect(callbackContext);
} else if (action.equals(SCAN)) {
this.scan(callbackContext, data);
+ } else if (action.equals(SCAN_RTT)) {
+ this.scanWithRTT(callbackContext, data);
} else if (action.equals(REMOVE_NETWORK)) {
this.remove(callbackContext, data);
} else if (action.equals(CONNECT_NETWORK)) {
@@ -357,6 +369,151 @@ public void run() {
return true;
}
+ /**
+ * Scans for RTT Ranging data, must call scan first to get Wifi Scan Results
+ *
+ * @param callbackContext A Cordova callback context
+ * @param data JSONArray with [0] == JSONObject
+ * @return true
+ */
+ private boolean scanWithRTT(final CallbackContext callbackContext, final JSONArray data) {
+ Log.v(TAG, "Entering Scan RTT");
+ final Context context = cordova.getActivity().getApplicationContext();
+ final ScanSyncContext syncContext = new ScanSyncContext();
+
+ synchronized (syncContext) {
+ if (syncContext.finished) {
+ Log.v(TAG, "In onReceive, already finished");
+ return false;
+ }
+
+ syncContext.finished = true;
+ }
+
+ Log.v(TAG, "Checking for RTT support");
+ if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+ callbackContext.error("ACCESS_FINE_LOCATION_FALSE");
+ return false;
+ }
+
+ final List wifiResults = wifiManager.getScanResults();
+ JSONArray rttData = new JSONArray();
+ final String[] error = {""};
+
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT) && API_VERSION > 27) {
+ Log.v(TAG, "RTT is supported");
+
+ if (rttWifiManager.isAvailable()) {
+ Log.v(TAG, "RTT is available");
+ RangingRequest.Builder builder = new RangingRequest.Builder();
+
+ int maxPeers = RangingRequest.getMaxPeers();
+ int peerCount = 0;
+
+ for (ScanResult result : wifiResults) {
+ if (peerCount >= maxPeers) {
+ break;
+ }
+
+ if (result.is80211mcResponder()) {
+ builder.addAccessPoint(result);
+ peerCount++;
+ }
+ }
+
+ RangingRequest request = builder.build();
+
+ try {
+ rttWifiManager.startRanging(request, cordova.getThreadPool(), new RangingResultCallback() {
+ @Override
+ public void onRangingResults(List results) {
+ // Process RTT results
+ for (RangingResult result : results) {
+ final int status = result.getStatus();
+
+ if (status != STATUS_CODE_FAIL) {
+ JSONObject rttItem = new JSONObject();
+
+ try {
+ rttItem.put("status", result.getStatus());
+ rttItem.put("macAddress", result.getMacAddress());
+ rttItem.put("distanceMm", result.getDistanceMm());
+ rttItem.put("distanceStdDevMm", result.getDistanceStdDevMm());
+ rttItem.put("rssi", result.getRssi());
+ rttData.put(rttItem);
+ } catch (JSONException e) {
+ error[0] = e.getMessage();
+ }
+ } else {
+ Log.v(TAG, "Result Failed With Status: " + status);
+ }
+ }
+
+ try {
+ JSONObject returnData = new JSONObject();
+ returnData.put("rttData", rttData);
+ returnData.put("error", error[0]);
+
+ callbackContext.success(returnData);
+ } catch (JSONException e) {
+ callbackContext.error("SCAN_WITH_RTT_FAILURE_1");
+ }
+ }
+
+ @Override
+ public void onRangingFailure(int code) {
+ // Handle failure
+ error[0] = "Ranging failed with code: " + code;
+ callbackContext.error(error[0]);
+ }
+ });
+ } catch (Exception e) {
+ error[0] = "SecurityException: " + e.getMessage();
+ callbackContext.error(error[0]);
+ }
+ } else {
+ Log.v(TAG, "RTT is not available");
+ error[0] = "RTT_NOT_AVAILABLE";
+ callbackContext.error("SCAN_WITH_RTT_FAILURE_2");
+ }
+ } else {
+ Log.v(TAG, "RTT is not supported");
+ error[0] = "RTT_NOT_SUPPORTED";
+ callbackContext.error("SCAN_WITH_RTT_FAILURE_3");
+ }
+
+ Log.v(TAG, "Submitting timeout to threadpool");
+ cordova.getThreadPool().submit(new Runnable() {
+ public void run() {
+ Log.v(TAG, "Entering timeout");
+ final int FIFTEEN_SECONDS = 15000;
+
+ try {
+ Thread.sleep(FIFTEEN_SECONDS);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Received InterruptedException e, " + e);
+ return;
+ // keep going into error
+ }
+
+ Log.v(TAG, "Thread sleep done");
+
+ synchronized (syncContext) {
+ if (syncContext.finished) {
+ Log.v(TAG, "In timeout, already finished");
+ return;
+ }
+ syncContext.finished = true;
+ }
+
+ Log.v(TAG, "In timeout, error");
+ callbackContext.error("TIMEOUT_WAITING_FOR_RTT");
+ }
+ });
+
+ return true;
+ }
+
/**
* This methods adds a network to the list of available WiFi networks. If the network already
* exists, then it updates it.
@@ -1911,4 +2068,4 @@ private static class AP {
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ios/WifiWizard2.h b/src/ios/WifiWizard2.h
index 3f2ab83..0080c69 100644
--- a/src/ios/WifiWizard2.h
+++ b/src/ios/WifiWizard2.h
@@ -6,6 +6,7 @@
- (void)iOSConnectNetwork:(CDVInvokedUrlCommand *)command;
- (void)iOSConnectOpenNetwork:(CDVInvokedUrlCommand *)command;
- (void)iOSDisconnectNetwork:(CDVInvokedUrlCommand *)command;
+- (void)getWifiIP:(CDVInvokedUrlCommand *)command;
- (void)getConnectedSSID:(CDVInvokedUrlCommand *)command;
- (void)getConnectedBSSID:(CDVInvokedUrlCommand *)command;
- (void)isWifiEnabled:(CDVInvokedUrlCommand *)command;
@@ -26,4 +27,4 @@
- (void)canPingWifiRouter:(CDVInvokedUrlCommand *)command;
- (void)canConnectToRouter:(CDVInvokedUrlCommand *)command;
-@end
+@end
\ No newline at end of file
diff --git a/src/ios/WifiWizard2.m b/src/ios/WifiWizard2.m
index 675c571..8e86c4e 100644
--- a/src/ios/WifiWizard2.m
+++ b/src/ios/WifiWizard2.m
@@ -1,11 +1,51 @@
#import "WifiWizard2.h"
#include
+#include
#import
#import
-#import
+#import
+#import
@implementation WifiWizard2
+- (void)getWifiIP:(CDVInvokedUrlCommand*)command {
+ CDVPluginResult *pluginResult = nil;
+
+ NSString *address = @"error";
+ struct ifaddrs *interfaces = NULL;
+ struct ifaddrs *temp_addr = NULL;
+ int success = 0;
+ // retrieve the current interfaces - returns 0 on success
+ success = getifaddrs(&interfaces);
+ if (success == 0) {
+ // Loop through linked list of interfaces
+ temp_addr = interfaces;
+ while(temp_addr != NULL) {
+ if(temp_addr->ifa_addr->sa_family == AF_INET) {
+ // Check if interface is en0 which is the wifi connection on the iPhone
+ if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
+ // Get NSString from C String
+ address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
+
+ }
+
+ }
+
+ temp_addr = temp_addr->ifa_next;
+ }
+ }
+ // Free memory
+ freeifaddrs(interfaces);
+ if (address) {
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:address];
+ } else {
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Not available"];
+ }
+
+ [self.commandDelegate sendPluginResult:pluginResult
+ callbackId:command.callbackId];
+}
+
- (id)fetchSSIDInfo {
// see http://stackoverflow.com/a/5198968/907720
NSArray *ifs = (__bridge_transfer NSArray *)CNCopySupportedInterfaces();
@@ -50,22 +90,31 @@ - (void)iOSConnectNetwork:(CDVInvokedUrlCommand*)command {
passwordString = [options objectForKey:@"Password"];
if (@available(iOS 11.0, *)) {
- if (ssidString && [ssidString length]) {
- NEHotspotConfiguration *configuration = [[NEHotspotConfiguration
- alloc] initWithSSID:ssidString
- passphrase:passwordString
- isWEP:(BOOL)false];
-
- configuration.joinOnce = false;
-
+ if (ssidString && [ssidString length]) {
+ NEHotspotConfiguration *configuration;
+
+
+ if (@available(iOS 13.0, *)) {
+ configuration = [[NEHotspotConfiguration
+ alloc] initWithSSIDPrefix:ssidString
+ passphrase:passwordString
+ isWEP:(BOOL)false];
+ } else {
+ configuration = [[NEHotspotConfiguration
+ alloc] initWithSSID:ssidString
+ passphrase:passwordString
+ isWEP:(BOOL)false];
+ }
+ configuration.joinOnce = false;
+
[[NEHotspotConfigurationManager sharedManager] applyConfiguration:configuration completionHandler:^(NSError * _Nullable error) {
NSDictionary *r = [self fetchSSIDInfo];
NSString *ssid = [r objectForKey:(id)kCNNetworkInfoKeySSID]; //@"SSID"
- if ([ssid isEqualToString:ssidString]){
- pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:ssidString];
+ if ([ssid hasPrefix:ssidString]){
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:ssid];
}else{
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.description];
}
@@ -73,7 +122,6 @@ - (void)iOSConnectNetwork:(CDVInvokedUrlCommand*)command {
callbackId:command.callbackId];
}];
-
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"SSID Not provided"];
[self.commandDelegate sendPluginResult:pluginResult
@@ -100,8 +148,16 @@ - (void)iOSConnectOpenNetwork:(CDVInvokedUrlCommand*)command {
if (@available(iOS 11.0, *)) {
if (ssidString && [ssidString length]) {
- NEHotspotConfiguration *configuration = [[NEHotspotConfiguration
- alloc] initWithSSID:ssidString];
+ NEHotspotConfiguration *configuration;
+
+
+ if (@available(iOS 13.0, *)) {
+ configuration = [[NEHotspotConfiguration
+ alloc] initWithSSIDPrefix:ssidString];
+ } else {
+ configuration = [[NEHotspotConfiguration
+ alloc] initWithSSID:ssidString];
+ }
configuration.joinOnce = false;
@@ -111,8 +167,8 @@ - (void)iOSConnectOpenNetwork:(CDVInvokedUrlCommand*)command {
NSString *ssid = [r objectForKey:(id)kCNNetworkInfoKeySSID]; //@"SSID"
- if ([ssid isEqualToString:ssidString]){
- pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:ssidString];
+ if ([ssid hasPrefix:ssidString]){
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:ssid];
}else{
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.description];
}
@@ -161,9 +217,8 @@ - (void)iOSDisconnectNetwork:(CDVInvokedUrlCommand*)command {
- (void)getConnectedSSID:(CDVInvokedUrlCommand*)command {
CDVPluginResult *pluginResult = nil;
- NSDictionary *r = [self fetchSSIDInfo];
- NSString *ssid = [r objectForKey:(id)kCNNetworkInfoKeySSID]; //@"SSID"
+ NSString *ssid = [self getWifiSsid]; //@"SSID"
if (ssid && [ssid length]) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:ssid];
@@ -329,5 +384,41 @@ - (void)canConnectToRouter:(CDVInvokedUrlCommand*)command {
callbackId:command.callbackId];
}
+- (NSString*) getWifiSsid {
+ if (@available(iOS 13.0, *)) {
+ CLLocationManager* manager = [[CLLocationManager alloc] init];
+ CLAuthorizationStatus authStatus = [manager authorizationStatus];
+
+ if (authStatus == kCLAuthorizationStatusNotDetermined) {
+ [manager requestWhenInUseAuthorization];
+ } else if (authStatus == kCLAuthorizationStatusDenied) {
+ NSLog(@"User has explicitly denied authorization for this application, or location services are disabled in Settings.");
+ return nil;
+ }
+ }
+
+ NSString *wifiName = nil;
+ CFArrayRef wifiInterfaces = CNCopySupportedInterfaces();
+ if (!wifiInterfaces) {
+ return nil;
+ }
+
+ NSArray *interfaces = (__bridge NSArray *)wifiInterfaces;
+ for (NSString *interfaceName in interfaces) {
+ CFDictionaryRef dictRef = CNCopyCurrentNetworkInfo((__bridge CFStringRef)(interfaceName));
+
+ if (dictRef) {
+ NSDictionary *networkInfo = (__bridge NSDictionary *)dictRef;
+ NSLog(@"network info -> %@", networkInfo);
+ wifiName = [networkInfo objectForKey:(__bridge NSString *)kCNNetworkInfoKeySSID];
+ CFRelease(dictRef);
+ }
+ }
+
+ CFRelease(wifiInterfaces);
+ return wifiName;
+}
+
+
-@end
+@end
\ No newline at end of file
diff --git a/www/WifiWizard2.js b/www/WifiWizard2.js
index 2408a31..431ebdd 100644
--- a/www/WifiWizard2.js
+++ b/www/WifiWizard2.js
@@ -299,6 +299,16 @@ var WifiWizard2 = {
});
},
+ /**
+ * Ranges for Wi-Fi RTT Data if it is supported (must call startScan, just use scan())
+ * @returns {Promise}
+ */
+ scanWithRTT: function () {
+ return new Promise(function (resolve, reject) {
+ cordova.exec(resolve, reject, 'WifiWizard2', 'scanWithRTT', []);
+ });
+ },
+
/**
* Check if WiFi is enabled
* @returns {Promise}