🐥

androidでconnect-kotlinを使ってみる

2024/09/30に公開

株式会社バニッシュ・スタンダードでアプリエンジニア(主にandroid)をやっている中本です。

弊社ではバックエンドのAPIの一部をconnectというライブラリを用いて実装しています
バックエンド↔︎アプリのAPIでもconnect使って実装してみたいよねという話になり、試しにconnect-kotlinのチュートリアルに沿って疎通を確認してみました。ほぼドキュメント通りではありますが、実際にAndroid Studioでの実装方法を書いていきます。

connectとは?

ConnectとはBufという組織によって開発されたブラウザとgRPC互換のHTTP APIを構築するための軽量なライブラリです。
誤解を恐れず超絶ざっくり言うと、Protocol buffersというプロトコルを用いてデータモデルを自動生成させることで、JSONでやっていたようにフロントエンドとバックエンドの両方でわざわざデコード・エンコードするという手間を削減し、かつ型安全なデータを作成できる。そして、そのProtocol buffersをめっちゃ簡単に利用できるというライブラリです(ざっくり過ぎて一部不正確な表現があります)。
gRPCとはなんぞやとか、connectの正確な表現とかは他の記事に譲って、早速チュートリアルに沿ってconnect-kotlinをやってみます。

やっていきます

環境

  • apple m3
  • macOs Sonoma 14.6.1
  • android studio Koala 2024.1.1 Patch 1
  • java 17
  • gradle 8.7
  • android gradle plugin 8.5.1

Buf CLIのインストール

$ brew install bufbuild/buf/buf
$ buf --version
#これでインストールできてるか確認できる

インストールが終わったら$PATHに追加しておきます

Android Studioで新規projectを作成

Empty Activityを選択して「次へ」をクリック
チュートリアルではElizaという名前にしていますがご自由にどうぞ。
なお、チュートリアルではMinimum SDKをAPI24としていますが、API23でもいけました。

サービスを定義する

サービス定義を含むProtobufファイルを追加します。プロジェクトのルートディレクトリにてprotoディレクトリを作成し、eliza.protoファイルを追加・編集します。

$ mkdir -p proto && touch proto/eliza.proto
eliza.proto
syntax = "proto3";

package connectrpc.eliza.v1;

message SayRequest 
  string sentence = 1;
}

message SayResponse {
  string sentence = 1;
}

service ElizaService {
  rpc Say(SayRequest) returns (SayResponse) {}
}

コードを生成する

ここからがお待ちかねのコードの自動生成の部分です。
プロジェクトのルートディレクトリにて

$ buf config init

をするとbuf.yamlというファイルが生成されているはずです。このファイルに先ほど作成したprotoディレクトリを使用するようにmodulesの部分を加えます

buf.yaml
version: v2
modules: #追加
  - path: proto #追加
lint:
  use:
    - STANDARD
breaking:
  use:
    - FILE

次にbuf.gen.yamlを作成して以下を追記します。各々、javaのファイルが生成されるディレクトリと、kotlinのファイルが生成されるディレクトリをoutに書いています。

buf.gen.yaml
version: v2
plugins:
  - remote: buf.build/protocolbuffers/java
    out: app/src/main/java
  - remote: buf.build/connectrpc/kotlin
    out: app/src/main/java

チュートリアルでは次にbuf lintをしろと書いてあるのですが、私の環境では警告的なものが出ました。

proto/eliza.proto:3:1:Files with package "connectrpc.eliza.v1" must be within a directory "connectrpc/eliza/v1" relative to root but were in directory ".".

ただ動作には影響ないっぽく、generateしたらファイルが生成されました

$ buf generate

依存関係を記述する

appレベルのbuild.gradleに依存関係を加えます。チュートリアルが書かれた時からライブラリの更新が進んでいて、versionをあげる必要があります。現状ktsが主流なのでktsで書きます。

build.gradle(app)
dependencies {
    implementation (libs.androidx.constraintlayout)
    implementation (libs.androidx.recyclerview)
    implementation (libs.androidx.lifecycle.runtime.ktx.v251)
    implementation (libs.okhttp)
    implementation (libs.connect.kotlin.okhttp)
    // Java specific dependencies.
    implementation("com.connectrpc:connect-kotlin-google-java-ext:0.7.0")
    implementation("com.google.protobuf:protobuf-java:4.28.2")
}

また、manifestファイルにpermissionを追加する必要があります。

AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

後はチュートリアル通りにitem.xml、activity_main.xml、ChatRecycler.ktを追加し、MainActivity.ktを修正すればElizaとの会話を楽しめるはずです。

所感

比較的簡単に疎通確認できました。意外と古いandroidもサポートしており、プロダクトでも使えそうだなぁと感じております。ただ、実際にプロダクトに入れ込むためにはtokenをはじめとしたheader情報などを考慮に入れる必要があり、まだまだ勉強が必要だなぁと思いました。また、dependenciesで追加するprotobuf-javaのversionが低いとruntimeエラーになりまして、ここは気をつかう必要がありそうです。

Discussion