アンドロイドアプリストア登録

2023-03-18 hit count image

リアクトネイティブ(React Native)で開発したアンドロイドアプリ(Android App)をアンドロイドアプリストア(Google Play)に登録して見ましょう。

概要

リアクトネイティブ(React Native)で開発したアンドロイドアプリ(Android App)をアンドロイドアプリストア(Google Play)に登録してみようかと思います。アンドロイドアプリ(Android App)をアンドロイドアプリストア(Google Play)に登録するためにはアンドロイド開発者登録(グーグルプレイ開発者登録)が必要です。アンドロイド開発者登録(グーグルプレイ開発者登録)をしてない方は以前のブログを参考して登録してください。(アンドロイド開発者登録)

このブログはシリーズです。下記のブログも確認してください。

準備

リアクトネイティブ(React Native)で開発したアンドロイドアプリ(Android App)をアンドロイドアプリストア(Google Play)に灯篭するためリアクトネイティブ(React Native)をアンドロイド用にビルドする必要があります。リアクトネイティブ(React Native)にアンドロイド署名キー(Android Signing Key)を登録してアンドロイド用にビルドする方法については以前のブログを参考してください。

ビルドファイルサイズ最適化

以前のブログであるアンドロイドビルドやテストでアンドロイド用にビルドされたファイルはファイルサイズの最適化がされてないです。リアクトネイティブ(React Native)で開発したアンドロイドアプリ(Android App)をアンドロイドアプリストア(Google Play)にアップロードするためにはビルドファイルサイズを最適化する必要があります。

リアクトネイティブ(React Native)プロジェクトフォルダでandroid/app/build.gradleを開いて下記のように修正します。

...
defaultConfig {
    ...
    // ndk {
    //     abiFilters "armeabi-v7a", "x86"
    // }
}
...
def enableSeparateBuildPerCPUArchitecture = true

def enableProguardInReleaseBuilds = true
...
buildTypes {
    release {
        shrinkResources true
        ...
    }
}
..
  • enableSeparateBuildPerCPUArchitecture: apkファイルビルドする時、各CPU別ファイルを分離してapkファイルを生成します。他のCPUへ必要な内容が抜けるので、ファイルサイズが小さくなります。しかし、apkファイルが複数生成されるので、アプリをデプロイする時はそのファイル全部をアップロードする必要があります。
  • enableProguardInReleaseBuilds: コード難読化へ必要なProguardを使います。Proguardはコードの難読化をするし、コードのサイズも減らしてくれるのでファイルサイズが小さくなります。
  • shrinkResources: いらないリソースを消してファイルサイズを小さくします。(アプリでローカルイメージが表示されない場合はこの部分をfalseで設定して使ってください。)

そして下記のコマンドを使ってリアクトネイティブ(React Native)をアンドロイド用にビルドします。

# react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle
# cd android
# ./gradlew assembleRelease
./gradlew app:assembleRelease --stacktrace

このように--stacktraceオプションを入れる理由はenableProguardInReleaseBuilds = trueを設定すると下記のようなビルドエラーが発生する場合があるからです。

...
Note: the configuration keeps the entry point 'okhttp3.internal.ws.WebSocketWriter { void writePong(okio.ByteString); }', but not the descriptor class 'okio.ByteString'
Note: the configuration keeps the entry point 'okhttp3.internal.ws.WebSocketWriter { void writeClose(int,okio.ByteString); }', but not the descriptor class 'okio.ByteString'
Note: the configuration keeps the entry point 'okhttp3.internal.ws.WebSocketWriter { void writeControlFrame(int,okio.ByteString); }', but not the descriptor class 'okio.ByteString'
Note: the configuration keeps the entry point 'okhttp3.internal.ws.WebSocketWriter$FrameSink { void write(okio.Buffer,long); }', but not the descriptor class 'okio.Buffer'
Note: the configuration keeps the entry point 'okio.AsyncTimeout { void scheduleTimeout(okio.AsyncTimeout,long,boolean); }', but not the descriptor class 'okio.AsyncTimeout'
Note: the configuration keeps the entry point 'okio.AsyncTimeout { boolean cancelScheduledTimeout(okio.AsyncTimeout); }', but not the descriptor class 'okio.AsyncTimeout'
Note: the configuration keeps the entry point 'okio.AsyncTimeout { okio.Sink sink(okio.Sink); }', but not the descriptor class 'okio.Sink'
Note: the configuration keeps the entry point 'okio.AsyncTimeout { okio.Source source(okio.Source); }', but not the descriptor class 'okio.Source'
Note: the configuration keeps the entry point 'okio.ForwardingSink { ForwardingSink(okio.Sink); }', but not the descriptor class 'okio.Sink'
Note: the configuration keeps the entry point 'okio.ForwardingSink { void write(okio.Buffer,long); }', but not the descriptor class 'okio.Buffer'
Note: the configuration keeps the entry point 'okio.ForwardingSource { ForwardingSource(okio.Source); }', but not the descriptor class 'okio.Source'
Note: the configuration keeps the entry point 'okio.ForwardingSource { long read(okio.Buffer,long); }', but not the descriptor class 'okio.Buffer'
...
* What went wrong:
Execution failed for task ':app:transformClassesAndResourcesWithProguardForRelease'.
> Job failed, see logs for details
...

上のようにビルドエラーが出る場合、android/app/proguard-rules.proファイルを開いて下記のように追加します。 파일을 열고 하단에 아래와 같이 추가합니다.

# Note: the configuration keeps the entry point 'okio.AsyncTimeout { void scheduleTimeout(okio.AsyncTimeout,long,boolean); }', but not the descriptor class 'okio.AsyncTimeou
-dontwarn okio.**
# Note: the configuration keeps the entry point 'okhttp3.internal.ws.WebSocketWriter$FrameSink { void write(okio.Buffer,long); }', but not the descriptor class 'okio.Buffer'
-dontwarn okhttp3.**

上のエラー以外も使ってるライブラリによってもっとエラーが出る可能性もあります。そのメッセージを見ってandroid/app/proguard-rules.proを修正してください。

ビルドされたファイルは下記の位置で確認できます。

android/app/build/outputs/apk/release/app-arm64-v8a-release.apk.apk
android/app/build/outputs/apk/release/app-armeabi-v7a-release.apk.apk
android/app/build/outputs/apk/release/app-x86_64-release.apk.apk
android/app/build/outputs/apk/release/app-x86-release.apk.apk

このファイル全てをアップロードする必要があります。

include

アプリ登録

下記のリンクを押してグーグルプレイコンソル(Google Play Console)に移動します。

グーグルプレイコンソル(Google Play Console)に移動したら下記の画面が見えます。

グーグルプレイコンソルホーム

画面の上にあるPUBLISH AN ANDROID APP ON GOOGLE PLAYボタンを押します。

グーグルプレイコンソルアプリタイトル

アンドロイドアプリストア(Google Play)に表示される名前と基本言語を選択します。

グーグルプレイコンソルアプリ情報

アンドロイドアプリストア(Google Play)に表示される情報を入力します。

  • タイトル(title): 50文字
  • 要約説明(short description): 80文字
  • 全体説明(full description): 4000文字
  • アプリイメージ(Screenshots)
  • アプリアイコン(App icon): 512x512(32-bit PNG, alpha), 1024x500(JPG or 24-bit PNG), 180x120(JPG or 24-bit PNG), 1280x720(JPG or 24-bit PNG), 4096x4096(JPG or 24-bit PNG)
  • プロモーションビデオ(Promo Video)
  • アプリカテゴリ(Category)
  • 開発者連絡先(Contact details)
  • 個人情報ポリシー(Privacy Policy)

全ての情報を入力したらapkファイルを登録する方法について説明します。

左上にあるApp releaseメニューを押したら下記の画面が見えます。

グーグルプレイアプリ登録

画面に見えるProduction trackProduction項目のMANAGEを押します。

グーグルプレイアプリproduction生成

上のような画面が見えたら下のCREATE RELEASEを押します。

グーグルプレイアプリ署名キー登録

グーグルプレイ(Google Play)を使ってアプリ署名(App Signing)をするためFINISHボタンを押します。

グーグルプレイ利用規約同意

上のような利用規約が表示されたら下にあるACCEPTボタンを押して同意します。

グーグルプレイapkアップロード

上でビルド下リアクトネイティブ(React Native)のapkファイルをアップロードします。

グーグルプレイapkリリースノート

アプリの配布名前(Release Name)と配布ノート(Release Note)を作成して右下のSAVEボタンを押します。そしたら右のREVIEWボタンがアクティブになります。アクティブになったREVIEWボタンを押します。

グーグルプレイ登録不可

アプリの登録手続きが終わってないので右下のSTART ROLLOUT TO PRODUCTIONボタンがアクティブになりません。左メニューのContent ratingを押します。

グーグルプレイコンテンツ評価

コンテンツ評価(Content Rating)を設定する画面です。CONTINUEを押します。

グーグルプレイコンテンツ評価情報入力

メール情報やアプリのカテゴリを選択します。

グーグルプレイコンテンツ評価情報同意

アプリのコンテンツ評価を決めるための情報を選択します。全て選択したら下のSAVE QUESTIONNAIREボタンを押してアクティブされたCALCULATE RATINGを押します。

グーグルプレイコンテンツ評価情報選択完了

入力した情報をベースでコンテンツ評価が計算されて出ます。内容を確認して下のAPPLYING RATINGを押します。

グーグルプレイコンテンツ評価完了

コンテンツ評価の入力を完了しました。コンテンツ評価に影響があるアップデートがあったら、コンテンツ評価を再計算する必要がありますので、上の手続きをまたしてください。

グーグルプレイコンテンツ評価

最後の手続きである料金の設定をするため左メニューのPricing & distributionを押します。

グーグルプレイアプリ料金情報

アプリの料金を設定する画面です。私たちは無料でアプリを提供する予定なので、FREEを設定して進めます。また、子供向け、アプリに広告が含まれてあるかなど情報を入力します。必須項目を全て入力したら下のSAVE DRAFTボタンを押します。

include

アプリ審査申請

アプリ審査(App Review)のための準備が終わりました。メニューのApp releaseを押します。

グーグルプレイアプリ審査

上で作成したProduction項目の横にあるEDIT RELEASEボタンを押します。

グーグルプレイアプリ審査情報

上で作成した情報が見えます。スクロールして下に移動して、REVIEWボタンを選択します。

グーグルプレイアプリ審査申請

上のような画面が見えたらスクロールして下に移動してSTART ROLLOUT TO PRODUCTIONを押します。

グーグルプレイアプリ登録

アプリ審査の準備が終わったらCONFIRMボタンを押してアプリ審査を申請します。

エラー対応

下記のコマンドでアンドロイドをビルドする時、

./gradlew assembleRelease

下記のようなエラーメッセージが出ってビルドが失敗される時があります。

Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForRelease'.

下記の内容をandroid/app/build.gradleに追加してもう一回ビルドします。

defaultConfig {
    ...
    multiDexEnabled true
}

ビルドエラー対応

リアクトネイティブ(React Native)のバージョン0.58で下記のコマンドを実行したら

./gradlew assembleRelease

下記のエラーが出ます。

  --auto-add-overlay\
          --non-final-ids\
          -0\
          apk\
          --no-version-vectors
  Daemon:  AAPT2 aapt2-3.2.1-4818971-osx Daemon #0

下記のコマンドで実行したらビルドができます。

./gradlew app:assembleRelease

権限エラー

リアクトネイティブ(React Native)のバージョン0.58でビルドしたファイルをグーグルプレイへアップロードする時android.permission.READ_PHONE_STATE権限が含めてるのでダメですのエラーが出ます。

公式サイトに解決方法があります。

https://facebook.github.io/react-native/docs/removing-default-permissions

それを見ながらやってみます。

リアクトネイティブ(React Native)プロジェクトのandroid/app/src/main/AndroidManifest.xmlのファイルを開いて下記のように修正します。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="XXXXXXXX"
+   xmlns:tools="http://schemas.android.com/tools"
    >

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+   <uses-permission tools:node="remove" android:name="android.permission.READ_PHONE_STATE" />
+   <uses-permission tools:node="remove" android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+   <uses-permission tools:node="remove" android:name="android.permission.READ_EXTERNAL_STORAGE" />
...

そしてandroid/app/src/release/AndroidManifest.xmlファイルを生成して下記の内容をコピペします。(パッケージ名は自分のパッケージ名を入れてください。)

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="XXXXXXX"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission tools:node="remove" android:name="android.permission.SYSTEM_ALERT_WINDOW" />

</manifest>

これでビルドしてアップロードしたら問題なくアップロードできることを確認できます。

include

Android 4.4.2 Kitkat

リアクトネイティブ(React Native) 0.58でビルドしたファイルをアンドロイド4.4.2(Kitkat)の端末でテストする時、アプリがCrashが発生して起動出来ない問題が発生しました。問題を調査した結果、multiDexEnabledの問題で下記の内容を追加して解決しました。

リアクトネイティブ(React Native)プロジェクトのandroid/app/build.gradleを開いて下記の内容を追加してください。

dependencies {
    implementation project(':react-native-firebase')
    ...
    implementation 'com.android.support:multidex:1.0.1'
}

また、MainApplication.javaを開いて下記のように修正してください。

import android.app.Application;
import android.content.Context;
import android.support.multidex.MultiDex;
...
public class MainApplication extends Application implements ReactApplication {
  @Override
  protected void attachBaseContext(Context base) {
      super.attachBaseContext(base);
      MultiDex.install(this);
  }
  ...
}

このように修正してアンドロイド4.4.2(Kitkat)でテストしたら無事に動作することを確認出来ます。

Unoptimised APK

最近APKファイルをアップロードしてアップデートすると下記の警告メッセージが表示されます。

unoptimised apk android app bundle 警告

下記のコマンドでAPKではなくapp bundleを生成します。

./gradlew app:bundleRelease

このコマンドで生成されたファイルはandroid/app/build/outputs/bundle/release/app.aabにあります。

この1つのファイルをアップロードすれば大丈夫です。

私の場合、package.jsonへ下記のスクリプトを追加して使っています。

...
"scripts": {
    ...
    "prebuild-android": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle",
    "build-android": "cd ./android && ./gradlew app:bundleRelease --stacktrace "
}
...

下記のコマンドでビルドします。

npm run build-android

完了

アンドロイドアプリストア(Google Play)にアプリを登録するための手続きが終わりました。アプリ審査は2~3時間くらいかかります。アプリの審査が終わったら登録申請したアプリをアンドロイドアプリストア(Google Play)で検索やダウンロードができます。

私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!

アプリ広報

今見てるブログを作成たDekuが開発したアプリを使ってみてください。
Dekuが開発したアプリはFlutterで開発されています。

興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。

Posts