Android官方关于Wi-Fi Hotspot (Soft AP)
的文章:https://source.android.com/docs/core/connect/wifi-softap?hl=zh-cn
在 Android 11 的WifiManager
类中有一套系统 API 可以控制热点的开和关,代码如下:
开启热点:
// SoftApConfiguration是Android R(11)版本才出的
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {val builder = SoftApConfiguration.Builder()builder.setSsid("30666")builder.setPassphrase("99999999", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)val softApConfig = builder.build()val success = wifiManager.startTetheredHotspot(softApConfig)
}// 或者:
val config = WifiConfiguration()
config.SSID = ssid
config.preSharedKey = password
// WifiConfiguration.KeyMgmt.WPA2_PSK是Android R(11)版本才出的
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK)
} else {config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK)
}
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN)
val success = wifiManager.startSoftAp(config)
停止热点:
val success = wifiManager.stopSoftAp()
对于startTetheredHotspot
和startSoftAp
的区别,通义千问的答案如下:
SoftApConfiguration.Builder
、startTetheredHotspot
、startSoftAp
、stopSoftAp
这些API都被@SystemApi
注解所标注,所以我们无法直接调用,只能通过反射来调用,而且这些API需要一个权限,这个权限需要系统签名的应用才可以使用,权限如下:
<uses-permission android:name="android.permission.NETWORK_STACK"/>
反射调用示例代码如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {// val builder = SoftApConfiguration.Builder() // 创建 SoftApConfiguration.Builder 对象val builderClass = Class.forName("android.net.wifi.SoftApConfiguration\$Builder")val builder = builderClass.newInstance()Log.i("ABCD","builder = $builder")// builder.setSsid("30666") 设置热点的 SSID(名称)val setSsidMethod = builderClass.getMethod("setSsid", String::class.java)setSsidMethod.invoke(builder, ssid)// builder.setPassphrase("99999999", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) 设置热点的密码val setPassphraseMethod = builderClass.getMethod("setPassphrase", String::class.java, Int::class.javaPrimitiveType)setPassphraseMethod.invoke(builder, password, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)// builder.build() 构建 SoftApConfiguration 对象val buildMethod = builderClass.getMethod("build")val softApConfig = buildMethod.invoke(builder) as SoftApConfiguration// wifiManager.startSoftAp(softApConfig) 启动热点val startTetheredHotspotMethod= WifiManager::class.java.getMethod("startTetheredHotspot", SoftApConfiguration::class.java)val success = startTetheredHotspotMethod.invoke(wifiManager, softApConfig) as Booleanif (success) {Toast.makeText(this, "Soft AP start successfully", Toast.LENGTH_SHORT).show()} else {Toast.makeText(this, "Failed to start Soft AP", Toast.LENGTH_SHORT).show()}
}
或者:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {val config = WifiConfiguration()config.SSID = ssidconfig.preSharedKey = passwordconfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK)config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN)val startSoftApMethod = WifiManager::class.java.getDeclaredMethod("startSoftAp", WifiConfiguration::class.java)val success = startSoftApMethod.invoke(wifiManager, config) as Booleanif (success) {Toast.makeText(this, "Soft AP start successfully", Toast.LENGTH_SHORT).show()} else {Toast.makeText(this, "Failed to start Soft AP", Toast.LENGTH_SHORT).show()}
}
在公司的一台Android11的布控球上,发现在系统界面上修改了热点的名称等一些设置,然后用代码关闭,再用代码打开,然后查看系统设备,发现热点是打开了,但是热点名称和相关设置并不是代码中的设置,后来发现只是系统显示有问题,实际我们用别的设备来搜索热点时,显示的确实是我们代码中设置的那个名称,并不是系统设置中显示的那个名称,所以可以认为系统显示有Bug。
对于启动热点,可用 WifiManager
中的 setWifiApEnabled
、startSoftAp
、startTetheredHotspot
,或者 ConnectivityManager
中 startTetheredHotspot
,其中,ConnectivityManager
的 startTethering
只负责启动或关闭热点,对于热点名称密码等的一些配置要用WifiManager
的 setWifiApConfiguration
函数。在ChatGPT中问这几个函数的区别时,答案如下:
-
setWifiApEnabled
-
作用: 启用或禁用 Wi-Fi 热点。
-
参数:
wifiConfiguration
: 配置热点的WifiConfiguration
对象。enabled
: 一个布尔值,用于指示是否启用热点。
-
使用情况:这是较早版本的 API(从 API 级别 8 开始)。但从 Android O(API 26)开始,此方法已被弃用,不推荐使用。
-
示例代码:
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiConfiguration wifiConfig = new WifiConfiguration(); wifiConfig.SSID = "MyHotspot"; wifiConfig.preSharedKey = "password"; wifiManager.setWifiApEnabled(wifiConfig, true);
-
-
startSoftAp
-
作用: 启动一个软件热点(Soft AP)。
-
参数:
softApConfiguration
: 配置热点的SoftApConfiguration
对象。
-
使用情况:这是从 Android O(API 26)开始引入的方法,用于替代
setWifiApEnabled
。这个方法更加灵活和现代化,允许更详细的热点配置。 -
示例代码:
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); SoftApConfiguration.Builder builder = new SoftApConfiguration.Builder(); builder.setSsid("MyHotspot"); builder.setPassphrase("password", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); SoftApConfiguration config = builder.build(); wifiManager.startSoftAp(config);
-
-
startTetheredHotspot
-
作用: 启动一个软件热点(Soft AP)。
-
参数:
softApConfiguration
: 配置热点的SoftApConfiguration
对象。
-
使用情况:
-
示例代码:
val builder = SoftApConfiguration.Builder() builder.setSsid("30666") builder.setPassphrase("99999999", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) val softApConfig = builder.build() val success = wifiManager.startTetheredHotspot(softApConfig)
-
直接访问系统API
问了一下GPT,说是把自己的应用配置为系统应用即可,不只是加系统签名,还需要把应用拷贝到/system/priv-app/
目录,这样手机连接Android Studio
后估计就能识别你这个app在这个手机上是一个系统级app,此时可能就会直接让你访问系统API了,这有时间需要验证一下,还有如果验证是对的,然后我们再把app从/system/priv-app/
中删除,然后直接运行app,看是否还能正常运行,即使调用系统API的代码报错是否还能正常运行,这也需要验证一下。
把apk转为系统应用步骤如下:
adb root // 需要有root权限
adb remount
adb push /path/to/your/app.apk /system/priv-app/YourApp.apk
adb shell chmod 644 /system/priv-app/YourApp.apk // 设置适当的权限
adb reboot