LoginSignup
17
20

More than 5 years have passed since last update.

Protocol BuffersでAPI通信 Android編

Last updated at Posted at 2017-05-14

protocol buffersとは

API通信などで、Jsonのようなテキスト形式で通信を行わずに、protocol buffersはバイナリ形式で通信を行います。
proto file(事前にスキーマを定義するファイル)から、サーバー側とクライアント側に、シリアライズ・デシリアライズ用のファイルを書き出し、それらを利用してデータの送受信を行います。

proto fileの定義

今回は都道府県のリストを返すAPIを作成して行きたいと思います。
まず、以下のようにproto fileを定義して行きいます。

prefectures.proto

syntax = "proto3";

option java_package = "com.takusemba.gouda.protos";
option java_outer_classname = "Prefectures";
option go_package = "proto";

package prefectures;

message Prefecture {
  int64 id                   = 1; // ID
  string name                = 2; // 名前
  string romaji              = 3; // 読み方(ローマ字)
}

message GetPrefecturesResponse {
  repeated Prefecture prefectures = 1;
}

実際のprotoのコードはこちらに上がっています。

Protoからjavaのfileを書き出す

先ほど定義したproto fileから、client側のシリアライズ・デシリアライズ用のファイルを書き出します。

こちらのsquare製のwireを使って書き出していきます。
https://github.com/square/wire

read.meからjarファイルをダウンロードして、protoを定義したフォルダに入れます。

その後以下のコマンドでjavaファイルが書き出せます。


java -jar wire-compiler-VERSION-jar-with-dependencies.jar \
    --proto_path=your/proto/path \
    --java_out=your/output/path

実行するとこのようなファイルが書き出されると思います。

ProtoでAPI通信を行う

必要なライブラリをgradleに追加
  // retrofit
  compile "com.squareup.retrofit2:retrofit:$retrofitVersion"
  compile "com.squareup.retrofit2:adapter-rxjava2:$retrofitVersion"
  compile "com.squareup.retrofit2:converter-wire:$retrofitVersion"
  compile "com.squareup.okhttp3:logging-interceptor:$okhttpVersion"
  compile "com.squareup.okhttp3:okhttp:$okhttpVersion"
retrofitのclientを定義

今回はkotlinを使って書いていきます。



private val okHttpClient: OkHttpClient = OkHttpClient
            .Builder()
            .addNetworkInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.HEADERS))
            .connectTimeout(15, TimeUnit.SECONDS)
            .readTimeout(15, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
            .build()


private val protoRetrofit: Retrofit = Retrofit
            .Builder()
            .baseUrl(endpoint)
            .client(okHttpClient)
            .addConverterFactory(WireConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()

インターフェースを定義

レスポンスの型は生成されたptoroの型(ここではGetPrefecturesResponse)にします。


    interface Service {

        @GET("prefectures") fun getProtoPrefectures(): Single<GetPrefecturesResponse>
    }

APIを叩く

fun getProtoPrefectures(): Single<List<Prefecture>> {
        return protoRetrofit
                .create(Service::class.java)
                .getProtoPrefectures()
                .map(GetPrefecturesResponse::prefectures)
                .map {
                    val prefectures: ArrayList<Prefecture> = ArrayList()
                    it.mapTo(prefectures) { value ->
                        Prefecture().apply {
                            id = value.id
                            name = value.name
                            romaji = value.romaji
                        }
                    }
                    prefectures.toList()
                }
    }


//APIを叩く
apiClient.getProtoPrefectures()
                    .doOnSubscribe({ disposables.add(it) })
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(
                            {
                                Timber.d("success: " + it?.toString())
                            },
                            {
                                Timber.d("error: " + it.message)
                            }
                    )

実際のコードは、こちらのレポジトリ
で公開しているので、ぜひ見て見てくだい。

17
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
20