I have a device emitting a Wi-Fi access point with a known SSID and password. I'm trying to connect my Android phone to that AP programmatically. I can connect my phone to it manually using the Wi-Fi settings, so I'm sure I have the right SSID and password and that the network is up. I'm using Flutter and a MethodChannel to talk to Java from Flutter.
Here's my Java-side code:
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "wifi";
private static final int TIMEOUT = 60000;
private static ConnectivityManager.NetworkCallback callback;
@Override
public void configureFlutterEngine(FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler((call, result) -> {
ConnectivityManager cm = (ConnectivityManager)getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
if(call.method.equals("request")) {
String ssid = call.argument("ssid");
String pass = call.argument("password");
if(callback != null) {
cm.unregisterNetworkCallback(callback);
}
callback = new ConnectivityManager.NetworkCallback() {
boolean first = true;
@Override
public void onAvailable(Network network) {
if(first) {
first = false;
result.success(cm.bindProcessToNetwork(network));
}
}
@Override
public void onUnavailable() {
callback = null;
result.success(false);
}
};
WifiNetworkSpecifier wfNetSpec = new WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.setWpa2Passphrase(pass)
.build();
NetworkRequest netReq = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(wfNetSpec)
.build();
cm.requestNetwork(netReq, callback, TIMEOUT);
} else if(call.method.equals("release")) {
if(callback != null) {
cm.unregisterNetworkCallback(callback);
}
cm.bindProcessToNetwork(null);
}
}
);
}
}
Here is my Flutter-side Dart code:
const MethodChannel _channel = MethodChannel('wifi');
Future<bool> request(String ssid, String password) async {
return await _channel.invokeMethod<bool>('request', {
'ssid': ssid,
'password': password,
}) == true;
}
void release() {
_channel.invokeMethod('release');
}
This approach was inspired by the questions below, yet onAvailable
is never called in my code:
Ask user to connect to a specific WiFi flutter
after called BindProcessToNetwork(network). APP never connect to internet through mobile data
What is the problem with this approach?
I'm using a Pixel 4a with Android 13.
Additionally, when I call the Dart request
function, a box will appear on-screen with "Searching for device..." and will fail after 30 seconds with the message "No devices found. Make sure devices are turned on and available to connect." with options "Cancel" and "Try again". If I hit "Try again" it will repeat and fail again after 30 seconds. This is not a UI I created. I believe it's an OS-created UI. What am I doing that is triggering this UI, could it be getting in the way of connecting to the AP, and how might I suppress it?