AndroidでgRPCクライアント

AndroidでgRPCクライアントの実装をしようと思ってチュートリアル読んだけど、すっと分からなかったのでメモ。まずは、Goで簡単なgRPCサーバーとクライアントを実装、その後クライアントをAndrodアプリとして実装する、というのをやってみました。

実装してみたソースコードはここです↓

github.com

gRPCがどんなものなのか触る

まず、Goで実装してみる。以下の記事が進めやすかったです、ありがとうございます。

zenn.dev

この記事の通りに進める。

  • protoファイルでクライアント・サーバー間のインタフェースを定義する
  • protocコマンドでprotoファイルからクライアントとサーバーの通信部分についてコード自動生成する
  • 自動生成したコードを利用するサーバーとクライアントを実装し動かして雰囲気を掴む

クライアントをAndroidアプリで実装する

上記のGoで実装したクライアントはCLIを持つプログラム。このクライアントをAndroidアプリにしてみる。

gRPC公式のQuick start

まずはgRPCの公式ドキュメントのAndroidのページを見に行く。

Quick start | Kotlin for Android | gRPC

以下のプロジェクトを使って説明されている。確認したときの最新のtagは v1.3.0

grpc-kotlin/examples at v1.3.0 · grpc/grpc-kotlin

このプロジェクトはgradleで構成されている。色々あってどこを見ればいいかすぐに分からなかったけど、AndroidアプリでgRPCクライアントについては3つのディレクトリ(Gradleのモジュール)だけを見れば良い。

examples/protos はprotoファイルが置いてあるモジュール。 examples/android はgRPCクライアントとなるAndroidアプリのモジュール。

では example/stub-android は?

stub

example/stub-android は、protoファイルからクライアントコードを自動生成するためのモジュール。生成されたクライアントコードをstubと呼ぶ。クライアントとなるAndroidアプリのソースコードからstubのメソッドを普通のメソッドとして呼び出すが、stubが提供しているメソッドの実態はサーバー側で実装されている。つまり、RPCとなる。

stubについて、gRPC公式で触れられている

Androidアプリつくる

ここまでで重要な登場人物は3つ。

  • protoファイル
  • protoファイルを元にstubを自動生成するためモジュール
  • stubを使うAndroidアプリ本体となるモジュール

上記のexampleの構造を参考にgRPCクライアントとなるAndroidアプリを作ってみた。

github.com

feature/grpc-client モジュールがgRPCクライアントとなるAndroidアプリ本体で、公式exampleの examples/android に相当する。

このAndroidアプリは client_stub モジュールに依存する。他にもgRPC関連のライブラリにも依存する。

dependencies {
    implementation(project(path: ":client_stub"))
    ...

    // gRPC
    implementation("io.grpc:grpc-kotlin-stub:$grpc_kotlin_version")
    implementation("com.google.protobuf:protobuf-kotlin-lite:$protobuf_version")
    implementation("io.grpc:grpc-android:$grpc_android_version")
    implementation("io.grpc:grpc-okhttp:$grpc_android_version")
}

feature/grpc-client/build.gradle

client_stub モジュールはprotoファイルからコード自動生成するモジュールで、公式exampleの example/stub-android に相当する。Android Libraryモジュールとする。

公式exampleの build.gradle を参考に色々いじってみる。これらの設定はprotocコマンドを使ってコード生成する代わりに、gradleでコード生成するための設定だと思えばいい。

protobuf {
    protoc {
        artifact = "com.google.protobuf:protoc:$protobuf_version"
    }
    plugins {
        java {
            artifact = "io.grpc:protoc-gen-grpc-java:$grpc_version"
        }
        grpc {
            artifact = "io.grpc:protoc-gen-grpc-java:$grpc_version"
        }
        grpckt {
            artifact = "io.grpc:protoc-gen-grpc-kotlin:$grpc_kotlin_version:jdk7@jar"
        }
    }
    ...
}

client_stub/build.gradle

以下の3つそれぞれとprotocコマンドとの対応をイメージすると把握しやすい。Kotlinを使う場合であってもJava実装のstubを自動生成しないといけないみたい。

  • com.google.protobuf:protoc
    • protoc コマンド自体
  • io.grpc:protoc-gen-grpc-java
    • Javaで実装されたstubを生成
    • Goの例で言うと protoc コマンドのオプション --go-grpc_out--go-grpc_opt
  • io.grpc:protoc-gen-grpc-kotlin
    • Kotlinで実装された上記のJava実装stubのラッパーを生成

これでgradle経由でprotocを使ってstubを自動生成できる。自動生成したstubをAndroid Libraryモジュールとして、Androidアプリのモジュールから参照すれば、あとは公式exampleのandroidを見ながら実装すれば良い。

おしまい

protocコマンドで生成する方がとっつきやすくはあるのですが、Android Libraryモジュールにしたい場合はGradleでやれると楽ですねぇ。今回は client_stub を同一プロジェクトにしましたが、別リポジトリとしてaarをpublishするのが良さそうです。