Android 10 / API 29:如何将手机连接到配置的网络?
Posted
技术标签:
【中文标题】Android 10 / API 29:如何将手机连接到配置的网络?【英文标题】:Android 10 / API 29 : how to connect the phone to a configured network? 【发布时间】:2020-03-05 06:24:45 【问题描述】:我正在开发一个用户必须按照以下步骤操作的应用程序:
-
将手机连接到wifi;
将手机从连接对象连接到专用热点。
当用户连接到连接对象的专用热点时,应用程序会执行一些 HTTP 请求以对其进行配置。然后,我想将应用程序自动重新连接到步骤 1 的全局 wifi。
从 API 21 到 API 28,这个功能很容易实现,因为我知道我也想重新连接手机的 SSID。几行代码就可以搞定:
private fun changeCurrentWifiNetworkLegacy(ssidToConnect: String)
val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
var ssidIdentifier: Int? = null
wifiManager.configuredNetworks?.forEach config ->
Log.d("SSID", config.SSID)
if (config.SSID == "\"$ssidToConnect\"")
ssidIdentifier = config.networkId
ssidIdentifier?.let id ->
wifiManager.enableNetwork(id, true)
根据这篇文章,这个简单的代码在 API 29 上不再起作用:https://developer.android.com/about/versions/10/privacy/changes#configure-wifi
根据文章,现在,我应该使用 2 个类:WifiNetworkSpecifier
和/或 WifiNetworkSuggestion
。
很遗憾,我找不到使用这些类来将用户连接到之前配置的 SSID 的工作示例。
有人已经做到了吗?
提前感谢您的帮助。
【问题讨论】:
【参考方案1】:以防万一任何可怜的灵魂遇到这种情况,完全有可能您的设备上的 API 被破坏了。在我的 OnePlus 5、Android 10、Build 200513 上,会发生这种情况:
-
呼叫请求网络。不管我使用的是 Listener 版本还是 PendingIntent 版本
操作系统找到网络,连接,onAvailable 和朋友被调用
操作系统立即断开连接。我可以在 logcat 中看到“App 已发布请求,正在取消 NetworkRequest”
然而,事实并非如此 - 请求未被取消,Android 依赖于此,并再次开始连接到网络的过程。转到 2. 并永远重复。
为此创建了一个 Android 错误:https://issuetracker.google.com/issues/158344328
此外,如果您不以正确的顺序终止您的应用程序和对话框,您可以让操作系统进入不再显示“与设备一起使用”对话框的状态,并且只有重新启动有帮助。
省去麻烦,以 Android 9 为目标并使用 WifiManager API(如果您以 10 为目标,这些 API 会很有帮助)。它甚至比新的 requestNetwork API 具有更好的用户体验。
【讨论】:
我同意您针对 Android 9 的建议,但是...“从 2020 年 11 月 2 日起,应用更新必须针对 Android 10(API 级别 29)或更高版本。” (来自developer.android.com/distribute/best-practices/develop/…) 是的。我们现在陷入了低劣的用户体验,甚至在某些手机上都被破坏了。 我处于完全相同的位置 - 这里唯一要补充的是,由于某种原因,如果我在应用程序屏幕中授予Display over other apps
权限,则 api 似乎可以使用已弃用的方法(addNetwork() 和等)和整个流程连接
这还开着吗? @BlueBot 我也无法使用 AddNetwork 进行连接:/
我想我实现了新机制并且它有效,老实说不记得了:/ @Singhal2【参考方案2】:
您可以使用以下代码设置要连接的网络:
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q)
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(
WifiNetworkSpecifier.Builder()
.setSsid("My ssid")
.build()
)
.build()
cm.requestNetwork(networkRequest, object: ConnectivityManager.NetworkCallback()
override fun onUnavailable()
Log.d("TEST", "Network unavailable")
override fun onAvailable(network: Network)
Log.d("TEST", "Network available")
)
这使用 ConnectivityManager 的 networkRequest 方法来请求具有特定 SSID 的网络。
此方法要求调用者持有Manifest.permission.CHANGE_NETWORK_STATE
权限或修改系统设置的能力,由Settings.System.canWrite(Context)
确定。
请参阅NetworkCallback 课程以获取有关您可以获得哪些信息的更多文档。
(编辑:错过添加传输类型。)
进一步编辑:我需要使用.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
让它正常工作。因为在 WifiNetworkSpecifier
只能用于请求本地 wifi 网络(即没有互联网 能力)
根据the docs
这给了我一个设备弹出请求,但最终向我显示了我要求的 Wifi 网络。
【讨论】:
感谢您的回答。我在互联网上找到了这个代码,但是当我尝试它时它不起作用。不幸的是,当我调用 requestNetwork 方法时,我可以看到一个带有进度条的对话框,上面写着“与我的应用程序一起使用的设备”。一段时间后,会出现另一个对话框,内容为“未找到设备。确保设备已打开并可连接”。我从来没有达到 onAvailable 方法。 是的,你是对的。我在自己的设置上尝试过。我通过在developer.android.com/reference/android/net/wifi/… 中看到他们特别要求removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
的示例来实现它。我试过了,让它到达 onAvailable 方法。然而,这只是使用模拟器,因为我没有 Q 设备。我会更新答案
设备弹出时间过长。有什么办法可以减少吗?
这是非常脆弱的代码,因为它无法与已经发布的 API 30 一起运行。将 == 更改为 >=【参考方案3】:
我尝试了很多代码,包括WifiManager.addNetworkSuggestions
和ConnectivityManager.requestNetwork
。最后我发现,只需拨打ConnectivityManager.unregisterNetworkCallback
即可恢复用户wifi 连接。这段代码唯一让我不满意的地方,如果用户保存了WiFi A和WiFi B,那么系统会自动选择一个连接,而不是我指定的那个。
【讨论】:
以上是关于Android 10 / API 29:如何将手机连接到配置的网络?的主要内容,如果未能解决你的问题,请参考以下文章
安卓10(Android10API29)保存图片到相册DCIM/Camera
安卓10(Android10API29)保存图片到相册DCIM/Camera
如何在android 10或更高版本中获得“总是”位置的许可? (高于 API 29)?