B4A Library MLwifi Library Updated to v4.00

Computersmith64

Well-Known Member
Licensed User
Longtime User

It's a timing issue. You're calling disconnectWifiAP in your ResetAP sub, then immediately returning the result (which is fine) - however you're then immediately calling GetSSID, which is returning in some cases before the AP has been disconnected (in which case you'll get the ssid of the AP you're disconnecting from) or when it's in a state between disconnecting & reconnecting to the previous AP (in which case you'll get an "unknown ssid" message).

- Colin.
 

RJB

Active Member
Licensed User
Longtime User
I don't think any of
Wifi.disconnectWifiAP (Android 10 and above?)
Wifi.connectWifiAP(SSID, 0, "", Timeout)
Wifi.reconnectWifiAP(SSID, TimeOut)
work on Android 9. But maybe I'm wrong?
If that is the case then is there any way to connect to a saved network without knowing its password?
 

RJB

Active Member
Licensed User
Longtime User
I'll take a look at the timing issue when I get a chance
 

Computersmith64

Well-Known Member
Licensed User
Longtime User
I'll take a look at the timing issue when I get a chance
There's not much you can do other than maybe wait in a loop checking the ssid until it changes back to the value you have stored in your Old SSID var. By disconnecting from the AP your app has connected to, you're allowing the OS to fall back to the AP it was connected to previously so there's no explicit connection request & therefore no callback when the connection succeeds (or fails).

- Colin.
 

RJB

Active Member
Licensed User
Longtime User
I tried the wait loop on Adroid 9 without success, but I must be doing something wrong because all three of the methods (Wifi.disconnectWifiAP, Wifi.connectWifiAP(SSID, 0, "", Timeout), and Wifi.reconnectWifiAP(SSID, TimeOut) ) result in it trying to reconnect to the same AP that has just been disconnected rather than the original one!
 

RJB

Active Member
Licensed User
Longtime User
I've changed the test APP to include the wait loop and lay out the set and reset to make it easier to see what's happening - attached
Summary of results:
Android 4 AP not saved or saved = very slow but results OK

Android 9 AP not saved = set OK, reset fails, reverts to AP being disconnected all three options
Android 9 AP saved = sets OK
Reset = wifi.connectWifiAP option, slow(timeout period) but resets
Reset = wifi.reconnectWifiAP option, reconnect slow(timeout period) but resets
Reset = wifi.disconnectWifiAP option, sometimes works sometimes doesn't

10 AP not saved = Set and Reset OK appart from the on-screen messages
10 AP saved = Unable to reset to original AP, all three options
 

Attachments

  • WifiTest.zip
    11.6 KB · Views: 284

RJB

Active Member
Licensed User
Longtime User
Change of tack for Android 9, now using wifi.removeWifiAP instead of wifi.disconnectWifiAP to reset the AP.
Relevant code is now as follows. This has worked correctly for all versions, 4, 9 and 10 but is not reliable.
Note the 1 second timeout for API 27- reconnect. This seems to set the minimum time to return from 'reconnect'. i.e. if 30 seconds is used then it will never return in less than 30 seconds!

B4X:
public Sub SetAP(APName As String, APPass As String, SecType As Int, Timeout As Int) As ResumableSub
    Try
        OldSSID = W.WifiSSID
        Select True
            Case w.APIVersion >= 29
                Log("Connect 29")
                W.connectWifiAP(APName, SecType, APPass, Timeout)
                wait for Wifi_ConnectionResult (Success As Boolean)
            Case w.APIVersion = 28
                Log("Connect 28")
                W.connectWifiAP(APName, SecType, APPass, Timeout)
                wait for Wifi_ConnectionResult (Success As Boolean)
            Case Else
                Log("27-, Save/ connect")
                W.saveWifiAP(APName, SecType, APPass, True, Timeout)
                wait for Wifi_ConnectionResult (Success As Boolean)
        End Select

        Return Success
    Catch
        Log("SetAp error: " & LastException)
    End Try
    Return False
End Sub

public Sub ResetAP As ResumableSub

    Log("RAP Old SSID = " & OldSSID)

    Select True
        Case W.APIversion>= 29
            Log("29+ reset")
            Return w.disconnectWifiAP

        Case w.APIVersion = 28
            Return W.removeWifiAP(W.WifiSSID)
            
        Case Else
            Log("27- reset")
            W.reconnectWifiAP(OldSSID, 1000)
            wait for Wifi_ConnectionResult (Success As Boolean)
            Return Success
    End Select
    
End Sub
 

Computersmith64

Well-Known Member
Licensed User
Longtime User

I'm running some tests & tweaking the code right now - however I'm 99% sure the delay issue is related to your test code. I suspect it has something to do with calling a resumable sub from another resumable sub (ie: "stacking" Wait For). If I test by making a call to any of the connect functions & using a Wifi_ConnectionResult callback sub, I don't see any delay at all.

- Colin.
 

RJB

Active Member
Licensed User
Longtime User
OK thanks, will be interested in your results.
In the mean time more thorough testing this morning gives the following results:
B4X:
Android 4 new AP originally not saved/ but saved by first 'connect to new'
==========================================================================

Connect to New
==============
OldAP = TALKTALKCBE7C4
27-, Save/ connect
Set AP = true : XXXXXXXX        [1S]
Reconnect to old
================
RAP Old SSID = TALKTALKCBE7C4
27- reset
Unregistering Receiver
Reset AP 1 false : TALKTALKCBE7C4    [1S, incorrect false]
Reset AP 3 true : TALKTALKCBE7C4
Connect to New
==============
OldAP = TALKTALKCBE7C4
27-, Save/ connect
Set AP = false : XXXXXXXX        [subsequent attempts anything up to 20S, incorrect false]
Reconnect to old
================
RAP Old SSID = TALKTALKCBE7C4
27- reset
Reset AP 1 false : TALKTALKCBE7C4    [Subsequent attempts anything up to 30S, incorrect false, corrected by wait loop]
Reset AP 3 true : TALKTALKCBE7C4


=================================================================================================================================
Android 9 new AP not saved            [connects but won't disconnect - reconnects to the new AP instead of the old one]
Android 9 new AP saved(but not connected)    [won't connect]

=================================================================================================================================
Android 10 new AP not saved            [works well, apart from the very anoying prompt to connect]
Android 10 new APsaved(but not connected)    [connects OK, but reconnects to the new AP instead of the old one]
 

Computersmith64

Well-Known Member
Licensed User
Longtime User
The tweaking & testing I've done has the Android 4 functionality working well, so now working my way through 9 & 10. Have discovered there's an issue with Android 9 connections in that it takes a second or 2 for isWifiConnected to report true after the Wifi_ConnectionResult is fired - so if isWifiConnected is called immediately, it will erroneously report false. I'm working on a fix.

- Colin.
 

RJB

Active Member
Licensed User
Longtime User
OK, I look forward to the update.
Unfortunately I have to go to a funeral today so won't be able to do anything further until tomorrow.
 

Computersmith64

Well-Known Member
Licensed User
Longtime User
I was just wondering if post #4 in https://www.b4x.com/android/forum/threads/how-does-mlwifi-actually-work.101691/ has any bearing on the re-connect problems?
Actually that was relevant - sort of... There was actually a bug in the original version of the library that would not try to connect if the id of a saved network was <= 0. Valid network ids are actually 0 to n - & the function(s) used to get the network id will return -1 in the case of a failure. I've changed so that it only declines a connection attempt if the network id comes back as -1.

- Colin.
 

Computersmith64

Well-Known Member
Licensed User
Longtime User
Updated to v4.30 in first post.

- Colin.
 

RJB

Active Member
Licensed User
Longtime User
Hi,
I don't know what I'm doing differently but the only way I can get 9 to connect is when the new AP is manually saved first, (using wifi.connectWifiAP, not save). Then it will connect and reset the AP (using either wifi.removeWifiAP or wifi.disconnectWifiAP. Reset takes anything up to 18 seconds and occasionally I get the following error logged:
B4X:
java.io.IOException: sendto failed: ENETUNREACH (Network is unreachable)
    at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:576)
    at libcore.io.IoBridge.sendto(IoBridge.java:544)
    at java.net.PlainDatagramSocketImpl.send(PlainDatagramSocketImpl.java:125)
    at java.net.DatagramSocket.send(DatagramSocket.java:721)
    at anywheresoftware.b4a.objects.SocketWrapper$UDPSocket$1.run(SocketWrapper.java:479)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:764)
Caused by: android.system.ErrnoException: sendto failed: ENETUNREACH (Network is unreachable)
    at libcore.io.Linux.sendtoBytes(Native Method)
    at libcore.io.Linux.sendto(Linux.java:227)
    at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:307)
    at libcore.io.IoBridge.sendto(IoBridge.java:542)
    ... 8 more

Android 10 works when the new AP is not saved but refuses to reset if it has been manually set
Android 4 works well and quickly, new AP saved or not.
 

Computersmith64

Well-Known Member
Licensed User
Longtime User
On my Android 9 device, connectWifiAP will fail if the AP isn't in the saved networks list:

Using saveWifiAP where the AP isn't in the saved networks list:

I haven't made any changes to removeWifiAP (or tested it), so I can't comment on it, but disconnectWifiAP results in the device going back to the AP it was connected to originally. I don't know about the error you posted. There's nothing in the stack trace to say where (if anywhere) it was triggered in the library - so it might not even be coming from there.
Android 10 works when the new AP is not saved but refuses to reset if it has been manually set
I'm not sure what you mean.

Are you planning on using this library in an app? If so, you might be better off implementing it in the app & seeing what your results are. I'm not convinced that your test app isn't causing some of the issues you're seeing - especially with the nested Wait Fors you're using. I think per this tutorial you need to use sender parameters so the second Wait For doesn't overwrite the first one. I also don't think using the Wait For for Wifi_ConnectionResult is going to be useful in an actual app because you're going to want to do other stuff once you're connected to the AP (like set up sockets, etc...). I think it would be much "cleaner" to declare the Wifi_ConnectionResult callback & then put that code in there - but that's just my opinion.

Regardless, with a simple test app I have been able to get all the functionality to work per my latest comments in the first post in this thread - albeit that the Android 10 functionality is pretty flakey & doesn't necessarily work as advertised in the Android API documentation.

- Colin.
 
Last edited:
Reactions: RJB

RJB

Active Member
Licensed User
Longtime User
Thanks
I think for my purposes the situation is:
Pre- Android 9: all OK
Android 10: I can work within the limitation of not having the AP saved in the list. (It would be nice if I could use 'remove' to make sure it's not there, but that doesn't work as in:
B4X:
            Case w.APIVersion >= 29
                Log("Connect 29")
                W.removeWifiAP(APName)
                W.connectWifiAP(APName, SecType, APPass, Timeout)
                wait for Wifi_ConnectionResult (Success As Boolean)

Android 9: I had thought of using save first, as in:
B4X:
            Case w.APIVersion = 28
                Log("Save 28")
                W.saveWifiAP(APName, SecType, APPass, False, Timeout)
                wait for Wifi_ConnectionResult (Success As Boolean)
                Log("Connect 28")
                W.connectWifiAP(APName, SecType, APPass, Timeout)
                wait for Wifi_ConnectionResult (Success As Boolean)
but that doesn't seem to work here. I can see save worked when you tried it so I'll have to experiment some more. If I can get it working then I think I can live with what we have. (Even the very annoying Android 10 prompt!!)
 

RJB

Active Member
Licensed User
Longtime User
Hi,
Further testing on Android 9:
Everything was getting more and more confusing so I went into the System Settings and reset all of the network settings so that nothing could remain to cause problems.
Now, using wifi.saveWifiAP(APName, SecType, APPass, True, Timeout) to set the new AP and wifi.removeWifiAP(W.WifiSSID) for reset IT IS WORKING!!!

I think I have a fully working solution now so can actually make some progress.
re. the 'wait fors' and '_connectionresults' all of the test App was taken from a fully working App. By which I mean it was fully working for Android versions below 9. I should be able now to put it straight back into that App. [Is that tempting fate?????]. I don't think there is any problem in the way I am using them and have never seen anything that looks like it was caused by them. Perhaps one of the experts on the forum could let me know if there something there waiting to catch me out?

Thanks, Colin, for all of your help.
 

Computersmith64

Well-Known Member
Licensed User
Longtime User
Android 10 doesn't allow apps to save to the list.

There is a limitation in Android 10 in that if the AP you're connecting to has internet access, you have to use saveWifiAP, because the API functions that connectWifiAP use will only allow connection to an AP that doesn't have internet. If you use connectWifiAP on an AP that has internet it will connect then immediately disconnect with the "Something went wrong" dialog.

You shouldn't need to use saveWifiAP, then connectWifiAP. If you set the connect parameter to true in saveWifiAP it will connect after it has saved the AP, or after it has skipped the save if the AP already exists.

- Colin.
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…