こんにちは。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はトランザクションの単位と考えれば間違えが無いと思います。
なお、こちらが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}は media
か resumable
を設定できますが、
今回はmedia
を指定した場合の説明だけをしておきます。
Content-Typeは application/octet-stream
か application/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
こちらに書いてあります。必須なのは track
と releases[].status
、releases[].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ライフを。
この記事の内容への質問等があればこちらまで気軽にどうぞ。
来年のDroidKaigiの話
ちなみに、来年のDroidKaigiでもCfPを出そうと思っているのですが、Kotlin Coroutinesで状態遷移を可視化して管理するみたいな話をしたいと思っています。Kotlin Coroutinesの無限のパワーをどう生かすかという話は来年はいっぱいCfPが出てきそうですが、今のうちにしっかり準備してめちゃくちゃ面白い発表にしたいと思っています。(通るといいな…)