diff --git a/README.md b/README.md
index de269d2e..8f44568a 100644
--- a/README.md
+++ b/README.md
@@ -11,11 +11,11 @@ Becareful, some commands as no effect on iOS because Apple don't let us to do wh
## WiFi connections
| Description | Android | iOS |
| :---------------------------------------------------- | :----------------: | :------------------: |
-| Enabling / Disabling WiFi module | :white_check_mark: | :x: |
+| Enabling / Disabling WiFi module | :warning:(5) | :x: |
| Getting WiFi status | :white_check_mark: | :x: |
| Scanning for networks, with "already-associated" flag | :white_check_mark: | :x: |
-| Connecting / Disconnecting on a network in WPA / WEP | :white_check_mark: | :white_check_mark:(1) |
-| Registering / Unregistering a WiFi network | :white_check_mark: | :warning:(2) |
+| Connecting / Disconnecting on a network in WPA / WEP | :white_check_mark:(6) | :white_check_mark:(1) |
+| Registering / Unregistering a WiFi network | :warning:(7) | :warning:(2) |
| Getting informations like : | :white_check_mark: | :warning:(3) |
| - SSID | :white_check_mark: | :white_check_mark: |
| - BSSID | :white_check_mark: | :x: |
@@ -31,6 +31,12 @@ Becareful, some commands as no effect on iOS because Apple don't let us to do wh
:question:(4) : I think there is a way to get the IP address but for now, this is not implemented..
+:warning:(5): On Android SDK >= 29, this is deprecated and will always fail (except DO, PO and system apps). [[docs](https://developer.android.com/reference/android/net/wifi/WifiManager#setWifiEnabled(boolean))]
+
+:white_check_mark:(6): On Android SDK >= 29, WEP security is deprecated and will always fail, also the network will be disconnected when the app is closed. [[docs](https://developer.android.com/reference/android/net/ConnectivityManager?hl=en#requestNetwork(android.net.NetworkRequest,%20android.net.ConnectivityManager.NetworkCallback))]. If permanent network is required(Check :warning:(7)), there is a way but that network will not be controlled by the app, it will be as if user is adding the network manually, not supported as of now, open issue if you want this feature.
+
+:warning:(7) On Android SDK >=29, this is deprecated. Although there could be ways for user to be sent to Settings App for registering only(pre-filled) but not supported as of now.
+
## Access Point
| Description | Android | iOS |
| :------------------------------------------------------------------------------------ | :----------------: | :------------------: |
diff --git a/android/build.gradle b/android/build.gradle
index 37ff19d6..818a711b 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -8,7 +8,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.5.3'
+ classpath 'com.android.tools.build:gradle:4.1.0'
}
}
@@ -22,7 +22,7 @@ rootProject.allprojects {
apply plugin: 'com.android.library'
android {
- compileSdkVersion 28
+ compileSdkVersion 30
defaultConfig {
minSdkVersion 16
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index ebcf6f19..03b3fb2a 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -6,5 +6,5 @@
-
+
diff --git a/android/src/main/java/com/alternadom/wifiiot/WifiIotPlugin.java b/android/src/main/java/com/alternadom/wifiiot/WifiIotPlugin.java
index 0ae97014..ffe8adc8 100644
--- a/android/src/main/java/com/alternadom/wifiiot/WifiIotPlugin.java
+++ b/android/src/main/java/com/alternadom/wifiiot/WifiIotPlugin.java
@@ -7,36 +7,32 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
-import android.os.Handler;
-import android.os.Looper;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.net.wifi.WifiNetworkSpecifier;
import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.DatagramSocket;
-import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
+import androidx.annotation.NonNull;
import info.whitebyte.hotspotmanager.ClientScanResult;
import info.whitebyte.hotspotmanager.FinishScanListener;
import info.whitebyte.hotspotmanager.WifiApManager;
+import io.flutter.embedding.engine.plugins.FlutterPlugin;
+import io.flutter.embedding.engine.plugins.activity.ActivityAware;
+import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
@@ -49,55 +45,122 @@
/**
* WifiIotPlugin
*/
-public class WifiIotPlugin implements MethodCallHandler, EventChannel.StreamHandler {
+public class WifiIotPlugin implements FlutterPlugin, ActivityAware, MethodCallHandler, EventChannel.StreamHandler {
+ /// This local reference serves to register the plugin with the Flutter Engine and unregister it
+ /// when the Flutter Engine is detached from the Activity
+ private MethodChannel channel;
+ private EventChannel eventChannel;
+
private WifiManager moWiFi;
private Context moContext;
private WifiApManager moWiFiAPManager;
private Activity moActivity;
private BroadcastReceiver receiver;
+ private ConnectivityManager.NetworkCallback networkCallback;
private List ssidsToBeRemovedOnExit = new ArrayList();
- private WifiIotPlugin(Activity poActivity) {
- this.moActivity = poActivity;
- this.moContext = poActivity.getApplicationContext();
- this.moWiFi = (WifiManager) moContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
- this.moWiFiAPManager = new WifiApManager(moContext.getApplicationContext());
+ // initialize members of this class with Context
+ private void initWithContext(Context context) {
+ moContext = context;
+ moWiFi = (WifiManager) moContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ moWiFiAPManager = new WifiApManager(moContext.getApplicationContext());
+ }
+
+ // initialize members of this class with Activity
+ private void initWithActivity(Activity activity) {
+ moActivity = activity;
+ }
+
+ // cleanup
+ private void cleanup() {
+ if (!ssidsToBeRemovedOnExit.isEmpty()) {
+ List wifiConfigList =
+ moWiFi.getConfiguredNetworks();
+ for (String ssid : ssidsToBeRemovedOnExit) {
+ for (android.net.wifi.WifiConfiguration wifiConfig : wifiConfigList) {
+ if (wifiConfig.SSID.equals(ssid)) {
+ moWiFi.removeNetwork(wifiConfig.networkId);
+ }
+ }
+ }
+ }
+ // setting all members to null to avoid memory leaks
+ channel = null;
+ eventChannel = null;
+ moActivity = null;
+ moContext = null;
+ moWiFi = null;
+ moWiFiAPManager = null;
}
+
/**
- * Plugin registration.
+ * Plugin registration. This is used for registering with v1 Android embedding.
*/
public static void registerWith(Registrar registrar) {
- if (registrar.activity() == null) {
- // When a background flutter view tries to register the plugin, the registrar has no activity.
- // We stop the registration process as this plugin is foreground only.
- return;
- }
final MethodChannel channel = new MethodChannel(registrar.messenger(), "wifi_iot");
final EventChannel eventChannel = new EventChannel(registrar.messenger(), "plugins.wififlutter.io/wifi_scan");
- final WifiIotPlugin wifiIotPlugin = new WifiIotPlugin(registrar.activity());
+ final WifiIotPlugin wifiIotPlugin = new WifiIotPlugin();
+ wifiIotPlugin.initWithActivity(registrar.activity());
+ wifiIotPlugin.initWithContext(registrar.activeContext());
eventChannel.setStreamHandler(wifiIotPlugin);
channel.setMethodCallHandler(wifiIotPlugin);
registrar.addViewDestroyListener(new ViewDestroyListener() {
@Override
public boolean onViewDestroy(FlutterNativeView view) {
- if (!wifiIotPlugin.ssidsToBeRemovedOnExit.isEmpty()) {
- List wifiConfigList =
- wifiIotPlugin.moWiFi.getConfiguredNetworks();
- for (String ssid : wifiIotPlugin.ssidsToBeRemovedOnExit) {
- for (WifiConfiguration wifiConfig : wifiConfigList) {
- if (wifiConfig.SSID.equals(ssid)) {
- wifiIotPlugin.moWiFi.removeNetwork(wifiConfig.networkId);
- }
- }
- }
- }
+ wifiIotPlugin.cleanup();
return false;
}
});
}
+ @Override
+ public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
+ // initialize method and event channel and set handlers
+ channel = new MethodChannel(binding.getBinaryMessenger(), "wifi_iot");
+ eventChannel = new EventChannel(binding.getBinaryMessenger(), "plugins.wififlutter.io/wifi_scan");
+ channel.setMethodCallHandler(this);
+ eventChannel.setStreamHandler(this);
+
+ // initializeWithContext
+ initWithContext(binding.getApplicationContext());
+ }
+
+ @Override
+ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
+ // set null as channel handlers
+ channel.setMethodCallHandler(null);
+ eventChannel.setStreamHandler(null);
+
+ // set member to null
+ cleanup();
+ }
+
+ @Override
+ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
+ // init with activity
+ initWithActivity(binding.getActivity());
+ }
+
+ @Override
+ public void onDetachedFromActivityForConfigChanges() {
+ // set activity to null
+ moActivity = null;
+ }
+
+ @Override
+ public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
+ // init with activity
+ initWithActivity(binding.getActivity());
+ }
+
+ @Override
+ public void onDetachedFromActivity() {
+ // set activity to null
+ moActivity = null;
+ }
+
@Override
public void onMethodCall(MethodCall poCall, Result poResult) {
switch (poCall.method) {
@@ -141,10 +204,16 @@ public void onMethodCall(MethodCall poCall, Result poResult) {
getIP(poResult);
break;
case "removeWifiNetwork":
- removeWifiNetwork(poCall, poResult);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
+ removeWifiNetwork(poCall, poResult);
+ else
+ poResult.error("Error", "removeWifiNetwork not supported for Android SDK " + Build.VERSION.SDK_INT, null);
break;
case "isRegisteredWifiNetwork":
- isRegisteredWifiNetwork(poCall, poResult);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
+ isRegisteredWifiNetwork(poCall, poResult);
+ else
+ poResult.error("Error", "isRegisteredWifiNetwork not supported for Android SDK " + Build.VERSION.SDK_INT, null);
break;
case "isWiFiAPEnabled":
isWiFiAPEnabled(poResult);
@@ -186,7 +255,6 @@ public void onMethodCall(MethodCall poCall, Result poResult) {
}
/**
- *
* @param poCall
* @param poResult
*/
@@ -207,7 +275,7 @@ private void setMACFiltering(MethodCall poCall, Result poResult) {
* (e.g., {@code 01a243f405}).
*/
private void getWiFiAPSSID(Result poResult) {
- WifiConfiguration oWiFiConfig = moWiFiAPManager.getWifiApConfiguration();
+ android.net.wifi.WifiConfiguration oWiFiConfig = moWiFiAPManager.getWifiApConfiguration();
if (oWiFiConfig != null && oWiFiConfig.SSID != null) {
poResult.success(oWiFiConfig.SSID);
return;
@@ -218,7 +286,7 @@ private void getWiFiAPSSID(Result poResult) {
private void setWiFiAPSSID(MethodCall poCall, Result poResult) {
String sAPSSID = poCall.argument("ssid");
- WifiConfiguration oWiFiConfig = moWiFiAPManager.getWifiApConfiguration();
+ android.net.wifi.WifiConfiguration oWiFiConfig = moWiFiAPManager.getWifiApConfiguration();
oWiFiConfig.SSID = sAPSSID;
@@ -232,7 +300,7 @@ private void setWiFiAPSSID(MethodCall poCall, Result poResult) {
* SSID-specific probe request must be used for scans.
*/
private void isSSIDHidden(Result poResult) {
- WifiConfiguration oWiFiConfig = moWiFiAPManager.getWifiApConfiguration();
+ android.net.wifi.WifiConfiguration oWiFiConfig = moWiFiAPManager.getWifiApConfiguration();
if (oWiFiConfig != null && oWiFiConfig.hiddenSSID) {
poResult.success(oWiFiConfig.hiddenSSID);
return;
@@ -243,7 +311,7 @@ private void isSSIDHidden(Result poResult) {
private void setSSIDHidden(MethodCall poCall, Result poResult) {
boolean isSSIDHidden = poCall.argument("hidden");
- WifiConfiguration oWiFiConfig = moWiFiAPManager.getWifiApConfiguration();
+ android.net.wifi.WifiConfiguration oWiFiConfig = moWiFiAPManager.getWifiApConfiguration();
oWiFiConfig.hiddenSSID = isSSIDHidden;
@@ -262,7 +330,7 @@ private void setSSIDHidden(MethodCall poCall, Result poResult) {
* string otherwise.
*/
private void getWiFiAPPreSharedKey(Result poResult) {
- WifiConfiguration oWiFiConfig = moWiFiAPManager.getWifiApConfiguration();
+ android.net.wifi.WifiConfiguration oWiFiConfig = moWiFiAPManager.getWifiApConfiguration();
if (oWiFiConfig != null && oWiFiConfig.preSharedKey != null) {
poResult.success(oWiFiConfig.preSharedKey);
return;
@@ -273,7 +341,7 @@ private void getWiFiAPPreSharedKey(Result poResult) {
private void setWiFiAPPreSharedKey(MethodCall poCall, Result poResult) {
String sPreSharedKey = poCall.argument("preSharedKey");
- WifiConfiguration oWiFiConfig = moWiFiAPManager.getWifiApConfiguration();
+ android.net.wifi.WifiConfiguration oWiFiConfig = moWiFiAPManager.getWifiApConfiguration();
oWiFiConfig.preSharedKey = sPreSharedKey;
@@ -312,8 +380,8 @@ public void onFinishScan(final ArrayList clients) {
Boolean clientIsReachable = client.isReachable();
Boolean shouldReturnCurrentClient = true;
- if ( finalOnlyReachables.booleanValue()) {
- if (!clientIsReachable.booleanValue()){
+ if (finalOnlyReachables.booleanValue()) {
+ if (!clientIsReachable.booleanValue()) {
shouldReturnCurrentClient = Boolean.valueOf(false);
}
}
@@ -379,9 +447,9 @@ private void getWiFiAPState(Result poResult) {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
- int PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION = 65655434;
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && moContext.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
- moActivity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION);
+ int PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION = 65655434;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && moContext.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+ moActivity.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION);
}
receiver = createReceiver(eventSink);
@@ -390,14 +458,14 @@ public void onListen(Object o, EventChannel.EventSink eventSink) {
@Override
public void onCancel(Object o) {
- if(receiver != null){
+ if (receiver != null) {
moContext.unregisterReceiver(receiver);
receiver = null;
}
}
- private BroadcastReceiver createReceiver(final EventChannel.EventSink eventSink){
+ private BroadcastReceiver createReceiver(final EventChannel.EventSink eventSink) {
return new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -405,7 +473,8 @@ public void onReceive(Context context, Intent intent) {
}
};
}
- JSONArray handleNetworkScanResult(){
+
+ JSONArray handleNetworkScanResult() {
List results = moWiFi.getScanResults();
JSONArray wifiArray = new JSONArray();
@@ -445,12 +514,13 @@ JSONArray handleNetworkScanResult(){
private void loadWifiList(final Result poResult) {
try {
- int PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION = 65655434;
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && moContext.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
- moActivity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION);
+ int PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION = 65655434;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && moContext.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+ moActivity.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION);
}
- moWiFi.startScan();
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P)
+ moWiFi.startScan();
poResult.success(handleNetworkScanResult().toString());
@@ -499,7 +569,7 @@ public void onAvailable(Network network) {
final Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
- public void run () {
+ public void run() {
poResult.success(result);
}
});
@@ -540,15 +610,8 @@ public void run() {
String security = poCall.argument("security");
Boolean joinOnce = poCall.argument("join_once");
- final boolean connected = connectTo(ssid, password, security, joinOnce);
-
- final Handler handler = new Handler(Looper.getMainLooper());
- handler.post(new Runnable() {
- @Override
- public void run () {
- poResult.success(connected);
- }
- });
+ connectTo(poResult, ssid, password, security, joinOnce);
+
}
}.start();
}
@@ -558,9 +621,9 @@ public void run () {
/// After 10 seconds, a post telling you whether you are connected will pop up.
/// Callback returns true if ssid is in the range
private void findAndConnect(final MethodCall poCall, final Result poResult) {
- int PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION = 65655434;
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && moContext.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
- moActivity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION);
+ int PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION = 65655434;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && moContext.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+ moActivity.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION);
}
new Thread() {
public void run() {
@@ -577,15 +640,7 @@ public void run() {
}
}
- final boolean connected = connectTo(ssid, password, security, joinOnce);
-
- final Handler handler = new Handler(Looper.getMainLooper());
- handler.post(new Runnable() {
- @Override
- public void run () {
- poResult.success(connected);
- }
- });
+ connectTo(poResult, ssid, password, security, joinOnce);
}
}.start();
}
@@ -606,18 +661,56 @@ private static String getSecurityType(ScanResult scanResult) {
/// Use this method to check if the device is currently connected to Wifi.
private void isConnected(Result poResult) {
- ConnectivityManager connManager = (ConnectivityManager) moContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo mWifi = connManager != null ? connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI) : null;
- if (mWifi != null && mWifi.isConnected()) {
- poResult.success(true);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ isConnectedDeprecated(poResult);
} else {
- poResult.success(false);
+ int PERMISSIONS_REQUEST_CODE_ACCESS_NETWORK_STATE = 656889657;
+ if (moContext.checkSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED) {
+ moActivity.requestPermissions(new String[]{Manifest.permission.ACCESS_NETWORK_STATE}, PERMISSIONS_REQUEST_CODE_ACCESS_NETWORK_STATE);
+ }
+
+ ConnectivityManager connManager = (ConnectivityManager) moContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ boolean result = false;
+ if (connManager != null) {
+ // `connManager.getActiveNetwork` only return if the network has internet
+ // therefore using `connManager.getAllNetworks()` to check all networks
+ for (final Network network : connManager.getAllNetworks()) {
+ final NetworkCapabilities capabilities = network != null
+ ? connManager.getNetworkCapabilities(network)
+ : null;
+ final boolean isConnected = capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
+ if (isConnected) {
+ result = true;
+ break;
+ }
+ }
+ }
+
+ poResult.success(result);
}
}
+ @SuppressWarnings("deprecation")
+ private void isConnectedDeprecated(Result poResult) {
+ ConnectivityManager connManager = (ConnectivityManager) moContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ android.net.NetworkInfo mWifi = connManager != null
+ ? connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
+ : null;
+
+ poResult.success(mWifi != null && mWifi.isConnected());
+ }
+
/// Disconnect current Wifi.
private void disconnect(Result poResult) {
- moWiFi.disconnect();
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+ //noinspection deprecation
+ moWiFi.disconnect();
+ } else {
+ if (networkCallback != null) {
+ final ConnectivityManager connectivityManager = (ConnectivityManager) moContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ connectivityManager.unregisterNetworkCallback(networkCallback);
+ }
+ }
poResult.success(null);
}
@@ -677,8 +770,8 @@ private void removeWifiNetwork(MethodCall poCall, Result poResult) {
poResult.error("Error", "No prefix SSID was given!", null);
}
- List mWifiConfigList = moWiFi.getConfiguredNetworks();
- for (WifiConfiguration wifiConfig : mWifiConfigList) {
+ List mWifiConfigList = moWiFi.getConfiguredNetworks();
+ for (android.net.wifi.WifiConfiguration wifiConfig : mWifiConfigList) {
String comparableSSID = ('"' + prefix_ssid); //Add quotes because wifiConfig.SSID has them
if (wifiConfig.SSID.startsWith(comparableSSID)) {
moWiFi.removeNetwork(wifiConfig.networkId);
@@ -695,10 +788,10 @@ private void isRegisteredWifiNetwork(MethodCall poCall, Result poResult) {
String ssid = poCall.argument("ssid");
- List mWifiConfigList = moWiFi.getConfiguredNetworks();
+ List mWifiConfigList = moWiFi.getConfiguredNetworks();
String comparableSSID = ('"' + ssid + '"'); //Add quotes because wifiConfig.SSID has them
if (mWifiConfigList != null) {
- for (WifiConfiguration wifiConfig : mWifiConfigList) {
+ for (android.net.wifi.WifiConfiguration wifiConfig : mWifiConfigList) {
if (wifiConfig.SSID.equals(comparableSSID)) {
poResult.success(true);
return;
@@ -726,9 +819,66 @@ private static String longToIP(int longIp) {
}
/// Method to connect to WIFI Network
- private Boolean connectTo(String ssid, String password, String security, Boolean joinOnce) {
+ private void connectTo(final Result poResult, final String ssid, final String password, final String security, final Boolean joinOnce) {
+ final Handler handler = new Handler(Looper.getMainLooper());
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+ final boolean connected = connectToDeprecated(ssid, password, security, joinOnce);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ poResult.success(connected);
+ }
+ });
+ } else {
+ // Make new network specifier
+ final WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder();
+ // set ssid
+ builder.setSsid(ssid);
+ // set security
+ if (security != null && security.toUpperCase().equals("WPA")) {
+ builder.setWpa2Passphrase(password);
+ } else if (security != null && security.toUpperCase().equals("WEP")) {
+ // WEP is not supported
+ poResult.error("Error", "WEP is not supported for Android SDK " + Build.VERSION.SDK_INT, "");
+ }
+
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .setNetworkSpecifier(builder.build())
+ .build();
+
+ final ConnectivityManager connectivityManager = (ConnectivityManager) moContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+
+ if (networkCallback != null)
+ connectivityManager.unregisterNetworkCallback(networkCallback);
+
+ networkCallback = new ConnectivityManager.NetworkCallback() {
+ @Override
+ public void onAvailable(@NonNull Network network) {
+ super.onAvailable(network);
+ poResult.success(true);
+ }
+
+ @Override
+ public void onUnavailable() {
+ super.onUnavailable();
+ poResult.success(false);
+ }
+ };
+
+
+ connectivityManager.requestNetwork(networkRequest, networkCallback, handler, 30 * 1000);
+
+ // TODO remove network in cleanup, if joinOnce
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private Boolean connectToDeprecated(String ssid, String password, String security, Boolean joinOnce) {
/// Make new configuration
- WifiConfiguration conf = new WifiConfiguration();
+ android.net.wifi.WifiConfiguration conf = new android.net.wifi.WifiConfiguration();
conf.SSID = "\"" + ssid + "\"";
if (security != null) security = security.toUpperCase();
@@ -740,38 +890,38 @@ private Boolean connectTo(String ssid, String password, String security, Boolean
/// ifcase of not added it will not be able to connect
conf.preSharedKey = "\"" + password + "\"";
- conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+ conf.allowedProtocols.set(android.net.wifi.WifiConfiguration.Protocol.RSN);
- conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+ conf.allowedKeyManagement.set(android.net.wifi.WifiConfiguration.KeyMgmt.WPA_PSK);
- conf.status = WifiConfiguration.Status.ENABLED;
+ conf.status = android.net.wifi.WifiConfiguration.Status.ENABLED;
- conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
- conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+ conf.allowedGroupCiphers.set(android.net.wifi.WifiConfiguration.GroupCipher.TKIP);
+ conf.allowedGroupCiphers.set(android.net.wifi.WifiConfiguration.GroupCipher.CCMP);
- conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+ conf.allowedKeyManagement.set(android.net.wifi.WifiConfiguration.KeyMgmt.WPA_PSK);
- conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
- conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+ conf.allowedPairwiseCiphers.set(android.net.wifi.WifiConfiguration.PairwiseCipher.TKIP);
+ conf.allowedPairwiseCiphers.set(android.net.wifi.WifiConfiguration.PairwiseCipher.CCMP);
- conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
- conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
+ conf.allowedProtocols.set(android.net.wifi.WifiConfiguration.Protocol.RSN);
+ conf.allowedProtocols.set(android.net.wifi.WifiConfiguration.Protocol.WPA);
} else if (security.equals("WEP")) {
conf.wepKeys[0] = "\"" + password + "\"";
conf.wepTxKeyIndex = 0;
- conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
- conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
+ conf.allowedKeyManagement.set(android.net.wifi.WifiConfiguration.KeyMgmt.NONE);
+ conf.allowedGroupCiphers.set(android.net.wifi.WifiConfiguration.GroupCipher.WEP40);
} else {
- conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+ conf.allowedKeyManagement.set(android.net.wifi.WifiConfiguration.KeyMgmt.NONE);
}
/// Remove the existing configuration for this netwrok
- List mWifiConfigList = moWiFi.getConfiguredNetworks();
+ List mWifiConfigList = moWiFi.getConfiguredNetworks();
int updateNetwork = -1;
if (mWifiConfigList != null) {
- for (WifiConfiguration wifiConfig : mWifiConfigList) {
+ for (android.net.wifi.WifiConfiguration wifiConfig : mWifiConfigList) {
if (wifiConfig.SSID.equals(conf.SSID)) {
conf.networkId = wifiConfig.networkId;
updateNetwork = moWiFi.updateNetwork(conf);
@@ -817,69 +967,5 @@ private Boolean connectTo(String ssid, String password, String security, Boolean
return connected;
}
-
- public static String sudoForResult(String... strings) {
- String res = "";
- DataOutputStream outputStream = null;
- InputStream response = null;
- try {
- Process su = Runtime.getRuntime().exec("su");
- outputStream = new DataOutputStream(su.getOutputStream());
- response = su.getInputStream();
-
- for (String s : strings) {
- outputStream.writeBytes(s + "\n");
- outputStream.flush();
- }
-
- outputStream.writeBytes("exit\n");
- outputStream.flush();
- try {
- su.waitFor();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- res = readFully(response);
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- Closer.closeSilently(outputStream, response);
- }
- return res;
- }
-
- private static String readFully(InputStream is) throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- byte[] buffer = new byte[1024];
- int length = 0;
- while ((length = is.read(buffer)) != -1) {
- baos.write(buffer, 0, length);
- }
- return baos.toString("UTF-8");
- }
-
- static class Closer {
- /// closeAll()
- public static void closeSilently(Object... xs) {
- /// Note: on Android API levels prior to 19 Socket does not implement Closeable
- for (Object x : xs) {
- if (x != null) {
- try {
- if (x instanceof Closeable) {
- ((Closeable) x).close();
- } else if (x instanceof Socket) {
- ((Socket) x).close();
- } else if (x instanceof DatagramSocket) {
- ((DatagramSocket) x).close();
- } else {
- throw new RuntimeException("cannot close " + x);
- }
- } catch (Throwable e) {
- // TODO : do something ?
- }
- }
- }
- }
- }
}
diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle
index d6350163..650cbdc1 100644
--- a/example/android/app/build.gradle
+++ b/example/android/app/build.gradle
@@ -15,7 +15,7 @@ apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
- compileSdkVersion 28
+ compileSdkVersion 30
lintOptions {
disable 'InvalidPackage'
@@ -25,10 +25,10 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.alternadom.wifiiotexample"
minSdkVersion 16
- targetSdkVersion 27
+ targetSdkVersion 30
versionCode 1
versionName "1.0"
- testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
buildTypes {
@@ -46,6 +46,6 @@ flutter {
dependencies {
testImplementation 'junit:junit:4.12'
- androidTestImplementation 'com.android.support.test:runner:1.0.1'
- androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.1'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
}
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index e2dc8b67..541f1e93 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -35,5 +35,8 @@
+
diff --git a/example/android/app/src/main/java/com/alternadom/wifiiotexample/MainActivity.java b/example/android/app/src/main/java/com/alternadom/wifiiotexample/MainActivity.java
index c1c764de..38596d24 100644
--- a/example/android/app/src/main/java/com/alternadom/wifiiotexample/MainActivity.java
+++ b/example/android/app/src/main/java/com/alternadom/wifiiotexample/MainActivity.java
@@ -1,14 +1,6 @@
package com.alternadom.wifiiotexample;
-import android.os.Bundle;
-
-import io.flutter.app.FlutterActivity;
-import io.flutter.plugins.GeneratedPluginRegistrant;
+import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- GeneratedPluginRegistrant.registerWith(this);
- }
}
diff --git a/example/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/example/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java
index 38a33ea2..7b5c1f91 100644
--- a/example/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java
+++ b/example/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java
@@ -1,25 +1,18 @@
package io.flutter.plugins;
-import io.flutter.plugin.common.PluginRegistry;
-import com.alternadom.wifiiot.WifiIotPlugin;
+import androidx.annotation.Keep;
+import androidx.annotation.NonNull;
+
+import io.flutter.embedding.engine.FlutterEngine;
/**
* Generated file. Do not edit.
+ * This file is generated by the Flutter tool based on the
+ * plugins that support the Android platform.
*/
+@Keep
public final class GeneratedPluginRegistrant {
- public static void registerWith(PluginRegistry registry) {
- if (alreadyRegisteredWith(registry)) {
- return;
- }
- WifiIotPlugin.registerWith(registry.registrarFor("com.alternadom.wifiiot.WifiIotPlugin"));
- }
-
- private static boolean alreadyRegisteredWith(PluginRegistry registry) {
- final String key = GeneratedPluginRegistrant.class.getCanonicalName();
- if (registry.hasPlugin(key)) {
- return true;
- }
- registry.registrarFor(key);
- return false;
+ public static void registerWith(@NonNull FlutterEngine flutterEngine) {
+ flutterEngine.getPlugins().add(new com.alternadom.wifiiot.WifiIotPlugin());
}
}
diff --git a/example/android/build.gradle b/example/android/build.gradle
index 44768875..c9e3db0a 100644
--- a/example/android/build.gradle
+++ b/example/android/build.gradle
@@ -5,7 +5,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.0.1'
+ classpath 'com.android.tools.build:gradle:4.1.0'
}
}
diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties
index aa901e1e..69e97a3f 100644
--- a/example/android/gradle/wrapper/gradle-wrapper.properties
+++ b/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Fri Jun 23 08:50:38 CEST 2017
+#Thu Oct 29 10:36:05 IST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 71f43872..ee019f92 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -1,62 +1,48 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
- archive:
- dependency: transitive
- description:
- name: archive
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.11"
- args:
- dependency: transitive
- description:
- name: args
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.5.2"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.4.0"
+ version: "2.5.0-nullsafety.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.5"
- charcode:
+ version: "2.1.0-nullsafety.1"
+ characters:
dependency: transitive
description:
- name: charcode
+ name: characters
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.2"
- collection:
+ version: "1.1.0-nullsafety.3"
+ charcode:
dependency: transitive
description:
- name: collection
+ name: charcode
url: "https://pub.dartlang.org"
source: hosted
- version: "1.14.11"
- convert:
+ version: "1.2.0-nullsafety.1"
+ clock:
dependency: transitive
description:
- name: convert
+ name: clock
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.1"
- crypto:
+ version: "1.1.0-nullsafety.1"
+ collection:
dependency: transitive
description:
- name: crypto
+ name: collection
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.3"
+ version: "1.15.0-nullsafety.3"
cupertino_icons:
dependency: "direct main"
description:
@@ -64,6 +50,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.2.0-nullsafety.1"
flutter:
dependency: "direct main"
description: flutter
@@ -74,55 +67,27 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
- image:
- dependency: transitive
- description:
- name: image
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.4"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
- version: "0.12.6"
+ version: "0.12.10-nullsafety.1"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.8"
+ version: "1.3.0-nullsafety.3"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
- version: "1.6.4"
- pedantic:
- dependency: transitive
- description:
- name: pedantic
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.8.0+1"
- petitparser:
- dependency: transitive
- description:
- name: petitparser
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.4.0"
- quiver:
- dependency: transitive
- description:
- name: quiver
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.5"
+ version: "1.8.0-nullsafety.1"
sky_engine:
dependency: transitive
description: flutter
@@ -134,70 +99,63 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.5.5"
+ version: "1.8.0-nullsafety.2"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
- version: "1.9.3"
+ version: "1.10.0-nullsafety.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
+ version: "2.1.0-nullsafety.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.5"
+ version: "1.1.0-nullsafety.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
+ version: "1.2.0-nullsafety.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.11"
+ version: "0.2.19-nullsafety.2"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.6"
+ version: "1.3.0-nullsafety.3"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.8"
+ version: "2.1.0-nullsafety.3"
wifi_iot:
dependency: "direct dev"
description:
path: ".."
relative: true
source: path
- version: "0.1.0"
- xml:
- dependency: transitive
- description:
- name: xml
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.5.0"
+ version: "0.1.1"
sdks:
- dart: ">=2.4.0 <3.0.0"
+ dart: ">=2.10.0-110 <2.11.0"
flutter: ">=1.10.0 <2.0.0"