2017年6月1日木曜日

react-native(re-natal)で作ったアプリをリリースする方法: Android編


ところどころ詰まったり迷ったりしたので、自分なりにまとめたメモを共有します。
なお、re-natalで作ったアプリのリリースに必要な設定内容は、ほとんどreact-nativeで作ったアプリのリリースに必要な手順と同じだったので、react-nativeを利用されている方も参考になると思います。

全体像

  • 使ったものの説明
  • keystoreの設定
  • デフォルト画像の変更
  • 権限の変更
  • リリース用とデバッグ用でアプリのIDとバージョンを変える
  • バージョンの更新
  • apkのビルド
  • デベロッパーコンソールにapkを登録

使ったものの説明

react-natie

facebookが公開しているスマホ(iOSとAndroid)アプリをjavascriptで開発できるフレームワークです。

https://facebook.github.io/react-native/

re-natal

react-nativeをclojurescriptで開発できるようにしたフレームワークです。
今回の説明に使うアプリは、re-natalで開発しています。

https://github.com/drapanjanas/re-natal

リリースしたいreact-nativeかre-natalのプロジェクト

今回はBLEを操作するこちらのアプリのリリース方法を説明します。

https://github.com/asukiaaa/re-natal-esp32control-app

$25

Google Play Consoleを利用するために必要です。

keystoreの設定

Androidアプリをリリースするには、アプリ用のkeystoreを設定する必要があります。
Generating Signed APKの説明に従い、下記のようにkeystoreを設定しました。

紹介する内容は、アプリ名に合わせてesp32-control-appという文字列をファイル名や変数名に利用しています。

android/appにkeystoreを設置

下記のコマンドでkeystoreを設置します。
コマンド実行時に要求される「STORE_PASSWORD」と「KEY_PASSWORD」は、この後の変数設定とgoogle play consoleでのアプリリリース時に利用するので、メモなどに残しておくと良いと思います。
cd [app-dir]/android/app
keytool -genkey -v -keystore esp32-control-app-release-key.keystore -alias esp32-control-app-key-alias -keyalg RSA -keysize 2048 -validity 10000

keystoreの値をアプリに設定

keystoreの作成に使ったパスワードなどをアプリに設定したいものの、gitのコミットにはパスワードなどを残したくないので、「~/.gradle/gradle.properties」経由で設定します。

まず、「~/.gradle/gradle.properties」(アプリのディレクトリではなく、PCのホームディレクトリにあるファイル)に下記の情報を記述します。
「*****」は入力したパスワードと置き換えてください。
~/.gradle/gradle.properties
ESP32_CONTROL_APP_RELEASE_STORE_FILE=esp32-control-app-release-key.keystore
ESP32_CONTROL_APP_RELEASE_KEY_ALIAS=esp32-control-app-key-alias
ESP32_CONTROL_APP_RELEASE_STORE_PASSWORD=*****
ESP32_CONTROL_APP_RELEASE_KEY_PASSWORD=*****

その後、gradle.propertiesに定義した変数を使って、アプリにkeystoreの情報を設定します。
下記のように行を追加もしくは編集を行ってください。
[app-dir]/android/app/build.gradle
...
android {
    ...
    defaultConfig { ... }
    signingConfigs {
        release {
            if (project.hasProperty('ESP32_CONTROL_APP_RELEASE_STORE_FILE')) {
                storeFile file(ESP32_CONTROL_APP_RELEASE_STORE_FILE)
                storePassword ESP32_CONTROL_APP_RELEASE_STORE_PASSWORD
                keyAlias ESP32_CONTROL_APP_RELEASE_KEY_ALIAS
                keyPassword ESP32_CONTROL_APP_RELEASE_KEY_PASSWORD
            }
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
}
...

keystoreをアプリのビルド時に紐付ける設定ができました。

デフォルト画像の変更


アプリ作成時から標準で使われている画像をアプリオリジナルの画像に置き換えます。
置き換えが必要な画像は、それぞれ下記の場所にあります。

androidアプリのアイコン
# 72x72px
android/app/src/main/res/mipmap-hdpi/*
# 48x48px
android/app/src/main/res/mipmap-mdpi/*
# 96x96px
android/app/src/main/res/mipmap-xhdpi/*
# 144x144px
android/app/src/main/res/mipmap-xxhdpi/*

re-natalで使われているイメージ
images/*

自分はre-natalで使われているclojure-scriptのロゴをトップページに残したままリリースしようとしたら、下記のメッセージで却下されました。

I reviewed ESP32StackCar, com.renatalesp32controlapp, and had to reject it because of an unauthorized use of copyrighted content. If you submitted an update, the previous version of your app is still live on Google Play.

画像をオリジナルのものに置き換えたら、承認されてリリース出来ました。

権限の変更

何も意識せずにリリースをしたら、BLEを扱うための権限だけを付与したつもりが、「端末上の画像、動画、音声など」と「電話番号、端末ID、通話状況」などの設定したつもりのない権限をインストール時に要求するアプリができてしまいました。


これは、READ_PHONE_STATEやREAD_EXTERNAL_STORAGEなどの権限が有効になってしまう問題がreact-nativeにあるため、こうなるようです。

React native is adding an unnecessary user permission

問題について議論している上記ページには、不要な権限に対して「tools:node="remove"」を設定すれば権限を削除できるということでした。
そのため、今回のアプリに対して下記の変更を行いました。
[app-dir]/android/app/build.gradle
android {
    ...
    buildTypes {
        debug {
            manifestPlaceholders = [excludeSystemAlertWindowPermission: "false"]
        }
        release {
            manifestPlaceholders = [excludeSystemAlertWindowPermission: "true"]
            ...
        }
    }
}
[app-dir]/android/app/src/main/AndroidManifest.xml
<manifest
    ...
    xmlns:tools="http://schemas.android.com/tools">
    ...

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" tools:remove="${excludeSystemAlertWindowPermission}"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove" />

</manifest>

SYSTEM_ALERT_WINDOWについてはbuild.gradleで変数を設定し、リリース版からは権限を削除するようにしています。

これにより、不要なパーミッションを削除することができ、この後リリースしたアプリでは期待するパーミッションだけを要求するようになりました。


参考コミット: Remove redundant permission for android app


リリース用とデバッグ用でアプリのIDとバージョンを変える


スマホで動作確認する場合に、デバッグ(開発)用アプリとリリース用アプリのIDが同じだと、片方をインストールするために、既にインストールしている片方をアンインストールする必要があります。

下記の記述を追加することで、開発用のアプリのIDを変えられるので、本番用アプリと開発用アプリと同じ端末にインストールできます。
[app-dir]/android/app/build.gradle
...
android {
    ...
    buildTypes {
        debug {
            ...
            versionNameSuffix "-dev"
            applicationIdSuffix ".dev"
        }
    }
}
...

本番アプリか開発アプリかは、アプリ情報のバージョンで識別できます。


ちなみに、この設定を行う前にインストールした開発用アプリは、リリース用アプリと同じIDが割り当てられているため、リリース用アプリインストール時は古いアプリのアンインストールが必要です。

注意
targetSdkVersionを23に指定した上でapplicationIdSuffixで開発用アプリのIDを変更すると、「react-native run-android」実行時に下記のエラーが出ます。
Starting: Intent { cmp=com.renatalesp32controlapp/.MainActivity }
Error type 3
Error: Activity class {com.renatalesp32controlapp/com.renatalesp32controlapp.MainActivity} does not exist.
targetSdkVersionが23の時に、上記のエラーを出さずにIDを出し分ける方法をご存知でしたら、共有していただけると嬉しいです。

参考ページ: ビルド バリアント向けにアプリケーション ID を変更する

参考コミット: Add suffix to name and version for debug app

バージョンの更新

初回リリース時は必要有りませんが、2回目以後のリリースでは下記のような変更でアプリのバージョンを変えられます。
この変更をしないと、apkアップロード時にバージョン重複でエラーになります。

[app-dir]/android/app/build.gradle
android {
    ...
    defaultConfig {
    ...
        versionCode 2
        versionName "1.1"
    }
}

apkのビルド

re-natalで開発している場合

re-natalで開発したアプリの場合、react-nativeのビルド用コマンドの実行前に、下記のコマンドを実行します。
react-nativeで開発されている方はこちらのコマンドは無視してください。
cd [app-dir]
lein prod-build

参考: re-natal#production-build

re-natal react-native共通

reacti-nativeのビルドコマンドを実行します。
cd [app-dir]/android
./gradlew assembleRelease

これによって、「[app-dir]/android/app/build/outputs/apk/app-release.apk」ができます。
上記のapkは下記のコマンドで動作確認ができます。
cd [app-dir]
react-native run-android --variant=release

参考: signed-apk-android.html

デベロッパーコンソールにapkを登録


googleのGUIは頻繁に変わるイメージがあるのと、色々なサイトで情報が共有されているので、ここでは文章でザックリと説明します。

Google Play Consoleにログイン

Google Play Consoleを初めて使う方は、情報を登録して、$25をお支払いください。

アプリの作成

リリースしたいアプリの名前などを入力して、アプリのアップロード先を作ります。

apkをアップロード

react-nativeのビルドコマンドで作成したapp-release.apkをアップロードします。

アプリの説明文とスクリーンショットの登録

PHONE_STATEなど個人情報に関する権限を必要とする場合は、プライバシーポリシーページも別途必要となります。
先程紹介した権限の無効化を行えば、プライバシーポリシーページは不要なはずです。

対象年齢(Content rating)の設定

アンケート回答後のボタン配置が個人的に分かりにくかったです。
操作し終えたつもりなのにまだ「不足する情報」に表示される場合は、回答が終えられていない可能性があるので、よくご確認ください。
(自分は確定していなかったのに、1日googleの動きを待ってしまいました。)

リリース申請

上記の操作ができたら、リリースを申請します。
アプリの内容に問題がなければ数時間から数日でリリースされると思います。
内容に不備があれば却下のメッセージが届きます。


共有する内容は以上です。
この情報がアプリ作成のお役に立てば嬉しいです。

変更履歴

2017/06/10
applicationIdSuffixでdebugアプリのIDを変更するとreact-native run-androidで実行できなかったため、それに関する修正を削除しました。

2017/07/02
applicationIdSuffixはtargetSdkVersionが22だと動作したので、注意書きと共に解説を加えました。

0 件のコメント :