非iOSエンジニアがExpoのReact Native(CRNA)で作ったアプリを初めてAppleに申請するまで

作ったアプリ
----
**最強のねこ21**
21の数字を言ったら負けなミニゲームです。よければ遊んでみてください🙇‍

- [🍎iOS](https://itunes.apple.com/jp/app/%E6%9C%80%E5%BC%B7%E3%81%AE%E3%81%AD%E3%81%9321/id1404193219?mt=8&ign-mpt=uo%3D4)
- [🚩Android](https://play.google.com/store/apps/details?id=com.firebaseapp.horieapp.strongestcat)

はじめに
------
### 対象者
- React Native(CRNA)で作ったアプリをはじめてAppleに申請する人
  - Androidも申請しましたが、はまるところがなかったので最後にちょこっと記述しています
- 話さないこと
  - React Nativeでアプリを作る方法
- 話すこと
  - アプリが完成しAppleに申請するまで

### Expoとは
- ReactNative開発補助ツール
  - https://expo.io/ 
  - [CRNA(create-react-native-app)](https://github.com/react-community/create-react-native-app)
      - ローカルに開発環境作成
  - [Expo Snack](https://snack.expo.io/)
      - React NativeをWeb上で簡単に体験
  - [Expo XDE](https://expo.io/tools)
      - iPhone、Androidのシミュレート
- 参考：[ExpoでReact Nativeアプリを開発するメリット5選](http://ducklings.hateblo.jp/entry/2018/04/09/142341)
  - ビルド時にプロビジョニングプロファイル不要。審査不要でアップデート可能

### 開発時のXcodeのバージョン
- OSX 10.11 for Xcode 7.3.1
  - Appleにアップロードしたときにエラーが出てダメでした
- OSX 10.13 for Xcode 9.4.1
  - 最新版にアップデートしたらうまくいきました。OSとXcodeを最新にするのが吉

### 全体の流れ
1. Developer登録
1. アプリアイコン作成
1. スクリーンショット作成
1. app.json作成
1. ExpoでスタンドアローンAppをビルド
1. Application Loaderでアップロード
1. 審査へ提出

---------------

1. Developer登録
-----------
- [Apple Developer](https://developer.apple.com/account/)
- 開発用のAppleIDがない場合は新規に作成してください
- 毎年$99かかります
- 注文してから48時間かかります
  - 申請する２日前くらいに購入するとちょうどいいです
- 基本的に入力フォームに従って入力していきます
  - 参考：[[iPhone] Appleの開発者登録をする, iOSアプリ作成準備](https://i-app-tec.com/ios/developer-registration.html)

2. アプリアイコン作成
----
- Apple申請用に 1024 x 1024 の正方形（丸角にしなくていい）のpngファイルを準備します
- クオリティの高いアイコンを作る技術がない場合、フリー素材を加工するのが楽です

### 今回使用したサイト
- フリー素材（無料）
  - [シルエットAC](https://www.silhouette-ac.com/)
      - メールアドレス登録必要
- 画像加工（無料）
  - [Figma](https://www.figma.com/files/recent)
       - メールアドレス登録必要
       - ブラウザで動作する
       - メニューが英語
       - **日本語テキストが４つしか使えない**
         - 参考：[Figmaで日本語を使う](https://qiita.com/sakapun/items/07577ac325aae3db44ba)
  - [FireAlpaca](http://firealpaca.com/ja/)
     - メニューが日本語
     - 今回は使わなかったけどこっちの方が簡単かもしれない？

### 作ったもの
![app-icon-128.png](https://qiita-image-store.s3.amazonaws.com/0/69627/f974e9a5-21e1-8d19-a24a-14dd988f2f0b.png)

- 制作時間30分くらい
- 画像が透過（アルファ）だとエラーになるため透過をなくします
   - 画像をプレビューで開いて ファイル -> 書き出し アルファのチェックを外す（透過無の場合はチェックが表示されない）
      - 参考：[Mac OS XでPNG画像を透過なしにする方法](http://blog.livedoor.jp/eienf/archives/1020555111.html)

3. スクリーンショット画像作成
---------
Apple申請用に 1242 x 2208 のpngファイルを１枚以上準備します

1. Expoのシミュレータでスクリーンショットをとる
1. 画像を開く（プレビュー）
1. デスクトップメニューバーの ツール -> サイズを調整
1. 🔒をクリックし幅と高さを変更して保存

4. app.json 作成
-----------

```js:app.json
{
  "expo": {
    "name": "StrongestCat21",
    "icon": "./assets/icons/app-icon.png",
    "version": "1.0.0",
    "slug": "cat21",
    "sdkVersion": "25.0.0",
    "ios": {
      "bundleIdentifier": "com.firebaseapp.horieapp.strongestcat"
    },
    "android": {
      "package": "com.firebaseapp.horieapp.strongestcat",
      "permissions": []
    }
  }
}
```

### name
- アプリの名前
- アプリアイコンの下に表示される文字になるため10文字以内にするべきでした...
- 日本以外にも配信する予定だったので英語にしました
  - 言語ごとに変更するやり方もあるみたいです
      - 参考：[iOSアプリの多言語対応](https://qiita.com/hikarut/items/825f0de352a254327d5e)

### icon
- アプリアイコンで作成したファイルのパス

### version
- アプリのバージョン
- JS以外の修正があった場合はバージョンを上げて再申請します

### sdkVersion
- ExpoのSDKのバージョン

### slug
- Expoで管理するID
- **英数字ハイフンアンダーバーのみ**

### ios: bundleIdentifier
- iOSアプリのID
- ドメイン名の逆＋アプリ名が一般的
- ユニークであればドメインを取得する必要はないらしいです
  - 念のため[Firebase Hosting](https://firebase.google.com/docs/hosting/?hl=ja)で仮ドメイン作りました

### android: package
- AndroidアプリのID
- **ハイフンを使ったら下記のエラーが出ました**
   - バグらしいのでハイフンなしにするしかない模様
       - 参考: https://github.com/expo/expo/issues/1439

```
Field: android.package - 'android.package' should be a reverse DNS notation unique name for your app. For example, host.exp.exponent, where exp.host is our domain and Expo is our app..
```

### android:permissions
- スタンドアローンAppがインストール時に要求する権限のリスト
  - [] に設定すると、必要最小限の権限のみが使用され、Androidアプリの申請時にプライバシーポリシーが不要になります
- カメラ機能などを使う場合は記述が必要になり、Androidアプリの申請時にプライバシーポリシーが必要になります
- 参考: https://docs.expo.io/versions/latest/workflow/configuration#android


5. iOS用のスタンドアローンAppをビルド
-------------
### expコマンドのインストール

```
$ npm install -g exp
```

### スタンドアローンAppビルド

```
$ exp login
$ exp build:ios
```

- 途中で何度か選択肢がでますが、Expoにまかせる（そのままEnter）を選べばOKです
- 10分くらいかかります
- 最後にスタンドアローン（ipa）ファイルのリンクが表示されるので、アクセスしダウンロードします

6. Appleにアプリをアップロード
-------------
1. Xcode を開く
1. デスクトップメニューバーの Xcode → Open Developer Tools → Application Loader
1. さきほどのipaファイルを選択
1. 完了まで15分くらいかかります

※数分待ってもApp Store Connectに表示されない場合は失敗している可能性があります

7. 審査へ提出
------------
※ブラウザはSafariがいいらしいですが、Chromeでも大丈夫でした

1. [App Store Connect](https://appstoreconnect.apple.com/)にログイン → マイApp → アクティビティ
1. さきほどアップロードしたのアプリが登録されているか確認します
1. アプリ情報などの入力
  - 参考：[App Storeでアプリを公開する為にiTunes Connectからアプリを申請する手順](http://unitynightowlgames.hatenablog.com/entry/2016/10/06/230911)
  - サポートURLは必須なので[Googleフォーム](https://www.google.com/intl/ja_jp/forms/about/)で作成しました
  - 契約／税金／口座情報
     - 参考： http://galakutaapp.blogspot.com/2016/12/blog-post.html
     - 無料アプリでも情報を入力しないとダメらしいです
          - 「審査OKだけど入力しないと公開できないよ」のメールが来ました
     - 役職を入力する必要があるのですが、個人なので何でもいいらしいです。私は Developer にしました
1. アプリの処理完了のメールが届いたら「審査へ提出」ボタンを押します
    - ※処理完了まで数時間かかります 
1. 広告無しでも「広告が存在する」とエラーが出ました
  - 何らかのパッケージが原因でエラーが出るようです
  - せっかくなので広告（AdMob）を追加してみます

AdMob
-----
- [ExpoでAdMobのツールが提供されています](https://docs.expo.io/versions/latest/sdk/admob)
- AdMobのアカウントを登録し、下記のタグを空いているスペースに追加します
   - adUnitIDは自分のAdMobのコードに差し替えてください
- 本物の広告が完全に表示されるまでは数時間かかりました（テスト用はすぐ出ます）

```jsx
import { AdMobBanner } from 'expo'

<AdMobBanner
  bannerSize="banner"
  adUnitID="ca-app-pub-3940256099942544/6300978111" // Test ID, Replace with your-admob-unit-id
/>
```

アプリをアップデート
-----
- JSだけの更新であれば下記のコマンドで反映されます
  - 再ビルドする必要なし  
  - app.jsonのバージョンを変更する必要なし

```
$ exp publish
```

※iOSアプリに関しては以上です。広告有りにして申請を出し、２日くらいで審査OKのメールが来ました

--------------

Google Playの申請
-------
- Appleの申請より待ち時間もなく、すぐに申請/公開できました
- 説明が日本語のため、はまるところも特にありませんでした
- 今回は試していませんが、プライバシーポリシーが必要な場合は少し大変そうです

### Appleとの主な違い
- 初回に $25 を１度支払うだけ
- アプリの審査なし
- アプリをそのままブラウザからアップロードできる
  - スタンドアローンApp作成コマンド
      - $ exp build:android
- アプリアイコン
  - 512 x 512 のpngファイルが必要
- ヘッダー画像
  - 1024 x 500 のpngファイルが必要
- スクリーンショットは最低２枚
  - サイズは下記を満たしていれば自由
     - １辺の最小の長さ:  320px
     - １辺の最大の長さ: 3840px

Expoを使うことで得るもの
------
- iOSアプリもAndroidアプリも両方作れる
- スタンドアローンAppが簡単に作れる
- JSだけのアップデートであれば、審査なしですぐにアップデートできる
- Expoのツールを使えば色々簡単
  - AdMobなど
- 参考：[ExpoでReact Nativeアプリを開発するメリット5選](http://ducklings.hateblo.jp/entry/2018/04/09/142341)

Expoの不満点
-----
- XCode上で作業する必要がある機能などがExpoが対応していないと使えない
  - アプリアイコン、アプリ名を多言語化  
  - アプリ内課金
      - Expoを外さないとできないらしい
         -  https://expo.canny.io/feature-requests/p/in-app-purchases 

多言語化
-----
- [i18nを使いReact Native(CRNA)で多言語化](https://qiita.com/HorieH/items/c93fc89e939da249cd71)
- アプリ名、アプリアイコンを多言語対応する場合
  - Xcodeで設定ファイルを作る必要がある
      - 参考：[iOSアプリの多言語対応](https://qiita.com/hikarut/items/825f0de352a254327d5e)
  - 画像に文字を入れず、アプリ名は英語にするのが簡単ですね

今回使用したモジュール
----
```js:package.json
    "@expo/vector-icons": "6.2.1",
    "ex-react-native-i18n": "0.0.3",
    "expo": "^25.0.0",
    "native-base": "2.3.9",
    "react": "16.2.0",
    "react-native": "https://github.com/expo/react-native/archive/sdk-25.0.0.tar.gz",
    "react-native-auto-scroll": "0.0.1",
    "react-native-i18n": "2.0.12",
    "react-native-storage": "0.2.2",
    "react-navigation": "1.4.0"
```