Golang中GOMOBILE在Android 19以上版本的权限问题
Golang中GOMOBILE在Android 19以上版本的权限问题 这个问题已经存在相当长一段时间了,并且在其他上下文中被多次提出,例如这里:
x/mobile: Calling net.InterfaceAddrs() fails on Android SDK 30
到目前为止还没有解决方案。我想知道,如果这个问题不能在不久的将来得到解决,因为它会妨碍在 Android 下正确使用 GOMOBILE 模块的网络功能。这是一个由 API 30 引入的权限问题,影响所有运行 GOMOBILE 且 Android 版本大于 10 的设备。
在我的案例中,这个问题在我使用基于 PION GO WebRtc 的 LiveKit GO SDK 时出现。
目前没有已知的解决办法。
I/GoLog: "msg"="could not create answer" "error"="failed to create network: route ip+net: netlinkrib: permission denied"
I/GoLog: "msg"="could not set remote description" "error"="failed to create network: route ip+net: netlinkrib: permission denied"
I/GoLog: "msg"="could not add ICE candidate" "error"="failed to create network: route ip+net: netlinkrib: permission denied"
I/GoLog: "msg"="could not add ICE candidate" "error"="failed to create network: route ip+net: netlinkrib: permission denied"
更多关于Golang中GOMOBILE在Android 19以上版本的权限问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
抱歉,标题有笔误。应该是 Android > 10。
更多关于Golang中GOMOBILE在Android 19以上版本的权限问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个在Android 10(API 29)及以上版本中确实存在的权限限制问题。从Android 10开始,应用对网络接口信息的访问受到了更严格的限制,导致net.InterfaceAddrs()等网络相关调用在非系统应用中会失败。
问题的核心是Android的权限模型变更。在API 29+中,普通应用无法直接访问/proc/net目录和网络路由表,而Go的net包在Android上正是通过这些系统文件来获取网络信息的。
目前可以通过以下两种方式解决:
1. 使用Android的Network API(推荐)
在Go代码中通过JNI调用Android的ConnectivityManager来获取网络信息:
// +build android
package main
/*
#include <jni.h>
#include <stdlib.h>
*/
import "C"
import (
"net"
"unsafe"
)
// 通过JNI获取网络接口信息
func getNetworkInterfaces() ([]net.IP, error) {
// 获取Android上下文
ctx := getAndroidContext()
// 调用ConnectivityManager获取活动网络信息
jniEnv := getJNIEnv()
// 获取ConnectivityManager实例
connectivityManager := getConnectivityManager(jniEnv, ctx)
// 获取活动网络信息
networkInfo := getActiveNetworkInfo(jniEnv, connectivityManager)
// 解析IP地址
return parseNetworkAddresses(jniEnv, networkInfo)
}
// 实际的JNI调用实现
func getActiveNetworkInfo(env *C.JNIEnv, cm C.jobject) C.jobject {
// JNI调用ConnectivityManager.getActiveNetworkInfo()
// 这里需要完整的JNI实现
return nil
}
2. 修改Go标准库的net包实现
创建一个自定义的net包实现,避免使用受限的系统调用:
// custom_net_android.go
// +build android
package customnet
import (
"errors"
"net"
"syscall"
)
// 重写InterfaceAddrs函数
func InterfaceAddrs() ([]net.Addr, error) {
// 尝试使用Android的NetworkCapabilities API
addrs, err := getAddressesViaAndroidAPI()
if err == nil {
return addrs, nil
}
// 回退到有限的信息获取
return getLimitedAddresses()
}
func getAddressesViaAndroidAPI() ([]net.Addr, error) {
// 实现通过JNI调用Android Network API的逻辑
// 获取ConnectivityManager -> Network -> LinkProperties -> LinkAddresses
return nil, errors.New("not implemented")
}
func getLimitedAddresses() ([]net.Addr, error) {
// 返回基本的本地地址(如127.0.0.1)
return []net.Addr{
&net.IPNet{
IP: net.IPv4(127, 0, 0, 1),
Mask: net.CIDRMask(8, 32),
},
}, nil
}
3. 对于WebRTC的具体解决方案
对于使用Pion WebRTC的情况,可以设置ICE服务器配置来避免网络探测:
package main
import (
"github.com/pion/webrtc/v3"
)
func createWebRTCConfig() webrtc.Configuration {
return webrtc.Configuration{
ICEServers: []webrtc.ICEServer{
{
URLs: []string{"stun:stun.l.google.com:19302"},
},
},
ICETransportPolicy: webrtc.ICETransportPolicyRelay, // 强制使用中继
}
}
func main() {
config := createWebRTCConfig()
// 创建PeerConnection时使用配置
peerConnection, err := webrtc.NewPeerConnection(config)
if err != nil {
// 处理错误
}
// 设置ICE候选收集策略
peerConnection.SetICECandidateFilter(func(c webrtc.ICECandidate) bool {
// 只允许中继类型的候选
return c.Typ == webrtc.ICECandidateTypeRelay
})
}
4. 在AndroidManifest.xml中添加权限
确保在Android清单文件中声明必要的权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- 对于API 29+ -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"
android:maxSdkVersion="28" />
这个问题确实影响了Go在Android上的网络功能使用,目前最可行的方案是通过JNI桥接Android的原生网络API,或者调整应用逻辑以避免直接访问受限的网络接口信息。

