Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,15 @@
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.ActivityResultListener;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener;
import io.flutter.plugin.common.PluginRegistry.ViewDestroyListener;
import io.flutter.view.FlutterNativeView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
Expand All @@ -56,7 +59,8 @@ public class WifiIotPlugin
ActivityAware,
MethodCallHandler,
EventChannel.StreamHandler,
RequestPermissionsResultListener {
RequestPermissionsResultListener,
ActivityResultListener {
/// 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;
Expand Down Expand Up @@ -85,6 +89,15 @@ public class WifiIotPlugin
65655437;
private static final int PERMISSIONS_REQUEST_CODE_ACCESS_NETWORK_STATE_IS_CONNECTED = 65655438;

// Activity results
private static final Map<Integer, Result> resultMap = new HashMap<Integer, Result>();
private static final int ACTIVITY_RESULT_REQUEST_CODE_ADD_NETWORKS = 66778899;

// Register network result flags
private static final int WIFI_REGISTER_NETWORK_RESULT_SUCCESS = 0;
private static final int WIFI_REGISTER_NETWORK_RESULT_FAILED = 1;
private static final int WIFI_REGISTER_NETWORK_RESULT_ALREADY_EXISTS = 2;

// initialize members of this class with Context
private void initWithContext(Context context) {
moContext = context;
Expand Down Expand Up @@ -141,6 +154,7 @@ public boolean onViewDestroy(FlutterNativeView view) {
}
});
registrar.addRequestPermissionsResultListener(wifiIotPlugin);
registrar.addActivityResultListener(wifiIotPlugin);
}

@Override
Expand Down Expand Up @@ -171,6 +185,7 @@ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
// init with activity
initWithActivity(binding.getActivity());
binding.addRequestPermissionsResultListener(this);
binding.addActivityResultListener(this);
}

@Override
Expand All @@ -184,6 +199,7 @@ public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBindin
// init with activity
initWithActivity(binding.getActivity());
binding.addRequestPermissionsResultListener(this);
binding.addActivityResultListener(this);
}

@Override
Expand Down Expand Up @@ -242,6 +258,44 @@ public boolean onRequestPermissionsResult(
return false;
}

@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultMap.containsKey(requestCode)) {
final Result result = resultMap.get(requestCode);
if (requestCode == ACTIVITY_RESULT_REQUEST_CODE_ADD_NETWORKS) {
int resultValue = -1;
if ((data != null) && data.hasExtra(Settings.EXTRA_WIFI_NETWORK_RESULT_LIST)) {
for (int code : data.getIntegerArrayListExtra(Settings.EXTRA_WIFI_NETWORK_RESULT_LIST)) {
if (code == Settings.ADD_WIFI_RESULT_SUCCESS) {
resultValue = WIFI_REGISTER_NETWORK_RESULT_SUCCESS;
break;
}
else if (code == Settings.ADD_WIFI_RESULT_ADD_OR_UPDATE_FAILED) {
resultValue = WIFI_REGISTER_NETWORK_RESULT_FAILED;
break;
}
else if (code == Settings.ADD_WIFI_RESULT_ALREADY_EXISTS) {
resultValue = WIFI_REGISTER_NETWORK_RESULT_ALREADY_EXISTS;
break;
}
}
if (resultValue == -1) {
result.error("Error", "Unknown return value for ADD_WIFI_RESULT", "");
}
else {
result.success(resultValue);
}
}
else {
result.success(WIFI_REGISTER_NETWORK_RESULT_FAILED);
}
}
resultMap.remove(requestCode);
return true;
}
return false;
}

@Override
public void onMethodCall(MethodCall poCall, Result poResult) {
switch (poCall.method) {
Expand Down Expand Up @@ -934,11 +988,12 @@ private static MacAddress macAddressFromBssid(String bssid) {
}

/**
* Registers a wifi network in the device wireless networks For API >= 30 uses intent to
* permanently store such network in user configuration For API <= 29 uses deprecated functions
* that manipulate directly *** registerWifiNetwork : param ssid, SSID to register param password,
* passphrase to use param security, security mode (WPA or null) to use return {@code true} if the
* operation succeeds, {@code false} otherwise
* Registers a wifi network in the device wireless networks. For API >= 30 uses intent to
* permanently store such network in user configuration. For API == 29 adds network as suggestion
* in the notification area. For API <= 28 uses deprecated functions that manipulate directly ***
* registerWifiNetwork : param ssid, SSID to register param password, passphrase to use param
* security, security mode (WPA or null) to use return {@code true} if the operation succeeds,
* {@code false} otherwise
*/
private void registerWifiNetwork(final MethodCall poCall, final Result poResult) {
String ssid = poCall.argument("ssid");
Expand All @@ -947,7 +1002,7 @@ private void registerWifiNetwork(final MethodCall poCall, final Result poResult)
String security = poCall.argument("security");
Boolean isHidden = poCall.argument("is_hidden");

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
final WifiNetworkSuggestion.Builder suggestedNet = new WifiNetworkSuggestion.Builder();
suggestedNet.setSsid(ssid);
suggestedNet.setIsHiddenSsid(isHidden != null ? isHidden : false);
Expand All @@ -974,14 +1029,27 @@ private void registerWifiNetwork(final MethodCall poCall, final Result poResult)
suggestionsList.add(suggestedNet.build());

Bundle bundle = new Bundle();
bundle.putParcelableArrayList(
android.provider.Settings.EXTRA_WIFI_NETWORK_LIST, suggestionsList);
Intent intent = new Intent(android.provider.Settings.ACTION_WIFI_ADD_NETWORKS);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
moContext.startActivity(intent);

poResult.success(null);
bundle.putParcelableArrayList(Settings.EXTRA_WIFI_NETWORK_LIST, suggestionsList);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Intent intent = new Intent(Settings.ACTION_WIFI_ADD_NETWORKS);
intent.putExtras(bundle);
if (moActivity != null) {
// listen for activity result
resultMap.put(ACTIVITY_RESULT_REQUEST_CODE_ADD_NETWORKS, poResult);
moActivity.startActivityForResult(intent, ACTIVITY_RESULT_REQUEST_CODE_ADD_NETWORKS);
} else {
poResult.error(
"NoActivityError",
"Activity object is null, are you running this from background?",
"");
}
} else {
// on Android 10 the intent is not available yet; instead, a message is shown in the
// notification area
final int status = moWiFi.addNetworkSuggestions(networkSuggestions);
Log.e(WifiIotPlugin.class.getSimpleName(), "status: " + status);
poResult.success(status == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS ? WIFI_REGISTER_NETWORK_RESULT_SUCCESS : WIFI_REGISTER_NETWORK_RESULT_FAILED);
}
} else {
// Deprecated version
android.net.wifi.WifiConfiguration conf =
Expand All @@ -992,7 +1060,7 @@ private void registerWifiNetwork(final MethodCall poCall, final Result poResult)
if (updateNetwork == -1) {
poResult.error("Error", "Error updating network configuration", "");
} else {
poResult.success(null);
poResult.success(WIFI_REGISTER_NETWORK_RESULT_SUCCESS);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/wifi_iot/example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ subprojects {
project.evaluationDependsOn(':app')
}

task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
32 changes: 25 additions & 7 deletions packages/wifi_iot/lib/wifi_iot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ enum WIFI_AP_STATE {

enum NetworkSecurity { WPA, WEP, NONE }

enum RegisterWifiNetworkResult {
success,
failed,
alreadyRegistered
}

const serializeNetworkSecurityMap = <NetworkSecurity, String>{
NetworkSecurity.WPA: "WPA",
NetworkSecurity.WEP: "WEP",
Expand Down Expand Up @@ -391,9 +397,9 @@ class WiFiForIoTPlugin {
///
/// @param [isHidden] Whether the SSID is hidden (not broadcasted by the AP).
///
/// @returns True in case the requested network could be registered, false
/// otherwise.
static Future<bool> registerWifiNetwork(
/// @returns Whether the network could be registered, the network failed to register,
/// or the network is already registered.
static Future<RegisterWifiNetworkResult> registerWifiNetwork(
String ssid, {
String? bssid,
String? password,
Expand All @@ -409,13 +415,13 @@ class WiFiForIoTPlugin {
// TODO: support any binary sequence as required instead of just strings.
if (ssid.length == 0 || ssid.length > 32) {
print("Invalid SSID");
return false;
return RegisterWifiNetworkResult.failed;
}

if (!Platform.isIOS && !await isEnabled()) await setEnabled(true);
bool? bResult;
int? iResult;
try {
await _channel.invokeMethod('registerWifiNetwork', {
iResult = await _channel.invokeMethod('registerWifiNetwork', {
"ssid": ssid.toString(),
"bssid": bssid?.toString(),
"password": password?.toString(),
Expand All @@ -425,7 +431,19 @@ class WiFiForIoTPlugin {
} on MissingPluginException catch (e) {
print("MissingPluginException : ${e.toString()}");
}
return bResult ?? false;

if (iResult == 0) {
return RegisterWifiNetworkResult.success;
}
else if (iResult == 1) {
return RegisterWifiNetworkResult.failed;
}
else if (iResult == 2) {
return RegisterWifiNetworkResult.alreadyRegistered;
}
else {
return RegisterWifiNetworkResult.failed;
}
}

/// Scan for Wi-Fi networks and connect to the requested AP Wi-Fi network if
Expand Down