How to Turn On/Off Wifi Hotspot Programmatically in Android 8.0 (Oreo)

How to turn on/off wifi hotspot programmatically in Android 8.0 (Oreo)

Finally I got the solution.
Android 8.0, they provided public api to turn on/off hotspot. WifiManager

Below is the code to turn on hotspot

private WifiManager.LocalOnlyHotspotReservation mReservation;

@RequiresApi(api = Build.VERSION_CODES.O)
private void turnOnHotspot() {
WifiManager manager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);

manager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {

@Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
Log.d(TAG, "Wifi Hotspot is on now");
mReservation = reservation;
}

@Override
public void onStopped() {
super.onStopped();
Log.d(TAG, "onStopped: ");
}

@Override
public void onFailed(int reason) {
super.onFailed(reason);
Log.d(TAG, "onFailed: ");
}
}, new Handler());
}

private void turnOffHotspot() {
if (mReservation != null) {
mReservation.close();
}
}

onStarted(WifiManager.LocalOnlyHotspotReservation reservation) method will be called if hotspot is turned on.. Using WifiManager.LocalOnlyHotspotReservation reference you call close() method to turn off hotspot.

Note:
To turn on hotspot, the Location(GPS) should be enabled in the device. Otherwise, it will throw SecurityException

Turn on/off WiFi hotspot programmatically

Theses methods works only for android 5.0 and less !

The EASY way :

Try instantiating the WifiConfiguration first :

AndroidJavaObject wifiConfiguration = new AndroidJavaClass("android.net.wifi.WifiConfiguration");

Now you can call methods and set/get fields within this object :

// to set SSID
wifiConfiguration.Set("SSID", meSSID); // string
wifiConfiguration.Set("preSharedKey", mePassword); // string

After settings all of the required fields just call your setWifiApEnabled method :

wifiManager.Call<bool>("setWifiApEnabled", wifiConfiguration, enabled);

Maybe you will have to set more fields than these two but to confirm that you should check the source and ensure what setWifiApEnabled method does internaly.


The HARD way :
( using reflection code )

Step 6 does not work for android 5.0+ !

Using reflection with AndroidJavaObject can be a bit tricky because you have to remember to dispose every object.

So from the beginning :

// android code for that should look like :
// wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);

// but in Unity C# you have to split this into few chunks:
// 1. Get calling class :
using ( AndroidJavaObject classObj = wifiManager.Call<AndroidJavaObject>("getClass") )
{
// classObj should contains your class object
// 2. call get WifiConfiguration class details :
using ( AndroidJavaObject wifiConfiguration = new AndroidJavaObject("setWifiApEnabled") )
{
// 3. Fill that object :
wifiConfiguration.Set("SSID", meSSID); // string
wifiConfiguration.Set("preSharedKey", mePassword); // string
// 4. Get WifiConfiguration class definition
using (AndroidJavaObject wifiCfgClass = wifiConfiguration.Call<AndroidJavaObject>("getClass") )
{
// 5. Get boolean definition
using ( AndroidJavaObject booleanObj = new AndroidJavaObject("java.lang.Boolean") )
{
using ( AndroidJavaObject booleanClass = booleanObj.Call<AndroidJavaObject>("getClass") )
// 6. Get method definition
using ( AndroidJavaObject methodObj = classObj.Call<AndroidJavaObject>("getMethod", "setWifiApEnabled", wifiCfgClass , booleanClass))
{
// 7. Call that method :)
methodObj.Call("invoke", wifiManager, wifiConfiguration, enabled);
}
}
}
}
}

WifiConfiguration :

I was trying to find out why the above code might not work but for me it was working okay ( tested on some virtual machines and Samsung Galaxy S5 Neo ).

What may be the case ( which I found out at almost midnight ) is a passphrase.

According to this wikipedia article in the section about WPA-PSK

Also referred to as WPA-PSK (pre-shared key) mode, this is designed for home and small office networks and doesn't require an authentication server.[9] Each wireless network device encrypts the network traffic using a 256 bit key. This key may be entered either as a string of 64 hexadecimal digits, or as a passphrase of 8 to 63 printable ASCII characters.[10] If ASCII characters are used, the 256 bit key is calculated by applying the PBKDF2 key derivation function to the passphrase, using the SSID as the salt and 4096 iterations of HMAC-SHA1.[11] WPA-Personal mode is available with both WPA and WPA2.)

My suggestion would be to use the same passphrase as in the article linked above to make sure it's valid.

Also another thing to note is the SSID part which has a short but good description here on wikipedia.

A common, albeit incorrect assumption, is that an SSID is a string of human-readable characters (such as ASCII), terminated by a NUL character (as in a C-string). SSIDs must be treated and handled as what they are, a sequence of 0–32 octets, some of which may not be human-readable

From what I've checked you do not need to null-terminate your string within Java or C# because it will be handled by native code but still you should not exceed 31 characters ( 32 will be the null character ).

I checked this with :

SSID:MeHotSpot
WPA-PSK:5260305714217573

How to create wifihotspot in Oreo programmatically?

Oreo doesnot support to create hotspot programmatically with no password. It always creates hotspot with unique ssid and key generated randomly.

 WifiManager manager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiManager.LocalOnlyHotspotReservation mReservation;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
assert manager != null;
manager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {

@SuppressLint("SetTextI18n")
@Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
Timber.d("Wifi Hotspot is on now , reservation is : %s", reservation.toString());
mReservation = reservation;
key = mReservation.getWifiConfiguration().preSharedKey;
ussid = mReservation.getWifiConfiguration().SSID;

}

@Override
public void onStopped() {
super.onStopped();
Timber.d("onStopped: ");
}

@Override
public void onFailed(int reason) {
super.onFailed(reason);
Timber.d("onFailed: ");
}
}, new Handler());
}


Related Topics



Leave a reply



Submit