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,417
  • mlwifi-src.zip
    16.4 KB · Views: 1,447
Last edited:

HotShoe

Well-Known Member
Licensed User
Longtime User
Oh, I see what you mean, yes that can be done easily in MLScan. I'll add it in the next update. BTW, you can check the MLScan.wifis array at any time, but it will not update without explicitly doing a new scan right now.

--- Jem
 

Peter Simpson

Expert
Licensed User
Longtime User
This library has just gotten better @HotShoe, thank you...
 

HotShoe

Well-Known Member
Licensed User
Longtime User
I am getting a NullPointerException when using connectToAP

Thanks John, I have updated the library and have also fixed the connectToAP method again. I missed a set of required quote marks on a wifimanager call.

A new version 2.11 is now available (as soon as I finish this reply), in the first post. Only MLscan is changed as follows.

This version no longer needs a timer or any other means of ensuring that the wifi scan list is ready. It now fires an event when the list is ready. The event looks like this assuming your scan event is called Scan :

Sub Scan_ScanDone(Results() As String, Count As Int)

Results is the string array as before, and Count is the number of results in the array. The wifis array is still available as well and is updated automatically.

The StartScan method has changed and now requires an event name to be passed. It also checks to see that wifi is enabled and enables it if it is not. Through a bit of magic, I was able to squeeze another 70% speed increase in the scan results time, so the speed is finally where I am comfortable with the library as a whole. It felt a bit clunky before, but my custom event was not working until today. Scans are virtually instant now.

Also, the getWifiList is now gone (I'm sorry, I promise I will stop breaking your code), and is replaced with updateWifiList. WifiList is no longer needed in this version since updates are done in the new event. A call to updateWifiList updates the scan results each time it is called, so you can set up a timer if you wish to do live updates of a listview for example as new AP's appear. You only need to call StartScan("eventname") the first time a scan is run, the same as you would use Initialize for any other library class. I was tempted to rename it to Initialize, but I can already here the pitchfoks rattling for all of the changes up to now. :)

If you see any more problems, let me know as always, and thanks for putting up with the changes.

--- Jem
 

praktikant

Member
Licensed User
Longtime User
Thanks John, I have updated the library and have also fixed the connectToAP method again. I missed a set of required quote marks on a wifimanager call.

A new version 2.11 is now available (as soon as I finish this reply), in the first post. Only MLscan is changed as follows.

This version no longer needs a timer or any other means of ensuring that the wifi scan list is ready. It now fires an event when the list is ready. The event looks like this assuming your scan event is called Scan :

Sub Scan_ScanDone(Results() As String, Count As Int)

Results is the string array as before, and Count is the number of results in the array. The wifis array is still available as well and is updated automatically.

The StartScan method has changed and now requires an event name to be passed. It also checks to see that wifi is enabled and enables it if it is not. Through a bit of magic, I was able to squeeze another 70% speed increase in the scan results time, so the speed is finally where I am comfortable with the library as a whole. It felt a bit clunky before, but my custom event was not working until today. Scans are virtually instant now.

Also, the getWifiList is now gone (I'm sorry, I promise I will stop breaking your code), and is replaced with updateWifiList. WifiList is no longer needed in this version since updates are done in the new event. A call to updateWifiList updates the scan results each time it is called, so you can set up a timer if you wish to do live updates of a listview for example as new AP's appear. You only need to call StartScan("eventname") the first time a scan is run, the same as you would use Initialize for any other library class. I was tempted to rename it to Initialize, but I can already here the pitchfoks rattling for all of the changes up to now. :)

If you see any more problems, let me know as always, and thanks for putting up with the changes.

--- Jem
hallo,thank you @@HotShoe , for this Lib
i have now a question.

when a wifi ist connected,
i scan wifi netzwerk again
I noticed that, signal strength of this connected wifi dont changes with different distances
how can i test this signal strength of the connected wifi with different distances???
Can you give me an example of that?

B4X:
Sub wifi_Tick
scan.startScan("Scan")
scan.updateWifiList
End Sub
Sub Scan_ScanDone(Results() As String, Count As Int)
    Dim tmp As String
   
    For i = 0 To Count - 1
    tmp = Results(i).Replace(",","    ")
    Log(CRLF&"temp:"&tmp)
    scanlist.AddSingleLine(tmp)
    Next
   
    ProgressDialogHide
   
End Sub

temp:TP-LINK_D1724A WPA2 -66 Saved

temp:publicwifispot WPA2 -67

temp:WiFi WPA2 -69

temp:SitecomD58344 WPA2 -80

temp:CZESKO WPA -89

temp:belkin.f5f WPA2 -90

temp:TP-LINK_B7210E WPA2 -91
----------------------------------------------------
temp:TP-LINK_D1724A WPA2 -66 Saved

temp:publicwifispot WPA2 -67

temp:WiFi WPA2 -69

temp:SitecomD58344 WPA2 -80

temp:CZESKO WPA -89

temp:belkin.f5f WPA2 -90

temp:TP-LINK_B7210E WPA2 -91
----------------------------------------------------



temp:TP-LINK_D1724A WPA2 -66 Saved



temp:publicwifispot WPA2 -67

temp:WiFi WPA2 -69

temp:SitecomD58344 WPA2 -80

temp:CZESKO WPA -89

temp:belkin.f5f WPA2 -90

temp:TP-LINK_B7210E WPA2 -91
----------------------------------------------------

temp:TP-LINK_D1724A WPA2 -66 Saved

temp:publicwifispot WPA2 -67

temp:WiFi WPA2 -69

temp:SitecomD58344 WPA2 -80

temp:CZESKO WPA -89

temp:belkin.f5f WPA2 -90

temp:TP-LINK_B7210E WPA2 -91
----------------------------------------------------



temp:TP-LINK_D1724A WPA2 -66 Saved



temp:publicwifispot WPA2 -67

temp:WiFi WPA2 -69

temp:SitecomD58344 WPA2 -80

temp:CZESKO WPA -89

temp:belkin.f5f WPA2 -90

temp:TP-LINK_B7210E WPA2 -91
----------------------------------------------------

temp:TP-LINK_D1724A WPA2 -66 Saved

temp:publicwifispot WPA2 -67

temp:WiFi WPA2 -69

temp:SitecomD58344 WPA2 -80

temp:CZESKO WPA -89

temp:belkin.f5f WPA2 -90

temp:TP-LINK_B7210E WPA2 -91
 
Last edited:

HotShoe

Well-Known Member
Licensed User
Longtime User
You can set a timer to repeat the update every minute or other length of time.

B4X:
'Dim a timer in process_globals named scantime and initialize it in activity_create
   scantime.Initialize("scantime", 60000)

'enable the timer after the initial scan is done
   scantime.Enabled = True

'create the tick event for the timer to update the scan list
Sub scantime_Tick
     scantime.Enable = False
     scan.updateWifiList

     scantime.Enable = True

End Sub

Some variation of this should work.

--- Jem
 

praktikant

Member
Licensed User
Longtime User
You can set a timer to repeat the update every minute or other length of time.

B4X:
'Dim a timer in process_globals named scantime and initialize it in activity_create
   scantime.Initialize("scantime", 60000)

'enable the timer after the initial scan is done
   scantime.Enabled = True

'create the tick event for the timer to update the scan list
Sub scantime_Tick
     scantime.Enable = False
     scan.updateWifiList

     scantime.Enable = True

End Sub

Some variation of this should work.

--- Jem


B4X:
Sub Service_Create
Log("start")
scan.startScan("Scan")
WiFiScanTimer.Initialize("WiFiScanTimer",5000)
WiFiScanTimer.Enabled=True
End Sub

Sub WiFiScanTimer_Tick
WiFiScanTimer.Enable = False
     scan.updateWifiList
   WiFiScanTimer.Enable = True
End sub

then
Error compiling programm.
error description:Unknown member:enable
WiFiScanTimer.Enable=false
Word:enable

i dont know, what happend
Code dont work.
 

HotShoe

Well-Known Member
Licensed User
Longtime User
Try the new version attached to the first post. Also look at the new wifitest example to se exactly how to do what you need.

--- Jem
 

XorAndOr

Active Member
Licensed User
Longtime User
Hi, I'm using your library, very useful. I have a question, when I go to connect with an access point in the moment that I enter the password I get the
B4X:
MsgBox("Could not connect to" & ssid, "Information")
, but if I do it from the list of devices your phone is everything ok, where do you think I'm wrong? I also added
B4X:
AddPermission (android.permission.WRITE_SETTINGS)
but I get always the msgbox, thanks
 

HotShoe

Well-Known Member
Licensed User
Longtime User
hmmm, I don't know. Look through the wifitest project and make sure you are doing the connection the same way.

--- Jem
 

XorAndOr

Active Member
Licensed User
Longtime User
hmmm, I don't know. Look through the wifitest project and make sure you are doing the connection the same way.

--- Jem
hello, thank you for responding, I am using the example attached in the first post. I noticed that in the list of access points do not see the message "Saved"
B4X:
If tmp.Contains("Saved") Then
   ok = scan.connectToAP(cursel)
I think that's why it does not work, but if I do it with paired device and insert the password from the phone menu, then returning to the example works ok. thanks
 

jjcc

Member
Licensed User
Longtime User
@HotShoe Great lib!
However, I tried the example project. connectToAP doesn't work with a few phones I tried. I tried to forget a connection within the android setting, then tried the sample code to let the the app saves the password and connect to phone. the result the of connectToAP is OK but it's not really connect to the AP. (the IP shows 0.0.0.0 and call isWifeConnected return false after init)

Did you have the same issue?
 

HotShoe

Well-Known Member
Licensed User
Longtime User
I have not seen this, but I will look at it again to see if there is something I missed.

Thanks,

--- Jem
 

camolas

Member
Licensed User
Longtime User
Hi,

Can some one please present a example using "forgetAP"? and how can i get the "NetId" from my saved wifis list?

Thanks in advance

cam
 

jjcc

Member
Licensed User
Longtime User
@HotShoe I guess it might be caused by quote string of SSID. There are different versions of SDK, some use quoted string, the others don't.

Here's the link about the problem

Do you have time to fix the lib? or if you have already uploaded the code somewhere in github?
 

HotShoe

Well-Known Member
Licensed User
Longtime User
Sorry I've been away so long.

Can some one please present a example using "forgetAP"? and how can i get the "NetId" from my saved wifis list?

Use the listSavedNetworks method. It returns a list of saved networks on your device. the 3rd item in each listing is the network ID. Each element is separated by a comma. Then you can call the forgetAP method based on the SSID and network ID that you want to erase from your device. I will update the wifitest project later and include an example in there.

Do you have time to fix the lib? or if you have already uploaded the code somewhere in github?

I have updated mlwifi to handle both quoted and unquoted SSID strings, so try version 2.13 attached in the 1st post of this thread.

--- Jem
 

omidaghakhani1368

Well-Known Member
Licensed User
Longtime User
Hi.
Thanks for useful library.
If user connect to internet via gsm,your library can detect it?
 

HotShoe

Well-Known Member
Licensed User
Longtime User
If user connect to internet via gsm,your library can detect it?

It can, but that is the only non-wifi related thing that it can do. The rest of the methods are specifically for wifi.

--- Jem
 

Mark Hollingworth

Member
Licensed User
Longtime User
Great Library has been working fine but I seem to have hit a problem and I am not sure whats causing it.

I have a service which listens for network connection events and then runs code depending on the connection state, it works fine when a wifi connection is found but when the wifi is disconnected I am getting the following error:

java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.wifi.SCAN_RESULTS flg=0x4000010 } in wifi.MLwifi$MLWifiScanner$WifiScanReceiver@274d9542
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:982)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6837)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
at wifi.MLwifi$MLWifiScanner.checkSSID(MLwifi.java:346)
at wifi.MLwifi$MLWifiScanner.access$0(MLwifi.java:339)
at wifi.MLwifi$MLWifiScanner$WifiScanReceiver.onReceive(MLwifi.java:324)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:972)

I have tried various things to resolve it but have been unable to. I am attaching a sample project that is causing the same error and it always happens after calling .StartScan, if I remove that line of code from the service then it doesn't crash.

Also the .StartScan seems to be continually returning results, is that intended or should it perform one scan then stop?

Your help is appreciated
 

Attachments

  • sample.zip
    7 KB · Views: 361
Top