android - 在 Android 上使用网络

标签 android go

我一直在尝试让 Go 应用程序在 Android 10 上运行并遇到了障碍。我很确定我现在知道为什么我会遇到这个障碍,但不知道如何解决它。首先,简单的事情适用于交叉编译。例如,

package main
import "fmt"
func main() {
    fmt.Println("Hello, Android!")
}
GOARM=arm64 GOOS=linux go build 编译会运行得很好
但是现在如果我添加一些网络代码:
package main

import (
    "fmt"
    "net/http"
    "io/ioutil"
)

func main() {
    fmt.Println("Hello, Android!")
    client := &http.Client{}
    resp, err := client.Get("https://www.google.com")
    if err != nil {
        fmt.Println(err)
        return
    }
    bodyBytes, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("%s", bodyBytes)
}
并以与运行相同的方式编译,但我会收到如下错误:
Get "https://www.google.com": dial tcp: lookup www.google.com on [::1]:53: read udp [::1]:47618->[::1]:53: read: connection refused
最初我认为这是我的 Android 设备上的一些网络配置,但经过大量的困惑之后,我很确定这与 Android 网络“不同”的事实有关。也许这是仿生 vs libc 的事情(?)但至少有其他人似乎已经击中了 same snag并通过使用 NDK 附带的工具链进行构建来解决。
有谁知道如何真正让它发挥作用?
最初我希望它像 GOOS=android GOARCH=arm64 go build 一样简单但这失败了:
# command-line-arguments
/usr/lib/golang/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: /tmp/go-link-384615804/go.o: Relocations in generic ELF (EM: 183)
<bunch of these>
/usr/bin/ld: /tmp/go-link-384615804/go.o: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status
一些谷歌搜索出现 https://github.com/golang/go/issues/30216 - 这表示您需要明确启用 CGO。但是GOARCH=arm64 GOOS=android CGO_ENABLED=1 go build仍然失败,这次是:
# runtime/cgo
gcc_android.c:6:10: fatal error: android/log.h: No such file or directory
    6 | #include <android/log.h>
      |          ^~~~~~~~~~~~~~~
compilation terminated.
我弄乱了很多其他组合,最接近的是在我的 NDK 安装中指向编译器。基本上类似于 GOARCH=arm64 GOOS=android CC=$NDKROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc CGO_ENABLED=1 CGO_CFLAGS="--sysroot $NDKROOT/sysroot -I$NDKROOT/sysroot/usr/include/arm-linux-androideabi/" go build .但这失败了:
# runtime/cgo
In file included from _cgo_export.c:4:0:
cgo-gcc-export-header-prolog:25:14: error: size of array '_check_for_64_bit_pointer_matching_GoInt' is negative
我指向编译器的方式有问题 - 例如,如果不指定 sysroot,我将找不到任何头文件 (stdlib.h),即使那样它也找不到特定于体系结构的包含 (asm/types.h)。 h) 没有指定额外的包含路径。所以错误可能是架构和编译器之间的不匹配,我只是不确定在哪里或如何修复它。
如果您已阅读所有这些内容,谢谢!一些额外的信息:
  • 去版本:1.14.13 linux/amd64
  • NDK 版本:r16b

  • 我也看过类似 gomobile 的东西但这似乎更适合构建 Android 应用程序(如 apks),尽管我可能在这里遗漏了一些东西。

    最佳答案

    弄清楚了!好吧,让我的具体示例工作,但我不确定为什么会这样。答案基本上来自https://github.com/golang/go/issues/20755你必须:

  • 构建独立版本的 NDK(执行此操作的 Python 脚本中的注释说它以更方便的方式将其打包以供其他工具使用)
  • 使用 NDK 中的交叉编译器重建 Go 的标准库
  • 使用 NDK 交叉编译器构建您的应用程序。

  • 所以对于我的例子:
    $ $(NDKROOT)/build/tools/make_standalone_toolchain.py --arch arm64 --api 24 --install-dir $(HOME)/ndk_standalone
    $ CC=$(HOME)/ndk_standalone/bin/clang CXX=$(HOME)/ndk_standalone/bin/clang GOOS=android GOARCH=arm64 go install std
    $ CC=$(HOME)/ndk_standalone/bin/clang CXX=$(HOME)/ndk_standalone/bin/clang GOOS=android GOARCH=arm64 CGO_ENABLED=1 go build
    
    和网络工作!
    我不太确定为什么(或如果)clang 与直接调用编译器不同。也许我会更多地玩这个。此外,在编译我的应用程序时(但不是为 go std 库),我仍然必须显式启用 CGO,否则链接失败。

    关于android - 在 Android 上使用网络,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65366107/

    相关文章:

    mysql - Google 是否不鼓励使用第 3 方 Go 驱动程序来使用云 sql?

    go - 为什么类型断言在一种情况下有效,而在另一种情况下无效?

    string - 如何使用 Go 将格式化字符串打印到标准输出中的同一行?

    go - 微服务中提取载体未找到SpanContext

    mysql - MySql 的 Golang ORDER BY 问题

    android Json Volley 如何创建界面

    android - setCurrentTab 不工作

    android - 添加日历时出现Android异常

    java - 每 x 分钟调用一个方法

    java - 在Android中如何检查设备是否有前置闪光灯(Camera2 API)