2015: add gophercon go-on-mobile talk slide and demo
Change-Id: I8be9d01dabf8800bf6b37d5144fac3d743b08af9
Reviewed-on: https://go-review.googlesource.com/12040
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/2015/gophercon-go-on-mobile.slide b/2015/gophercon-go-on-mobile.slide
new file mode 100644
index 0000000..58a48ac
--- /dev/null
+++ b/2015/gophercon-go-on-mobile.slide
@@ -0,0 +1,340 @@
+Go on Mobile
+
+GopherCon 2015
+
+Hana Kim
+Google
+
+* Caution
+
+.image gophercon-go-on-mobile/caution.png 300 _
+
+The Go Mobile project is experimental. Use this at your own risk.
+
+While we are working hard to improve it, neither Google nor the Go
+team can provide end-user support.
+
+* Background
+
+Mobile support was frequently requested
+
+Some users built their own Go binaries for Android with cgo + external linking through NDK tool chains
+
+Some Android Apps used Go even before Go 1.4
+
+- Camlistore android app (out-of-process model)
+- Goandroid+Mandala (in-process model)
+- ...
+
+* golang.org/x/mobile
+
+Goal: Bring Go to Mobile Platforms
+
+Why?
+
+- Use Go to program a complete system (server/client)
+- Write a single cross-platform Go library
+- Bring a simple language and development tooling to mobile
+
+* Two ways of using Go
+
+Native Apps
+
+- Write the whole app in Go
+- Use Go packages for graphics, event handling, audio, etc.
+
+SDK Apps
+
+- Write Android UI in Java, iOS UI in Objective-C/Swift
+- Write common functionality in Go as a library
+
+* Native Apps
+
+* Challenge #1: Cross-platform APIs
+
+Work for Android, iOS, and Desktop environments
+
+Provide a rich set of APIs
+
+Follow idiomatic Go style
+
+* Demo: Hello, Gopher!
+
+.image gophercon-go-on-mobile/gophercloud.png 400 _
+
+This program uses the packages from golang.org/x/mobile repo
+There is no Java or Objective-C or C in my code
+
+* What's available?
+
+golang.org/x/mobile/...
+
+- [[http://golang.org/x/mobile/app][app: App control]]
+- [[http://golang.org/x/mobile/asset][asset: Asset management]]
+- [[http://golang.org/x/mobile/gl][gl: OpenGL ES 2]]
+- [[https://golang.org/x/mobile/event][event: Events]]
+- [[https://golang.org/x/mobile/geom][geom: Screen geometry]]
+
+golang.org/x/mobile/exp/...
+
+- [[https://golang.org/x/mobile/exp/audio][audio: Audio]]
+- [[https://golang.org/x/mobile/exp/font][font: System font]]
+- [[https://golang.org/x/mobile/exp/sprite][sprite: 2-D rendering]]
+- [[https://golang.org/x/mobile/exp/sensor][sensor: Sensors]]
+
+* Challenge #2: Build systems
+
+Dealing with
+
+- Toolchain installation
+
+- Cross compilation for `GOOS/GOARCH` combos
+
+- Android/iOS-specific build details
+
+That is not fun!
+
+* The gomobile tool
+
+ $ go get golang.org/x/mobile/cmd/gomobile
+
+Simplifies toolchain installation and app deployment
+
+To install the Android/iOS compiler tool chain:
+
+ $ gomobile init
+
+To build an Android APK and an iOS app
+
+ $ gomobile -target=android build
+ $ gomobile -target=ios build
+
+(Demo)
+
+* SDK Apps
+
+* Go as a library
+
+Go 1.5 can build Go programs as a library that can be used by non-Go programs
+
+- Shared library for dynamic linking (`-buildmode=c-shared`)
+- Archive file for static linking (`-buildmode=c-archive`)
+
+Functions marked with `//export` cgo annotations are callable.
+
+.link http://golang.org/s/execmodes
+
+* Working with Foreign Languages
+
+.image gophercon-go-on-mobile/gobind.png 300 _
+
+Manually mapping data structures and functions between languages is tedious and error-prone!
+
+
+* The gobind tool
+
+ $ go get golang.org/x/mobile/cmd/gobind
+
+Automates language binding through code generation
+
+Defines the language binding from exported Go APIs; no explicit annotation
+
+Currently supports a [[http://golang.org/x/mobile/cmd/gobind][subset of Go types]]
+
+
+* Binding Functions, Basic Types & Errors
+
+Go API
+
+ package mypkg
+
+ func Hello() (string, error) { return "Gopher", nil }
+
+Generated Java API
+
+ public abstract class Mypkg {
+ public static String Hello() throws Exception { ... }
+ }
+
+Generated Objective-C API
+
+ FOUNDATION_EXPORT BOOL GoMypkgHello(NSString** ret0_, NSError** error);
+
+* Binding Structs
+
+ package mypkg
+
+ type Counter struct {
+ Value int64
+ }
+
+ func (c *Counter) Inc() {
+ c.Value++
+ }
+
+ func NewCounter() *Counter {
+ return &Counter{}
+ }
+
+* Generated Java API
+
+ public abstract class Mypkg {
+ 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();
+
+
+* Generated Objective-C API
+
+ @interface GoMypkgCounter : NSObject { }
+ @property(strong, readonly) GoSeqRef *ref;
+ - (int64_t)Value;
+ - (void)setValue:(int64_t)v;
+ - (void)Inc;
+ @end
+
+ FOUNDATION_EXPORT GoMypkgCounter* GoMypkgNewCounter();
+
+Use it from Objective-C
+
+ GoMypkgCounter* counter = GoMypkgNewCounter();
+ [counter setValue:12345];
+ [counter Inc];
+
+* How to build it?
+
+.image gophercon-go-on-mobile/memegobind.jpg 500 _
+
+
+* The gomobile bind command
+
+Simplifies the build process. For example, for Android,
+
+- Generates language bindings for Go packages
+
+- Compiles Go code to a shared library
+
+- Compiles the generated target language code
+
+- Bundles everything into a `.aar` file (modern way to distribute android libraries)
+
+(DEMO)
+
+iOS support is a work in progress.
+
+* Android Studio Integration
+
+Android Studio 1.2+ supports `.aar` import.
+
+.image gophercon-go-on-mobile/androidstudio2.png 250 _
+
+To update the .aar,
+
+- Build script to invoke `gomobile` `bind`, or
+- Gradle plugin to invoke `gomobile` `bind` and publish the output
+
+
+* The Story of Ivy
+
+The [[robpike.io/ivy][Ivy]] is a command line tool developed by Rob Pike
+
+It's a useful desktop calculator that handles big int, rational and floating-point numbers, vectors, matrices, ...
+
+.image gophercon-go-on-mobile/ivyscreenshot2.png 300 _
+
+It is in fact an interpreter for an [[https://en.wikipedia.org/wiki/APL_(programming_language)][APL]]-like language
+
+* Ivy on Mobile?
+
+~5k lines of Go code (not including tests, docs)
+
+Dependency on `math`, `math/big`, `math/rand`, `unicode`, ...
+
+.image gophercon-go-on-mobile/canihas.jpg 300 _
+
+Rewriting in Java or Objective-C is a non-starter
+
+* Ivy apps
+
+.image gophercon-go-on-mobile/ivymobile.png 300 _
+.caption Ivy logo by [[http://www.reneefrench.com][Renée French]]
+.link https://play.google.com/store/apps/details?id=org.golang.ivy Google Play Store
+.link https://itunes.apple.com/us/app/ivy-big-number-calculator/id1012116478 Apple App Store
+
+* Gomobile bind
+
+Write it once as a library in Go
+
+Enjoy great language features and packages available in Go
+
+* Where are we now?
+
+* Go 1.4: Hello Android!
+
+Released in December 2014
+
+Can build Android apps (`arm`)
+
+Android builder
+
+The `gobind` tool for Java and Go language binding
+
+Packages for cross-device apps: basic app control, OpenGL ES 2, touch
+
+.link https://golang.org/s/go14android
+.link https://golang.org/s/gobind
+
+* Go 1.5: Hello iOS!
+
+Planned release early August 2015
+
+Experimental support for iOS (`arm,arm64`)
+
+iOS builder
+
+* Go 1.5: Go programs as libraries
+
+Can call Go functions from foreign language in a clean way
+
+.link golang.org/s/execmodes
+
+* Go 1.5: Better tools & more packages
+
+`golang.org/x/mobile` repo getting better
+
+- The `gomobile` tool for mobile app/library build
+
+- Extended `gobind` tool: Objective-C binding
+
+- `golang.org/x/mobile/exp`: experimenting with audio, sensor, sprite, ...
+
+* Go 1.6+
+
+- Improvement in GL/UI packages
+
+- More APIs available to "pure Go" apps
+
+- Testing, profiling, debugging
+
+- Support for more platforms (e.g. android/x86, iOS simulator)
+
+- Richer type support in `gobind`
+
+- IDE integration
+
+* Contributions from Go community
+
+.image gophercon-go-on-mobile/contributors.png 480 _
+.caption git log | word_cloud
+
diff --git a/2015/gophercon-go-on-mobile/README b/2015/gophercon-go-on-mobile/README
new file mode 100644
index 0000000..1732cd8
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/README
@@ -0,0 +1,38 @@
+Demo Setup
+----------------------
+
+- Download and install Android SDK
+
+https://developer.android.com/sdk/index.html
+Or, easiest way is to install Android Studio.
+
+
+- Download go1.5 and build for your host.
+
+- Set the following environment variables.
+
+GOPATH: your go path
+ANDROID_HOME: Android SDK directory
+PATH: make sure $GOROOT/bin, $GOPATH/bin are included in the path
+
+- Install the gomobile tool and run init before demo.
+
+% go install golang.org/x/mobile/cmd/gomobile
+% gomobile init
+
+- Hello Gopher demo
+
+% demo1.bash
+
+For android screen mirroring, I used Mobizen (mobizen.com).
+For ios screen mirroring, you can use quicktime.
+
+- Gobind demo
+
+% demo2.bash
+
+- Ivy demo: In my gophercon talk, I used pre-recorded video
+clips for mobile versions and ran the command line version from
+my laptop in order to emphasize the cross-platform support.
+
+Enjoy.
diff --git a/2015/gophercon-go-on-mobile/androidstudio2.png b/2015/gophercon-go-on-mobile/androidstudio2.png
new file mode 100644
index 0000000..add1106
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/androidstudio2.png
Binary files differ
diff --git a/2015/gophercon-go-on-mobile/canihas.jpg b/2015/gophercon-go-on-mobile/canihas.jpg
new file mode 100644
index 0000000..1d94c61
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/canihas.jpg
Binary files differ
diff --git a/2015/gophercon-go-on-mobile/caution.png b/2015/gophercon-go-on-mobile/caution.png
new file mode 100644
index 0000000..cdb9faa
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/caution.png
Binary files differ
diff --git a/2015/gophercon-go-on-mobile/contributors.png b/2015/gophercon-go-on-mobile/contributors.png
new file mode 100644
index 0000000..0da8a6c
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/contributors.png
Binary files differ
diff --git a/2015/gophercon-go-on-mobile/demo1.bash b/2015/gophercon-go-on-mobile/demo1.bash
new file mode 100755
index 0000000..8d750ed
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/demo1.bash
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+prompt() {
+ read -p "$1"
+}
+
+cd hello
+
+declare -a arr=(
+"wc -l main.go"
+"go run main.go"
+"gomobile install -target=android"
+)
+
+for i in "${arr[@]}"
+do
+ prompt "\$ $i"
+ $i
+ echo
+done
diff --git a/2015/gophercon-go-on-mobile/demo2.bash b/2015/gophercon-go-on-mobile/demo2.bash
new file mode 100755
index 0000000..d377162
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/demo2.bash
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+prompt() {
+ read -p "$1"
+}
+
+declare -a arr=(
+"cd mypkg"
+"tree"
+"cat mypkg.go"
+"export ANDROID_HOME=${ANDROID_HOME}"
+"gomobile bind ."
+"tree"
+"unzip -l mypkg.aar"
+)
+
+for i in "${arr[@]}"
+do
+ prompt "\$ $i"
+ $i
+ echo
+done
+
+rm mypkg.aar
diff --git a/2015/gophercon-go-on-mobile/gobind.png b/2015/gophercon-go-on-mobile/gobind.png
new file mode 100644
index 0000000..905b5ea
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/gobind.png
Binary files differ
diff --git a/2015/gophercon-go-on-mobile/gophercloud.png b/2015/gophercon-go-on-mobile/gophercloud.png
new file mode 100644
index 0000000..2bb5d25
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/gophercloud.png
Binary files differ
diff --git a/2015/gophercon-go-on-mobile/hello/assets/gophersmall.png b/2015/gophercon-go-on-mobile/hello/assets/gophersmall.png
new file mode 100644
index 0000000..53b4b4a
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/hello/assets/gophersmall.png
Binary files differ
diff --git a/2015/gophercon-go-on-mobile/hello/assets/hello.wav b/2015/gophercon-go-on-mobile/hello/assets/hello.wav
new file mode 100644
index 0000000..1551ebf
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/hello/assets/hello.wav
Binary files differ
diff --git a/2015/gophercon-go-on-mobile/hello/main.go b/2015/gophercon-go-on-mobile/hello/main.go
new file mode 100644
index 0000000..32aba94
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/hello/main.go
@@ -0,0 +1,207 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Based on golang.org/x/mobile/example/audio
+
+package main
+
+import (
+ "image"
+ "log"
+ "time"
+
+ _ "image/png"
+
+ "golang.org/x/mobile/app"
+ "golang.org/x/mobile/asset"
+ "golang.org/x/mobile/event/config"
+ "golang.org/x/mobile/event/lifecycle"
+ "golang.org/x/mobile/event/paint"
+ "golang.org/x/mobile/event/touch"
+ "golang.org/x/mobile/exp/app/debug"
+ "golang.org/x/mobile/exp/audio"
+ "golang.org/x/mobile/exp/f32"
+ "golang.org/x/mobile/exp/sprite"
+ "golang.org/x/mobile/exp/sprite/clock"
+ "golang.org/x/mobile/exp/sprite/glsprite"
+ "golang.org/x/mobile/geom"
+ "golang.org/x/mobile/gl"
+)
+
+func main() {
+ app.Main(func(a app.App) {
+ for e := range a.Events() {
+ switch e := app.Filter(e).(type) {
+ case lifecycle.Event:
+ switch e.Crosses(lifecycle.StageVisible) {
+ case lifecycle.CrossOn:
+ onStart()
+ case lifecycle.CrossOff:
+ onStop()
+ }
+ case config.Event:
+ globalCfg = e // dimension change. move to the center.
+ touchLoc = geom.Point{globalCfg.Width / 2, globalCfg.Height / 2}
+ case paint.Event:
+ onPaint(globalCfg)
+ a.EndPaint()
+ case touch.Event:
+ onTouch(e)
+ }
+ }
+ })
+}
+
+const (
+ width = 72
+ height = 74
+)
+
+var (
+ startClock = time.Now()
+ eng = glsprite.Engine()
+ scene *sprite.Node
+
+ player *audio.Player
+
+ started = false
+ activate = false
+ acceptTouch = false
+ touchLoc geom.Point
+ globalCfg config.Event
+)
+
+func onTouch(t touch.Event) {
+ if t.Type != touch.TypeStart {
+ return
+ }
+
+ touchLoc = t.Loc
+ acceptTouch = true
+ if !activate {
+ activate = true
+ }
+}
+
+func onStart() {
+ gl.Enable(gl.BLEND)
+ gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
+
+ rc, err := asset.Open("hello.wav")
+ if err != nil {
+ log.Fatal(err)
+ }
+ player, err = audio.NewPlayer(rc, 0, 0)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func onStop() {
+ player.Close()
+}
+
+func onPaint(c config.Event) {
+ if !started {
+ touchLoc = geom.Point{c.Width / 2, c.Height / 2}
+ started = true
+ }
+ if scene == nil {
+ loadScene()
+ }
+ gl.ClearColor(242/255.0, 240/255.0, 217/255.0, 1) // gophercon bg color
+ gl.Clear(gl.COLOR_BUFFER_BIT)
+
+ now := clock.Time(time.Since(startClock) * 60 / time.Second)
+ eng.Render(scene, now, c)
+ debug.DrawFPS(c)
+}
+
+func newNode() *sprite.Node {
+ n := &sprite.Node{}
+ eng.Register(n)
+ scene.AppendChild(n)
+ return n
+}
+
+func loadScene() {
+ gopher := loadGopher()
+ scene = &sprite.Node{}
+ eng.Register(scene)
+ eng.SetTransform(scene, f32.Affine{
+ {1, 0, 0},
+ {0, 1, 0},
+ })
+
+ var x, y float32
+ dx, dy := float32(1), float32(1)
+
+ n := newNode()
+ n.Arranger = arrangerFunc(func(eng sprite.Engine, n *sprite.Node, t clock.Time) {
+ eng.SetSubTex(n, gopher)
+
+ if acceptTouch {
+ dx = (float32(touchLoc.X) - x) / 60
+ dy = (float32(touchLoc.Y) - y) / 60
+ acceptTouch = false
+ hello()
+ x += dx
+ y += dy
+ } else if activate {
+ if x < 0 {
+ dx = 1
+ }
+ if y < 0 {
+ dy = 1
+ }
+ if x+width > float32(globalCfg.Width) {
+ dx = -1
+ }
+ if y+height > float32(globalCfg.Height) {
+ dy = -1
+ }
+ x += dx
+ y += dy
+ }
+
+ if dx < 0 {
+ eng.SetTransform(n, f32.Affine{ // change direction
+ {-width, 0, x + width},
+ {0, height, y},
+ })
+ } else {
+ eng.SetTransform(n, f32.Affine{
+ {width, 0, x},
+ {0, height, y},
+ })
+ }
+ })
+}
+
+func hello() {
+ player.Seek(0)
+ player.Play()
+}
+
+func loadGopher() sprite.SubTex {
+ a, err := asset.Open("gophersmall.png")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer a.Close()
+
+ img, _, err := image.Decode(a)
+ if err != nil {
+ log.Fatal(err)
+ }
+ t, err := eng.LoadTexture(img)
+ if err != nil {
+ log.Fatal(err)
+ }
+ return sprite.SubTex{t, image.Rect(0, 0, 360, 370)}
+}
+
+type arrangerFunc func(e sprite.Engine, n *sprite.Node, t clock.Time)
+
+func (a arrangerFunc) Arrange(e sprite.Engine, n *sprite.Node, t clock.Time) { a(e, n, t) }
diff --git a/2015/gophercon-go-on-mobile/ivyabout.png b/2015/gophercon-go-on-mobile/ivyabout.png
new file mode 100644
index 0000000..3b515f7
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/ivyabout.png
Binary files differ
diff --git a/2015/gophercon-go-on-mobile/ivymobile.png b/2015/gophercon-go-on-mobile/ivymobile.png
new file mode 100644
index 0000000..3ea7d21
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/ivymobile.png
Binary files differ
diff --git a/2015/gophercon-go-on-mobile/ivyscreenshot2.png b/2015/gophercon-go-on-mobile/ivyscreenshot2.png
new file mode 100644
index 0000000..c0701b7
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/ivyscreenshot2.png
Binary files differ
diff --git a/2015/gophercon-go-on-mobile/memegobind.jpg b/2015/gophercon-go-on-mobile/memegobind.jpg
new file mode 100644
index 0000000..16b5a75
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/memegobind.jpg
Binary files differ
diff --git a/2015/gophercon-go-on-mobile/mypkg/assets/myassets.txt b/2015/gophercon-go-on-mobile/mypkg/assets/myassets.txt
new file mode 100644
index 0000000..7e2f179
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/mypkg/assets/myassets.txt
@@ -0,0 +1 @@
+assets
diff --git a/2015/gophercon-go-on-mobile/mypkg/mypkg.go b/2015/gophercon-go-on-mobile/mypkg/mypkg.go
new file mode 100644
index 0000000..12c88ec
--- /dev/null
+++ b/2015/gophercon-go-on-mobile/mypkg/mypkg.go
@@ -0,0 +1,7 @@
+package mypkg
+
+import "fmt"
+
+func Hello(name string) string {
+ return fmt.Sprintf("Hello, %s!", name)
+}