This post was originally published at Connecting your App to a Wi-Fi Device

Posted by Rich Hyndman, Android Developer Advocate

With the growth of the Internet of Things, connecting Android applications to
Wi-Fi enabled devices is becoming more and more common. Whether you’re building
an app for a remote viewfinder, to set up a connected light bulb, or to control
a quadcopter, if it’s Wi-Fi based you will need to connect to a hotspot that may
not have Internet connectivity.

From Lollipop onwards the OS became a little more intelligent, allowing multiple
network connections and not routing data to networks that don’t have Internet
connectivity. That’s very useful for users as they don’t lose connectivity when
they’re near Wi-Fis with captive portals. Data routing APIs were added for
developers, so you can ensure that only the appropriate app traffic is routed
over the Wi-Fi connection to the external device.

To make the APIs easier to understand, it is good to know that there are 3 sets
of networks available to developers:

  • WiFiManager#startScan returns a list of available Wi-Fi networks. They are
    primarily identified by SSID.
  • WiFiManager#getConfiguredNetworks returns a list of the Wi-Fi networks
    configured on the device, also indexed by SSID, but they are not necessarily
    currently available.
  • ConnectivityManager#getAllNetworks returns a list of networks that are being
    interacted with by the phone. This is necessary as from Lollipop onwards a
    device may be connected to multiple networks at once, Wi-Fi, LTE, Bluetooth,
    etc… The current state of each is available by calling ConnectivityManager#getNetworkInfo
    and is identified by a network ID.

In all versions of Android you start by scanning for available Wi-Fi networks
with WiFiManager#startScan,
iterate through the ScanResults
looking for the SSID of your external Wi-Fi device. Once you’ve found it you can
check if it is already a configured network using WifiManager#getConfiguredNetworks
and iterating through the WifiConfigurations
returned, matching on SSID. It’s worth noting that the SSIDs of the configured
networks are enclosed in double quotes, whilst the SSIDs returned in ScanResults
are not.

If your network is configured you can obtain the network ID from the
WifiConfiguration object. Otherwise you can configure it using WifiManager#addNetwork
and keep track of the network id that is returned.

To connect to the Wi-Fi network, register a BroadcastReceiver that listens for
and then call WifiManager.enableNetwork
(int netId, boolean disableOthers)
, passing in your network ID. The
enableNetwork call disables all the other Wi-Fi access points for the next scan,
locates the one you’ve requested and connects to it. When you receive the
network broadcasts you can check with WifiManager#getConnectionInfo
that you’re successfully connected to the correct network. But, on Lollipop and
above, if that network doesn’t have internet connectivity network, requests will
not be routed to it.

Routing network requests

To direct all the network requests from your app to an external Wi-Fi device,
call ConnectivityManager#setProcessDefaultNetwork
on Lollipop devices, and on Marshmallow call ConnectivityManager#bindProcessToNetwork
instead, which is a direct API replacement. Note that these calls require
android.permission.INTERNET; otherwise they will just return false.

Alternatively, if you’d like to route some of your app traffic to the Wi-Fi
device and some to the Internet over the mobile network:

Now you can keep your users connected whilst they benefit from your innovative
Wi-Fi enabled products.

image image


This post was originally published at Connecting your App to a Wi-Fi Device