Android 通过编程方式打开/关闭 WiFi HotSpot

是否有一个 API 可以程序化地打开或关闭 Android 上的 WiFi HotSpot?

我应该调用什么方法来打开/关闭它?

更新: 有一个选项可以启用 HotSpot,只需打开/关闭 WiFi,但这对我来说不是一个好的解决方案。

125853 次浏览

您最好的选择是查看 WifiManager 类,特别是 setWifiEnabled(bool)函数。

请参阅以下文档: Http://developer.android.com/reference/android/net/wifi/wifimanager.html#setwifienabled(boolean)

如何使用它(包括您需要什么权限)的教程可以在这里找到: Http://www.tutorialforandroid.com/2009/10/turn-off-turn-on-wifi-in-android-using.html

WifiManager wifiManager = (WifiManager)this.context.getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(status);

其中状态可能是 truefalse

添加权限清单: <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

警告: 此方法不能在5.0以后使用,它是一个相当过时的条目。

您可以使用以下代码以编程方式启用、禁用和查询 wifi 直接状态。

package com.kusmezer.androidhelper.networking;


import java.lang.reflect.Method;
import com.google.common.base.Preconditions;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.util.Log;


public final class WifiApManager {
private static final int WIFI_AP_STATE_FAILED = 4;
private final WifiManager mWifiManager;
private final String TAG = "Wifi Access Manager";
private Method wifiControlMethod;
private Method wifiApConfigurationMethod;
private Method wifiApState;


public WifiApManager(Context context) throws SecurityException, NoSuchMethodException {
context = Preconditions.checkNotNull(context);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
wifiControlMethod = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class,boolean.class);
wifiApConfigurationMethod = mWifiManager.getClass().getMethod("getWifiApConfiguration",null);
wifiApState = mWifiManager.getClass().getMethod("getWifiApState");
}
public boolean setWifiApState(WifiConfiguration config, boolean enabled) {
config = Preconditions.checkNotNull(config);
try {
if (enabled) {
mWifiManager.setWifiEnabled(!enabled);
}
return (Boolean) wifiControlMethod.invoke(mWifiManager, config, enabled);
} catch (Exception e) {
Log.e(TAG, "", e);
return false;
}
}
public WifiConfiguration getWifiApConfiguration()
{
try{
return (WifiConfiguration)wifiApConfigurationMethod.invoke(mWifiManager, null);
}
catch(Exception e)
{
return null;
}
}
public int getWifiApState() {
try {
return (Integer)wifiApState.invoke(mWifiManager);
} catch (Exception e) {
Log.e(TAG, "", e);
return WIFI_AP_STATE_FAILED;
}
}
}

这对我很有效:

WifiConfiguration apConfig = null;
Method method = wifimanager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
method.invoke(wifimanager, apConfig, true);

警告: 此方法不能在5.0以后使用,它是一个相当过时的条目。

使用下面的类更改/检查 Wifi hotspot设置:

import android.content.*;
import android.net.wifi.*;
import java.lang.reflect.*;


public class ApManager {


//check whether wifi hotspot on or off
public static boolean isApOn(Context context) {
WifiManager wifimanager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);
try {
Method method = wifimanager.getClass().getDeclaredMethod("isWifiApEnabled");
method.setAccessible(true);
return (Boolean) method.invoke(wifimanager);
}
catch (Throwable ignored) {}
return false;
}


// toggle wifi hotspot on or off
public static boolean configApState(Context context) {
WifiManager wifimanager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);
WifiConfiguration wificonfiguration = null;
try {
// if WiFi is on, turn it off
if(isApOn(context)) {
wifimanager.setWifiEnabled(false);
}
Method method = wifimanager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
method.invoke(wifimanager, wificonfiguration, !isApOn(context));
return true;
}
catch (Exception e) {
e.printStackTrace();
}
return false;
}
} // end of class

您需要添加以下权限到您的 Android Mainfest:

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

在任何地方都可以使用这个独立的 ApManager 类,如下所示:

ApManager.isApOn(YourActivity.this); // check Ap state :boolean
ApManager.configApState(YourActivity.this); // change Ap state :boolean

希望这能帮到别人

我已经发布了非官方的 API 的相同,它包含的不仅仅是热点转 on/off.链接

适用于 API 的 DOC-链接

对于 Android 8.0,有一个新的 API 来处理热点。据我所知,使用反射的旧方法已经不起作用了。 请参阅:

Android 开发者 Https://developer.android.com/reference/android/net/wifi/WifiManager.html#startlocalonlyhotspot (android.net.wifi. WifiManager. LocalOnlyHotspotCallback,% 20android. os. Handler)

void startLocalOnlyHotspot (WifiManager.LocalOnlyHotspotCallback callback,
Handler handler)

请求一个本地唯一的热点,一个应用程序可以使用连接到创建的 WiFi 热点的共同位置的设备之间的通信。由此方法创建的网络将不具有 Internet 访问权限。

堆栈溢出
如何在 Android 8.0(Oreo)中以编程方式打开/关闭 wifi 热点

OnStarted (WifiManager.如果热点处于打开状态,则将调用 LocalOnlyHotspotReserve 保留)方法。.使用 WifiManager。调用 close ()方法以关闭热点的 LocalOnlyHotspotReserve 引用。

只适用于奥利奥 + ..。

我用代码 在 GitHub 上做了一个应用程序,它使用反射和 DexMaker来“获取”奥利奥的系绳功能,现在是在 ConnectionManager,而不是 WifiManager

WifiManager中的内容只适用于封闭的 wifi 网络(这解释了类名中的“封闭位”).

更多解释 https://stackoverflow.com/a/49356255/772333

奥利奥和馅饼,我在下面找到了 通过这个

private WifiManager.LocalOnlyHotspotReservation mReservation;
private boolean isHotspotEnabled = false;
private final int REQUEST_ENABLE_LOCATION_SYSTEM_SETTINGS = 101;


private boolean isLocationPermissionEnable() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION}, 2);
return false;
}
return true;
}


@RequiresApi(api = Build.VERSION_CODES.O)
private void turnOnHotspot() {
if (!isLocationPermissionEnable()) {
return;
}
WifiManager manager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);


if (manager != null) {
// Don't start when it started (existed)
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;
isHotspotEnabled = true;
}


@Override
public void onStopped() {
super.onStopped();
//Log.d(TAG, "onStopped: ");
isHotspotEnabled = false;
}


@Override
public void onFailed(int reason) {
super.onFailed(reason);
//Log.d(TAG, "onFailed: ");
isHotspotEnabled = false;
}
}, new Handler());
}
}


@RequiresApi(api = Build.VERSION_CODES.O)
private void turnOffHotspot() {
if (!isLocationPermissionEnable()) {
return;
}
if (mReservation != null) {
mReservation.close();
isHotspotEnabled = false;
}
}


@RequiresApi(api = Build.VERSION_CODES.O)
private void toggleHotspot() {
if (!isHotspotEnabled) {
turnOnHotspot();
} else {
turnOffHotspot();
}
}


@RequiresApi(api = Build.VERSION_CODES.O)
private void enableLocationSettings() {
LocationRequest mLocationRequest = new LocationRequest();
/*mLocationRequest.setInterval(10);
mLocationRequest.setSmallestDisplacement(10);
mLocationRequest.setFastestInterval(10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);*/
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest)
.setAlwaysShow(false); // Show dialog


Task<LocationSettingsResponse> task= LocationServices.getSettingsClient(this).checkLocationSettings(builder.build());


task.addOnCompleteListener(task1 -> {
try {
LocationSettingsResponse response = task1.getResult(ApiException.class);
// All location settings are satisfied. The client can initialize location
// requests here.
toggleHotspot();


} catch (ApiException exception) {
switch (exception.getStatusCode()) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the
// user a dialog.
try {
// Cast to a resolvable exception.
ResolvableApiException resolvable = (ResolvableApiException) exception;
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
resolvable.startResolutionForResult(HotspotActivity.this, REQUEST_ENABLE_LOCATION_SYSTEM_SETTINGS);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
} catch (ClassCastException e) {
// Ignore, should be an impossible error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
}


@RequiresApi(api = Build.VERSION_CODES.O)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
switch (requestCode) {
case REQUEST_ENABLE_LOCATION_SYSTEM_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
// All required changes were successfully made
toggleHotspot();
Toast.makeText(HotspotActivity.this,states.isLocationPresent()+"",Toast.LENGTH_SHORT).show();
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to
Toast.makeText(HotspotActivity.this,"Canceled",Toast.LENGTH_SHORT).show();
break;
default:
break;
}
break;
}
}

使用年龄

btnHotspot.setOnClickListenr(view -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Step 1: Enable the location settings use Google Location Service
// Step 2: https://stackoverflow.com/questions/29801368/how-to-show-enable-location-dialog-like-google-maps/50796199#50796199
// Step 3: If OK then check the location permission and enable hotspot
// Step 4: https://stackoverflow.com/questions/46843271/how-to-turn-off-wifi-hotspot-programmatically-in-android-8-0-oreo-setwifiapen
enableLocationSettings();
return;
}
}


<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />


implementation 'com.google.android.gms:play-services-location:15.0.1'

我们可以通过程序打开和关闭

setWifiApDisable.invoke(connectivityManager, TETHERING_WIFI);//Have to disable to enable
setwifiApEnabled.invoke(connectivityManager, TETHERING_WIFI, false, mSystemCallback,null);

使用回调类,要以编程方式打开 pie (9.0)中的热点,需要以编程方式关闭并打开开关。

您可以对该选项使用控制台和服务。

我想你可以用这个来解决这个问题。我直接在控制台上做了一个测试,启用了热点

我在这篇文章里找到了这个 是否有可能通过 USB 通过终端使用 adb 来连接机器人设备?

读取接口后,我们可以使用相同的24,但需要更多的参数

服务呼叫连接24 i320 i321 i320 s16随机

如果你想在你的 android 应用程序中以编程的方式实现 wifi 热点功能,这里有一个完整的解决方案。

空气污染指数的解决方案 < 26:

适用于 < API 26的器件。Android 没有用于此目的的公共 API。因此,为了使用这些 API,您必须通过 反思访问私有 API。不推荐这样做,但如果你没有其他选择,那么这里有一个窍门。

首先,你需要在清单上有这个许可,

  <uses-permission
android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions"/>


<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

以下是您在运行时询问它的方法:

 private boolean showWritePermissionSettings() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
if (!Settings.System.canWrite(this)) {
Log.v("DANG", " " + !Settings.System.canWrite(this));
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + this.getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
return false;
}
}
return true; //Permission already given
}

然后可以通过反射访问 setWifiEnabled方法。如果您请求的操作正在处理,即启用/禁用热点,则返回 true。

     public boolean setWifiEnabled(WifiConfiguration wifiConfig, boolean enabled) {
WifiManager wifiManager;
try {
if (enabled) { //disables wifi hotspot if it's already enabled
wifiManager.setWifiEnabled(false);
}


Method method = wifiManager.getClass()
.getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
return (Boolean) method.invoke(wifiManager, wifiConfig, enabled);
} catch (Exception e) {
Log.e(this.getClass().toString(), "", e);
return false;
}
}

你也可以通过反射得到你的热点的 wificonconfiguration。我在 StackOverflow 上有这个问题的 回答方法。

附注: 如果你不想以编程方式打开热点,你可以启动这个 意图并打开 wifi 设置屏幕,让用户手动打开它。

API > = 26的解决方案:

最后,android 发布了一个官方的版本 > = Oreo 的 API。您可以通过 android 使用公开的 API,即 StartLocalOnlyHotspot

它打开一个本地热点没有互联网接入。因此,它可以用来承载服务器或传输文件。

它需要 Manifest.permission.CHANGE_WIFI_STATEACCESS_FINE_LOCATION权限。

下面是一个简单的例子,说明如何使用这个 API 打开热点。

private WifiManager wifiManager;
WifiConfiguration currentConfig;
WifiManager.LocalOnlyHotspotReservation hotspotReservation;

打开热点的方法:

@RequiresApi(api = Build.VERSION_CODES.O)
public void turnOnHotspot() {


wifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {


@Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
hotspotReservation = reservation;
currentConfig = hotspotReservation.getWifiConfiguration();


Log.v("DANG", "THE PASSWORD IS: "
+ currentConfig.preSharedKey
+ " \n SSID is : "
+ currentConfig.SSID);


hotspotDetailsDialog();


}


@Override
public void onStopped() {
super.onStopped();
Log.v("DANG", "Local Hotspot Stopped");
}


@Override
public void onFailed(int reason) {
super.onFailed(reason);
Log.v("DANG", "Local Hotspot failed to start");
}
}, new Handler());
}
`

下面介绍如何获得本地创建的热点的详细信息

private void hotspotDetaisDialog()
{


Log.v(TAG, context.getString(R.string.hotspot_details_message) + "\n" + context.getString(
R.string.hotspot_ssid_label) + " " + currentConfig.SSID + "\n" + context.getString(
R.string.hotspot_pass_label) + " " + currentConfig.preSharedKey);


}

如果它抛出,一个安全异常,甚至在给予所需的权限,然后你应该尝试启用你的位置使用全球定位系统。这是 解决方案

最近,我开发了一个名为 观察员的演示应用程序。它为所有 API > = 15的设备打开 wifi 热点,并在热点上托管一个演示服务器。你可以查看更多细节。希望这个能帮上忙!

接入点管理器

步骤1: 将 jcenter 存储库添加到构建文件中
allprojects {
repositories {
...
jcenter()
}
}
步骤2: 添加依赖项
dependencies {
implementation 'com.vkpapps.wifimanager:APManager:1.0.0'
}
第三步在你的应用程序中使用
APManager apManager = APManager.getApManager(this);
apManager.turnOnHotspot(this, new APManager.OnSuccessListener() {


@Override
public void onSuccess(String ssid, String password) {
//write your logic
}


}, new APManager.OnFailureListener() {


@Override
public void onFailure(int failureCode, @Nullable Exception e) {
//handle error like give access to location permission,write system setting permission,
//disconnect wifi,turn off already created hotspot,enable GPS provider
        

//or use DefaultFailureListener class to handle automatically
}


});

查看源代码 Https://github.com/vijaypatidar/androidwifimanager

您可以使用具有 root 访问权限的命令行

打开热点。

adb shell su -c service call connectivity 24 i32 0 i32 0 i32 0 s16 random

关闭热点

adb shell su -c service call connectivity 25 i32 0 i32 0 i32 0 s16 random