Android
 Computer >> コンピューター >  >> システム >> Android

Android App Bundle を Play ストアに自動的にアップロードする方法

この記事では、Android アプリ バンドル (.aab ファイル) を Play ストアのベータ トラックに自動的にアップロードする方法を説明します。クラウド インフラストラクチャ プロバイダーとして Android Studio と AWS を使用します。

アプリ バンドルをアップロードすると、Slack 通知がトリガーされます。

これは、オブザーバビリティの作成やプロセスの優先順位付けなど、さまざまな理由で貴重な時間の使い方です。

使用するテクノロジー

このチュートリアルで使用するリソースは次のとおりです。

<オール>
  • Android Studio
  • AWS CodeBuild
  • AWS ラムダ
  • S3
  • たるみ
  • プロジェクトの概要

    Android App Bundle を Play ストアに自動的にアップロードする方法

    上の画像は、全体をどのように構成するかの一般的な概要を示しています。

    基本的に、Android リポジトリ用に AWS にコード パイプラインを設定する必要があります。このコード パイプラインには、ステージの 1 つとしてコード ビルドがあります。

    Android アプリ リポジトリのマスター ブランチにプッシュすると、コード ビルドがトリガーされます。 Code Build プロジェクトは、コマンドラインから Android アプリに署名し、アーティファクトを S3 バケットにアップロードします。

    バンドルを S3 にアップロードすると、Lambda がトリガーされ、バンドルがダウンロードされ、Google Publishing API を使用して Play ストアにアップロードされます。 200 応答を受け取ると、Lambda は Slack 通知をトリガーします。

    Google Play Service アカウント キーを取得する方法

    Google Play Publisher API を使用できるようにするには、Google Play サービス アカウント キーが必要です。

    サービス アカウントは、サーバーが相互に通信しているときにユーザーに代わって動作できるアカウントです。 Google がサーバー間通信に OAuth2.0 をどのように使用しているかについては、こちらをご覧ください。

    サービス アカウントを作成して Google Play Publisher API へのアクセスを許可する方法については、こちらをご覧ください。

    サービス アカウントを作成して適切な権限を付与したら、サービス アカウント キーをダウンロードして安全に保管してください。これをすぐに S3 バケットにアップロードします。

    Android バンドルに署名する方法

    理解すべき主なことは、Android App Bundle に署名する方法です。 Google には、ここで見つけることができるかなり適切なドキュメントがあります。

    以下にリンクをまとめます。

    keytool を使用して秘密鍵を生成します このように:

    keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias
    

    好きなようにキーを呼び出すことができます。ここでは、my-release-key.jks と呼びます。 .必要なエイリアスを選択することもできます。このチュートリアル全体を通して、キーに正しい名前とエイリアスを使用していることを確認してください。

    build.gradle を開く あなたの app 内 Android Studio のディレクトリに次のコード ブロックを追加します:

    android {
        ...
        defaultConfig { ... }
        signingConfigs {
            release {
                // You need to specify either an absolute path or include the
                // keystore file in the same directory as the build.gradle file.
                storeFile file("my-release-key.jks")
                storePassword "password"
                keyAlias "my-alias"
                keyPassword "password"
            }
        }
        buildTypes {
            release {
                signingConfig signingConfigs.release
                ...
            }
        }
    }
    

    リリース キーの名前をデフォルト以外の名前に変更した場合は、必ず新しい名前を指定してください。エイリアスについても同じです。

    ストアのパスワードは、最初にアプリを Play ストアにアップロードしたときに生成したパスワードになります。

    ここで、コマンド ./gradlew :app:bundleRelease を実行すると Android Studio のコマンドラインから実行すると、署名された App Bundle が生成されることがわかります。

    署名情報をスクラブする方法

    build.gradle でプレーン テキストとして利用可能な署名情報を使用してコードをコミットする ファイルはセキュリティ リスクであり、攻撃ベクトルになる可能性があります。

    Google にはこれに関するドキュメントがあり、ここで見つけることができます。

    まず、keystore.properties を作成します プロジェクト ディレクトリのルートにあるファイル。

    ファイルの内容は次のようになります:

    storePassword=myStorePassword
    keyPassword=myKeyPassword
    keyAlias=myKeyAlias
    storeFile=myStoreFileLocation
    

    ストア パスワードとキー パスワードは、アプリ バンドルを初めて App Store にアップロードしたときに使用したパスワードになります。

    あなたの keyAlias そして storeFile それぞれ、秘密鍵の作成時に割り当てたエイリアスと、作成した秘密鍵の場所になります。

    次に、このファイルを build.gradle にロードする必要があります .これには最初は驚きましたが、Gradle は実際には DSL として機能します。そのため、Gradle を使用して構成を記述しやすくなります。

    //  Load properties from keystore.properties
    def keystorePropertiesFile = rootProject.file("keystore.properties")
    
    //  Creating a new Properties() object
    def keystoreProperties = new Properties()
    
    //  If keystorePropertiesFile exists, read from that, else set from build environment
    if (keystorePropertiesFile.exists()) {
        //  Loading the keystoreProperties file
        keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
    } else {
        //  Read all environment variables from the build environment
        keystoreProperties.setProperty("storeFile", "${System.getenv('STORE_FILE')}")
        keystoreProperties.setProperty("keyAlias", "${System.getenv('KEY_ALIAS')}")
        keystoreProperties.setProperty("keyPassword", "${System.getenv('KEY_PASSWORD')}")
        keystoreProperties.setProperty("storePassword", "${System.getenv('STORE_PASSWORD')}")
    }
    

    そこに if 条件があることに気付くでしょう。今は気にしないでください。後でコード ビルドを説明するために特にあります。

    これを行ったら、 signingConfigs を変更します build.gradle のセクション 次のようになります:

    signingConfigs {
            release {
                storeFile file(keystoreProperties['storeFile'])
                keyAlias keystoreProperties['keyAlias']
                keyPassword keystoreProperties['keyPassword']
                storePassword keystoreProperties['storePassword']
            }
        }
    

    AWS Code Pipeline の設定方法

    比較的簡単なので、これについてはあまり詳しく説明しません。

    次の 3 つのステージで AWS Code Pipeline をセットアップします。

    <オール>
  • GitHub リポジトリの master に接続されたソース ステージ 支店
  • AWS Code Build に接続されたビルド ステージ
  • S3 バケットにデプロイするデプロイ ステージ
  • コード パイプラインの設定に関するその他のドキュメントは、こちらにあります。

    AWS S3 の設定方法

    まず、ステージの 1 つとしてコード ビルドを使用してコード パイプラインが設定されていることを確認します。次に、2 つの S3 バケットをセットアップします。

    <オール>
  • リリースキーを保存するバケット。私はこのバケットを release-key.jks と呼んでいます
  • Google Play サービス アカウントの秘密鍵を保存するバケット。 (サービス アカウントの作成時にこのキーをダウンロードしておく必要があります。)
  • Code Build サービス ロールからこれらのバケットへのアクセスを許可する必要があります。コード パイプラインをセットアップするときに、コード ビルド サービス ロールが作成されているはずです。

    IAM コンソールに移動し、コード ビルド サービス ロールを見つけて、ARN を取得します。

    次に、コンソールを使用して、バケット release-key.jks の [アクセス許可] タブに移動します。 そこに次のポリシーを追加します:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "AWS": [
                        "arn:aws:iam::123456789:role/service-role/codebuild-service-role-dummy",
                    ]
                },
                "Action": "s3:GetObject",
                "Resource": "arn:aws:s3:::release-key-bucket/*"
            }
        ]
    }
    

    このポリシーは、CodeBuild プロジェクトが実行されるマシンから S3 バケットへのアクセスを許可します。

    上記の ARN をアカウントの ARN に置き換える必要があります。ポリシーを更新するときは、Code Build サービスロールに正しい ARN を指定してください。

    2 番目のバケットのアクセス許可ポリシーを変更する必要はありません。関連する権限を AWS Lambda ロールに追加して、バケットへのアクセスを許可します。

    AWS CodeBuild のセットアップ方法

    次に、buildspec.yml を作成します。 プロジェクト ルート フォルダー内のファイル。

    version: 0.2
    
    phases:
      build:
        commands:
          - aws s3api get-object --bucket release-key.jks --key release-key.jks ./releaseKey.jks
          - cp ./releaseKey.jks ${CODEBUILD_SRC_DIR}/app/releaseKey.jks
          - export STORE_FILE=releaseKey.jks
          - export KEY_ALIAS=$keyAlias
          - export KEY_PASSWORD=$keyPassword
          - export STORE_PASSWORD=$storePassword
          - ./gradlew :app:bundleRelease
    
    artifacts:
      files:
        - app/build/outputs/bundle/release/app-release.aab
    

    このファイルは非常に単純です。指定されたバケットからリリース キーを取得し、コード ビルド サーバー上の指定された場所にあるローカル ファイルに保存します。

    次に、build.gradle に必要なすべての変数をエクスポートします。 正しく動作するための構成。最後に、コマンド ラインから Gradle のリリース コマンドを実行します。

    このスクリプトを Code Build で実行する前に、変数を Code Build 環境に追加する必要があります。これを行うには、まず AWS Code Build コンソールに移動し、Android アプリのビルド プロジェクトを選択します。

    次に、下のスクリーンショットのように [編集]> [環境] を選択します。

    Android App Bundle を Play ストアに自動的にアップロードする方法

    これを行うとポップアップする画面で、[追加の構成] ドロップダウンを選択します。キーと値のペアを使用して環境変数を追加するオプションが表示されます。

    コードビルドが buildspec.yml を実行すると ファイルを作成すると、指定された変数をエクスポートできるようになります。

    現状では、パイプラインが実行されると、Code Build は秘密鍵をダウンロードして Android アプリに署名およびビルドし、署名済みバンドルを S3 バケットにアップロードできます。

    Slack アプリの設定方法

    可観測性は自動化の特徴です。自動化がいつ実行されるか、成功したか失敗したか、失敗した場合は失敗の理由を知りたい.

    AWS がオブザーバビリティを処理する通常の方法は、CloudWatch を使用することです。しかし、Slack の統合も同様に目的を果たしていると思います。

    Slack をオートメーション ワークフローに統合する最も簡単な方法は、Slack アプリをセットアップし、オートメーション ワークフローからそのアプリに通知を送信することです。

    Slack アプリのセットアップ方法については、こちらのドキュメントを参照してください。プロセスは非常に簡単で、数分でアプリを起動して実行できます。

    アプリを作成すると、アプリを呼び出して関連するチャネルに投稿するために使用できる WebHook URL が取得されます。 AWS Lambda 関数でこれを使用するため、この WebHook URL を追跡します。

    AWS Lambda の設定方法

    これまでのところ、Android App Bundle が署名され、ビルドされ、S3 バケットにアップロードされました。次に、バンドルを Play ストアのベータ トラックにアップロードする方法を理解する必要があります。

    これを行う方法は、バンドルが S3 バケットにアップロードされたときにトリガーされる AWS Lambda をセットアップすることです。このトリガーが発生すると、Lambda が実行され、バンドルがダウンロードされ、サービス アカウント キーが取得され、バンドルが Play ストア ベータ トラックにアップロードされます。

    Lambda を作成し、ファイルがバケットにアップロードされたときに実行するトリガーを追加したら、以下のコードを見てください:

    """This Python3 script is used to upload a new .aab bundle to the play store. The execution of this Python script
        occurs through an AWS Lambda which is invoked when a new file is uploaded to the relevant S3 buckets"""
    
    import json
    import boto3
    import os
    from urllib import request, parse
    from google.oauth2 import service_account
    import googleapiclient.discovery
    
    #   Defining the scope of the authorization request
    SCOPES = ['https://www.googleapis.com/auth/androidpublisher']
    
    #   Package name for app
    package_name = 'com.app.name'
    
    #   Define the slack webhook url
    slack_webhook_url = os.environ['SLACK_WEBHOOK_URL']
    
    def send_slack_message(message):
        data = json.dumps({ 'text': message })
        post_data = data.encode('utf-8')
        req = request.Request(slack_webhook_url, data=post_data, headers={ 'Content-Type': 'application/json' })
        request.urlopen(req)
    
    #   This is the main handler function
    def lambda_handler(event, context):
        #   Create a new client S3 client and download the correct file from the bucket
        s3 = boto3.client('s3')
        s3.download_file('service-account-bucket-key', 'service-account-bucket-key.json', '/tmp/service-account-key.json')
        SERVICE_ACCOUNT_FILE = '/tmp/service-account-key.json'
    
        #   Download the app-release.aab file that triggered the Lambda
        bucket_name = event['Records'][0]['s3']['bucket']['name']
        file_key = event['Records'][0]['s3']['object']['key']
        s3.download_file(bucket_name, file_key, '/tmp/app-release.aab')
        APP_BUNDLE = '/tmp/app-release.aab'
    
        print(f"A bundle uploaded to {bucket_name} has triggered the Lambda")
    
        #   Create a credentials object and create a service object using the credentials object
        credentials = service_account.Credentials.from_service_account_file(
            SERVICE_ACCOUNT_FILE, scopes=SCOPES
        )
        service = googleapiclient.discovery.build('androidpublisher', 'v3', credentials=credentials, cache_discovery=False)
        
        #   Create an edit request using the service object and get the editId
        edit_request = service.edits().insert(body={}, packageName=package_name)
        result = edit_request.execute()
        edit_id = result['id']
    
        #   Create a request to upload the app bundle
        try:
            bundle_response = service.edits().bundles().upload(
                editId=edit_id,
                packageName=package_name,
                media_body=APP_BUNDLE,
                media_mime_type="application/octet-stream"
            ).execute()
        except Exception as err:
            message = f"There was an error while uploading a new version of {package_name}"
            send_slack_message(message)
            raise err
    
        print(f"Version code {bundle_response['versionCode']} has been uploaded")
    
        #   Create a track request to upload the bundle to the beta track
        track_response = service.edits().tracks().update(
            editId=edit_id,
            track='beta',
            packageName=package_name,
            body={u'releases': [{
                u'versionCodes': [str(bundle_response['versionCode'])],
                u'status': u'completed',
            }]}
        ).execute()
    
        print("The bundle has been committed to the beta track")
    
        #   Create a commit request to commit the edit to BETA track
        commit_request = service.edits().commit(
            editId=edit_id,
            packageName=package_name
        ).execute()
    
        print(f"Edit {commit_request['id']} has been committed")
    
        message = f"Version code {bundle_response['versionCode']} has been uploaded from the bucket {bucket_name}.\nEdit {commit_request['id']} has been committed"
        send_slack_message(message)
        
        return {
            'statusCode': 200,
            'body': json.dumps('Successfully executed the app bundle release to beta')
        }
    

    上記の Lambda は googleapiclient を使用します ライブラリとその検出モジュールを使用して、Google Play の Publishing API の URL を構築します。

    次に、Lambda は、以前に設定したバケットからサービス アカウント キーをダウンロードします。正しいバケット名を指定する必要があります。

    アップロードが成功するか失敗するかに応じて、Slack メッセージを送信します。前のセクションの Slack WebHook URL を Lambda の環境変数に追加します。上記の関数は Python の os を使用しています モジュールを使用して環境変数にアクセスし、メッセージを Slack に投稿します。

    Lambda が失敗した場合、Google Play サービス アカウントのキーが保存されている S3 バケットにアクセスする権限が Lambda にないことが原因である可能性があります。その場合、これを示すエラー メッセージが表示されます。

    これを修正するには、関連するアクセス許可を Lambda ロールに追加するだけです。

    追加する必要があるポリシーは次のとおりです:

    {
        "Version": "2012-10-07",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "s3:GetObjectVersion",
                    "s3:GetBucketVersioning",
                    "s3:GetBucketAcl",
                    "s3:GetObject",
                    "s3:GetBucketTagging",
                    "s3:GetBucketLocation",
                    "s3:GetObjectVersionAcl"
                ],
                "Resource": [
                    "arn:aws:s3:::arn:aws:s3:::your-bucket-name-with-service-account-key"
                ]
            }
        ]
    }
    

    バケットの ARN をアカウントに関連するものに置き換えれば、準備完了です。

    結論

    それで、あなたはそれを持っています。確かに簡単ではなく、可動部分がたくさんありますが、これは時間と労力を大幅に節約できる自動化です。

    新しいアプリのアップデートを頻繁にリリースするチームの一員である場合、アップデートのリリースを担当する担当者が 1 人いないことで妨げられたくはありません。

    この種の自動化を構築すると、CI/CD ワークフローがよりスムーズで堅牢になります。

    このようなブログに興味がある場合は、https://redixhumayun.github.io で詳細を読むか、Twitter でフォローしてください。


    1. 2019 年に Android アプリを開発する方法:「新しい」Android の採用

      Bitotsav 19 アプリがどのように実現したか 背景:パンテオン ’17 ⏪ ほぼ 2 年前の 2017 年 9 月、友人の Ashank Anshuman が、私たちの研究所のテクニカル フェスト用のアプリに取り組むよう説得してくれました。私たちは昼夜を問わず約 2 週間作業を行い、フェスティバルに間に合うようにリリースの準備を整えました。私たちは疲れ果てていましたが、人々が実際に使用した製品を「世に出して」手に入れたのは素晴らしい気分でした!主催者が参加者にすべてを簡単に伝えるのに役立ち、その目的を完全に果たしました. パンテオン 17 - Google Play のアプリ

    2. Amazon App Store から Windows 11 で Android アプリを実行する方法 (ハンズオン ビデオ)

      Windows 11 で最も期待されていた機能がついに登場しました。 Amazon App Store と Windows Subsystem for Android を介して、Windows 11 で Android アプリを実行できるようになりました。これがどのように機能するのか疑問に思われるかもしれませんが、私たちはあなたをカバーし、機能を実際に使ってみました. ステップ 1:要件を満たす 何かに飛び込む前に、Windows 11 で Android アプリを実行するための Microsoft の要件を考慮する必要があります。これらは非常に基本的なものです。現在の状態では、ベータ