Android - 绑定移动网络套接字时权限被拒绝(OkHttp.socketFactory(network.socketFactory))
Posted
技术标签:
【中文标题】Android - 绑定移动网络套接字时权限被拒绝(OkHttp.socketFactory(network.socketFactory))【英文标题】:Android - Permission denied when binding a mobile network socket (OkHttp.socketFactory(network.socketFactory)) 【发布时间】:2022-01-02 19:51:04 【问题描述】:我正在寻找与以下问题相关的帮助/想法:
我想要达到的目标:
使用 Retrofit2、OktHttp 在 android 上通过移动网络路由请求我做了什么:
使用ConnectivityManager获得了所需的Network实例 为 OkHttpClient 设置 socketFactory 以使用 Network 实例中的那个 在AndroidManifest.xml中指定了这些权限。:<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
示例代码:
val network: Network = connectivityManager.allNetworks.first
connectivityManager.getNetworkCapabilities(it)?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == true
val okHttpClient = OkHttpClient.Builder()
.socketFactory(network.socketFactory)
.build()
结果:
抛出异常:java.net.SocketException:将套接字绑定到网络 505 失败:EACCES(权限被拒绝)注意事项/免责声明:
以上适用于 WiFi 我知道这是一种不好的做法:它不是应用程序的默认行为。用户可以随时选择加入和退出。有一个特定的用例是有意义的。如果您对我做错了什么有任何想法,或者为什么它不适用于移动网络,请告诉我。
【问题讨论】:
【参考方案1】:我设法找出我做错的原因。
简而言之:
使用 ConnectivityManager.requestNetwork() 代替 ConnectivityManager.getAllNetworks(),指定网络详细信息并使用收到的详细信息。val cellularRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()
connectivityManager.requestNetwork(cellularRequest, object :
ConnectivityManager.NetworkCallback()
override fun onAvailable(network: Network)
// use the network...
)
说来话长: 测试时,我打开了 WiFi 和移动数据。 来自关于 ConnectivityManager.getAllNetworks() 的文档:
“返回框架当前跟踪的所有网络的数组。” 我想这里的关键词是我强调的部分(移动数据网络接口从一开始就不会被跟踪,它不会出现在列表中。当我看到具有CELLULAR功能的那个时,我想那就是我要找的那个。我弄错了。那是一个不同的界面。我没有观察到它没有互联网功能。) 默认返回2个网络实例,如下:Network ID | Capabilities |
---|---|
525 | Transports: CELLULARCapabilities: IMS&NOT_METERED&TRUSTED&NOT_***&VALIDATED&NOT_ROAMING&FOREGROUND&NOT_CONGESTED&NOT_SUSPENDED |
767 | Transports: WIFICapabilities: NOT_METERED&INTERNET&NOT_RESTRICTED&TRUSTED&NOT_***&VALIDATED&NOT_ROAMING&FOREGROUND&NOT_CONGESTED&NOT_SUSPENDED |
请注意,CELLULAR one(ID:525)没有互联网功能,并且有 IMS(如果我从文档中正确理解,它指的是 GSM 网络)。 当我尝试将套接字绑定到此网络时,它显然失败了。 然后我调用了 requestNetwork() 方法,发现我收到了一个新的(第三个)网络实例:
Network ID | Capabilities |
---|---|
770 | Transports: CELLULARCapabilities: SUPL&INTERNET&NOT_RESTRICTED&TRUSTED&NOT_***&VALIDATED&NOT_ROAMING&FOREGROUND&NOT_CONGESTED&NOT_SUSPENDED |
使用这个,绑定可以无缝地工作。
【讨论】:
以上是关于Android - 绑定移动网络套接字时权限被拒绝(OkHttp.socketFactory(network.socketFactory))的主要内容,如果未能解决你的问题,请参考以下文章