Slide 1

Slide 1 text

1 © 2012-2021 BASE, Inc. Flutter + Go で 組み合わせた モバイルアプリ開発  永野 峻輔(@glassmonekey) Go Conference2021 Spring

Slide 2

Slide 2 text

2 © 2012-2021 BASE, Inc. 自己紹介 所属 BASE BANK株式会社 Software Developer Go, PHP, Pythonあたりをよく書いています Go Conference 初参加です。 趣味 Flutterアプリ開発の勉強 締め切りに追われること アニメ鑑賞 / ウマ娘 SNS Twitter: @glassmonekey  Github: https://github.com/glassmonkey (永野 なので エターナルフィールドです) 永野 峻輔 (ながの しゅんすけ)

Slide 3

Slide 3 text

3 © 2012-2021 BASE, Inc. Today’s topic ● Why Flutter + gomobile ? ● What is Flutter ? ● What is gomobile ? ● Try Flutter + gomobile ● Conclustion

Slide 4

Slide 4 text

© 2012-2021 BASE, Inc. Why Flutter + gomobile?

Slide 5

Slide 5 text

5 © 2012-2021 BASE, Inc. Why Flutter + gomobile ? ● I want to reduce the difference between IOS and Android. ● I want to use the Go library when developing Flutter mobile app. ● Both Go and Flutter have wonderful development experience.

Slide 6

Slide 6 text

6 © 2012-2021 BASE, Inc. gomobile is experiments

Slide 7

Slide 7 text

© 2012-2021 BASE, Inc. What is Flutter?

Slide 8

Slide 8 text

8 © 2012-2021 BASE, Inc. What is Flutter ? Flutter is Google’s UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase. https://flutter.dev/

Slide 9

Slide 9 text

9 © 2012-2021 BASE, Inc. Flutter features ● Hot reload !!!!!! ● Declarative ● Multi Platform (Android, iOS, Web etc…) https://flutter.dev/docs/resources/architectural-overview

Slide 10

Slide 10 text

10 © 2012-2021 BASE, Inc. Hot reload demo https://www.youtuwbwfe.com/watch?v=sgPQklGe2K8

Slide 11

Slide 11 text

11 © 2012-2021 BASE, Inc. Flutter architecture https://flutter.dev/docs/resources/architectural-overview Using

Slide 12

Slide 12 text

12 © 2012-2021 BASE, Inc. Why Flutter Uses Dart? https://hackernoon.com/why-flutter-uses-dart-dd635a054ebf 2 ways compile ○ AOT (Ahead of time) ○ JIT (Just in time) Ecosystems ○ pub.dev (Plugin Repository ) ○ dart.pad (play ground) ○ etc….

Slide 13

Slide 13 text

13 © 2012-2021 BASE, Inc. Flutter + Native https://flutter.dev/docs/development/platform-integration/platform-channels Objective-C

Slide 14

Slide 14 text

14 © 2012-2021 BASE, Inc. Flutter + Native + Go(mobile) https://flutter.dev/docs/development/platform-integration/platform-channels Objective-C gomobile (SDK)

Slide 15

Slide 15 text

© 2012-2021 BASE, Inc. What is gomobile?

Slide 16

Slide 16 text

16 © 2012-2021 BASE, Inc. What is gomobile https://github.com/golang/mobile Tools to build mobile applications. ● Writing all-Go native mobile applications. ● Writing SDK applications by generating bindings from a Go package and invoke them from Java (on Android) and Objective-C (on iOS).

Slide 17

Slide 17 text

17 © 2012-2021 BASE, Inc. How to use gomobile https://github.com/golang/go/wiki/Mobile Go 1.15.8~ 😇 (cgo bug fixed) Android NDK, Android studio (Flutter / Android) Xcode (iOS) conditions $ go get golang.org/x/mobile/cmd/gomobile $ gomobile init

Slide 18

Slide 18 text

18 © 2012-2021 BASE, Inc. Remember... https://github.com/golang/go/issues/42655

Slide 19

Slide 19 text

© 2012-2021 BASE, Inc. Native Application

Slide 20

Slide 20 text

20 © 2012-2021 BASE, Inc. native applications https://github.com/golang/go/wiki/Mobile l $ go get -d golang.org/x/mobile/example/basic $ gomobile build -target=android \ golang.org/x/mobile/example/basic $ gomobile build -target=ios \ golang.org/x/mobile/example/basic Current version is not working 😇 Build for Android Initialize for Sample Application Build for iOS

Slide 21

Slide 21 text

21 © 2012-2021 BASE, Inc. Remember... https://github.com/golang/go/issues/42743

Slide 22

Slide 22 text

22 © 2012-2021 BASE, Inc. Waiting... https://go-review.googlesource.com/c/mobile/+/271926

Slide 23

Slide 23 text

23 © 2012-2021 BASE, Inc. Demo (Native Application)

Slide 24

Slide 24 text

© 2012-2021 BASE, Inc. SDK

Slide 25

Slide 25 text

25 © 2012-2021 BASE, Inc. Example code (Go) package example type Result struct { Message string } func (r Result) Run() (string, error) { return r.Message, nil }

Slide 26

Slide 26 text

26 © 2012-2021 BASE, Inc. For SDK applications https://github.com/golang/go/wiki/Mobile $ gomobile bind -target ios -o /path/to/file.framework source_dir $ export ANDROID_NDK_HOME=/path/to/ndk_dir $ gomobile bind -target android -o /path/to/file.aar source_dir Build for iOS Build for Android

Slide 27

Slide 27 text

27 © 2012-2021 BASE, Inc. Part of Java file package example; import ... public final class Result implements Proxy { ...(omitted)... public native string run() throws Exception public boolean equals(Object var1) {...} public int hashCode() {...} public String toString() {...} ...(omitted)... } func (r Result) Run() (string, error) { return r.Message, nil } Java Go

Slide 28

Slide 28 text

28 © 2012-2021 BASE, Inc. Part of Objective-C file … omit …. @class ExampleResult; @interface ExampleResult : NSObject { } @property(strong, readonly) _Nonnull id _ref; … omit …. @property (nonatomic) NSString* _Nonnull message; - (NSString* _Nonnull)run:(NSError* _Nullable* _Nullable)error; @end #endif func (r Result) Run() (string, error) { return r.Message, nil } Objective-C Go

Slide 29

Slide 29 text

29 © 2012-2021 BASE, Inc. Available types https://pkg.go.dev/golang.org/x/mobile/cmd/gobind - Signed integer and floating point types. - String and boolean types. - Byte slice types. Note that byte slices are passed by reference, and support mutation. - Any function type all of whose parameters and results have supported types. Functions must return either no results, one result, or two results where the type of the second is the built-in 'error' type. - Any interface type, all of whose exported methods have supported function types. - Any struct type, all of whose exported methods have supported function types and all of whose exported fields have supported types.

Slide 30

Slide 30 text

30 © 2012-2021 BASE, Inc. In Other Words … We can’t use Slices and Map 🥺🥺🥺…

Slide 31

Slide 31 text

31 © 2012-2021 BASE, Inc. Remember...

Slide 32

Slide 32 text

© 2012-2021 BASE, Inc. Try Flutter + Gomobile

Slide 33

Slide 33 text

33 © 2012-2021 BASE, Inc. Goal

Slide 34

Slide 34 text

34 © 2012-2021 BASE, Inc. Repository https://github.com/glassmonkey/flutter_with_golang

Slide 35

Slide 35 text

35 © 2012-2021 BASE, Inc. Use External LIbrary example expression, err := govaluate.NewEvaluableExpression("10 > 0"); result, err := expression.Evaluate(nil); // result is now set to "true", the bool value https://github.com/Knetic/govaluate Provides support for evaluating arbitrary C-like artithmetic/string expressions. govaluate

Slide 36

Slide 36 text

36 © 2012-2021 BASE, Inc. Development Flow ● Flutter setting ● Flutter + Native ○ Android ○ iOS ● gomobile setting ● gomobile + Native ○ Android ○ iOS I'll spare you the details of Flutter this time 🙏

Slide 37

Slide 37 text

© 2012-2021 BASE, Inc. Flutter settings

Slide 38

Slide 38 text

38 © 2012-2021 BASE, Inc. Flutter Project initilize $ flutter create ${PROJECT_NAME} $ mkdir -p ${PROJECT_NAME}/golang // Root Directory for Go 2. Create Flutter new project 1. Pass Flutter doctor $ flutter doctor [✓] Flutter (Channel stable, 2.0.4, on Mac OS X 10.15.7 19H524 darwin-x64, locale ja-JP) [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2) [✓] Xcode - develop for iOS and macOS [✓] Android Studio (version 4.0) Android NDK: 22.0.7026061 version 12.4 (12D4e)

Slide 39

Slide 39 text

39 © 2012-2021 BASE, Inc. Flutter + Native https://flutter.dev/docs/development/platform-integration/platform-channels

Slide 40

Slide 40 text

40 © 2012-2021 BASE, Inc. Pigeon ネイティブから逃げるな。Pigeonを使ったタイプセーフな Flutter + ネイティブ開発 https://qiita.com/glassmonkey/items/51d150da15ceeae a2960 Pigeon is a code generator tool to make communication between Flutter and the host platform type-safe and easier.
 For details https://pub.dev/packages/pigeon

Slide 41

Slide 41 text

41 © 2012-2021 BASE, Inc. Flutter Code evaluation(String text) async { final req = Request(); req.expression = text; final response = await this.client.eval(req); this.state = this.state.copyWith(text: response.message ?? "result"); } import 'package:pigeon/pigeon.dart'; class Request { late String expression; } class Response { late String message; } @HostApi() abstract class Api { Response eval(Request req); } iOS or Android Application Code Scheme for Pigeon

Slide 42

Slide 42 text

© 2012-2021 BASE, Inc. Flutter + Native(Android)

Slide 43

Slide 43 text

43 © 2012-2021 BASE, Inc. Configure Build Settings android { … omit … kotlinOptions { jvmTarget = '1.8' } … omit ... 2. Sync project gradle (Android studio) 1. edit app/build.gradle Pigeon uses calling to static methods in Java interfaces prohibited in JVM target 1.6.

Slide 44

Slide 44 text

44 © 2012-2021 BASE, Inc. Native Code (Kotlin) package nagano.shunsuke.flutter_with_golang import nagano.shunsuke.plugins.Pigeon class Api() : Pigeon.Api { override fun eval(arg: Pigeon.Request): Pigeon.Response { val response = Pigeon.Response() response.message = "fake"; // fake response return response } } Api.kt @HostApi() abstract class Api { Response eval(Request req); } Kotlin Flutter

Slide 45

Slide 45 text

45 © 2012-2021 BASE, Inc. Native Code (Kotlin) package nagano.shunsuke.flutter_with_golang import androidx.annotation.NonNull import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import nagano.shunsuke.plugins.Pigeon class MainActivity: FlutterActivity() { override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) Pigeon.Api.setup(flutterEngine.dartExecutor.binaryMessenger, Api()) } } MainActivety.kt

Slide 46

Slide 46 text

© 2012-2021 BASE, Inc. Flutter + Native(iOS)

Slide 47

Slide 47 text

47 © 2012-2021 BASE, Inc. Configure Build Settings 2. To be callable from swift 1. Add Pigeon files to Runner (Xcode) #import "GeneratedPluginRegistrant.h" #import "Pigeon.h" // add Runner-Bridging-Header.h

Slide 48

Slide 48 text

48 © 2012-2021 BASE, Inc. Native Code (Swift) import Foundation import API class Api: FlutterApi { func eval(_ input: FlutterRequest, error: AutoreleasingUnsafeMutablePointer) -> FlutterResponse? { let response = FlutterResponse() response.message = "fake" return response } } api.swift @HostApi() abstract class Api { Response eval(Request req); } Swift Flutter

Slide 49

Slide 49 text

49 © 2012-2021 BASE, Inc. Native Code (Swift) import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) let controller: FlutterViewController = window?.rootViewController as! FlutterViewController FlutterApiSetup(controller.binaryMessenger, Api()) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }

Slide 50

Slide 50 text

50 © 2012-2021 BASE, Inc. Progress

Slide 51

Slide 51 text

© 2012-2021 BASE, Inc. gomobile

Slide 52

Slide 52 text

52 © 2012-2021 BASE, Inc. Sample Project ├── android ├── golang │ ├── go.mod │ ├── go.sum │ └── pkg │ └── api ├── ios └── lib root directory for Go exported package to Native

Slide 53

Slide 53 text

53 © 2012-2021 BASE, Inc. Go for gomobile (Part) func Evaluate(formula string) (float64, error) { expression, err := govaluate.NewEvaluableExpression(formula) if err != nil { return 0, err } i := make(map[string]interface{}) result, err := expression.Evaluate(i) if err != nil { return 0, err } v, ok := result.(float64) if !ok { return 0, fmt.Error("invalid formula result.”) } return v, nil }

Slide 54

Slide 54 text

54 © 2012-2021 BASE, Inc. How to use gomobile https://github.com/golang/go/wiki/Mobile Go 1.15.8~ 😇 (cgo bug fixed) Android NDK, Android studio Xcode, etc... conditions $ go get golang.org/x/mobile/cmd/gomobile $ gomobile init

Slide 55

Slide 55 text

55 © 2012-2021 BASE, Inc. Build SDK applications $ gomobile bind -target ios -o ../ios/API.framework \ github.com/glassmonkey/flutter_with_golang/golang/pkg/api $ export ANDROID_NDK_HOME=/path/to/ndk_dir $ gomobile bind -target android -o ../android/API.aar \ github.com/glassmonkey/flutter_with_golang/golang/pkg/api Build for iOS Build for Android (Required Android NDK)

Slide 56

Slide 56 text

© 2012-2021 BASE, Inc. gomobile + Native(Android)

Slide 57

Slide 57 text

57 © 2012-2021 BASE, Inc. Configure Build Settings dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation (name:'API', ext:'aar') repositories { flatDir { dirs '../' } } 2. Sync project gradle (Android studio) 1. edit app/build.gradle

Slide 58

Slide 58 text

58 © 2012-2021 BASE, Inc. Part of Native Code (Kotlin) override fun eval(arg: Pigeon.Request): Pigeon.Response { val response = Pigeon.Response() return try { val result = Api.evaluate(arg.expression) response.message = result.toString() response } catch (e: Exception ) { response.message = e.toString() response } } Api.kt @HostApi() abstract class Api { Response eval(Request req); } Flutter func Evaluate(formula string) (float64, error) {...} Go

Slide 59

Slide 59 text

© 2012-2021 BASE, Inc. gomobile + Native(iOS)

Slide 60

Slide 60 text

60 © 2012-2021 BASE, Inc. Configure Build Settings 1. Build Phases > LinkBinary With Libraries 2. Add Files (API.framework)

Slide 61

Slide 61 text

61 © 2012-2021 BASE, Inc. Part of Native Code (Swift) func eval(_ input: FlutterRequest, error: AutoreleasingUnsafeMutablePointer) -> FlutterResponse? { let response = FlutterResponse() var result: Double = 0 var error: NSError? ApiEvaluate(input.expression, &result, &error) if error != nil { response.message = "\(error)" return response } response.message = "\(result)" return response } api.swift @HostApi() abstract class Api { Response eval(Request req); } Flutter func Evaluate(formula string) (float64, error) {...} Go

Slide 62

Slide 62 text

62 © 2012-2021 BASE, Inc. Result

Slide 63

Slide 63 text

© 2012-2021 BASE, Inc. Performance & Size

Slide 64

Slide 64 text

64 © 2012-2021 BASE, Inc. Setting 1. Run “Profile” 2. Flutter Performance → Open Dev tools

Slide 65

Slide 65 text

65 © 2012-2021 BASE, Inc. Dev tools

Slide 66

Slide 66 text

66 © 2012-2021 BASE, Inc. Performance when rebuild Flutter Flutter + Native + gomobile Draw Draw CPU Sampling rate (≒5s) clock_ gettime syscall syscall clock_ gettime I couldn't find any clear differences 🥺

Slide 67

Slide 67 text

67 © 2012-2021 BASE, Inc. FileSize (Demo) OS with gomobile (Yes, No) release file size Android (apk) Yes 20MB ( 125%) iOS Yes 56MB (103%) Android (apk) No 16.2MB iOS No 54 MB

Slide 68

Slide 68 text

© 2012-2021 BASE, Inc. In Conclution

Slide 69

Slide 69 text

69 © 2012-2021 BASE, Inc. Flutter + gomobile Pros👍 ● It can reduce the difference between IOS and Android. ● We can easily use the Go library when developing Flutter mobile app. ● Both Go and Flutter have wonderful development experience. Cons👎 ● Generated size of Artifacts is bigger. ● Language bindings have a performance overhead. ○ I couldn't find any clear differences 🥺 ● The available types are limited.

Slide 70

Slide 70 text

70 © 2012-2021 BASE, Inc. Next Action Flutter + WebAssembly 🤔?

Slide 71

Slide 71 text

71 © 2012-2021 BASE, Inc. Remember (n times)

Slide 72

Slide 72 text

72 © 2012-2021 BASE, Inc. Our Product https://thebase.in/yellbank

Slide 73

Slide 73 text

73 © 2012-2021 BASE, Inc. We are hiring https://herp.careers/v1/base/LRWfutPqUSPs 「銀行をかんたんにし、全ての人が挑戦できる世の中に」

Slide 74

Slide 74 text

74 © 2012-2021 BASE, Inc. https://www.slideshare.net/takuyaueda967/go-mobileandroid https://medium.com/flutter-community/using-go-library- in-flutter-a04e3496aa05 Reference アプリ開発にgomobileを利用する (Android/iOS/Flutter) Using Go Library in Flutter Go MobileてAndroidアプリを開発 https://qiita.com/kabochapo/items/b37c03ea9d30572fbd59