【ReactNative】Androidビルドエラー④
エラー
Failed to capture snapshot of input files for task ':app:bundleReleaseJsAndAssets' property '$1' during up-to-date check.
解決
rm -rf node_modules
npm i
考察
わからない
【ReactNative】単一ソースを複数アプリ(target)にビルドしたときの話
背景
同じようなシステムを別のターゲットに少しだけ内容を変えてリリースしたいという状況だった。 具体的には、国家試験対策アプリを歯科医師用と歯科衛生士用に出したかった。 歯科医師用アプリはiOS, Androidでリリース済みで、衛生士用も同じく両プラットフォームで出したかった。 システムはほぼ同じで、コンテンツ(クイズの内容・カテゴリ)と少しのUI、iconなどだけ変えて別アプリとして出したかった。
検討したこと
1. xcodeでtargetを2つ作る 2. 共通部分をnpm pacakge化 3. 【採用した】共通部分をgit submodule化
採用しなかったやつとその理由
1. xcodeでtargetを2つ作る
これが一番スマートだと思って、一度はやってみた。しかし、
- iOS, Android両方でビルドを分けるのは思ったより大変だった - targetによって切り分ける処理はネイティブコードでしかできない(僕調べ)ので、環境変数 などで切り分けるしかなくてメリットが小さかった - ※1 ReactNative特有の原因により、解決困難なエラーが出まくった - だだでさえ不確定要素の多いReactNativeで、nativeでもあまりやらないことをすると危険
swiftとかで書かれたアプリなら、この方法(複数targetを作る)が良いんだと思う。この方法はネット上に意外と多く転がっているので、swiftなら時間かけずにできそう。
※1 ReactNative特有の原因により、解決困難なエラーが出まくった => 詳しくは割愛する(後日書くかも)が、ReactNativeの実装上、複数targetにビルドするのは想定されていない気がしている。
2. 共通部分をnpm pacakge化
2と3は似ているが、submoduleによる管理・共通化の方が運用が楽そうだった。(後述)
あと単純に、npm pacakgeに詳しい人
よりもgitに詳しい人
の方が世の中に多そうなので引き継いだ人が楽になる可能性が高いと判断した。
【採用した】共通部分をgit submodule化
git submodule
については詳しく触れないが、使いどころさえミスらなければ非常に便利だと思うので知っておくと良いと思う。
今回のプロジェクトはこんなディレクトリ構成になっていて、基本的な実装部分はsrc
以下にまとめた。
そして、今回submodule化したのはsrc
以下の全て。
画像を見ればわかるように、redux関連の処理と各スクリーン・コンポーネント、ナビゲーション設定系も全てまとめている。
submoduleを使ったメリットは沢山あるしsubmoduleについて調べれば分かりやすいと思うので割愛するが、大きなデメリットが1つあるので紹介する。それは依存ライブラリのリンク(Linking Libraries)
をプロジェクトごとにしなければならないことだ。(Linking Librariesについては「参考」のリンク参照)
NativeがいじれないからReactNaitveを選定したのに結局触らなアカンのかい!って気持ちになるのをプロジェクトごとにやるのか。。って気持ちになるが、意外と2回目の作業は詰まらずいけた。むしろ復習になってすごく理解が進んだ。なのでこれについては実はあまりデメリットに感じていない。 ただ、複数人でプロジェクトを回す場合はやはり大きなデメリットになるかも。
追記
BuildSettings (iOS), BuildVariant (Android)を使うとプラットフォーム側でビルド時に処理してくれるらしい。 speakerdeck.com
参考
【ReactNative】iOSアプリのリリースフロー
前提・背景
この記事は、「使用中のmacで1度以上iOSアプリをリリースしたことがある」前提です。 自分がその状態のため、思い出しながら備忘録として書いています。 リリース経験がない人は、この記事最下部におすすめ記事を書いているので、それがすごく参考になると思います。 この記事の対象読者にとっては、「この部分は1回だけで良いんだ」「この作業は毎回必要なんだ」という風に理解が進む狙いなので、お役に立てると思います。
そして、
Appleの開発者登録(Apple Developer Program)が済んでいる前提です。 登録 - サポート - Apple Developer
iOS Certificateが作成されている前提です。 iOS CertificateはXcode上でアプリを実機用にビルドするのに必要なもの。逆に言えば、一度作成しているとそれ以降は必要ない。 以下の記事がすごく詳しい(少し古いが2018-12-04現在問題ない)のでおすすめです。 i-app-tec.com
Provisioning Profile Provisioning ProfileもXcode上でアプリを実機用にビルドするのに必要なもののようです。 作成手順に関してはやはりこちらの記事が詳しいです。 iOSアプリ Provisioning Profile を作ってみる
リリースの流れ
1. App IDを作成 2. AppStoreConnect上でアプリを作成 3. XcodeでArchive
以上になります。下記に1つ1つについて詳しく書きます。
1. App IDを作成
Sign In - Apple へ飛びます。画像のようにApp IDを新規作成します。
- App ID Description(IDの説明)
- Explicit App ID
- App Services
を入力します。Explicit App IDはつまり
Bundle ID
です。(Xcodeで設定するやつ・アプリ固有のID) 基本的にはリバースドメイン(アプリ名を逆にしたやつ)が推奨されています。 例: news.oned.jp => jp.oned.news
App Services
に関しては、使用している機能だけにcheckが基本です。checkしていない機能を使っていたら審査時にリジェクトされることは当たり前ですが、逆に使ってない機能にcheck入れすぎてると怒られるらしいです。(経験なし)
が、実際、PushNotificationsとか「後々使うよなー」って機能は入れちゃってます。怒られた試しはありません。「とりあえず全部チェック入れとく」とか適当なことせずにいくつかだけチェック入れるなら良いんだと思います。(Appleも審査大変やろ)
以上3つを全て入力し、Continue => Submitすればdoneです。
2. AppStoreConnect上でアプリを作成
https://appstoreconnect.apple.com/ へアクセスし、「新規 App」を作成します。
- プラットフォーム(大体iOSでしょう)
- 名前(アプリ名)
- プライマリ言語(大体日本語でしょう)
- バンドルID(「1. App IDを作成」を経ていたら選択肢として出るはずです)
- SKU(Appleが内部で使うIDらしい。僕はbundleIDと一緒にしています。なんでも良さそう)
- ユーザアクセス(「なし」で良いでしょう)
を入力します。 これで、Xcode上でArchiveができるようになります。
3. XcodeでArchive
以上を入力して、メニューバーからProduct => Archive
すればアップロード完了です。
参考にした・関連おすすめ記事
【ReactNaitve】ReactNativeDebuggerが便利すぎた
開発し開発しながら書いてるので思いつき次第随時拡充していきます。
イメージ
これだけで大体分かる思うけど、 - stateの確認 - reduxアクション確認 - reduxアクション毎のstateの差分(diff)の確認 - 要素検証(Chromeの「検証」に近い) - console.logの確認 などが出来る。
これだけでも凄いなー便利だなーって思っていたけど、AsyncStorageの中身まで確認できちゃうと知って舞い上がった。 頑張ってconsole.logとかに中身をDumpしてた自分がかわいそう。。。
AsyncStoreの中身を確認する方法
consoleで
showAsyncStorageContentInDev()
をうつ。
すると中身がテーブル表記で綺麗に表示される。
中身がない場合は No AsyncStorage content.
が帰ってくる。
(ちゃんと確認せず「テーブル表示されないじゃねぇーかー!」ってなってしまった僕のような人へ。安心してください。ちゃんと確認すれば何かしら帰ってくる。)
【ReactNative】git clone直後のBuild input file cannot be found: エラー解決方法
エラー
❌ error: Build input file cannot be found: 'path_to_project/node_modules/react-native/third-party/double-conversion-1.1.6/src/strtod.cc' ▸ Compiling fast-dtoa.cc ❌ error: Build input file cannot be found: 'path_to_project/node_modules/react-native/third-party/double-conversion-1.1.6/src/fast-dtoa.cc' ▸ Compiling fixed-dtoa.cc ❌ error: Build input file cannot be found: 'path_to_project/node_modules/react-native/third-party/double-conversion-1.1.6/src/fixed-dtoa.cc'
解決
【ReactNative】Androidリリースをイチからメモ
流れ
- 鍵を生成・配置
- gradle.propertiesにgradle変数を追加
- build.gradleにsigningConfigsを追加
- APKファイルを生成
- APKファイルをplay storeへアップロード
1. 鍵を生成・配置
生成
keytool -genkey -v -keystore your_app_name.keystore -alias your_app_name -keyalg RSA -keysize 2048 -validity 10000
※ your_app_nameの部分を適宜変更する
姓名・組織単位名・組織名・都市名・州名・国番号などを聞かれるので適宜答える。 あまり重要じゃなさそう。
※国番号に関しては、日本の場合はJP
とする。
配置
生成されたキー(your_app_name.keystore)をandroid/app
へ配置。
2. gradle.propertiesにgradle変数を追加
android/gradle.properties
に以下を記述
MYAPP_RELEASE_STORE_FILE=your_app_name.keystore MYAPP_RELEASE_KEY_ALIAS=your_app_name MYAPP_RELEASE_STORE_PASSWORD=your_password MYAPP_RELEASE_KEY_PASSWORD=your_password
他のgradleファイルから参照される値なのでキーは独自に変えても良いと思うが、公式でもこのキーが例に上がっているので素直に従っておく。
3. build.gradleにsigningConfigsを追加
... android { ... defaultConfig { ... } signingConfigs { release { if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) { storeFile file(MYAPP_RELEASE_STORE_FILE) storePassword MYAPP_RELEASE_STORE_PASSWORD keyAlias MYAPP_RELEASE_KEY_ALIAS keyPassword MYAPP_RELEASE_KEY_PASSWORD } } } buildTypes { release { ... signingConfig signingConfigs.release } } } ...
siginigConfig {}とsigningConfig signingConfigs.release
の部分を追加。
4. APKファイルを生成
cd android && ./gradlew assembleRelease
を実行。
すると
android/app/build/outputs/apk/release/app-release.apk
ファイルが生成される。これがアプリ本体らしい。
5. APKファイルをplay storeへアップロード
https://play.google.com/apps/publish
へアクセスし、左サイドバーのリリース管理 > アプリのリリース
からAPKファイルをアップロードする。「リリース名」や「このリリースの新機能」などを記入して公開する。
iOSと違い、Androidのリリースは審査なしですぐに反映される。
2回目以降のリリースについて
ここに書いた。 kang.hateblo.jp
参考
公式ドキュメント facebook.github.io
【ReactNative】コスパ良くクオリティ上げるならとりあえずLayoutAnimation入れとこ
苦労せずになんとなーくアプリのクオリティを上げたいあなたにおすすめです。
Animationを適用したいScreenのcomponentWillUpdate
にでも書いておきます。
import { LayoutAnimation } from 'react-native' --------------------------------------------- componentWillUpdate() { LayoutAnimation.easeInEaseOut() }
↓は開発中のアプリに適用してみた例。 「パッ」じゃなくて「フワッ」っとなってる感じ。。。わかるかな?w
アニメーションのオプションは
- easeInEaseOut
- linear
- spring
があるみたいなので、全部試して好みを見つけると良さそうです。
個人的にはScreenに適用するならeaseInEaseOut
一択です。
こんな感じでもっとかっちょいいアニメーションにもできる。
LayoutAnimation.configureNext({ duration: 700, create: { type: 'linear', property: 'opacity', }, update: { type: 'spring', springDamping: 0.4, property: 'scaleXY', }, delete: { type: 'linear', property: 'opacity', }, })
※参考: https://blog.callstack.io/react-native-animations-revisited-part-i-783143d4884
僕はそんなに凝れないので極力やらないが、
onPress()なんかの最初に書いておいて発火されるたびにAnimationをかけることもできる。
※参考: rskull.hateblo.jp
特別な理由がなければ、ほぼ全てのScreenに入れて良いはず。 これ入れとくだけで「あ、ちゃんと凝ってんな」って思われそう。