go.mobile で Android 開発 
黒川 洋 / @hydrakecat
Go 1.4 で Android がサポート 
されるらしい 
“Go 1.4 can build binaries for ARM processors 
running the Android operating system. It can also 
build a .so library that can be loaded by an 
Android application using the supporting 
packages in the mobile subrepository.” 
せっかく、Gopher 兼 Androider なので、なにか作ってみたい
Go でなにができるのか 
https://godoc.org/golang.org/x/mobile 
ネイティブアプリ 
Go を使って NDK で開発するアプリ。基本的に OpenGL で描 
画する。アクティビティは1つのみ。 
→ ゲーム開発向け 
共有ライブラリ 
共有ライブラリ(.soファイル)を生成して、Java から JNI 
呼び出しをするアプリ。アプリ本体は、通常の SDK で開発で 
きる。
ネイティブアプリの 
開発手順(1/2) 
以降では、NDK および go.mobile の開発環境が整っているとします。詳細 
はgolang - go.mobileを動かしてみた。 - Qiitaを参照。 
普通に Go でプログラムを書ける 
app.Run() を呼ぶと、アプリが起動する 
描画関数や、タッチイベントのコールバック関数は、この 
ときに引数として渡す 
描画は Open GL ES 2 の API が用意されているのでそれを利 
用する 
func main() { 
app.Run(app.Callbacks{ 
Draw: draw, 
Touch: touch, 
}) 
}
ネイティブアプリの 
開発手順(2/2) 
ビルドについてはサンプル 
のgolang.org/x/mobile/example/basic/make.bashが 
参考になる 
以下のようにgo buildでライブラリファイルをビルドし 
てndk-buildを走らせるだけ 
CGO_ENABLED=1 GOOS=android GOARCH=arm GOARM=7 go build -ldflags="-shared" -o jni/armeabi/ndk-build NDK_DEBUG=1 
ant debug
共有ライブラリの 
開発手順(1/5) 
必要なものがちょっと多い 
1. Android アプリ本体 
2. ライブラリ本体のコード 
3. それを Java と binding するラッパーコード(Go と Java の 
ファイルが1つずつ) 
4. ライブラリのエントリポイントとなる main.go
共有ライブラリの 
開発手順(2/5) 
ここでは、以下のprime.goをライブラリにするとする 
package prime 
func MaxPrime(n int32) int32 { 
... 
return p 
} 
次に binding コードを自動生成する必要がある 
1. gobindコマンドのインストール 
$ go install golang.org/x/mobile/cmd/gobind 
2. 以下のコマンドを実行してコードを生成する 
$ gobind -lang=go github.com/hkurokawa/godroid-sample > go_prime/go_prime.go 
$ gobind -lang=java github.com/hkurokawa/godroid-sample > Prime.java
共有ライブラリの 
開発手順(3/5) 
続いて、以下のようなコードをmain.goとして保存して、共 
有ライブラリを作成する 
package main 
import ( 
"golang.org/x/mobile/app" 
_ "github.com/hkurokawa/godroid-sample/go_prime" 
_ "golang.org/x/mobile/bind/java" 
) 
func main() { 
app.Run(app.Callbacks{}) 
} 
$ CGO_ENABLED=1 GOOS=android GOARCH=arm GOARM=7 go build -ldflags="-shared" . 
ブランク識別子(_)を使って、生成した binding コードの 
import だけを行うのがミソ
共有ライブラリの 
開発手順(4/5) 
最後に生成されたファイルを Android プロジェクト以下に配 
置すれば完了。注意点としては、 
.soファイルの名前はlibgojni.soにすること 
golang.org/x/mobile/bind/java/Seq.java および 
app/*.javaが必須(シンボリックリンク推奨) 
エミュレータの ABI は ARM にすること
共有ライブラリの 
開発手順(5/5) 
呼び出すときは以下のように行う。Go.init()を忘れずに。 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
mButton.setOnClickListener(new View.OnClickListener() { 
@Override 
public void onClick(View v) { 
final long n = Long.parseLong(mInput.getText().toString()); 
final long p = Prime.MaxPrime(n); 
mResult.setText(p); 
} 
}); 
Go.init(this.getApplicationContext());
動かしたところ 
実装も違うのでなんとも言えないけれど、意外と遅い...(要 
調査) ←すみません、これはプログラムの書き方の問題で普 
通に書けば Go の方が速いです(2014-11-25 追記)
とりあえずのまとめ 
まだ制限が多くて、いますぐの開発は辛そう 
OpenGL の API は(意図的に)最小限なのでライブラリなどが必要? 
JNI 呼び出しの場合、引数および戻り値の型に制限がある(× array 
型、× channel 型、× 複数戻り値...) 
Android Studio および gradle がサポートされていない 
Lollipop では動かない(“cannot open /proc/self/auxv: 
Permission denied”) 
JNI呼び出しのパフォーマンスは気になる 
C/C++ に比べてどれくらいメリットがあるかというと微妙 
とはいえ 
Go が書けるのはうれしい 
クロスコンパイルが容易なのはうれしい。iOS もサポートされた 
ら、共通する処理は Go で書くのもあり。

go.mobile で Android 開発

  • 1.
    go.mobile で Android開発 黒川 洋 / @hydrakecat
  • 2.
    Go 1.4 でAndroid がサポート されるらしい “Go 1.4 can build binaries for ARM processors running the Android operating system. It can also build a .so library that can be loaded by an Android application using the supporting packages in the mobile subrepository.” せっかく、Gopher 兼 Androider なので、なにか作ってみたい
  • 3.
    Go でなにができるのか https://godoc.org/golang.org/x/mobile ネイティブアプリ Go を使って NDK で開発するアプリ。基本的に OpenGL で描 画する。アクティビティは1つのみ。 → ゲーム開発向け 共有ライブラリ 共有ライブラリ(.soファイル)を生成して、Java から JNI 呼び出しをするアプリ。アプリ本体は、通常の SDK で開発で きる。
  • 4.
    ネイティブアプリの 開発手順(1/2) 以降では、NDKおよび go.mobile の開発環境が整っているとします。詳細 はgolang - go.mobileを動かしてみた。 - Qiitaを参照。 普通に Go でプログラムを書ける app.Run() を呼ぶと、アプリが起動する 描画関数や、タッチイベントのコールバック関数は、この ときに引数として渡す 描画は Open GL ES 2 の API が用意されているのでそれを利 用する func main() { app.Run(app.Callbacks{ Draw: draw, Touch: touch, }) }
  • 5.
    ネイティブアプリの 開発手順(2/2) ビルドについてはサンプル のgolang.org/x/mobile/example/basic/make.bashが 参考になる 以下のようにgo buildでライブラリファイルをビルドし てndk-buildを走らせるだけ CGO_ENABLED=1 GOOS=android GOARCH=arm GOARM=7 go build -ldflags="-shared" -o jni/armeabi/ndk-build NDK_DEBUG=1 ant debug
  • 6.
    共有ライブラリの 開発手順(1/5) 必要なものがちょっと多い 1. Android アプリ本体 2. ライブラリ本体のコード 3. それを Java と binding するラッパーコード(Go と Java の ファイルが1つずつ) 4. ライブラリのエントリポイントとなる main.go
  • 7.
    共有ライブラリの 開発手順(2/5) ここでは、以下のprime.goをライブラリにするとする package prime func MaxPrime(n int32) int32 { ... return p } 次に binding コードを自動生成する必要がある 1. gobindコマンドのインストール $ go install golang.org/x/mobile/cmd/gobind 2. 以下のコマンドを実行してコードを生成する $ gobind -lang=go github.com/hkurokawa/godroid-sample > go_prime/go_prime.go $ gobind -lang=java github.com/hkurokawa/godroid-sample > Prime.java
  • 8.
    共有ライブラリの 開発手順(3/5) 続いて、以下のようなコードをmain.goとして保存して、共 有ライブラリを作成する package main import ( "golang.org/x/mobile/app" _ "github.com/hkurokawa/godroid-sample/go_prime" _ "golang.org/x/mobile/bind/java" ) func main() { app.Run(app.Callbacks{}) } $ CGO_ENABLED=1 GOOS=android GOARCH=arm GOARM=7 go build -ldflags="-shared" . ブランク識別子(_)を使って、生成した binding コードの import だけを行うのがミソ
  • 9.
    共有ライブラリの 開発手順(4/5) 最後に生成されたファイルをAndroid プロジェクト以下に配 置すれば完了。注意点としては、 .soファイルの名前はlibgojni.soにすること golang.org/x/mobile/bind/java/Seq.java および app/*.javaが必須(シンボリックリンク推奨) エミュレータの ABI は ARM にすること
  • 10.
    共有ライブラリの 開発手順(5/5) 呼び出すときは以下のように行う。Go.init()を忘れずに。 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final long n = Long.parseLong(mInput.getText().toString()); final long p = Prime.MaxPrime(n); mResult.setText(p); } }); Go.init(this.getApplicationContext());
  • 11.
    動かしたところ 実装も違うのでなんとも言えないけれど、意外と遅い...(要 調査)←すみません、これはプログラムの書き方の問題で普 通に書けば Go の方が速いです(2014-11-25 追記)
  • 12.
    とりあえずのまとめ まだ制限が多くて、いますぐの開発は辛そう OpenGLの API は(意図的に)最小限なのでライブラリなどが必要? JNI 呼び出しの場合、引数および戻り値の型に制限がある(× array 型、× channel 型、× 複数戻り値...) Android Studio および gradle がサポートされていない Lollipop では動かない(“cannot open /proc/self/auxv: Permission denied”) JNI呼び出しのパフォーマンスは気になる C/C++ に比べてどれくらいメリットがあるかというと微妙 とはいえ Go が書けるのはうれしい クロスコンパイルが容易なのはうれしい。iOS もサポートされた ら、共通する処理は Go で書くのもあり。