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

匆匆过客 提交于 2019-11-27 01:45:42
Jon

I thought the LocalOnlyHotspot route was the way to, but as @edsappfactory.com said in the comments - it only gives closed network, no internet access.

In Oreo hot-spotting/tethering moved to ConnectionManager, and its annotated @SystemApi, so (nominally) inaccessible.

As part of something else I was doing, I made an app and put it on github here. It uses reflection to get at the function and DexMaker to generate a subclass of ConnectionManager.OnStartTetheringCallback (which is also inaccessible).

Think it all works okay - bit rough around the edges, so please feel free to make better!

Relevant bits of code are in:

I lost patience trying to get my DexMaker-generated callback to fire the MyOnStartTetheringCallback so all that code is in disarray and commented out.

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

As per Jon suggestion, I got another way to enable WifiHotSpot in Android Oreo and above.

public boolean enableTetheringNew(MyTetheringCallback callback) {
    File outputDir = mContext.getCodeCacheDir();
    try {
        proxy = ProxyBuilder.forClass(classOnStartTetheringCallback())
                .dexCache(outputDir).handler(new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                       switch (method.getName()) {
                            case "onTetheringStarted":
                                callback.onTetheringStarted();
                                break;
                            case "onTetheringFailed":
                                callback.onTetheringFailed();
                                break;
                            default:
                                ProxyBuilder.callSuper(proxy, method, args);
                        }
                        return null;
                    }

                }).build();
    } catch (IOException e) {
        e.printStackTrace();
    }
    ConnectivityManager manager = (ConnectivityManager) mContext.getApplicationContext().getSystemService(ConnectivityManager.class);

    Method method = null;
    try {
        method = manager.getClass().getDeclaredMethod("startTethering", int.class, boolean.class, classOnStartTetheringCallback(), Handler.class);
        if (method == null) {
            Log.e(TAG, "startTetheringMethod is null");
        } else {
            method.invoke(manager, TETHERING_WIFI, false, proxy, null);

        }
        return true;
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
    return false;
}

private Class classOnStartTetheringCallback() {
    try {
        return Class.forName("android.net.ConnectivityManager$OnStartTetheringCallback");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    return null;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!