Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wi-Fi RTT Manager Ranging Feature for Android + iOS Fixes to request Location Perms #140

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
</config-file>

<config-file target="res/xml/config.xml" parent="/*">
Expand Down
167 changes: 162 additions & 5 deletions src/android/wifiwizard2/WifiWizard2.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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<ScanResult> 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<RangingResult> 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.
Expand Down Expand Up @@ -1911,4 +2068,4 @@ private static class AP {
}

}
}
}
3 changes: 2 additions & 1 deletion src/ios/WifiWizard2.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,4 +27,4 @@
- (void)canPingWifiRouter:(CDVInvokedUrlCommand *)command;
- (void)canConnectToRouter:(CDVInvokedUrlCommand *)command;

@end
@end
Loading