【问题标题】:Android turn On/Off WiFi HotSpot programmaticallyAndroid以编程方式打开/关闭WiFi热点
【发布时间】:2011-09-17 16:27:43
【问题描述】:

是否有 API 以编程方式打开/关闭 Android 上的 WiFi 热点?

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

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

【问题讨论】:

标签: android wifi android-wifi


【解决方案1】:

警告此方法在 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

您需要将以下权限添加到您的 AndroidMainfest:

<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

希望这会对某人有所帮助

【讨论】:

  • 你的答案很长......但问题的主人似乎不认为这是一个答案@AshishSahu?
  • 它对我有用!谢谢,我必须先禁用 wifi 功能,然后才能在 AP 模式下运行 wifi。否则我收到错误:无法使用正在运行的请求者启动软 AP
  • 谢谢。我必须添加以下权限才能使其在 Android 6 上运行:&lt;uses-permission android:name="android.permission.WRITE_SETTINGS" /&gt;
  • 这不再适用于 Android 6+。见这里:stackoverflow.com/a/35504709/4307173。代替 ACTION_SETTINGS,使用 ACTION_PICK_WIFI_NETWORK
  • @KenKenKen 这是错误的,我刚刚在带有 7.1.1 的 Nexus 5X 上进行了测试,但是您必须授予 WRITE_SETTINGS 权限,这需要用户专门接受。
【解决方案2】:

如果您想在您的 Android 应用程序中以编程方式实现 wifi 热点功能,这里是完整的解决方案。

API

对于设备 reflection 访问私有 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; 
}   
}

您还可以通过反射获取热点的wifi配置。对于 StackOverflow 上的这个问题,我有 answered 那个方法。

P.S:如果您不想以编程方式打开热点,您可以启动此intent 并打开 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);

}

如果它抛出安全异常,即使在授予所需权限后,您也应该尝试使用 GPS 启用您的位置。这是solution

最近,我开发了一个名为Spotserve 的演示应用程序。这将为所有 API>=15 的设备打开 wifi 热点,并在该热点上托管一个演示服务器。您可以检查以获取更多详细信息。希望这会有所帮助!

【讨论】:

  • 以及如何在应用内连接到本地唯一的热点。以及如何设置特定的 ssid 和密码
  • 指定设备是否可以关闭热点?
  • API >= 26 方法有效,但我需要先初始化 wifiManager:wifiManager = (WifiManager) this.getSystemService(this.WIFI_SERVICE);
【解决方案3】:

对于 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。

堆栈溢出
How to turn on/off wifi hotspot programmatically in Android 8.0 (Oreo)

onStarted(WifiManager.LocalOnlyHotspotReservation reservation) 方法会在热点开启时被调用。使用 WifiManager.LocalOnlyHotspotReservation 引用调用 close() 方法来关闭热点。

【讨论】:

    【解决方案4】:

    警告此方法在 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;
           }
          }
    }
    

    【讨论】:

    • @ldce 反射它不是一个 API。 Feathermore,我用 Lollipop 在 Nexus 5 上检查过它仍然有效。
    • @Divers 它可以在带有 Lollipop 的 Nexus 5 上运行吗?不适用于我的 AT&T S6 Lollipop 5.1.1
    • 可能他们在新版本中删除了它
    • 为什么要发布第三方库com.google.common.base.Preconditions;的示例?
    • 这是一个相当过时的条目,所以基本上它不会与新版本一起使用。
    【解决方案5】:

    这对我很有效:

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

    【讨论】:

    • 如果你可以这样打开 Wifi 热点,那么……你怎么能把它关掉?
    • 这仅适用于 Android 4.4。 Android 5.0 及以上版本无法连接热点。
    【解决方案6】:

    仅适用于 Oreo+...

    我用代码here on GitHub 制作了一个应用程序,它使用反射和DexMaker 来“获取”奥利奥的网络共享功能,该功能现在位于ConnectionManager,而不是WifiManager

    WifiManager 中的内容仅适用于封闭的 wifi 网络(这解释了类名中的 Closed 位!)。

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

    【讨论】:

      【解决方案7】:

      APManager - 接入点管理器

      第 1 步:将 jcenter 存储库添加到您的构建文件
      allprojects {
          repositories {
              ...
              jcenter()
          }
      }
      
      第二步:添加依赖
      dependencies {
          implementation 'com.vkpapps.wifimanager:APManager:1.0.0'
      }
      
      第 3 步在您的应用中使用
      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

      【讨论】:

      • 这会创建热点但不共享移动数据的互联网连接。
      • 我喜欢这个答案
      【解决方案8】:

      您最好的选择是查看 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

      【讨论】:

      • 是否可以不开启/关闭WiFi?
      • 可能,仍在使用 WifiManager 类。看到这个 SO 问题:stackoverflow.com/questions/3023226/…(我认为这是你最好的选择。)
      • 他谈到了 WiFi 热点,而不仅仅是 WiFi
      【解决方案9】:

      我已经发布了相同的非官方 api,它包含的不仅仅是热点转 on/offlink

      对于 API 的文档 - link

      【讨论】:

      • 请注意,提供的 API 是为设备充当客户端连接到 AP,而 OP 正在寻找控制内置 AP 的方法。
      【解决方案10】:

      **For Oreo & PIE **我在下面找到through this

      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'
      

      【讨论】:

        【解决方案11】:

        我们可以通过编程方式开启和关闭

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

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

        【讨论】:

        • 提供更多关于您在此处添加的代码的信息。
        【解决方案12】:

        您可以将控制台和服务用于该选项。

        我认为你可以解决这个问题。我直接在控制台做了一个测试,开启热点

        我在这篇文章中找到了这个 Is it possible to USB tether an android device using adb through the terminal?

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

        服务呼叫连接 24 i32 0 i32 1 i32 0 s16 随机

        【讨论】:

          【解决方案13】:
          WifiManager wifiManager = (WifiManager)this.context.getSystemService(Context.WIFI_SERVICE);
          wifiManager.setWifiEnabled(status);
          

          其中状态可能是truefalse

          添加权限清单:&lt;uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /&gt;

          【讨论】:

          • 这只会打开/关闭 wifi,而不是 HotSpot。
          猜你喜欢
          • 1970-01-01
          • 2014-11-04
          • 1970-01-01
          • 1970-01-01
          • 2018-02-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-25
          相关资源
          最近更新 更多