dely Tech Blog

クラシル・TRILLを運営するdely株式会社の開発ブログです

Google Play Developer APIを活用してAPKのアップロードを自動化する(DroidKaigi 2019の発表を終えて)

こんにちは。Androidエンジニアのうめもりです。

もう終わってからだいぶ経ってしまいましたが、今年のDroidKaigiもとても面白かったですね。自分は去年から参加し始めたのですが、去年と比べても 色々な部分で改善が見られ、運営の方々には頭が下がる思いです。来年以降も続いていくといいですね。

さて、自分は今年のDroidKaigiではこんな発表をしてきました。

ちなみに去年の発表はこんな感じなので、大分毛色が違う感じでしたね。(資料のアス比が…)

正直内容としてはそこまでレベルが高い感じもしなかったので、資料を作りながら(大丈夫かな…いやでもこれCfP通りだしな…いやでもな…)みたいな葛藤がありつつも、当日はそこそこ楽しんでいただけたようで良かったです。日本語から英語への同時通訳をしていただく中での発表は初めてだったのですが、終わった後にゆっくり喋ってもらったのが良かったとコメントをいただいて安心しました。(余談ですが、DroidKaigiの同時通訳の方はAndroid Specificな内容も理解しつつ的確に翻訳してくださる素晴らしい方々だったみたいです。どれだけ事前に勉強されたのでしょうか…。事前の打ち合わせでもお話をさせていただきましたが、安心して発表に臨むことが出来ました。)

発表内容の中でGoogle PlayへのAPK、Proguardのマッピングファイルの自動アップロードを行っているという話をチラッと出したのですが、登壇後のオフィスアワーでも、Twitter上でもどうやっているのかという質問をいただいたりしたので、こちらのブログで補足しておこうと思います。ちなみにAWS Lambdaからゴリゴリやっているので、ナウい感じのCIサービス(Bitriseとか)の話は出てこないことをご了承ください。

APKのアップロードをどのように自動化したか?

タイトルでネタバレしてしまっていますが、delyのAndroidチームでは、Google Play Developer Publishing APIを使って

  • APKのアップロード
  • Proguardのマッピングファイルのアップロード
  • リリースのドラフト作成(アルファ公開チャンネルに作成しています)

のタスクを自動化しています。クラシルはRealmを使っていた関係でSplit APKを行っているので、APKのアップロードやProguardのマッピングファイルのアップロードは地味に面倒なタスクになっています。ファイルをアップロードするだけといえばアップロードするだけなのですが、リリース時の心理的な作業負担感が大分低減しているような実感があります。

Google Play Developer Publishing APIの叩き方

2019年2月21日現在でのGoogle Play Console上での説明なので、もしかしたらこの部分の説明は間違っている可能性があります。

まずはGoogle Play Developer Publishing APIを使うためのサービスアカウントを発行しましょう。今回の用途では各ユーザーの権限でAPIを呼ぶことは無いと思うので、サービスアカウントを使うのが簡単だと思います。

Google Play Developer Consoleの「設定」から、「APIアクセス」を開きます。(なお、この操作は適切な権限のあるアカウントでないと出来ませんのでご注意ください。)

まだ1回もAPIを使ったことが無いのであれば、「新しいプロジェクトを作成」からプロジェクトを作成しましょう。

作成すると、画面の下にサービスアカウントというセクションが現れるはずなので、そこから「サービスアカウントを作成」をクリックします。

基本的にはそこに書いてある通りに操作を行えばいいのですが、Google API Consoleに移動して、「サービスアカウントを作成」から要求された項目を入力し、サービスアカウントを作成します。重要なのは、キーの作成を行って(JSONがいいと思います)、それを控えておくことです。

次に、Google Play Consoleの「ユーザーと権限」から、先ほど作成したサービスアカウントのメールアドレスを指定して、権限を与えます。「リリースマネージャー」にしておくのが手っ取り早くていいと思います。

以上で、先ほど作成したキーを使ってGoogle Play Developer Publishing APIを使うことが出来るようになりました。

Google Play Developer Publishing APIを呼び出す

先程作成したキーを使ってAPIを叩くのはGoogle APIs SDKを使うのが一番簡単です。弊社ではAWS Lambda上でGoを使ってAPIを叩いていますが、以降の説明はGoogleのAPIドキュメントを使って行います。(どのプラットフォーム用のSDKでも基本的には同じようにマッピングされているはずなので、適宜読み替えて使ってください。)

さて、APKやProguardのマッピングファイルをアップロードするのにはまずEditsを作成する必要があります。Google Play Developer Publishing APIはAPIをまたいだトランザクションに対応しており、Editsはトランザクションの単位と考えれば間違えが無いと思います。

developers.google.com

なお、こちらがGoogle Play Developer Publishing APIのドキュメントなので、こちらを見て分かる方はそちらを読んでいただいた方がいいと思います。

Editsを作成する

まずは、

https://developers.google.com/android-publisher/api-ref/edits/insert

POST https://www.googleapis.com/androidpublisher/v3/applications/{packageName}/edits

こちらのAPIをコールしてEditsを作成します。{packageName}にはアプリケーションIDを入れます。

レスポンスはこのような構造になっています。

https://developers.google.com/android-publisher/api-ref/edits

重要なのはidで、こちらのidを使って以降のAPIをコールしてファイルのアップロードを行います。

APKをアップロードする

次に、APKのアップロードのやり方です。

https://developers.google.com/android-publisher/api-ref/edits/apks/upload

POST https://www.googleapis.com/upload/androidpublisher/v3/applications/{packageName}/edits/{editId}/apks?uploadType={uploadType}

こちらのAPIをコールしてAPKをアップロードします。先程作成したEditのidを{editId}に挿入します。{uploadType}は mediaresumable を設定できますが、 今回はmediaを指定した場合の説明だけをしておきます。

Content-Typeは application/octet-streamapplication/vnd.android.package-archive を設定し、ファイルのバイナリ列をリクエストボディとして送信しましょう。

なお、弊社ではAPKごとにゴルーチンを立ち上げて並列アップロードしています。

Proguardのマッピングファイルをアップロードする

次に、Proguardのマッピングファイルをアップロードします。

https://developers.google.com/android-publisher/api-ref/edits/deobfuscationfiles/upload

POST https://www.googleapis.com/upload/androidpublisher/v3/applications/{packageName}/edits/{editId}/apks/{apkVersionCode}/deobfuscationFiles/{deobfuscationFileType}?uploadType={uploadType}

基本的にはAPKと同じ要領ですが、どのAPKのマッピングファイルなのかを指定する必要があります。{apkVersionCode}には、対応するAPKのVersionCodeを挿入します。{deobfuscationFileType}には現在は proguard しか指定できませんので、それを指定しましょう。

Content-Typeには application/octet-stream を指定し、マッピングファイルのテキストをリクエストボディに入れて送信しましょう。

余談ですが、難読化を意味するobfuscationはネイティブの方でも馴染みのない単語みたいですね。事前打ち合わせでその話題が出てきて、確かに日本語でも難読化なんて言葉そんなに使わないわ…と思った記憶があります。

TracksをUpdateする

最後に、どのトラックにアップロードするかを指定します。

https://developers.google.com/android-publisher/api-ref/edits/tracks/update

PUT https://www.googleapis.com/androidpublisher/v3/applications/packageName/edits/editId/tracks/{track}

{track}には alpha, beta, production, rollout, internal を指定しましょう。弊社では毎回 alpha でアップロードしています。( internal の方がGoogle Playへの反映が早いですし、そちらでアップロードすることを検討してもいいかもしれませんね…。)

Content-Typeは application/json を指定しましょう。

リクエストボディのフォーマットは

https://developers.google.com/android-publisher/api-ref/edits/tracks#resource

こちらに書いてあります。必須なのは trackreleases[].statusreleases[].versionCodes です。versionCodesにはアップロードしたAPKのVersionCodeを指定しましょう。statusは completed, draft, halted, inProgress ですが、弊社では draft でアップロードし、リリースノート等は後で入力するという運用にしています。

Editsをcommitする

https://developers.google.com/android-publisher/api-ref/edits/commit

POST https://www.googleapis.com/androidpublisher/v3/applications/{packageName}/edits/{editId}:commit

上記APIをeditIdを指定して呼び出せば、今まで行った全ての操作がGoogle Playに反映されます。リクエストボディは指定する必要はありません。

注意点

一つだけ注意点ですが、Editsを編集している際にはGoogle Play上でリリースを操作するのはやめましょう。トランザクション外で操作が発生していると、commitする段階でAPIリクエストが失敗します。

まとめ

以上がGoogle PlayへのAPKのアップロード方法です。少しAPIに癖はありますが、Editsの操作さえ分かってしまえば他のAPIも同じように呼ぶことが出来るはずです。皆さんも良いGoogle Playライフを。

この記事の内容への質問等があればこちらまで気軽にどうぞ。

https://twitter.com/kr9ly

来年のDroidKaigiの話

ちなみに、来年のDroidKaigiでもCfPを出そうと思っているのですが、Kotlin Coroutinesで状態遷移を可視化して管理するみたいな話をしたいと思っています。Kotlin Coroutinesの無限のパワーをどう生かすかという話は来年はいっぱいCfPが出てきそうですが、今のうちにしっかり準備してめちゃくちゃ面白い発表にしたいと思っています。(通るといいな…)