webentwicklung-frage-antwort-db.com.de

WLAN-Hotspot in Android 8.0 (Oreo) programmgesteuert ein-/ausschalten

Ich weiß, wie man den WLAN-Hotspot mit Reflexion in Android mit der untenstehenden Methode ein/ausschaltet.

private static boolean changeWifiHotspotState(Context context,boolean enable) {
        try {
            WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            Method method = manager.getClass().getDeclaredMethod("setWifiApEnabled", WifiConfiguration.class,
                    Boolean.TYPE);
            method.setAccessible(true);
            WifiConfiguration configuration = enable ? getWifiApConfiguration(manager) : null;
            boolean isSuccess = (Boolean) method.invoke(manager, configuration, enable);
            return isSuccess;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

Aber die obige Methode funktioniert nicht mit Android 8.0 (Oreo).  

Wenn ich die obige Methode in Android 8.0 ausführen, erhalte ich in logcat die folgende Aussage.

com.gck.dummy W/WifiManager: com.gck.dummy attempted call to setWifiApEnabled: enabled = true

Gibt es eine andere Möglichkeit, Hotspot unter Android 8.0 ein- oder auszuschalten?

10
Chandrakanth

Endlich bekam ich die Lösung ... __ Android 8.0, sie lieferte ein öffentliches API, um Hotspot ein-/auszuschalten. WifiManager

Unten ist der Code zum Aktivieren von 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();
    }
}

Die onStarted(WifiManager.LocalOnlyHotspotReservation reservation)-Methode wird aufgerufen, wenn Hotspot aktiviert ist. Mit WifiManager.LocalOnlyHotspotReservation reference rufen Sie die close()-Methode auf, um hotspot auszuschalten.

Hinweis: Um den Hotspot zu aktivieren, muss die Location(GPS) im Gerät aktiviert sein. Andernfalls wird SecurityException ausgegeben.

11
Chandrakanth

Ich dachte, die LocalOnlyHotspot-Route wäre der Weg zu, aber wie @ edsappfactory.com in den Kommentaren sagte - es gibt nur ein geschlossenes Netzwerk, keinen Internetzugang. 

In Oreo wurde Hot-Spotting/Tethering nach ConnectionManager verschoben, und sein kommentierter @SystemApi ist (nominell) nicht zugänglich.

Als Teil von etwas anderem machte ich eine App und legte sie auf github hier . Es verwendet Reflektion, um an die Funktion zu gelangen und DexMaker , um eine Unterklasse von ConnectionManager.OnStartTetheringCallback (die auch nicht zugänglich ist) zu generieren. 

Ich finde, es funktioniert alles in Ordnung - etwas rau an den Rändern. 

Relevante Codebits sind in:

Ich verlor die Geduld, als ich versuchte, meinen von DexMaker generierten Callback dazu zu bringen, die MyOnStartTetheringCallback auszulösen, sodass der gesamte Code in Unordnung geraten ist und auskommentiert wird.

13
Jon

Laut Jon-Vorschlag erhielt ich eine weitere Möglichkeit, Wifi HotSpot in Android Oreo und höher zu aktivieren. 

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;
}
3
Vishal Sharma