Android调用go语言 - 详细版
Posted 大雄童鞋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android调用go语言 - 详细版相关的知识,希望对你有一定的参考价值。
android调用go语言就一句话:Android Studio 引入go代码打包的aar进行代码调用
准备工作:
Android 方面:
1、JDK环境
2、Android SDK
3、Android NDK
Go方面:
1、Golang环境
2、gomobile安装
Android方面JDK,SDK,NDK我就不说了,注意环境变量配置的时候,不要出错(比如空格)
安装好后,dos中分别执行 java;javac;java -version 来验证JDK环境配置成功与否,避免后面打包aar出问题。
SDK和NDK基本不需要怎么配置,指定路径即可。
go方面Golang的安装也很简单,下载安装并配置环境变量(安装的时候会自动配置好)即可
gomobile由于翻墙问题,我们就自己配置了。
具体操作如下(本人使用的是Windows10,此教程也是win10环境下的):
首先先搭建Android环境:
环境变量:(%JAVA_HOME%代表引用JAVA_HOME的地址)
JAVA_HOME : E:\\Java\\jdk1.8.0_161
CLASSPATH : .;%JAVA_HOME%\\lib;%JAVA_HOME%\\lib\\tools.jar
PATH: %JAVA_HOME%\\bin;%JAVA_HOME%\\jre\\bin;
- Android SDK + Android NDK
建议直接下载Android Studio 进行在线安装(File - > Setting - > Android SDK)
环境变量:
--- Android SDK ---
ANDROID_HOME: E:\\Android\\SDK
PATH: %ANDROID_HOME%\\platform-tools;%ANDROID_HOME%\\tools;
--- Android NDK ---
NDK_ROOT:E:\\Android\\SDK\\ndk-bundle
PATH:%NDK_ROOT%;
然后搭建Go环境:
- Golang下载安装(我安装在F盘Go文件夹下)
环境变量(安装后这些环境变量有些会自动配置好,检查下即可)
GOROOT: F:\\Go\\
GOBIN: F:\\Go\\bin
GOPATH: F:\\goWorks
- gomobile
自己手动配置:
1、下载go仓库的mobile项目
2、执行以下命令:
$ mkdir -p $GOPATH/src/github.com/golang
$ cd $GOPATH/src/github.com/golang
$ git clone https://github.com/golang/mobile.git
$ mkdir -p $GOPATH/src/golang.org/x
$ cp -r $GOPATH/src/github.com/golang/mobile $GOPATH/src/golang.org/x
cd $GOPATH/src/golang.org/x/mobile/cmd/gobind
$ go install //会在$GOPATH/bin 目录下生成gobind
$ cd $GOPATH/src/golang.org/x/mobile/cmd/gomobile
$ go install //会在$GOPATH/bin 目录下生成gomobile
$ gomobile init
gomobile init -ndk /usr/local/androidNDK/android-ndk-r20
由于这些命令是Linux命令,我们在Windows下,我就直接根据顺序手动操作了。
之前在安装Golang的时候指定了一个GOPATH: F:\\goWorks 路径,上面的$GOPATH 就是指我们这个路径。
(src/github.com/golang 即$GOPATH下新建src,src下新建github.com,github.com下新建golang)
- 在$GOPATH下新建 文件夹src/github.com/golang
- Dos中切换到src/github.com/golang路径下(cd F:\\goWorks\\src\\github.com\\golang)
- 通过git下载mobile (git clone https://github.com/golang/mobile.git),之前下载过,复制进来即可
- 在$GOPATH下新建文件夹/src/golang.org/x
- 将mobile文件拷贝到/src/golang.org/x 下
- Dos中切换到gomobile下(cd F:\\goWorks\\src\\golang.org\\x\\mobile\\cmd\\gomobile)
- 执行go install //会在$GOPATH/src/bin 目录下生成gomobile.exe
- Dos中切换到gomobile下(cd F:\\goWorks\\src\\golang.org\\x\\mobile\\cmd\\gobind)
- 执行go install //会在$GOPATH/src/bin 目录下生成gobind.exe
- gomobile init -ndk D:\\Android\\SDK\\ndk-bundle
-----------------------------更新-----------------------------
- 路径更新
2018.5.4更新,今天看到mobile项目在3天前(即2018.5.1)更新了一个版本,所以我就重新下载了试试新版本的功能,发现执行了go build 和 go install 后,生成的gobind.exe 和gomobile.exe转移到了 F:\\Go\\bin目录下
同时aar包和jar包也转移到了 F:\\Go\\bin目录下,而不是之前的$GOPATH/src/bin目录。
- 支持的基本数据类型
经过测试,Java支持的基本类型有:float32 ,float64, uint8
不支持的类型有:uint,uint32,uint64
更多类型待更新。。。
初始化结束后是这样的:
这样,gomobile的配置就结束了。
下面你就可以编写Golang代码进行编译打包aar或者打包apk了。
其实我们下载的mobile项目中本身就有一些demo,可以直接使用的在mobile/example下
打包:首先cd 到 F:\\goWorks\\bin 目录,因为bin目录下有gobind.exe 和gomobile.exe,所以可以执行下面操作
--- 打包apk ---
gomobile build -target=android golang.org/x/mobile/example/basic
--- 打包aar ---
1、将example下的bind中的hello文件夹复制到src下面
2、gomobile bind -target=android hello
--------------------------------附加(真实项目实战):------------------------------
//cd 到 F:\\goWorks\\bin
//打aar包:gomobile bind -target=android github.com\\zx\\largezx
//其中largezx文件夹下要有一个largezx.go (go文件的名称要和文件夹一样)
//打包成功
将example下的bind中的hello文件夹复制到src下面,如图
打包之后就会在bin下生成aar文件或apk文件
最后就是Android Studio 里面的调用了。
1、把aar包放入libs中
2、配置app文件夹下的build.gradle文件
完整如下:
apply plugin: 'com.android.application'
android
compileSdkVersion 26
defaultConfig
applicationId "com.fzm.go"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild
cmake
cppFlags ""
buildTypes
release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
externalNativeBuild
cmake
path "CMakeLists.txt"
repositories
flatDir
dirs 'libs'
dependencies
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation(name: 'hello', ext: 'aar')
配置完后,就可以在External Libraries 中看到了。
客户端调用:
效果:
附加问题库:
问题一:
最开始我们引用了2个aar(hello 和largezx),两个项目引用同一个库可能有冲突
dependencies
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
//implementation(name: 'hello', ext: 'aar')
implementation(name: 'largezx', ext: 'aar')
如上,那么运行的时候就出错了:
错误如下:
Error:Execution failed for task ':app:transformNativeLibsWithMergeJniLibsForDebug'.
> More than one file was found with OS independent path 'lib/x86/libgojni.so'
问题二:打包出的aar包中go的方法不全
因为你执行gomobile bind -target=android github.com\\zx\\largezx
这个操作打包的时候会打出2个包:
aar包和jar包,如:largezx.aar和largezx-sources.jar
,当出现这个问题后,我去代码里面找相关的方法,发现无法编译成功的方法中都有一个类型: uint32,我就猜测是不是java不支持这个类型。
然后我查了查largezx-sources.jar里面的这个类发现了一行一行的错误:即
skipped const TypeAIB with unsupported type: uint32(不支持类型的跳过const类型:uTI32)
意思是:Java进行编译go语言的时候,不支持该类型,所以跳过编译操作了,那么打包里面肯定调用不了了。
编译源代码如下:
我们看jar包中的largezx.java文件:
// Java class bipwallet.Bipwallet is a proxy for talking to a Go program.
// gobind -lang=java gitlab.33.cn/wallet/bipwallet
//
// File is generated by gobind. Do not edit.
package largezx;
import go.Seq;
public abstract class largezx
static
Seq.touch(); // for loading the native library
_init();
private Largezx() // uninstantiable
// touch is called from other bound packages to initialize this package
public static void touch()
private static native void _init();
// skipped const Types with unsupported type: uint32
// skipped function method1 with unsupported parameter or return types
// skipped function methodAddress with unsupported parameter or return types
可以发现跳过了好多类型,另外测试了下uint, uint64等都不支持,解决办法是让go开发人员把方法包装一下,入参和返回参数都设置成常用类型:string, int等。
问题三:go语言返回值可以有多个,但是Java只能有1个返回值,所以go语言想要给Java编译调用,必须要避免多返回值的情况
不然就会报如下错:
functions and methods must return either zero or one values, and optionally an error
下面看看多个返回值的方法:
func TestMehtod(index int) (priv, pub []byte, err error)
return priv, pub, err
解读下:入参:index(int类型),返回值 priv,pub,err
上面的写法等同于:
func TestMehtod(index int) (priv []byte, pub []byte, err error)
return priv, pub, err
解决办法:拆分go方法,避免多返回类型
拓展:该方法需要指定对象调用,什么意思?
如下代码:
func (w *HDWallet) TestMehtod(index int) (pub []byte, err error)
return pub, err
那么怎么调用TestMehtod呢?
调用如下:
pub, err := wallet.TestMehtod(index) (即想调用该方法必须先拿到wallet对象,用wallet进行调用。)
那么怎么解决呢?
很简单,我们提供一个方法,先拿到wallet,
最后总结一下:
1、不能使用java不支持的数据类型,比如uint32
2、不能使用多返回值
3、Android引用多个aar包注意资源重复
附加在Android Sudio中编写go代码并编译调用和go语言语法的熟悉
1、用Go语言写Android应用 (1) - 用Go写本地应用
2、用Go语言写Android应用 (2) - 从Android的Java调用Go代码
3、用Go写Android应用(3) - Go语言速成
附加:可以在工具里面直接打包
也可以直接在walletapi下面执行:gomobile bind -target=android即可。
新增注意点:
gomobile bind -target=android gitlab\\wallet\\syncstockapi
这样是会有问题的,应该换为(斜杠的问题)
gomobile bind -target=android gitlab/wallet/syncstockapi
另外如果你的项目下有2个包,也可以打成一个包:
//后面的路径用空格隔开即可
D:\\goWorks\\src>gomobile bind -target=android gitlab/wallet/syncstockapi gitlab/wallet/walletapi
这样打出来的包里面就会有2个api
温馨提示2
注意:所有下载的包都会默认放在GOPATH,因此这个目录是必须的,且一般包含src pkg bin三个目录,分别存放源码包,编译包以及可执行文件
执行go build会报一个错误:
解决方法如下:
将mobile更换为2018年的mobile文件夹,新版本的mobile会出现这个问题
温馨提示3,
出现上面的问题,那么就需要在C盘中进行go build了,需要在C盘中创建go\\src\\golang.org\\x\\mobile文件夹然后拷贝mobile进来
如图。
温馨提示4,
这个报错是说当前的go支持的是15以上的,但是NDK却是最低只支持16以上的,所以解决方案就是把C:\\Users\\33\\go\\src\\golang.org\\x\\mobile\\cmd\\gomobile下的env.go里面进行修改到支持16以上即可。参考:
https://github.com/golang/go/issues/27265
var ndk = ndkConfig
"arm":
arch: "arm",
abi: "armeabi-v7a",
platform: "android-15",
gcc: "arm-linux-androideabi-4.9",
toolPrefix: "arm-linux-androideabi",
,
"arm64":
arch: "arm64",
abi: "arm64-v8a",
platform: "android-21",
gcc: "aarch64-linux-android-4.9",
toolPrefix: "aarch64-linux-android",
,
"386":
arch: "x86",
abi: "x86",
platform: "android-15",
gcc: "x86-4.9",
toolPrefix: "i686-linux-android",
,
"amd64":
arch: "x86_64",
abi: "x86_64",
platform: "android-21",
gcc: "x86_64-4.9",
toolPrefix: "x86_64-linux-android",
,
修改为:
var ndk = ndkConfig
"arm":
arch: "arm",
abi: "armeabi-v7a",
platform: "android-16",
gcc: "arm-linux-androideabi-4.9",
toolPrefix: "arm-linux-androideabi",
,
"arm64":
arch: "arm64",
abi: "arm64-v8a",
platform: "android-21",
gcc: "aarch64-linux-android-4.9",
toolPrefix: "aarch64-linux-android",
,
"386":
arch: "x86",
abi: "x86",
platform: "android-16",
gcc: "x86-4.9",
toolPrefix: "i686-linux-android",
,
"amd64":
arch: "x86_64",
abi: "x86_64",
platform: "android-21",
gcc: "x86_64-4.9",
toolPrefix: "x86_64-linux-android",
,
以上是关于Android调用go语言 - 详细版的主要内容,如果未能解决你的问题,请参考以下文章