Android apps with Gomobile

10 November 2016

Daniel Esteban

Video

This talk was presented at the I Meetup Gophers Murcia

Watch the talk on Youtube (Spanish)

2

Caution

The Go Mobile project is experimental. Use this at your own risk.

3

Motivation

4

Two strategies

5

Native applications

6

In short

Build with

$ gomobile build -target=android path/to/your/project
$ gomobile build -target=ios path/to/your/project
7

SDK applications (what this talk is really about)

8

Advantages

9

Disadvantages

10

Before we start

$ go get golang.org/x/mobile/cmd/gomobile
$ gomobile init # it might take a few minutes
11

Binding in action

Go code

package mygolibrary

func Hello(name string) string {
    return "Hello " + name + "! (from go)"
}

Generated Java code

public abstract class Mygolibrary {
    public static String hello(String name) { ... }
}

Compile with

$ gomobile bind -target android -o mygolibrary.aar -v .
12

More binding (structs)

Go code

package mygolibrary

type Counter struct {
    Value int64
}

func (c *Counter) Inc() {
    c.Value++
}

func NewCounter() *Counter {
    return &Counter{}
}
13

Generated Java API

public abstract class Mygolibrary {
    public static final class Counter {
        public void inc() { ... }
        public long getValue() { ... }
        public void setValue(long value) { ... }
    }

    public static Counter newCounter() { ... }
}

Use it from Java

Counter counter = newCounter();
counter.setValue(12345);
counter.inc();
14

Calling Go from Java

mygolibrary.go

package mygolibrary

func Hello(name string) string {
    return "Hello " + name + "! (from go)"
}

MainActivity.java

import go.mygolibrary.Mygolibrary;

public class MainActivity {
    ...
    private void someJavaFunction()
    {
            String resultFromGo = Mygolibrary.hello("JAVA");
            Log.d(TAG, resultFromGo);
    }
    ...
}
15

Calling Go from Java (with errors)

mygolibrary.go

package mygolibrary

func HelloWithError(name string) (string, error) {
    return "Hello " + name + "! (from go)", nil
}

MainActivity.java

    ...
    private void someJavaFunction()
    {
            try {
                String resultFromGo = Mygolibrary.helloWithError("JAVA");
                Log.d(TAG, resultFromGo);
            } catch(Exception e) { // If error != nil in Go, will enter the catch
                Log.e(TAG, e.toString());
            }
    }
    ...
16

Calling Java from Go (1/3)

We create an interface in Go that will be exported (gomobile bind) to Java and we need to implement it

mygolibrary.go

package mygolibrary

var jc JavaCallback

type JavaCallback interface {
    OneMethod()
    AnotherMethod(string)
}

func RegisterJavaCallback(c JavaCallback) {
    jc = c
}
17

Calling Java from Go (2/3)

Implement our callback in Java

GoCallback.java

import go.mygolibrary.JavaCallback;

public class GoCallback implements JavaCallback {

    public void oneMethod() {
        ...
    }

    public void anotherMethod(String data) {
        ...
    }

}
18

Calling Java from Go (3/3)

Register your callback (in Java)

// REGISTER CALLBACK
GoCallback gocb = new GoCallback();
Mygolibrary.registerJavaCallback(gocb);

After that point, you could call Java from Go

jc.OneMethod();
jc.AnotherMethod("Some string here");
19

How to build

$ gomobile bind -target android -o mygolibrary.aar -v .

In your android project:

android/settings.gradle

include ':app', ':mygolibrary'

android/app/build.gradle

dependencies {
    ...
    compile project(':mygolibrary')
}
20

But it doesn't recompile

If you modify mygolibrary.aar it will not add the new changes to the project

21

But it doesn't recompile

We need to make gradle to recompile it

android/build.gradle (add)

repositories {
    ...
    flatDir {
        dirs "$rootDir/mygolibrary"
    }
}

android/app/build.gradle (modify)

dependencies {
    ...
    compile (':mygolibrary@aar') { changing = true }
}
22

Success story

Password Manager for TREZOR on Android devices

23

Password Manager (continuation)

(early app version)

24

Password Manager (continuation)

How to glue things together

+--------------+   async promise   +--------+  blocking call    +--------+
| REACT NATIVE +-----------------> |  JAVA  +-----------------> |   GO   |
+-------+------+                   ++----+--+                   +----+---+
        ^                           |    ^                           |
        |          events           |    |    registered callback    |
        +---------------------------+    +---------------------------+
25

Why we used a callback instead of direct calls?

26

Other successful stories

Ivy
- Ivy is an interpreter for an APL-like language
- Written by Rob Pike
- Source at github.com/robpike/ivy
- Google Play Store play.google.com/store/apps/details?id=org.golang.ivy

Goku
- Sudoku solver
- React-native as UI
- Written by Miguel Espinoza
- Source at github.com/miguelespinoza/react-goku
- Google Play Store play.google.com/store/apps/details?id=com.miguelespinoza.goku

27

Some tricks (based in our experience)

func CallThisFromJava() {
    go runThisAsync()
}
func runThisAsync() {
    /* your code here */
}
28

Notes

29

Thank you

Daniel Esteban

Use the left and right arrow keys or click the left and right edges of the page to navigate between slides.
(Press 'H' or navigate to hide this message.)