調研: GoMobile SDK 在 iOS 與 Android 上的集成與邊界

問題java

在手機應用的開發中,一般會將複雜的業務邏輯層實現放在服務端,客戶端僅負責表現層。可是對於某些手機應用而言,業務邏輯的實現位於服務端反而是不安全的或是不合理的,而是須要將其邏輯直接在手機端實現。android

目的ios

面對不一樣系統的手機客戶端,單獨重複實現相同的業務邏輯,並不是最佳實踐。如何經過第三方語言 Go 語言將業務邏輯封裝成庫的形式,並以靜態打包的方式提供給不一樣系統的手機客戶端使用,是本次調研的目的。git

理想目標圖:github

具體調研內容包括:golang

其中關於 gRPC 在 iOS 與 Android 的實現,自己官方就已經提供了樣例。本次調研會用到相關內容,因此將其做爲調研的一部分記錄下來,方便後來者閱讀。調研中全部涉及的項目代碼均存放於: grpc-apps 倉庫中, 須要的朋友能夠直接下載測試。sql

1. 環境安裝

1.1 GoMobile 工具安裝

首先保證開發環境處於"全球通"狀態,保證順利安裝相關依賴包與工具。數據庫

注意: GoMobile 不支持最新的 Go Module 包依賴功能,因此建議在開始本教程以前, 執行 export GO111MODULE=off 關閉 Go Module 功能。編程

經過如下命令直接源碼安裝swift

$: go get golang.org/x/mobile/cmd/gomobile 
$: gomobile -h
Usage:

	gomobile command [arguments]

Commands:

	bind        build a library for Android and iOS
	build       compile android APK and iOS app
	clean       remove object files and cached gomobile files
	init        build OpenAL for Android
	install     compile android APK and install on device
	version     print version
複製代碼

從命令輸出可以看出,gomobile 可以經過子命令build直接構建不一樣系統的客戶端應用,還能夠經過子命令bind構建支持不一樣系統的開發庫。基於本次調研的目的,主要使用bind子命令生成相應平臺的SDK。

1.2 iOS 工具安裝

XCode 安裝是必備的,請參考:iOS 應用實現 gRPC 調用

若是使用gomobile生成 iOS SDK,還須要安裝Command Line Tools for XCode工具, 直接經過開發者帳號登陸蘋果官網上下載.

安裝完成後執行:

$: xcode-select -s /Applications/Xcode.app/
複製代碼

1.3 Android 工具安裝

Android Studio 安裝是必備的,請參考:Android 應用實現 gRPC 調用

若是使用gomobile生成 Android SDK,還須要安裝 Android NDK 環境。未安裝時會報如下錯誤:

$: gomobile bind -target=android github.com/liujianping/golib
gomobile: no Android NDK found in $ANDROID_HOME/ndk-bundle nor in $ANDROID_NDK_HOME
複製代碼

打開 Android Studio,進入Tools > Android > SDK Manager 勾選安裝:

  • LLDB
  • CMAKE
  • NDK

過程有點慢,耐心等待。完成安裝後,設置環境變量便可。

export ANDROID_HOME=~/Library/Android/sdk/
export ANDROID_NDK_HOME=$ANDROID_HOME/ndk-bundle
複製代碼

2. Go SDK 樣例實現

在官方的GoMobile/Wiki上,安裝包內就已經提供了最簡單的樣例代碼了,能夠直接使用。由於是現成的代碼,缺乏過程,因此這裏仍是從頭開始建立,記錄過程。

2.1 Golib 實現

首先建立一個新的本地 Go 項目:Golib, 具體代碼放在Golib中。

$: mkdir -p $GOPATH/src/github.com/liujianping/golib
$: cd $GOPATH/src/github.com/liujianping/golib
$: cat <<EOF > golib.go
package golib

import (
	"errors"
	"fmt"
)

func Greetings(name string) string {
	return fmt.Sprintf("Hello, %s!", name)
}

func NumberError(num int) (int, error) {
	if num >= 10 {
		return 0, errors.New("num > 10")
	}
	return num, nil
}
EOF

複製代碼

這個樣例程序比官方的多了一個函數NumberError實現。由於真實項目必定會存在異常處理,因此增長這個函數順便調研一下。

若是前一節的環境所有都安裝成功的話,如今咱們就能夠生成相應平臺的SDK了。

2.2 生成 iOS SDK

生成 iOS SDK 過程很簡單:

$: gomobile bind -target=ios github.com/liujianping/golib
$: ls
Golib.framework  golib.go  
複製代碼

完成命令後,在當前目錄下就生成了Golib.framework的目錄,固然也能夠經過指定-o設置輸出路徑。

2.3 生成 Andorid SDK

Android SDK 的生成過程,一樣很簡單:

$: gomobile bind -target=android github.com/liujianping/golib
$: ls
golib-sources.jar  golib.aar  Golib.framework  golib.go  
複製代碼

不一樣的是,android 平臺生成的是 jararr 兩個包。具體 jararr 包的區別,貼下 google 的結果:

The main difference between a Jar and a AAR is that AARs include resources such as layouts, drawables etc. This makes it a lot easier to create self-contained visual components.

3. GoMobile SDK 的集成

3.1 在 iOS 上集成

打開iOS 應用實現 gRPC 調用中建立的項目,將Golib.framework拖拽到項目中。

打開ViewController.swift文件:

import UIKit
import Golib


class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // gRPC client
        ...
        
        // golib
        let reply = GolibGreetings("JayL")
        print("golib reply: \(reply)")

        // golib error
        var err1: NSError?
        var num: Int = 0
        GolibNumberError(11, &num, &err1)
        print("golib num: \(num), err: \(err1)")
    }

}
複製代碼

從新編譯並執行測試項目,在控制檯輸出得出預期結果。完成 iOS 上集成 GoMobile SDK的集成。

3.2 在 Android 上集成

在 Android 上集成沒有 iOS 上拖拽那麼簡單, 能夠按如下步驟經過新建一個新Module的方式將 Golib SDK 導入到項目中。

打開Android 應用實現 gRPC 調用中建立的項目,執行 File -> New -> NewModule菜單建立一個新的 Module golib。再打開 Module: appGradle文件,引入 Module: golib, 即增長項目依賴: implementation project(":golib")。以下圖:

完成上面步驟,就能夠在代碼中引用該 SDK 了。 打開主實現 java 文件:

String goLib_hello = Golib.greetings("GoLib Hello");
	Log.i("golib", goLib_hello);

	try {
		long l = Golib.numberError(11);
		Log.i("golib", Long.toString(l));
	}
	catch (Exception e) {
		Log.e("golib", e.getMessage());
	}
複製代碼

設置不一樣的Golib.numberError(11)輸入參數,查看控制檯的輸出狀況。完成 Android 上集成 GoMobile SDK的集成。

4. GoMobile SDK 功能邊界

完成了 GoMobile SDK 的集成工做, 如今看看它能作什麼。

4.1 日誌打印

在 GoMobile SDK 上的日誌輸出是否能夠正常的在 iOS 與 Android 平臺正常輸出,不妨在 Golib 的實現上增長 log.Println 輸出。

經過驗證,GoMobile SDK 上的日誌輸出在 iOS 與 Android 上能夠正常輸出。有了日誌輸出就能夠很是方便的調試 GoMobile SDK 的具體功能了。

4.2 文件系統

不一樣的手機系統平臺,第三方應用的文件目錄存儲路徑不同的。因此,具體路徑仍是讓上層調用代碼做爲參數傳入比較合理。

在 golib 實現庫中增長目錄枚舉函數,並增長日誌:

package golib

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
)

func WalkDirectory(path string) error {
	return filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			log.Println("walk fn failed: ", err)
			return err
		}
		log.Printf("walked file or dir: %q\n", path)
		return nil
	})
}
複製代碼

從新編譯生成對應平臺的SDK,再集成測試。

4.3 數據存儲

大部分手機應用的本地數據存儲都會使用sqlite做爲數據庫存儲。因此就sqlite再GoMobile SDK 中的實現進行調研。

$: get get github.com/mattn/go-sqlite3
複製代碼

能夠直接取github.com/mattn/go-sqlite3倉庫中的樣例代碼進行實驗。具體代碼請參考:golib/sqlite.go

編譯從新集成測試可知,在 GoMobile SDK在 iOS/Android實現 sqlite 的功能可行。

4.4 網絡操做

網絡操做是最不須要驗證的功能了,SDK 中徹底能夠將手機應用的網絡操做所有封裝到其中。

小結

本文僅僅是對 GoMobile SDK 在集成與邊界的簡單驗證,提供一套解決手機應用混合編程的新思路。雖然可以完成本次調研的預期目的,可是若是須要用於生產環境中,請進行更多的功能驗證。

相關文章
相關標籤/搜索