Flutterで GooglePlay(Android) / AppStore(iOS) / FirebaseHosting(Web) にリリースする方法まとめ

---
# :book: Flutterの記事を整理し本にしました :book:
https://zenn.dev/kazutxt/books/flutter_practice_introduction

* <font color="red"><b>本稿の記事を含む様々な記事を体系的に整理し本にまとめました</b></font>
* 今後はこちらを最新化するため、<font color="red"><b>最新情報はこちらをご確認ください</b></font>
* 30万文字を超える超大作になっています!!

---

## まとめ記事
* [Flutter系の記事のまとめ](https://qiita.com/kazutxt/items/524acb1c134015682ccf)

# はじめに
* 過去に、Flutterアプリをリリースする手順を整理していたのですが、古くなり手順や項目が変わっていたので、再度確認しました。

#リリース編1:GooglePlay/Android

## 初回のみ行う作業
### 1. GooglePlayConsoleのアカウントを作る
下記、公式のGooglePlayConsoleにアクセスし、必要事項を入力しアカウントを登録して、登録料25$を払います。
https://play.google.com/console/signup

支払いが終わると、GooglePaymentsから「Google: ありがとうございます」というメールが来ます。

アカウントが承認されると「Google Play へようこそ」というメールが来ます。

◆ 注意
承認には時間がかかり、5日程度かかる場合もあります。

### 2. 証明書を作成する
公式のコマンドに従い、下記コマンドで証明書を生成します

```sh:command.sh
$ keytool -genkey -v -keystore ~/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key
```

上記で生成された、key.jksをアプリ内でパスワードと共に指定します。

```properties:key.properties
storePassword=<password from previous step>
keyPassword=<password from previous step>
keyAlias=key
storeFile=<location of the key store file, such as /Users/<user name>/key.jks>
```

## アプリごとに行う作業
### 1. 署名の組み込み
作った証明書をビルド時に組み込まれるようにします。

```groovy:appdir/build.gradle
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
 // androidブロックの前に入れる
android {
      ...
 }
```

```groovy:appdir/build.gradle
// buildTypesの前に入れる
signingConfigs {
  release {
    keyAlias keystoreProperties['keyAlias']
    keyPassword keystoreProperties['keyPassword']
    storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
    storePassword keystoreProperties['storePassword']
    }
}
   //debugからreleaseに変える
   buildTypes {
       release {
           signingConfig signingConfigs.release
       }
   }

```


### 2.アプリ名をつける
アプリ名をlabel部分に入れます。日本語も可能でアプリアイコンの下に表示されます。

```xml:appdir/android/app/src/main/AndroidManifest.xml

<application
    android:label="XXX"
    <!--中略-->
>
```

◆ 注意
必要なパーミッションが必要な場合(カメラやGPSを使うなど)は権限を追記します

### 3.ビルド構成の確認
```groovy:appdir/android/app/build.gradle
defaultConfig{
    applicationId "XXX"
    minSdkVersion XXX
    targetSdkVersion XXX
    versionCode flutterVersionCode.toInteger()
    versionName flutterVersionName
}
```

パッケージがデフォルト「com.example」だとリリース時にエラーになるため、自分のドメインに変更します。

◆ 注意
パッケージドメインの変更の仕方は「[Firebase編1:概要](https://zenn.dev/kazutxt/books/flutter_practice_introduction/viewer/firebase_overview)」チャプターで紹介しています。

minSdkVersion/targetSdkVersionは、Flutterのバージョンやパッケージによりエラーが出るときは、バージョンを上げてください。

### 4.ビルドをする

アプリバンドル形式でビルドします。

```sh:command.sh
$ flutter build appbundle
```

◆ 注意
null safetyかどうかはアプリの状況によりますが、ビルド/デプロイには影響はありません。

出力先は`appdir/build/app/outputs/bundle/release/app.aab`となります。

### 5.公開の準備をする

#### アプリ作成

GooglePlayからアプリの作成を行います。
`Google Play Console > すべてのアプリ > アプリを作成`で行います。

![8qm9grmbezd9w9zk1ztd26ksesuq.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/f2a93dcf-74eb-63ec-6a29-98cc89bf49a0.png)


その後、案内に従ってアプリの基本情報を入力します。

* アプリ名:アプリの名称
* デフォルトの言語:日本語-jp-JPを選択
* アプリ/ゲーム:作成したアプリの分類を選択
* 無料/有料:無料/有料を選択。無料をあとから有料に変更は可能
* 申告：ポリシー遵守/米国輸出法同意にチェックを入れる

![y2m2e0v76zpqxfmbiui9i734hvbx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/f3d98c9c-1cbd-c357-bc0f-4a806ebbc6a7.png)


#### 初期設定タスク
つづいて、初期設定タスクを行います。
`ダッシュボード > アプリのセットアップ`に必要な項目を入力します。

* アプリのアクセス権
* 広告
* コンテンツのレーティング
* ターゲットユーザー
* ニュースアプリ
* アプリのカテゴリを選択し、連絡先情報を提供する
* ストアの掲載情報を設定する

![qoj3f90s4l78pbsojyna4ne38ji9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/cdedb66f-d26c-26f2-ccd6-d28c4d4c844a.png)


#### リリースの作成
最後に、リリースに必要な情報を入力します。
`ダッシュボード > GooglePlayにアプリを公開する`に必要な項目を入力します。

* 国や地域を選択する
* 新しいリリースを作成する
* リリースを確認して公開する

![nk4cjfxq9wxzmb7qkbl8qvchcscl.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/ad059b4a-6458-d933-e60c-30518f4a5e2f.png)


◆ 注意
アプリ登録時に、警告で「ネイティブコードが含まれ、デバッグシンボルがアップロードされていません」と出ますが、警告なのでリリースはできます。

### 6.公開申請をする
リリースの準備ができると公開の申請ができるようになり、審査を受けることができます。
初回は比較的時間がかかり、長いと1週間程度になります。
2回目以降で小さいアプリだと、1日程度で終わります。


### 7.リリースされたことの確認
審査で問題がないと、公開のステータスとなります。
* 公開のステータス管理などをしていない限りは、審査が終わり次第公開されます
* GooglePlayで表示のリンクがでて、DL可能な状態になりますが、GooglePlayでの検索でヒットするようになるにはさらに1日～2日程度の時間がかかります
* また、アプリ名や開発者名で直接検索しても1番最初に出るわけではないので、スクロールして確認してください。

![g7o0nkl96y3ufjb4xzxjm459n4f2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/a18e1df0-4411-b84a-c359-e5dd5a368010.png)


# リリース編2:AppStore/iOS

## 初回のみ行う作業

### 1. AppleDeveloperのアカウントを作る
下記、公式のAppleDeveloperにアクセスし、必要事項を入力しアカウントを登録して、登録料11,800円を支払います。
https://developer.apple.com/programs/enroll/

◆ 注意
登録完了メールはすぐにはきません。
数時間後にメールが来てアクセスできるようになります。

◆ 注意
AppleDeveloperの方は、GooglePlayと異なり年会費になっているため、毎年上記の費用が必要です

### 2. 証明書を作成する

Macアプリのキーチェーンアクセスを起動し、`キーチェーンアクセス > 証明書アシスタント > 証明局`に証明書を要求し、メールアドレスなどを入れ、デスクトップに保存します。

AppleDeveloperで開発者アカウントのアプリIDページを開きます。
Certificatesで+をクリックして、**iOS Distribution (App Store and Ad Hoc)** を選択し、作った証明書を登録します。
その後Downloadをクリックし、ダウンロードしたものをダブルクリックでXCodeにインストールします。

![u2znmjd8zgopsq3agg5m9o6pva01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/c9cabe33-7105-c4e3-a7ee-fadcbcd2fc54.png)



## アプリごとに行う作業
### 1. AppIDを登録する
AppleDeveloperでIdentifiersの**Register an AppID**を選択します。
**App IDs**を選択し、continueを選びます。
APPを選択し、**BundleID,Descriptoin,Capablitiy**を入れます。

![3s5kqi14nnvicz3di1dfvif33h6y.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/2136d32b-17c3-0277-9d1b-96be40a02ccf.png)


◆ 注意
BundleIDはパッケージのリバースで入れるのが一般的です

### 2.Profileを作成する
AppleDeveloperで **Profiles(初回)/AppStore(２回目以降)** を選択します。
**iOS App Development**を指定し、AppIDを紐付けします。
profileを生成しダウンロードします。ダウンロードしたものをダブルクリックするとXcodeに入ります。

![iecxobkyo3tra8gstu11iluqcpo4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/3978d166-f072-c325-632c-a759de1f101c.png)


### 3. アプリ名をつける
アプリ名を{アプリ名}部分に入れます。

```xml:iOS/Runner/info.plit
<key>CFBundleName</key>
<string>{アプリ名}</string>
```

### 4.ビルドとアップロードを行う
Xcodeを起動し `Produce > Archive` を選択します。

◆ 注意
SimuratorがGeneric iOSDeviceになっていないと、グレーアウトしてArchiveが選択できません

画面右の **Distribute App** をクリックし、 **AppStoreConnect** を選択しUploadを選択します

![1rgllzvscqcbywv5qn9tfh7i9r9u.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/37f24931-3e11-10ec-708d-bb9b2218efb8.png)


**Select Certificated and iOS AppStoreprofiles**で **Distribution,certificate** に上記で作成したファイルを指定します。

![x0cmk9fct2psvzyttv9wxl94ncd9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/97c66b12-8ea9-47dd-a94a-e58c5988d3c3.png)


Nextで進め、最後にUploadを選択します。

◆ 注意
メールで受付状況などが通知されます。
アップロード処理開始と完了が通知され、完了通知が来るとAppStoreで資材を選択できるようになります

◆ 注意
ビルドで設定エラーになる場合は、下記のRunnerの設定が適切か確認してください。
* GeneralタブのBundleIdentifier,Version,Build
* Signing&CapabilitiesタブでBundleIdentifierとProvisioningProfile

◆ 注意
ビルドがうまくいかない場合は
`flutter clean`
`flutter build ios`
を実行してください

### 5.サポートサイトとプライバシーポリシーサイトの作成
アプリの登録時にサポートサイトとプライバシーポリシーサイトが必要になります。
下記のような、シンプルなもので十分審査に通ります。
    
サポートサイトの例
https://smart-simple-tools.kazutxt.com/contents/whats-today/howtouse.html

プライバシーサイトの例
https://smart-simple-tools.kazutxt.com/contents/whats-today/privacypolicy.html



### 6.公開の準備をする

◆ 注意
入力項目や選択肢は比較的よく変更されるようです。
下記が最新でない可能性があるため、公式サイトや増減した項目の解説などをチェックされること推奨します

#### アプリの作成
AppStoreConnectでアプリの登録を行います

https://appstoreconnect.apple.com/login

Appのプラスボタンから新規Appを選択し、必要事項を入力し登録します。

![eakxbst3ws9eacwrkvq2nanluna4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/14623bc4-91c8-629e-54cc-c71ca021e656.png)
![1vaa02siggfcpahtk92zdx080gq6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/37d44752-b582-ce99-1965-270580a09255.png)


#### iOS App

* スクリーンショット(端末サイズ毎に必要)
* プロモーションテキスト/概要
* キーワード
* サポートURL
* ビルド/バージョン
    * 輸出コンプライアンス
        * HTTPS通信を使う場合は「はい」
* 年齢制限
* 著作権

![x98v7kvu1933sh73noml3d9sd9vi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/8cb977b0-44f4-bd6d-6686-6c149147069e.png)


#### App情報

* カテゴリ
* コンテンツ配信権
    * admobを使う場合は「はい」
* 年齢制限指定

![ttl2gkbopo9huwoezzdb6lestkh2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/db15bb06-815f-55da-56c1-66310ec56f16.png)



#### 価格および配信状況

* 価格表

![oxpmfbpge7qfvbiei8ir8sb27oo4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/445b7ac2-23a7-c50b-cbe9-a243d1ebc120.png)


#### Appのプライバシーポリシー

* プライバシーポリシーURL
* データ収集
    * 「はじめに」から選択肢に従って選んでいく
    * admob広告を使う場合は、データ収集やサードパーティの利用となるため「はい」を選択する

![caitrymhnydm9eypkolbrvvlh76e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/ed7ad7c9-cff8-ca94-95d3-56e14f996414.png)


### 7.公開申請をする
リリースの準備ができると公開の申請ができるようになり、審査を受けることができます。
初回は比較的時間がかかり、長いと2,3日かかります。
2回目以降で小さいアプリだと、1日程度で終わります。

◆ 注意
GooglePlayと異なり、人間がレビューを行っているようで、比較的審査は短いのですが、審査内容や時間にムラがある傾向にあります。


### 8.リリースされたことの確認
申請の状態は常にメールで配信されます。
(受付→レビュー待ち→レビュー中→リリース/却下)

リリースされると公式HPに掲載されます

![v1apzerst4hgssac6pvi2s8prstx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/16566921-ce54-7a76-f29b-1bf69647ca0b.png)


# リリース編3:FirebaseHosting/Web

## 初回のみ行う作業
Firebaseのアカウントさえ作成すれば、特にありません。

## アプリごとに行う作業
### 1. Hostingの初期設定
Firebaseのプロジェクトができたら、サイドメニューの`Hosting > 始める`をクリックします。

まず、npmで`firebase-tools`のインストールを行います。

◆ 注意
npmはnodeのパッケージ管理システムです。
npmが入っていない場合は、先にnpmのインストールを行う必要があります。

```sh:command.sh
$ npm install -g npm # npmを最新化
$ npm install -g firebase-tools #ツールのインストール
```

つづいて、firebaseへログインをして、`init Hosting`で初期化を行います。

```sh:command.sh
$ firebase login #ログインとアカウントの紐付け
$ firebase init Hosting
「Use an existing project」を選択しEnter
使用するプロジェクトを選択しEnter
「? What do you want to use as your public directory?」に 「build/web」 を入力
「? Configure as a single-page app (rewrite all urls to /index.html)?」に 「N」 を入力
「? Set up automatic builds and deploys with GitHub」に「N」を入力
```
上記で、build/webにindex.htmlと404.htmlが作成されます。

### 2. FlutterでWebの設定を有効化する
```sh:command.sh
$ flutter channel stable
$ flutter upgrade
$ flutter config --enable-web
# com.exampleから変更していれば--orgオプションは省略可
$ flutter create --org package_name .　
```

◆ 注意
Flutter1まではWebはbeta版だったため、channelをbetaに切り替える必要がありましたが、Flutter2からはstableのままでも動作します。

### 3.ビルド

まず、Web用資材をビルドします。

```sh:command.sh
$ flutter build web
Building without sound null safety
For more information see https://dart.dev/null-safety/unsound-null-safety

Compiling lib/main.dart for the Web...               925ms
```

◆ 注意
null safetyかどうかはアプリの状況によりますが、ビルド/デプロイには影響はありません。

### 4.デプロイ

つづいて、FirebaseのHostingにデプロイします。

```sh:command.sh
$ firebase deploy     

=== Deploying to '{AppName}'...

i  deploying hosting
i hosting[{AppName}]: beginning deploy...
i hosting[{AppName}]: found 17 files in build/web
✔ hosting[{AppName}]: file upload complete
i hosting[{AppName}]: finalizing version...
✔ hosting[{AppName}]: version finalized
i hosting[{AppName}]: releasing new version...
✔ hosting[{AppName}]: release complete

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/{AppName}/overview
Hosting URL: https://{AppName}.web.app
```

**Hosting URLにアクセスることで、デプロイされたアプリを確認することができます。**


### 5.動作イメージ
![r2c08yb9fmi9er8hi292ey9jrf62.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/764b12ab-a293-c38d-fa11-5d69e2d5eb03.png)


### デバッグ方法
`flutter run -d chrome`でgoogle chromeが起動し、動作を確認できます。
エラーが起きたときも、デバッグコンソールに表示されるので、デバッグに役立ちます