B4A Library Simple WIFI library

NOTICE :

I am looking for someone to take over development and maintenance on this and other libraries. I am just no longer interested in programming and don't know how long I will feel that way. Anyone interested in taking over this library or any of my others, let me know a bit about yourself by email to jem@mlsoft.org

Thanks,

--- Jem Miller

The Eclipse project and all source code has been attached below.


This is a very simple library that uses only 16 methods:

This is version 2.17. Don't panic, this version does not break anything!

I re-wrote the MACAddress method to handle Android M (API 23) and above. I also added the INTERNET and ACCESS_FINE_LOCATION permissions which seems to be required in API 23, and added a new method getAPI() that returns the version of Android running on the device as an integer.

SEE THE NEW WIFITEST EXAMPLE included in the zip file for examples of how to use this library.


MLwifi
Author:
Jem Miller - Missing Link Software
Version: 2.17
  • MLScan
    Events:
    • ScanDone (Results() As String, Count As Int)
    Fields:
    • wifis As String[]
      A string array containing all scanned access points in the area of the device.
      These are comma separated entries consisting of the following:
      SSID, Security type, signal strength, and "Saved" if this network was previously saved for use on this device.
    Methods:
    • Disconnect As Boolean
      Disconnects the current wifi AP connection
      Returns True on success
    • WifiCap (EntryNumber As Int) As String
      Returns a String containing info about the entry. A startScan must have already been done. The string contains the SSID, the BSSID, and the capabilities of the network access point.
      Each item is separated by a comma (SSID,BSSID,CapabilityString). The capabilities part can be quite long.
      EntryNumber - If you display the string array wifis or the array returned in the getWifiList method UNSORTED, you can pass the Position variable from your ListView_Click event.
      Otherwise, you must pass the entry number from the string array since that is what is used as a reference.
      Returns a string of comma separated entries of SSID,BSSID, and capability string. Returns an empty string on error.
    • addAP (EntryNumber As Int, securityType As String, Password As String) As Boolean
      Adds an entry to the wifi manager and connects to it. This method saves the configuration of the new entry onto the device. Use the forgetAP method to delete them. Updated to handle quoted or unquoted SSID strings.
      EntryNumber - If you display the string array wifis or the array returned in the getWifiList method UNSORTED, you can pass the Position variable from your ListView_Click event.
      Otherwise, you must pass the entry number from the string array since that is what is used as a reference.
      securityType - The Access Point security type (returned in the scan result string array)
      Password - The password/phrase for the wifi access point. Pass "" for an open network. Handles WEP HEX or text phrases
      It is up to you to supply all information. The security type is found in the scan results array.

      Returns True if the connection is successful
    • connectToAP (EntryNumber As Int) As Boolean
      Connects to a network already configured on the device. The device will use saved values to connect. Updated to handle quoted or unquoted SSID strings.
      EntryNumber - If you display the string array wifis or the array returned in the getWifiList method UNSORTED, you can pass the Position variable from your ListView_Click event.
      Otherwise, you must pass the entry number from the string array since that is what is used as a reference.
      Returns true if successful
    • forgetAP (NetId As Int) As Boolean
      Forgets (erases) a stored access point on the device.
      NetId - The network ID number to forget (returned in the listSavedNetworks method)
      Returns True if successful
    • getBSSID (EntryNumber As Int) As String
      Returns the BSSID for the selected entry.
      EntryNumber - If you display the string array wifis or the array returned in the getWifiList method UNSORTED, you can pass the Position variable from your ListView_Click event.
      Otherwise, you must pass the entry number from the string array since that is what is used as a reference.
    • isStored (EntryNumber As Int) As Boolean
      Checks the stored networks on the device to see if this entry is a previously saved access point
      EntryNumber - The entry number in the wifis array to check. If you display the string array wifis or the array returned in the getWifiList method UNSORTED, you can pass the Position variable from your ListView_Click event.
      Otherwise, you must pass the entry number from the string array since that is what is used as a reference.
      Returns True if this is a stored network
    • listSavedNetworks As List
      Builds a list of all saved networks on the device.
      Returns a comma separated list of SSID's and their BSSID and network ID number.
    • startScan (EventName As String)
      Initializes all objects and scans for wifi networks. Builds a string array of results (wifis) that can be accessed directly or with a call to updateWifiList.
      THIS METHOD SHOULD ONLY BE CALLED ONCE!
    • updateWifiList
      Call only after startScan has already been called and a string array of Access Points has been built. This method returns a string array containing the access points from the most recent scan, including background scans done automatically by the Android WifiManager. *
      Calls the ScanDone event when a new list is ready.
      Returns the string array of comma separated wifi access points by SSID. Each entry may contain the following:
      SSID, Security type, Signal level (in DB's), and the word "Saved" if the network was previously saved for use on this device.
    Properties:
    • LinkSpeed As Int [read only]
      Returns the LinkSpeed of the connected wifi access point
  • MLwifi
    Methods:
    • EnableWifi (Enabled As Boolean)
      Turns wifi on or off
      Pass True to enable wifi or False to disable.
      Example
      dim wifi as MLwifi
      wifi.EnableWifi(true)
    • IpAddress As String
      Get IP address from the wifi interface)
      Returns address or empty string
    • MACAddress As String
      Returns MAC address of the current interface

      Returns MAC address or empty string
    • SSID As String
      Returns the current SSID
    • WifiSignal As Int
      Returns the raw signal strength in decibels as an integer
      Returns 0 on error
    • WifiStrength As Int
      Returns an integer between 0 and 100 as a percentage of signal strength
      Returns 0 on error.
    • isOnLine As Boolean
      Checks for internet connection
      This method does not check or care what type of network is used.
      It can be wifi, 2g, 3g, 4g, wimax, etc. It just tests for internet connectivity.
      Returns True if internet is available.
    • isWifiConnected As Boolean
      Checks if wifi is connected. This only checks for wifi connection to a router.
      It does NOT test for internet availability. Use isOnLine() for that.
      Returns True if wifi is connected or False if 2g, 3g, 4g, wimax or no connection.
    Permissions:
    • android.permission.ACCESS_FINE_LOCATION
    • android.permission.ACCESS_NETWORK_STATE
    • android.permission.ACCESS_WIFI_STATE
    • android.permission.CHANGE_WIFI_STATE
    • android.permission.INTERNET
    Properties:
    • API As Int [read only]
      Returns the current devices Android API (the version of Android running on the device.) as an integer such as 19, 21, 23, etc.


There is a small test app included and a readme file as well. The whole mess is tiny and requires no other libs.

--- Jem

Version 1.00 - Initial release.

Version 1.01 - Added EnableWifi that I forgot in the initial release.

Version 1.02 - Using a different method to find IP address.

Version 1.03 - Adds getSSID

Version 1.04 - Removed "'s from getSSID. Renamed IsWifiConnected to isWifiConnected.

Version 1.05 - Adding AP scanning.

Version 1.06 - Adds getWifiSignal and getWifiStrength

Version 1.07 - Fixed an error in the test project and forced getSSID to return an empty string instead of Null if no SSID is found.

Version 2.00 - New connection manager methods in the MLScan class. Also changed the string array returned on a scan to include more information in a comma separated list of: SSID, security type, signal strength, and the word "Saved" if this network is saved on the device.

Version 2.01 - Added a new method WifiCap(SSID). This returns a string with comma separated fields of SSID, BSSID, and network capabilities. The capabilities refers to its security protocols. I also included a new version of the wifitest app. I forgot to add it to the version 2.00 library zip file. Tapping on a listed SSID will allow you to connect to that network.

Version 2.10 - Added Disconnect, isStored, and LinkSpeed and changed the way you must call several methods.

Version 2.11 - Removed WifiList and added updateWifiList. Fixed the connectToAP and isStored methods. Added a ScanDone event to automate scan results (no more timers needed). Added error correction and more speed.

Version 2.1.2 - Updated ScanDone event to allow real time scan results.

Version 2.13 - Updated the connect methods to handle either quoted or unquoted SSID values so in theory any version of the API should now work correctly for connecting to an AP.

Version 2.14 - Fixed the ConnectToAP method (Hopefully). Also updated the wifitest app to fix a few minor bugs.

Version 2.15 - Corrected a null pointer error if wifi is turned off during operation.

Version 2.16 - Added some error checking an changed the connecttoAP method slightly. It now checks both the SSID and BSSID to ensure that correct AP is connect to.

Version 2.17 - Added permissions for API 23, Re-wrote the MACAddress method so it returns a valid MAC address on Android M OR any lower version of Android. Added the getAPI method to get the current version of Android on the device.

.
 

Attachments

  • mlwifi-2.17.zip
    23.2 KB · Views: 2,435
  • mlwifi-src.zip
    16.4 KB · Views: 1,469
Last edited:

B4AinNY

Member
Licensed User
Question about when Connection is complete
I've just started exploring this library.

After enabling WiFi it of course takes some time for the connection to be complete.
Is there some way to generate an event when the WiFi connection is completed after calling EnableWifi(True) ?
Or should I just run a loop checking isWificonnected until either connection is made, or some amount of time has elapsed ?
 

B4AinNY

Member
Licensed User
My goal in using this library is to allow me to turn WiFi off in case I am connected to a WiFi network that doesn't support Internet, and then to turn it back on and link to a specific SSID for printing to a WiFi Printer as needed ( in case of truly mobile environment such as in a truck such a printer is unlikely to be on an Internet connected network ) . Anyone wanting to see the code I'm working on for that can see at

https://www.b4x.com/android/forum/t...with-cellular-for-internet.73358/#post-466689

I'd welcome comments / corrections / suggestions

- Jeff
 

B4AinNY

Member
Licensed User
A few questions about the library
  1. After an Activity is resumed, which should be used - StartScan or UpdateWiFiList ?

  2. Is there a practical difference between reading the list of WiFi networks
    (a) from .Wifis,
    or (b) from Results parameter of ScanDone ?

  3. Can Scan be called modally so that code after StartScan is not executed until the ScanDone event is complete and/ or WiFis list is filled ?

    - My guess is not, so I am planning to end my subroutine immediately after calling ScanStart or UpdateWiFiList and then have the ScanDone event call a follow up Subroutine so my following code only executes after the scan is complete.

    Is this reasonable or is there a better approach ?

  4. It seems that once I have started calling StartScan and UpdateWiFiList,
    that the ScanDone event is repeatedly triggered.
    I don't have any timer in my app,
    and I am not repeatedly calling the UpdateWiFiList
    but the event keeps getting triggered.

    Is this the designed behavior or a problem ?
Thanks

- Jeff
 

HotShoe

Well-Known Member
Licensed User
Longtime User
The eclipse project and all source code for MLwifi has been attached to the first post. Feel free to modify and redistribute it to the B4A community.

--- Jem
 

HotShoe

Well-Known Member
Licensed User
Longtime User
A few questions about the library
  1. After an Activity is resumed, which should be used - StartScan or UpdateWiFiList ?

  2. Is there a practical difference between reading the list of WiFi networks
    (a) from .Wifis,
    or (b) from Results parameter of ScanDone ?

  3. Can Scan be called modally so that code after StartScan is not executed until the ScanDone event is complete and/ or WiFis list is filled ?

    - My guess is not, so I am planning to end my subroutine immediately after calling ScanStart or UpdateWiFiList and then have the ScanDone event call a follow up Subroutine so my following code only executes after the scan is complete.

    Is this reasonable or is there a better approach ?

  4. It seems that once I have started calling StartScan and UpdateWiFiList,
    that the ScanDone event is repeatedly triggered.
    I don't have any timer in my app,
    and I am not repeatedly calling the UpdateWiFiList
    but the event keeps getting triggered.

    Is this the designed behavior or a problem ?
Thanks

- Jeff

StartScan should only be called once at the beginning of the app. It is not necessary to call it again after a resume event. UpdateWifiList checks the results of the background scans that are done automatically by the Android OS. ScanDone will be called each time one of those background scans gets done so you can automatically update your wifi list presented to the user more easily. This way you can always have an up-to-date list of AP's around you.

Thanks,

--- Jem
 

B4AinNY

Member
Licensed User
Thank you - that's very helpful.
  1. Is there a practical difference between reading the list of WiFi networks
    (a) from .Wifis, or (b) from Results parameter of ScanDone ?

  2. It seems that ScanDone will not get triggered and .WiFis will not be updated until the subroutine that called either ScanStart or UpdateWiFiList is done ( at least that's what I'm finding in my tests). So what I do is to set a process global boolean to indicate whether I need to continue with some coding after ScanDone completes. I can then check for that variable in ScanDone and if set I call subroutine to do the follow up processing. Does this make sense ?
- Jeff
 

HotShoe

Well-Known Member
Licensed User
Longtime User
Is there a practical difference between reading the list of WiFi networks
(a) from .Wifis, or (b) from Results parameter of ScanDone ?

No, wifis is only there for older code.

It seems that ScanDone will not get triggered and .WiFis will not be updated until the subroutine that called either ScanStart or UpdateWiFiList is done ( at least that's what I'm finding in my tests). So what I do is to set a process global boolean to indicate whether I need to continue with some coding after ScanDone completes. I can then check for that variable in ScanDone and if set I call subroutine to do the follow up processing. Does this make sense ?

That sounds reasonable, but scandone should be called by the OS scans (every 15 secs to 2 minutes depending on the build).

--- Jem
 

B4AinNY

Member
Licensed User
ARGH ! I like a good challenge but I'm getting frustrated.

I'm having problems disconnecting from one WiFi network and connecting to another.

In trying the Disconnect method, this returns true, but reading the .SSID continues to return the same SSID that should now be disconnected.
Then in calling bSuccess = WifiScanner.connectToAP(EntryNumber) I get an error.

| java.lang.NullPointerException: Attempt to invoke virtual
| method 'boolean java.lang.String.equals(java.lang.Object)'
| on a null object reference

I have of course verified the EntryNumber is correct ( by reading WiFiCap( EntryNumber)

Here is are some details.

B4X:
  Subroutine 1
  MLWiFi.EnableWiFi ( True)
  '  loop waiting for isWiFiConnected = True
  MLScan.startScan

  Subroutine 2  ( Called from ScanDone)
  Dim DesiredSSID  as string =  ( whatever the desired SSID is )
  MLScan.updateWiFiList
  if  not ( MLWiFi.SSID = desiredSSID ) then
  ' If false I loop through .Wifis to find entry number
  ' this is successful, I get the desired entry number
  ' and I verify this looking at  .WifiCap

  bSuccess = WifiScanner.Disconnect
     log (bSuccess)    ' This returns success

  ' ***  BUT Reading Wifi.SSID  still gives the disconnected SSID

  bSuccess = WifiScanner.connectToAP(EntryNumber)

  This call generates Debug output
  |  Results SSID = "linksys"
  |  Stored.ssid = "attwifi" Searched ssid = "linksys"
  |  Stored.ssid = "DIRECT-4D-HP OfficeJet Pro 6960" Searched ssid = "linksys"
  |  Stored.ssid = "BAFB60" Searched ssid = "linksys"
  |  Stored.ssid = "HOME 2" Searched ssid = "linksys"
  |  Stored.ssid = "5BoroGreen" Searched ssid = "linksys"
  |  Stored.ssid = "DIRECT-8CED802E" Searched ssid = "linksys"
  |  Stored.ssid = "DIRECT-70-HP OfficeJet 250" Searched ssid = "linksys"
  |  Stored.ssid = "linksys" Searched ssid = "linksys"
  |  java.lang.NullPointerException: Attempt to invoke virtual
  method 'boolean java.lang.String.equals(java.lang.Object)'
  on a null object reference

  and then returns false

SSID still returns the originally connected SSID
 

Jmu5667

Well-Known Member
Licensed User
Longtime User
Hello to anyone who is linked to this thread.

I implemented MLWifi lib in one of our core app's, and I must say, WOW !

We have just installed the app on Android 7, API 24, and it runs very smoothly.

Jem has made the source available, most kind of him, so hopefully some java guru, @DonManfred , will take ownership, or maybe a group of guru's.

Regards

John.

P.s

Jem come back we miss you :)
 

Jmu5667

Well-Known Member
Licensed User
Longtime User
ARGH ! I like a good challenge but I'm getting frustrated.

I'm having problems disconnecting from one WiFi network and connecting to another.

In trying the Disconnect method, this returns true, but reading the .SSID continues to return the same SSID that should now be disconnected.
Then in calling bSuccess = WifiScanner.connectToAP(EntryNumber) I get an error.

| java.lang.NullPointerException: Attempt to invoke virtual
| method 'boolean java.lang.String.equals(java.lang.Object)'
| on a null object reference

I have of course verified the EntryNumber is correct ( by reading WiFiCap( EntryNumber)

Here is are some details.

B4X:
  Subroutine 1
  MLWiFi.EnableWiFi ( True)
  '  loop waiting for isWiFiConnected = True
  MLScan.startScan

  Subroutine 2  ( Called from ScanDone)
  Dim DesiredSSID  as string =  ( whatever the desired SSID is )
  MLScan.updateWiFiList
  if  not ( MLWiFi.SSID = desiredSSID ) then
  ' If false I loop through .Wifis to find entry number
  ' this is successful, I get the desired entry number
  ' and I verify this looking at  .WifiCap

  bSuccess = WifiScanner.Disconnect
     log (bSuccess)    ' This returns success

  ' ***  BUT Reading Wifi.SSID  still gives the disconnected SSID

  bSuccess = WifiScanner.connectToAP(EntryNumber)

  This call generates Debug output
  |  Results SSID = "linksys"
  |  Stored.ssid = "attwifi" Searched ssid = "linksys"
  |  Stored.ssid = "DIRECT-4D-HP OfficeJet Pro 6960" Searched ssid = "linksys"
  |  Stored.ssid = "BAFB60" Searched ssid = "linksys"
  |  Stored.ssid = "HOME 2" Searched ssid = "linksys"
  |  Stored.ssid = "5BoroGreen" Searched ssid = "linksys"
  |  Stored.ssid = "DIRECT-8CED802E" Searched ssid = "linksys"
  |  Stored.ssid = "DIRECT-70-HP OfficeJet 250" Searched ssid = "linksys"
  |  Stored.ssid = "linksys" Searched ssid = "linksys"
  |  java.lang.NullPointerException: Attempt to invoke virtual
  method 'boolean java.lang.String.equals(java.lang.Object)'
  on a null object reference

  and then returns false

SSID still returns the originally connected SSID
Hi

In relation to disconnecting, I think you will find that Android still maintains the AP details as being the most recent wifi AP you are using, it doe'nt matter is you are connected or not.

After you disconnected did you connect to a different AP ?

Regards

John.
 

Stern0m1

Member
Licensed User
This library didnt work for me. I belive there is an issue how its dealing with the password. it adds the Access Point but cant connect. When I manually change the password it connects. There is some wrong how its storing the password.

But anyways by analyzing the source code I code what I wanted, Big thanks to HotShoe!
 

sorex

Expert
Licensed User
Longtime User
I have been using this lib in a project for a while (still 1.07) so I went to update the project a bit with the latest version (2.17).

The only difference was the change of .hasIpAddress to .IpAddress... so far so good.

While we have 3 different wifi networks here I wanted to modify the project to be sure it connects to the right access point all the time.

But I can't get it to work.

It lists everything as expected but when I use the .connectToApp I just get a false result
and it just connects to the one it was connected before.

The connection is saved on the devices so when I manually switch to that AP it connects without prompting for a password.

Any idea? :)


Edit: I just tried with your example app and that one doesn't connect either to any of the networks here.
 
Last edited:

bgsoft

Well-Known Member
Licensed User
Longtime User
NOTICE :

I am looking for someone to take over development and maintenance on this and other libraries. I am just no longer interested in programming and don't know how long I will feel that way. Anyone interested in taking over this library or any of my others, let me know a bit about yourself by email to jem@mlsoft.org

Thanks,

--- Jem Miller


Hi Jem:

First of all, thank you for your contribution of the library and the source code.

I needed some new methods that your library did not have, for an application I'm implementing, and instead of creating a library from scratch, I preferred to take advantage of your library and add those methods that I needed.

To be able to hang the files and give support as much as I can, I have created a new thread that is here:
https://www.b4x.com/android/forum/threads/simple-wifi-library-updated.76233/

Thank you very much for your contribution.

Regards
 

sorex

Expert
Licensed User
Longtime User
darn... that came a few hours late.

I just updated and deployed my project with that WifiConnect (1.59) library (https://www.b4x.com/android/forum/threads/wifi-connect-library-wep-wpa-open.27254/page-2#post-360262)
as I couldn't get this lib to auto connect to any access points. (see post above)

might have been debug mode that prevented this tho, I didn't verify this but the other lib only worked right in release mode.
(some part of the lib didn't get included in debug mode or something)

I will test this update tomorrow.
 

Neojoy

Member
Licensed User
Longtime User
I have tested your lib and works like a charm to get the wifi network list but only if GPS is on, if GPS is off it returns a empty list. Any idea?

This happened with wifi classical library "ABwifi" as well.

Thanks
 

DonManfred

Expert
Licensed User
Longtime User

Neojoy

Member
Licensed User
Longtime User
Thank you guys :)

I found over the web more peoples with same trouble, but no solution.
It looks like it's a feature from Android 6 and above like FrankBerra said
 
Top