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

fix: registerWifiNetwork for Android 10 and proper result returned #318

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
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
Loading