前提需要了解的

gomobile

准备好Go代码

mobilego
mkdir code/mobilego
cd code/mobilego
echo export GOPATH=\$GOPATH:$(pwd) >> ~/.zshrc # .zshrc 为你的bash地址
source ~/.zshrc
code/mobilego
mobilego
└── src
    └── mobile
        └── mobile.go
mobile.go
package mobile

import "fmt"

func SayHello() {
      fmt.Println("Hello Mobile")
}

func SayHelloWithParams(name string) {
      fmt.Println("Hello", name)
}

func SayHelloWithParamsAndReturn(name string) string {
      return "Hello" + name
}

func SayHelloWithParamsAndReturnAndException(name string) (string, 
error) {
      return "Hello" + name, fmt.Errorf("some error")
}
mobile.goMobile
mobile.go

准备gomobile

https://github.com/golang/go/wiki/Mobile#tools
  1. 首先下载这个工具
go get golang.org/x/mobile/cmd/gomobile
golang.org/x/mobile/cmd/gomobilegolang.org/x/github.com/golang/
go get github.com/golang/mobile/cmd/gomobile

这时候你会发现,这个包下载到了GOPATH/github.com下面了。我们要把它拷贝到golang.org目录下面

mv $GOPATH/src/github.com/golang/mobile $GOPATH/src/golang.org/x/mobile 

然后重新执行:

go get golang.org/x/mobile/cmd/gomobile
gomobile version

编译go代码

这一步要把go代码编译成Android平台使用的机器码。gomobile是一个非常好用的工具,通过一个命令不仅能把go代码编译成平台码,同时还会使用aar包来包装它,也就是说,我们完全不用写恶心的native代码了,直接调用gomobile生成的Java代码就好了。

首先来到go项目目录下面,执行gomobile编译命令。gomobile需要NDK,再次确定一下是否安装NDK。

gomobile bind -target=android mobile.go
mobile.gomobile.aarmobile-sources.jarmobile.aar

Android调用Go

mobile.aarbuild.gradle

默认值:

implementation fileTree(dir: 'libs', include: ['*.jar'])

修改后:

implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])

Sync一下工程,通过Java测试一下我们的go代码。

internal class RunTask : AsyncTask<Void, Void, Any?>() {

    override fun doInBackground(vararg params: Void): Any? {
        Mobile.sayHello()
        Mobile.sayHelloWithParams("lecon")
        val result = Mobile.sayHelloWithParamsAndReturn("spawn")
        Log.d("AndroidGo",result)
        try {
            Mobile.sayHelloWithParamsAndReturnAndException("liucl")
        } catch (e:Exception) {
            e.printStackTrace()
        }
        return null
    }
}

运行结果:

2019-04-18 13:31:04.566 7925-7982/? D/AndroidGo: Hellospawn
2019-04-18 13:31:04.571 7925-7982/? W/System.err:     at mobile.Mobile.sayHelloWithParamsAndReturnAndException(Native Method)
2019-04-18 13:31:04.590 7925-7987/? I/GoLog: Hello Mobile
2019-04-18 13:31:04.590 7925-7987/? I/GoLog: Hello lecon

这时候,你也许会发现,这几行代码的执行顺序是不确定的。因为java和go通信是跨进程调用,这几个方法有几个log是在go中输出,就不能保证执行顺序。