Как включить/отключить wifi hotspot программно в Android 8.0 (Oreo)
Я знаю, как включить/выключить горячую точку Wi-Fi, используя отражение в андроиде, используя метод ниже.
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;
}
Но вышеупомянутый метод не работает с Android 8.0 (Oreo).
Когда я выполняю выше метод в Android 8.0, я получаю ниже выражение в logcat.
com.gck.dummy W/WifiManager: com.gck.dummy attempted call to setWifiApEnabled: enabled = true
Есть ли другой способ включения/выключения hotspot на android 8.0
Ответы
Ответ 1
Наконец-то я получил решение. Android 8.0, они предоставили публичный API для включения/выключения точки доступа. WifiManager
Ниже приведен код для включения горячей точки
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)
будет вызван, если WifiManager.LocalOnlyHotspotReservation
горячая точка. Используя ссылку WifiManager.LocalOnlyHotspotReservation
вы вызываете метод close()
чтобы отключить горячую точку.
Примечание. Чтобы включить точку доступа, на Location(GPS)
должно быть включено Location(GPS)
. В противном случае он выдаст исключение SecurityException
Ответ 2
Я думал, что путь LocalOnlyHotspot
- это путь, но, как сказал @edsappfactory.com в комментариях, он дает только закрытую сеть, а не доступ в Интернет.
В Oreo хот-споттинг/привязка перемещены в ConnectionManager
, а его аннотированный @SystemApi
, поэтому (номинально), недоступен.
Как часть чего-то другого, что я делал, я сделал приложение и поместил его на github здесь. Он использует отражение, чтобы добраться до функции, и DexMaker, чтобы сгенерировать подкласс ConnectionManager.OnStartTetheringCallback
(который также недоступен).
Думаю, что все работает хорошо - немного грубовато, так что, пожалуйста, не стесняйтесь, чтобы сделать лучше!
Соответствующие биты кода находятся в:
Я потерял терпение, пытаясь заставить мой сгенерированный DexMaker обратный вызов запустить MyOnStartTetheringCallback
чтобы весь этот код был в замешательстве и закомментирован.
Ответ 3
Согласно предложению Джона, я получил еще один способ включить WifiHotSpot в Android Oreo и выше.
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;
}