Cómo activar/desactivar el punto de acceso wifi mediante programación en Android 8.0(Oreo)
android-wifi hotspot (3)
Sé cómo activar / desactivar el punto de acceso wifi usando la reflexión en Android usando el método a continuación.
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;
}
Pero el método anterior no funciona con Android 8.0 (Oreo).
Cuando ejecuto el método anterior en Android 8.0, obtengo la siguiente declaración en logcat.
com.gck.dummy W/WifiManager: com.gck.dummy attempted call to setWifiApEnabled: enabled = true
¿Hay alguna otra forma de activar / desactivar el punto de acceso en Android 8.0
Finalmente obtuve la solución. Android 8.0, proporcionaron una API pública para activar / desactivar el punto de acceso. WifiManager
A continuación se muestra el código para activar el punto de acceso
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)
método
onStarted(WifiManager.LocalOnlyHotspotReservation reservation)
si la zona activa está activada. Usando la referencia
WifiManager.LocalOnlyHotspotReservation
se llama al método
close()
para
desactivar la zona activa
.
Nota:
Para activar el punto de acceso, la
Location(GPS)
debe estar habilitada en el dispositivo.
De lo contrario, arrojará
SecurityException
Pensé que la ruta
LocalOnlyHotspot
era el camino a seguir, pero como dijo @ edsappfactory.com en los comentarios, solo ofrece una red cerrada, sin acceso a Internet.
En Oreo, el hot-spotting / tethering se movió a
ConnectionManager
y su
@SystemApi
anotado, por lo tanto (nominalmente) inaccesible.
Como parte de algo más que estaba haciendo, hice una aplicación y la puse en
Github aquí
.
Utiliza la reflexión para llegar a la función y
DexMaker
para generar una subclase de
ConnectionManager.OnStartTetheringCallback
(que también es inaccesible).
Piensa que todo funciona bien, un poco áspero en los bordes, ¡así que no dudes en mejorar!
Los bits de código relevantes están en:
Perdí la paciencia al intentar que mi devolución de llamada generada por
MyOnStartTetheringCallback
para que todo ese código esté en desorden y
MyOnStartTetheringCallback
.
Según la sugerencia de Jon, obtuve otra forma de habilitar WifiHotSpot en Android Oreo y superior.
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;
}