web-dev-qa-db-fra.com

Comment activer/désactiver le point d'accès wifi par programme dans Android 8.0 (Oreo)

Je sais comment activer/désactiver le point d'accès Wi-Fi à l'aide de la réflexion dans Android à l'aide de la méthode ci-dessous.

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;
    }

Mais la méthode ci-dessus ne fonctionne pas avec Android 8.0 (Oreo).  

Lorsque j'exécute la méthode ci-dessus dans Android 8.0, la déclaration ci-dessous apparaît dans logcat.

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

Existe-t-il un autre moyen d'activer/de désactiver le point d'accès sur Android 8.0?

10
Chandrakanth

Enfin, j’ai eu la solution . Android 8.0, ils ont fourni l’API publique pour activer/désactiver le hotspot. WifiManager

Voici le code pour activer le 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();
    }
}

La méthode onStarted(WifiManager.LocalOnlyHotspotReservation reservation) sera appelée si le hotspot est activé. À l'aide de la référence WifiManager.LocalOnlyHotspotReservation, vous appelez la méthode close() pour désactiver le hotspot.

Remarque: Pour activer le point d'accès, le Location(GPS) doit être activé sur le périphérique. Sinon, il lancera SecurityException

11
Chandrakanth

Je pensais que la route LocalOnlyHotspot était la voie à suivre, mais comme @ edsappfactory.com l’a dit dans ses commentaires, il ne donne qu’un réseau fermé, pas d’accès à Internet. 

Dans Oreo, le repérage à chaud/le partage de connexion est passé à ConnectionManager, et son @SystemApi annoté, donc (nominalement) inaccessible.

Dans le cadre de quelque chose que je faisais, j'ai créé une application et je l'ai mise sur github ici . Il utilise la réflexion pour accéder à la fonction et DexMaker pour générer une sous-classe de ConnectionManager.OnStartTetheringCallback (également inaccessible). 

Pensez que tout fonctionne bien - un peu rude sur les bords, alors n'hésitez pas à faire mieux! 

Les bits de code pertinents sont dans:

J'ai perdu patience en essayant d'obtenir mon rappel généré par DexMaker pour déclencher le MyOnStartTetheringCallback afin que tout ce code soit en désordre et mis en commentaire.

13
Jon

Selon la suggestion de Jon, j'ai eu un autre moyen d'activer le HotSpot Wifi dans Android Oreo et au-dessus. 

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