diff --git a/android_api_level.go b/android_api_level.go new file mode 100644 index 0000000..a0a93e8 --- /dev/null +++ b/android_api_level.go @@ -0,0 +1,7 @@ +//go:build !(android && cgo) + +package anet + +func androidDeviceApiLevel() int { + return -1 +} diff --git a/android_api_level_cgo.go b/android_api_level_cgo.go new file mode 100644 index 0000000..992feee --- /dev/null +++ b/android_api_level_cgo.go @@ -0,0 +1,23 @@ +//go:build android && cgo + +package anet + +// #include +import "C" + +import "sync" + +var ( + apiLevel int + once sync.Once +) + +// Returns the API level of the device we're actually running on, or -1 on failure. +// The returned value is equivalent to the Java Build.VERSION.SDK_INT API. +func androidDeviceApiLevel() int { + once.Do(func() { + apiLevel = int(C.android_get_device_api_level()) + }) + + return apiLevel +} diff --git a/interface.go b/interface.go index 6064947..384f29c 100644 --- a/interface.go +++ b/interface.go @@ -27,5 +27,4 @@ func InterfaceAddrsByInterface(ifi *net.Interface) ([]net.Addr, error) { return ifi.Addrs() } -// Deprecated: Android version is detected automatically. func SetAndroidVersion(version uint) {} diff --git a/interface_android.go b/interface_android.go index 31c7ace..6b080c5 100644 --- a/interface_android.go +++ b/interface_android.go @@ -1,8 +1,5 @@ package anet -// #include -import "C" - import ( "bytes" "errors" @@ -19,6 +16,7 @@ const ( ) var ( + customAndroidApiLevel = -1 errInvalidInterface = errors.New("invalid network interface") errInvalidInterfaceIndex = errors.New("invalid network interface index") errInvalidInterfaceName = errors.New("invalid network interface name") @@ -125,6 +123,31 @@ func InterfaceAddrsByInterface(ifi *net.Interface) ([]net.Addr, error) { return ifat, err } +// SetAndroidVersion set the Android environment in which the program runs. +// The Android system version number can be obtained through +// `android.os.Build.VERSION.RELEASE` of the Android framework. +// If version is 0 the actual version will be detected automatically if possible. +func SetAndroidVersion(version uint) { + switch { + case version == 0: + customAndroidApiLevel = -1 + case version >= 11: + customAndroidApiLevel = android11ApiLevel + default: + customAndroidApiLevel = 0 + } +} + +func androidApiLevel() int { + if customAndroidApiLevel != -1 { + // user-provided api level should be used + return customAndroidApiLevel + } + + // try to autodetect api level + return androidDeviceApiLevel() +} + // An ipv6ZoneCache represents a cache holding partial network // interface information. It is used for reducing the cost of IPv6 // addressing scope zone resolution. @@ -417,18 +440,3 @@ func nameToFlags(name string) (net.Flags, error) { return linkFlags(*(*uint32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ]))), nil } - -// Returns the API level of the device we're actually running on, or -1 on failure. -// The returned value is equivalent to the Java Build.VERSION.SDK_INT API. -var androidApiLevel = func() func() int { - var apiLevel int - var once sync.Once - - return func() int { - once.Do(func() { - apiLevel = int(C.android_get_device_api_level()) - }) - - return apiLevel - } -}()