go打包aar及flutter调用aar流程详解

 更新时间:2023年03月19日 10:06:15   作者:ClzSkywalker  
这篇文章主要为大家介绍了go打包aar及flutter调用aar流程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

一、目的

本篇文章的目的是记录本人使用flutter加载与调用第三方aar包。

二、背景

本人go后端,业余时间喜欢玩玩flutter。一直有一个想法,go可以编译为第三方平台的可执行程序,而flutter可以是一个用于开发跨平台UI的工具,如果开发一个程序,go用于后台服务,flutter只用于描绘UI,是否可以做到。

查询了下github上的开源项目,有几个类似的:

上述三个,大致都是将flutter做为一个跨平台的UI工具来进行使用(思源不是flutter),然后使用第三方语言实现基本业务逻辑。

三、流程

问题:

  • go如何打包为移动端的包
  • flutter如何调用该包

问题一:go如何打包为移动端的包

1.环境配置

第一步需要解决的是环境配置,想打包安卓的包,肯定需要安卓的工具。

下载android studio

打开SDK Tools 工具库,安装NDK,请务必安装该版本:21.0.6113669

NDK解释:

Native Development Kit,是 Android的一个工具开发包

快速开发CC++的动态库,并自动将so和应用一起打包成 APK,即可通过NDKAndroid中 使用JNI与本地代码(如C、C++)交互

踩坑:默认安装是23最高版本,打包失败,请勾选show package details,会展开更加详细的NDK版本,务必下载21.0.6113669 版本!!!

2.go配置与打包

golang.org/x/mobile/cmd/gomobile

在项目中执行命令:

go build golang.org/x/mobile/cmd/gomobile
gomobile init

使用gomobile库可以将go程序打包为移动端的包

本项目程序截图:

在cmd/mobile中有一个kernel.go文件,该文件就是提供给移动端方法调用的入口StartKernel,里面是启动一个协程,该协程中会启动对应的http服务。

在我本地,我增加了一个构建安卓aar包的脚本

#!/usr/bin/env bash
# 构建移动端脚本
CRTDIR=$(pwd)
# 判断是否有output文件夹
if [ ! -d "${CRTDIR}/output" ]; then
  mkdir ${CRTDIR}/output
fi
# gomobile bind [-target android|ios|iossimulator|macos|maccatalyst] [-bootclasspath <path>] [-classpath <path>] [-o output] [build flags] [package]
# gomobile bind ./kernel/
gomobile bind -target=android -o=./output/mobile.aar -ldflags '-s -w'  ./cmd/mobile

执行该脚本,本地output会生成两文件:

  • mobile-sources.jar -- 具体实现的可以看该包,内部提供了一些静态本地方法
  • mobile.aar -- 我们真正需要的包

mobile-sources.jar内容:

// Code generated by gobind. DO NOT EDIT.
// Java class mobile.Mobile is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java github.com/clz.skywalker/event.shop/kernal/cmd/mobile
package mobile;
import go.Seq;
public abstract class Mobile {
	static {
		Seq.touch(); // for loading the native library
		_init();
	}
	private Mobile() {} // uninstantiable
	// touch is called from other bound packages to initialize this package
	public static void touch() {}
	private static native void _init();
	public static native void startKernel(long port, long local, String mode, String dbPath, String logPath);
}

好了,现在我们已经拿到了aar包了。

问题二:flutter如何调用aar

找半天文章,没有看到flutter直接调用aar包,如果你找到了请告诉我。

我现在的解决方案是参考官网的:用写插件的方式去实现,安卓加载aar,然后flutter再调用。

第一步:存放aar与修改gradle配置

在android文件夹下的app/libs 中放入mobile.aar文件,如果没有libs文件夹的话就创一个。

编辑app/build.gradle文件,增加如下代码:

dependencies {
    // implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    // implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
    // implementation files('libs/kernel.aar')
    implementation(name:'mobile',ext:'aar')
}

注释的是本人尝试后有问题的使用方式,本人非安卓开发人员,不是很清楚为什么不能那么使用,如果你知道的话可以告诉下我,没有注释的是本人亲试没问题的加载方式。

第二步:修改MainActivity.java入口代码

参考该文章,实现 configureFlutterEngine 方法,通过向 configureFlutterEngine 注册方法,可以实现调用native的方法。

MethodChannel的名字与flutter代码约定好,必须一模一样。

package github.com/ClzSkywalker;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.NonNull;
import java.util.Objects;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;
// 引入go打包的aar库
import mobile.Mobile;
public class MainActivity extends FlutterActivity {
    // 约定通道的名称,flutter可以通过通道名调用对应的方法
    private static final String CHANNEL = "kernel.startKernel";
    private static boolean kernelIsRunning = false;
    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
      GeneratedPluginRegistrant.registerWith(flutterEngine);
      new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
              .setMethodCallHandler(
                      (call, result) -> {
                          if (call.method.contentEquals("startKernel")) {
                            if (kernelIsRunning) {
                              result.success("");
                              return;
                            }
                            long port= Long.parseLong(Objects.requireNonNull(call.argument("port")).toString());
                              long local= Long.parseLong(Objects.requireNonNull(call.argument("local")).toString());
                              String mode= Objects.requireNonNull(call.argument("mode")).toString();
                              String dbPath= Objects.requireNonNull(call.argument("dbPath")).toString();
                              String logPath= Objects.requireNonNull(call.argument("logPath")).toString();
                              new Thread(() -> {
                                  // 调用aar中的方法
                                  Mobile.startKernel(port,local,mode,dbPath,logPath);
                              }).start();
                            kernelIsRunning=true;
                            result.success("");
                          }else{
                              result.notImplemented();
                          }
                      }
              );
  }
}

第三步:flutter调用

简短写一下,调用还是挺简单的,MethodChannel("name"),name的名字必须要与java中约定的通道名称一致。

    static const channel = MethodChannel('kernel.startKernel');
    kernelMap['port'] = 4935;
    kernelMap['local'] = 0;
    if (kDebugMode) {
      kernelMap['mode'] = 'test';
    } else {
      kernelMap['mode'] = 'release';
    }
    kernelMap['dbPath'] = dirPath;
    kernelMap['logPath'] = logPath.path;
    await channel.invokeMethod<void>('startKernel', kernelMap);

四、结论

总的来说难度没有那么大,在过去的时候尝试过类似操作,不过一直想的是flutter直接调用第三方平台库,错误的思路实现起来阻塞重重。

如果要调用第三方库,可以尝试做成一个flutter插件。

以上就是go打包aar及flutter调用aar流程详解的详细内容,更多关于go打包aar flutter调用aar的资料请关注脚本之家其它相关文章!

相关文章

  • Golang使用协程实现批量获取数据

    Golang使用协程实现批量获取数据

    服务端经常需要返回一个列表,里面包含很多用户数据,常规做法当然是遍历然后读缓存。使用Go语言后,可以并发获取,极大提升效率,本文就来聊聊具体的实现方法,希望对大家有所帮助
    2023-02-02
  • 一文带你深入了解Golang中的Mutex

    一文带你深入了解Golang中的Mutex

    这篇文章主要为大家详细介绍了Golang中Mutex的相关知识,知其然,更要知其所以然。文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2023-03-03
  • Golang爬虫框架 colly的使用

    Golang爬虫框架 colly的使用

    本文主要介绍了Golang爬虫框架 colly的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 使用go mod导入本地自定义包问题

    使用go mod导入本地自定义包问题

    这篇文章主要介绍了使用go mod导入本地自定义包问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • 详解如何使用Golang实现Cron定时任务

    详解如何使用Golang实现Cron定时任务

    定时任务是许多应用程序中常见的一种需求,它们可以用于执行定期的清理任务,发送通知,生成报告等,在这篇博客中,我们将介绍如何在Go语言中使用robfig/cron包来实现Cron定时任务,需要的朋友可以参考下
    2024-04-04
  • Go基于struct tag实现结构体字段级别的访问控制

    Go基于struct tag实现结构体字段级别的访问控制

    本文将会基于这个主题展开,讨论Go中的结构体tag究竟是什么,我们该如何利用它,另外,文末还提供了一个实际案例,实现结构体字段级别的访问,帮助我们进一步提升对struct tag的理解
    2024-02-02
  • 深入探究Go语言中for range语句

    深入探究Go语言中for range语句

    为了更加便捷地遍历这些数据类型,Go语言引入了for...range语句,本文将以数组遍历为起点,逐步介绍for...range语句在不同数据类型中的应用,希望对大家有所帮助
    2023-06-06
  • Go中Context使用源码解析

    Go中Context使用源码解析

    这篇文章主要为大家介绍了Go中Context使用源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Go语言使用Json的方法实现

    Go语言使用Json的方法实现

    本文主要介绍了Go语言使用Json的方法实现
    2024-05-05
  • 详解go语言判断管道是否关闭的常见误区

    详解go语言判断管道是否关闭的常见误区

    这篇文章主要想和大家一起探讨一下在Go语言中,我们是否可以使用读取管道时的第二个返回值来判断管道是否关闭,文中的示例代码讲解详细,有兴趣的可以了解下
    2023-10-10

最新评论