Is there an API to turn On/Off the WiFi HotSpot on Android programmatically?

What methods should I call to turn it On/Off?

UPDATE:There's this option to have the HotSpot enabled, and just turn On/Off the WiFi, but this is not a good solution for me.

Solution 1

Warning This method will not work beyond 5.0, it was a quite dated entry.

Use the class below to change/check the Wifi hotspot setting:

import android.content.*;
import android.net.wifi.*;
import java.lang.reflect.*;

public class ApManager {

//check whether wifi hotspot on or off
public static boolean isApOn(Context context) {
    WifiManager wifimanager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);     
    try {
        Method method = wifimanager.getClass().getDeclaredMethod("isWifiApEnabled");
        method.setAccessible(true);
        return (Boolean) method.invoke(wifimanager);
    }
    catch (Throwable ignored) {}
    return false;
}

// toggle wifi hotspot on or off
public static boolean configApState(Context context) {
    WifiManager wifimanager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);
    WifiConfiguration wificonfiguration = null;
    try {  
        // if WiFi is on, turn it off
        if(isApOn(context)) {               
            wifimanager.setWifiEnabled(false);
        }               
        Method method = wifimanager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);                   
        method.invoke(wifimanager, wificonfiguration, !isApOn(context));
        return true;
    } 
    catch (Exception e) {
        e.printStackTrace();
    }       
    return false;
}
} // end of class

You need to add the permissions below to your AndroidMainfest:

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

Use this standalone ApManager class from anywhere as follows:

ApManager.isApOn(YourActivity.this); // check Ap state :boolean
ApManager.configApState(YourActivity.this); // change Ap state :boolean

Hope this will help someone

Solution 2

Here's the complete solution if you want to implement the wifi hotspot feature programmatically in your android app.

SOLUTION FOR API < 26:

For devices < API 26. There is no public API by Android for this purpose. So, in order to work with those APIs you've to access private APIs through reflection. It is not recommended but if you've no other options left, then here's a trick.

First of all, you need to have this permission in your manifest,

  <uses-permission  
  android:name="android.permission.WRITE_SETTINGS"  
  tools:ignore="ProtectedPermissions"/>

  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

Here's how you can ask it on run-time:

 private boolean showWritePermissionSettings() {    
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M  
    && Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { 
  if (!Settings.System.canWrite(this)) {    
    Log.v("DANG", " " + !Settings.System.canWrite(this));   
    Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS); 
    intent.setData(Uri.parse("package:" + this.getPackageName()));  
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    this.startActivity(intent); 
    return false;   
  } 
}   
return true; //Permission already given 
}

You can then access the setWifiEnabled method through reflection. This returns true if the action you asked for is being process correctly i.e. enabling/disabling hotspot.

     public boolean setWifiEnabled(WifiConfiguration wifiConfig, boolean enabled) { 
 WifiManager wifiManager;
try {   
  if (enabled) { //disables wifi hotspot if it's already enabled    
    wifiManager.setWifiEnabled(false);  
  } 

   Method method = wifiManager.getClass()   
      .getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);   
  return (Boolean) method.invoke(wifiManager, wifiConfig, enabled); 
} catch (Exception e) { 
  Log.e(this.getClass().toString(), "", e); 
  return false; 
}   
}

You can also get the wificonfiguration of your hotspot through reflection. I've answered that method for this question on StackOverflow.

P.S: If you don't want to turn on hotspot programmatically, you can start this intent and open the wifi settings screen for user to turn it on manually.

SOLUTION FOR API >= 26:

Finally, android released an official API for versions >= Oreo. You can just use the public exposed API by android i.e. startLocalOnlyHotspot

It turns on a local hotspot without internet access. Which thus can be used to host a server or transfer files.

It requires Manifest.permission.CHANGE_WIFI_STATE and ACCESS_FINE_LOCATION permissions.

Here's a simple example of how you can turn on hotspot using this API.

private WifiManager wifiManager;
WifiConfiguration currentConfig;
WifiManager.LocalOnlyHotspotReservation hotspotReservation;

The method to turn on hotspot:

@RequiresApi(api = Build.VERSION_CODES.O)
public void turnOnHotspot() {

      wifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {

        @Override
        public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
          super.onStarted(reservation);
          hotspotReservation = reservation;
          currentConfig = hotspotReservation.getWifiConfiguration();

          Log.v("DANG", "THE PASSWORD IS: "
              + currentConfig.preSharedKey
              + " \n SSID is : "
              + currentConfig.SSID);

          hotspotDetailsDialog();

        }

        @Override
        public void onStopped() {
          super.onStopped();
          Log.v("DANG", "Local Hotspot Stopped");
        }

        @Override
        public void onFailed(int reason) {
          super.onFailed(reason);
          Log.v("DANG", "Local Hotspot failed to start");
        }
      }, new Handler());
    }
`

Here's how you can get details of the locally created hotspot

private void hotspotDetaisDialog()
{

    Log.v(TAG, context.getString(R.string.hotspot_details_message) + "\n" + context.getString(
              R.string.hotspot_ssid_label) + " " + currentConfig.SSID + "\n" + context.getString(
              R.string.hotspot_pass_label) + " " + currentConfig.preSharedKey);

}

If it throws, a security exception even after giving the required permissions then you should try enabling your location using GPS. Here's the solution.

Recently, I've developed a demo app called Spotserve. That turns on wifi hotspot for all devices with API>=15 and hosts a demo server on that hotspot. You can check that for more details. Hope this helps!

Solution 3

For Android 8.0, there is a new API to handle Hotspots. As far as I know, the old way using reflection doesn't work anymore. Please refer to:

Android Developers https://developer.android.com/reference/android/net/wifi/WifiManager.html#startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback,%20android.os.Handler)

void startLocalOnlyHotspot (WifiManager.LocalOnlyHotspotCallback callback, 
                Handler handler)

Request a local only hotspot that an application can use to communicate between co-located devices connected to the created WiFi hotspot. The network created by this method will not have Internet access.

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

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.

Solution 4

Warning This method will not work beyond 5.0, it was a quite dated entry.

You can use the following code to enable, disable and query the wifi direct state programatically.

package com.kusmezer.androidhelper.networking;

import java.lang.reflect.Method;
import com.google.common.base.Preconditions;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.util.Log;

public final class WifiApManager {
      private static final int WIFI_AP_STATE_FAILED = 4;
      private final WifiManager mWifiManager;
      private final String TAG = "Wifi Access Manager";
      private Method wifiControlMethod;
      private Method wifiApConfigurationMethod;
      private Method wifiApState;

      public WifiApManager(Context context) throws SecurityException, NoSuchMethodException {
       context = Preconditions.checkNotNull(context);
       mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
       wifiControlMethod = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class,boolean.class);
       wifiApConfigurationMethod = mWifiManager.getClass().getMethod("getWifiApConfiguration",null);
       wifiApState = mWifiManager.getClass().getMethod("getWifiApState");
      }   
      public boolean setWifiApState(WifiConfiguration config, boolean enabled) {
       config = Preconditions.checkNotNull(config);
       try {
        if (enabled) {
            mWifiManager.setWifiEnabled(!enabled);
        }
        return (Boolean) wifiControlMethod.invoke(mWifiManager, config, enabled);
       } catch (Exception e) {
        Log.e(TAG, "", e);
        return false;
       }
      }
      public WifiConfiguration getWifiApConfiguration()
      {
          try{
              return (WifiConfiguration)wifiApConfigurationMethod.invoke(mWifiManager, null);
          }
          catch(Exception e)
          {
              return null;
          }
      }
      public int getWifiApState() {
       try {
            return (Integer)wifiApState.invoke(mWifiManager);
       } catch (Exception e) {
        Log.e(TAG, "", e);
            return WIFI_AP_STATE_FAILED;
       }
      }
}

Solution 5

Applies to Oreo+ only...

I made an app with code here on GitHub which uses reflection and DexMaker to 'get at' Oreo's tethering functionality, which is now in ConnectionManager, rather than WifiManager.

The stuff in WifiManager is good only for a closed wifi network (which explained the Closed bit in the class names!).

More explanation https://stackoverflow.com/a/49356255/772333.

Solution 6

This works well for me:

WifiConfiguration apConfig = null;
Method method = wifimanager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
method.invoke(wifimanager, apConfig, true);

Solution 7

APManager - Access Point Manager

Step 1 : Add the jcenter repository to your build file
allprojects {
    repositories {
        ...
        jcenter()
    }
}
Step 2 : Add the dependency
dependencies {
    implementation 'com.vkpapps.wifimanager:APManager:1.0.0'
}
Step 3 use in your app
APManager apManager = APManager.getApManager(this);
apManager.turnOnHotspot(this, new APManager.OnSuccessListener() {

    @Override
    public void onSuccess(String ssid, String password) {
        //write your logic
    }

}, new APManager.OnFailureListener() {

    @Override
    public void onFailure(int failureCode, @Nullable Exception e) {
        //handle error like give access to location permission,write system setting permission,
        //disconnect wifi,turn off already created hotspot,enable GPS provider
        
        //or use DefaultFailureListener class to handle automatically
    }

});

check out source code https://github.com/vijaypatidar/AndroidWifiManager

Solution 8

Your best bet will be looking at the WifiManager class. Specifically the setWifiEnabled(bool) function.

See the documentation at: http://developer.android.com/reference/android/net/wifi/WifiManager.html#setWifiEnabled(boolean)

A tutorial on how to use it (including what permissions you need) can be found here: http://www.tutorialforandroid.com/2009/10/turn-off-turn-on-wifi-in-android-using.html

Solution 9

I have publish unofficial api's for same, it's contains more than just hotspot turn on/off. link

For API's DOC - link.

Solution 10

You can use command line with root access

To turn on hotspot.

adb shell su -c service call connectivity 24 i32 0 i32 0 i32 0 s16 random

To turn off hotspot

adb shell su -c service call connectivity 25 i32 0 i32 0 i32 0 s16 random

Solution 11

**For Oreo & PIE ** I found below way through this

private WifiManager.LocalOnlyHotspotReservation mReservation;
private boolean isHotspotEnabled = false;
private final int REQUEST_ENABLE_LOCATION_SYSTEM_SETTINGS = 101;

private boolean isLocationPermissionEnable() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION}, 2);
        return false;
    }
    return true;
}

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

    if (manager != null) {
        // Don't start when it started (existed)
        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;
                isHotspotEnabled = true;
            }

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

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

@RequiresApi(api = Build.VERSION_CODES.O)
private void turnOffHotspot() {
    if (!isLocationPermissionEnable()) {
        return;
    }
    if (mReservation != null) {
        mReservation.close();
        isHotspotEnabled = false;
    }
}

@RequiresApi(api = Build.VERSION_CODES.O)
private void toggleHotspot() {
    if (!isHotspotEnabled) {
        turnOnHotspot();
    } else {
        turnOffHotspot();
    }
}

@RequiresApi(api = Build.VERSION_CODES.O)
private void enableLocationSettings() {
    LocationRequest mLocationRequest = new LocationRequest();
    /*mLocationRequest.setInterval(10);
    mLocationRequest.setSmallestDisplacement(10);
    mLocationRequest.setFastestInterval(10);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);*/
    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
    builder.addLocationRequest(mLocationRequest)
            .setAlwaysShow(false); // Show dialog

    Task<LocationSettingsResponse> task= LocationServices.getSettingsClient(this).checkLocationSettings(builder.build());

    task.addOnCompleteListener(task1 -> {
        try {
            LocationSettingsResponse response = task1.getResult(ApiException.class);
            // All location settings are satisfied. The client can initialize location
            // requests here.
            toggleHotspot();

        } catch (ApiException exception) {
            switch (exception.getStatusCode()) {
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    // Location settings are not satisfied. But could be fixed by showing the
                    // user a dialog.
                    try {
                        // Cast to a resolvable exception.
                        ResolvableApiException resolvable = (ResolvableApiException) exception;
                        // Show the dialog by calling startResolutionForResult(),
                        // and check the result in onActivityResult().
                        resolvable.startResolutionForResult(HotspotActivity.this, REQUEST_ENABLE_LOCATION_SYSTEM_SETTINGS);
                    } catch (IntentSender.SendIntentException e) {
                        // Ignore the error.
                    } catch (ClassCastException e) {
                        // Ignore, should be an impossible error.
                    }
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    // Location settings are not satisfied. However, we have no way to fix the
                    // settings so we won't show the dialog.
                    break;
            }
        }
    });
}

@RequiresApi(api = Build.VERSION_CODES.O)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
    switch (requestCode) {
        case REQUEST_ENABLE_LOCATION_SYSTEM_SETTINGS:
            switch (resultCode) {
                case Activity.RESULT_OK:
                    // All required changes were successfully made
                    toggleHotspot();
                    Toast.makeText(HotspotActivity.this,states.isLocationPresent()+"",Toast.LENGTH_SHORT).show();
                    break;
                case Activity.RESULT_CANCELED:
                    // The user was asked to change settings, but chose not to
                    Toast.makeText(HotspotActivity.this,"Canceled",Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }
            break;
    }
}

UseAge

btnHotspot.setOnClickListenr(view -> {
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        // Step 1: Enable the location settings use Google Location Service
        // Step 2: https://stackoverflow.com/questions/29801368/how-to-show-enable-location-dialog-like-google-maps/50796199#50796199
        // Step 3: If OK then check the location permission and enable hotspot
        // Step 4: https://stackoverflow.com/questions/46843271/how-to-turn-off-wifi-hotspot-programmatically-in-android-8-0-oreo-setwifiapen
        enableLocationSettings();
        return;
    }
}

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

implementation 'com.google.android.gms:play-services-location:15.0.1'

Solution 12

We can programmatically turn on and off

setWifiApDisable.invoke(connectivityManager, TETHERING_WIFI);//Have to disable to enable
setwifiApEnabled.invoke(connectivityManager, TETHERING_WIFI, false, mSystemCallback,null);

Using callback class, to programmatically turn on hotspot in pie(9.0) u need to turn off programmatically and the switch on.

Solution 13

You can use the console and service for that option.

I think with this you can solve that. I made a test directly in console and enable hotspot

I found this in this article Is it possible to USB tether an android device using adb through the terminal?

And after read the interface we can use the same 24 but needs more parameters

service call connectivity 24 i32 0 i32 1 i32 0 s16 random

Solution 14

WifiManager wifiManager = (WifiManager)this.context.getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(status);

where status may be true or false

add permission manifest: <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />