- 投稿日:2022-02-24T23:22:55+09:00
2022年のiOS/Androidの技術をざっくりキャッチアップ
ネイティブアプリにも宣言型UIとかなんかいろいろ入ってきたので、「いい加減そろそろ覚えないとな~~」ってなってる人は少なくないと思ってるんですけれど、一足先に一通り触ったのでどんな感じで学べばいいのかなという参考になればという感じの記事です。 宣言型UI WebにjQueryがもたらされたとき、だれでも簡単に直接DOMを触ってViewを弄れるようになった結果、アプリの大規模化・保守の長期化に伴って手に負えなくなったので、それを解決するためにReact辺りが宣言型UIの思想を生み出した…というざっくりした認識を持ってるんですけれど、合ってるかは知りません。 とまれ、ネイティブアプリにも数周遅れではありますが宣言型UIの流れがきています。 SwiftUI SwiftUIの現在の最新バージョンは3です。 どんどん便利になるのはいいことなんですけれど、サポートするiOSのバージョン指定によっては使えない機能とかがあります…。 これは公式のコードなのですけれど、 struct Content: View { @State var model = Themes.listModel var body: some View { List(model.items, action: model.selecteItem) { item in Image(item.image) VStack(alignment: .leading) { Text(item.title) Text(item.subtitle) .color(.gray) } } } } Opaque Result Type Property Wrapper Dynamic Member Lookup のような最近の言語仕様の追加を駆使して実現されてるため、UIを作るだけならスッキリなんですけれど、挙動についてもスッキリと理解するにはこうした言語仕様の変更も追いかける必要があります。 それぞれの言語仕様について、プロポーザルを眺めながら簡単なコードで動きを見てみたり、$model.itemsとか_model.items.wrappedValueとかの型情報をインスペクションで眺めたりすると掴めてくるのかなと思います。 Jetpack Compose ComposeはViewの組み立てが関数で構成されているというのが面白ポイントですね。 @Composable fun JetpackCompose() { Card { var expanded by remember { mutableStateOf(false) } Column(Modifier.clickable { expanded = !expanded } ) { Image(painterResource(R.drawable.jetpack_compose)) AnimatedVisibility(expanded) { Text( text = "Jetpack Compose", style = MaterialTheme.typography.h2, ) } } } } 最初はby rememberやmutableStateOf() が見慣れないかもしれませんが、翻訳済みの公式ドキュメントがかなり整備されているので、とっつきやすいと思います。 状態ホイスティングのようなCompose構築のための良いプラクティスも書いてありますし、ComposeはAndroid SDKとは別のライブラリとして提供されているので、バージョンによる分断もめいびーありません。 Composeがバージョンごとに特定のKotlinバージョンをロックインしている点と、Material Designも並行してアップデートしている辺りはちょっと困りポイントかもしれません。 リアクティブプログラミングっぽいの 初期の学習コストこそ高いものの、Reactive Extensionsを一つ覚えれば、他の言語でも知識を応用できる、みたいな話がありましたよね…。 Combine これはApple的にはリアクティブプログラミングではなく、非同期イベントを処理する仕組みみたいです。個人的な感想では、どう見てもRxでは…という感じです。 そういうわけで、Rxを理解しているとほぼほぼ「そーなのねー」で終わると思います。あとはSwift固有の問題として、オペレーターを挟むと型がどんどん入り組んでいくので、eraseAnyPublisher()による型消去を適当に挟む感じというのだけ覚えればよさそう。 CombineはSwiftUIの裏側ではいろいろ出てくるので、その辺りの理解度を高めるために習得するのはありなのかもですけれど、あんまり直接いじる印象はないと思います。たぶん。 Flow Flowも見た目はRxこそ似ていますが、Coroutineの一種という点に違いがあります。 RxやChannelは不慣れだとあっさりリソースをリークさせてしまうのですが、Flowは基本的にColdなストリームを扱いつつ、HotなStateFlowに変換するにはCoroutineScope内でやってね~みたいな感じがあり、ある程度安全性も担保している印象があります。 こちらも結局非同期イベントによる状態変化をComposeへ流す用途に使うのがメインだと思っていて、直接いじる印象は少ないです。 とはいえ、Hot/Coldについての最小限の知識がないと、サーバーに何度もアクセスしてしまう問題のあるコードが生まれるリスクはあるので、公式ドキュメントを眺めるくらいはしてもいいかも…。 非同期処理 C#にasync/awaitが出てから10年くらいでしょうか。ようやくどの言語でも同じような書き方ができるようになりました。 Swift Concurrency Swiftで非同期処理を書こうとすると、completionクロージャがネストしまくり、非常に追い辛いコードになりがちでした。 待ちに待ったSwift Concurrencyの登場によって、とても簡潔に書けるようになったと思います。 func fetchImage(request: URLRequest) async throws -> UIImage { let (data, response) = try await URLSession.shared.data(for: request) guard let image = UIImage(data: data) else { throw ImageDecodeError } return image } Swiftは2.0でキャッチ例外を取り入れることを選択したので、async/awaitだけではなく、async throws/try awaitがあるのが特色ですね。 ほかにもActorという非同期処理におけるRace Conditionの問題解決に大きく貢献する仕組みも入っています。 この辺りはWWDCのビデオを見るのが手っ取り早いと思います。非常に便利なんですけれど、SDKやエコシステムが対応していくようになるのはまだこれからかなという印象です。
- 投稿日:2022-02-24T21:57:49+09:00
【Flutter】api通信がAndroidでのみうまくいかない件
何があったのか? GitHubApiを使用した通信処理がAndroidでのみ失敗して詰まったので、備忘録を残しておく。 解決法 AndroidManifest.xmlにネットワーク権限を追加 以下のようにandroid / src / main /AndroidManifest.xmlに<uses-permission>の記述を加えるとネットワーク権限が加えられ、api通信もできるようになります。 <manifest xmlns:android...> ... <uses-permission android:name="android.permission.INTERNET" /> <application ... </manifest> 参考
- 投稿日:2022-02-24T19:09:08+09:00
Nature Remo Cloud API + Lambdaで温度を記録して折れ線グラフを表示する自分ち専用のAndroidアプリを作った
Nature Remo Cloud API + Lambdaで温度を記録して折れ線グラフを表示する自分ち専用のAndroidアプリを作りました。 経緯 我が家ではNature Remoというスマートリモコンを使っており、Alexaやスマホアプリ経由でいろんな家電を操作できるようにしている そのNature RemoではNature Remo Cloud APIというものが提供されており、HTTPで簡単に情報が取れるらしい 最近エアコン暖房がついててもたいしてあったかくない気がする Nature Remoに搭載されている温度センサーの値と、エアコンの稼働状況をAPIから定期的に取得し、保存して見える化すればエアコンが本当に調子が悪いのかわかるのでは? 単純に室温の変化が見えたら面白そう 気象庁ホームページのリニューアルでアメダスのデータも簡単に取れるようになったらしいのでついでに外気温も取得してみよう つくったもの AWS Lambdaで動くバッチ(RemoBatch) Cloud Watch Eventsで10分おきに動作させる Nature Remoから室内気温、エアコンがついているorいない、動作モード(冷房か暖房か)、エアコンの設定温度を取得 同時に気象庁HPのアメダスデータから外気温を取得 それらをDynamoDBに保存 AWS Lambda + API Gatewayによるデータ取得API(GetRemoInfo) DynamoDBに保存したデータを取得するためのAPI リクエストでいつからいつまでのデータを取得したいか指定し、JSONでその期間内のデータを返す 折れ線グラフを表示するAndroidアプリ(RemoTemperatureViewer) 上記GetRemoInfoAPIを叩き、取得したJSONから折れ線グラフを表示する RemoBatch コード:https://github.com/nishinsoba/RemoBatch 年末年始に作成。 とりあえずすぐ動くものが欲しかったので、業務で触ったことがあるC#でコーディングしました。 基本的にはひたすら外部のAPIを叩き、レスポンスのJSONを解析して、最後にDynamoDBに詰めているだけなので難しいことはしていないです。 Nature Remo Cloud APIを叩く際に必要となるトークンはLambdaの環境変数としています。 年末年始に作成してしばらく放置していたので、その間にDynamoDBにデータがたまっていったのですが、途中でNature Remo Cloud API側で仕様変更があったらしく(?)途中からエアコンを使用しているorしていないが取得できなくなっていたので修正しました。 参考ページ Nature Remo Cloud API Nature Remoの公式APIの使い方 新しい気象庁サイトからJSONデータが取得できる件 AWS公式 .NETドキュメントモデル DynamoDBへの書き込みにドキュメントモデルを使ってみました。 気象庁アメダスデータの取得 外気温を知るために気象庁のアメダスデータを使用しています。(我が家は神奈川県某所にあるので、神奈川県内のアメダス地点のデータを使っています) https://www.jma.go.jp/bosai/amedas/data/map/yyyyMMddHHmm00.json (yyyyMMddHHmmは任意)でデータを取得できるようですが、10分おきに更新されているようなので、mmは10で割り切れる数である必要があります。 つまり、 https://www.jma.go.jp/bosai/amedas/data/map/20220222222000.json (2022/2/22 22:20)ならばOKですが、 https://www.jma.go.jp/bosai/amedas/data/map/20220222222200.json (2022/2/22 22:22)だとNot Foundとなります。 また、現在時刻から近すぎるとこれまたNot Foundになるようなので、RemoBatchでは現在時刻より15分以上前のデータを取得するようにしています。(そのため外気温のデータはリアルタイムではないですが、目安として使えればいいやということで) //現在時刻(JST) var jstZoneInfo = TZConvert.GetTimeZoneInfo("Tokyo Standard Time"); DateTime jst = TimeZoneInfo.ConvertTime(DateTimeOffset.Now, jstZoneInfo).DateTime; string jstStr = jst.ToString("yyyy/MM/dd HH:mm:ss"); //アメダスデータ //現在気温の取得には15分程度ラグがあるので、15分前の気温を取得することにする var before15Minutesjst = jst.AddMinutes(-15); var jstAmedasStr = before15Minutesjst.ToString("yyyyMMddHH"); var jstAmedasStrMinute = before15Minutesjst.ToString("mm").Substring(0, 1); var amedasUrl = "https://www.jma.go.jp/bosai/amedas/data/map/" + jstAmedasStr + jstAmedasStrMinute + "000.json"; 力技ではある。 DynamoDB こんなかんじです。 プライマリーキーを日付にしてしまったのが若干使いづらくて後悔はしています。 GetRemoInfo コード:https://github.com/nishinsoba/GetRemoInfo DynamoDBの中身を検索してJSONで返すAPIです。バッチと同じくC#で書きました。 APIキーを設定しています(我が家のエアコン稼働状況とかが見れてしまうので!) requestにクエリパラメータで取得したい期間fromとto(どちらもyyyyMMddHHmmss)を指定してGETすると、from ~ toの間の日時のレコードを検索して返却します。 DynamoDBからの読み込みには、Batchの方はドキュメントモデルを使ったのでこちらではオブジェクト永続性モデルを使ってみました。 レスポンスにそこそこ時間がかかるのが改善したいポイントです。 費用が高くならないようにプロビジョンドキャパシティーユニットを低めに設定している そもそもScanに時間がかかる(DB設計の問題?) Lambdaのコールドスタートにも時間がかかる のが原因かなと思っています。 以下はレスポンスの一例です。 取得期間中の外気温と室温の平均値も返すようにしてみました。 response { "result_message": "SUCCESS", "remo_data": [ { "datetime": "2022/02/22 10:10:15", "is_using_aircon": 0, "outdoor_temperature": 7.3, "room_temperature": 17, "aircon_mode": "warm", "aircon_temperature": 20 }, { "datetime": "2022/02/22 10:20:15", "is_using_aircon": 0, "outdoor_temperature": 7.6, "room_temperature": 17, "aircon_mode": "warm", "aircon_temperature": 20 } ], "start_date_time": "2022/02/22 10:10:15", "end_date_time": "2022/02/22 10:20:15", "average_room_temperature": "17", "average_outdoor_temperature": "7.449999999999999" } RemoTemperatureViewer コード:https://github.com/nishinsoba/RemoTemperatureViewer 上記GetRemoInfo APIで取得したJSONデータを折れ線グラフで表示するAndroidアプリです。 別にAndroidでなくてもよいのですが、最近触れていないので復習と、MVVM + LiveDataの勉強がしたかったのでAndroidにしました。 StartFragmentでユーザにfrom(データ取得期間の開始)とto(取得期間の終わり)を入力してもらう FirstFragmentで入力された日付・時間情報をRemoTemperatureViewModelが保持 OKボタンが押されたらRemoTemperatureViewModelがAPIを叩く APIからレスポンスが帰ってきたら、折れ線グラフ描画の準備をする GraphFragmentが折れ線グラフを表示する グラフを表示は横画面にも対応 (※エアコンを使用していないときは緑の線が0℃になる) というのが基本的な流れになります。 工夫したところ⓵ 誰からでもAPIを叩けてしまうと困るので、GetRemoInfoにAPIキーを設定しています。そのためこのアプリから叩くときもAPIキーが必要となるので、初回起動時にユーザに入力してもらうようにしています。 内部的にはSharedPreferencesとして入力してもらったトークンを保存しています。 FirstFragment /** * GetRemoInfoを叩くためのトークンを持っているかチェックし、持っていなければ入力ダイアログを表示する */ private fun checkTokenExist(): String?{ val sharedPref = requireActivity().getSharedPreferences("remo_viewer_setting",Context.MODE_PRIVATE) var token = sharedPref.getString("token",null) if (token == null){ // ダイアログを二重表示しない if( dialog != null && dialog!!.isShowing() ) { return null } // トークン入力ダイアログを表示する val myEdit = EditText(activity) dialog = AlertDialog.Builder(requireActivity()) .setTitle("トークンを入力してください") .setView(myEdit) .setPositiveButton("OK", DialogInterface.OnClickListener { _, _ -> // OKボタン押したときの処理 val inputText = myEdit.getText().toString() if (!inputText.isEmpty()) { sharedPref.edit().putString("token", inputText).apply() token = inputText } }) .show() } return token } 工夫したところ② また、最初の画面で日付と時刻を入力するのがめんどくさいので、よく使われるであろう「直近24時間」と「直近1週間」の設定を一発でできるボタンを設置しました。 感想 せっかくMVVMで作ってみたのにFragment内も結構ごちゃごちゃしてしまったのが今後直したい…という感じです。 折れ線グラフの表示はこちらの記事が大変わかりやすく、必要な情報もすべて網羅されていたので大変助かりました。 外気温と室温の連動がわかるような、わからないような… 料理をする夜の時間帯が室温のピークだということがわかります。 結果 初めて個人でがっつり何かを作ったので楽しかった AndroidのMVVM,LiveDataが理解できた(と思う) 結局エアコンの暖房の効きが悪いどうかはわからない Qiitaに初投稿してみてドキドキです
- 投稿日:2022-02-24T13:32:30+09:00
ネイティブアプリの審査通過に向けて気をつけたポイント(2022年2月版)
0. 概要 この度、新規のネイティブアプリをiOS/Androidの両プラットフォームにてスケジュール通りにリリース可能な(Apple/Googleによる審査が通過した)状態にすることができました! ※審査時間がとても早かった(通常、初回は2週間ほどを見るのが良いと言われていますが、提出から通過までなんと1営業日…!)というラッキーはありましたが、間違いなく開発チームの努力の成果だと思っています! チームの中でも私個人は今回、技術的な側面ではなく、アプリが審査基準を満たせているか?審査提出に必要なタスクは何か?といった側面において、リスク回避に努めました。スケジュール通りに何かを成し遂げる際は「不確定要素」をどれだけ減らしていくかといったことが重要だと思いますが、アプリのサービスリリースにおいて最大の不確定要素は「審査でのリジェクト」になるかと思います。今回得た知見で、どなたかの「不確定要素」を減らす手助けが出来れば…!という気持ちです。 1. 公式のガイドラインを読む 兎にも角にもまずは公式のガイドラインを読みました。入り口が分かりづらかったり、各所に情報が散らばっていたり、色々と思うところはありますがまずは一読しておいた方が良いと思います。 iOS https://developer.apple.com/jp/app-store/review/ https://developer.apple.com/jp/ios/submit/ 特に注視したのは、App Store Reviewガイドラインです。審査はこちらの基準に則って行われるはずなので、少々文量はありますが、端から端までしっかり読むのが良いと思います。中でも気になった点を以下に紹介しておきます。 アカウントの作成に対応したAppの場合は、App内でアカウントの削除もできるようにする必要があります。 こちらに公式のプレスが載っていますが、アプリ内にてアカウント作成機能を提供している場合は、2022年1月31日よりApp内のアカウント削除機能の提供が必須要件になっています。引用した文章は太字にもなっておらずしれっと記載されています。ググるといくつか記事も見当たりますので、iOSエンジニアの方からすると知っていて当然のニュースという感じかもしれませんが、アプリ開発未経験者からするとあまりにも不親切…と思いました。 ユーザーコンテンツやアプリ内課金がある場合などアプリの要件に合わせて、各項目をしっかりチェックする方が良いと思います。上記のように機能開発が必要なのにも関わらず、審査でリジェクトされるまで気づけないと精神的にかなりきついところがあると思います。当然リリース日は伸びてしまいますし、急ぎで作った機能は品質の面などで不安になってしまうでしょう。今回は他の開発メンバーがプレスに気づき比較的早い段階で対応できましたが、不安要素は早め早めに潰しておくと良いなと改めて感じました。 Android https://play.google.com/about/developer-content-policy/?hl=ja https://support.google.com/googleplay/android-developer/answer/9859152?hl=ja こんなことを言うと怒られてしまうかもしれませんが、個人的にAndroidはiOSほど情報が上手くまとまっていないように思いました。昔はそもそも審査がなかったり、審査基準がAppleと比較すると緩いという話もあったりしますし、整備がまだまだ行き届いていないのかもしれません。 私は特に1つ目のデベロッパーポリシーの方を注視しました。こちらもかなりの文量ですが、iOS同様しっかり読むことをおすすめします。中でも気になった点をいくつかご紹介します。 著作権で保護されているコンテンツを使用する場合は、その権利の証拠を示すよう求められることがあります。 例えば、他社からアプリ開発の委託を受けている場合や他社とアライアンスを組んでいる場合など、デベロッパーアカウントの情報と直接に関係のないロゴを使用していると、権限を保有しているのか審査で尋ねられることがあるそうです。私達のアプリは前述の例でいうところの後者に該当するサービスなのですが、幸いなことに今回は指摘がありませんでした。こういった権利周りのセンシティブな情報の外部公開にはそれなりに時間がかかると思います。Googleの審査チームへの事前フォームがあり、ファイルを添付してメッセージを送信できるようになっているので、用意可能な場合は必要書類をフォームで提出しておくと良さそうです。 アプリの Google Play 掲載情報に記載されている主体(デベロッパーや会社等)がプライバシー ポリシーに明記されている、もしくはアプリ名がプライバシーポリシーに明記されている必要があります。 1つの会社でいくつもサービスを持っている場合、全社で共通のプライバシーポリシーを使用しているという場合があると思います。私達が正に同じ状況にあり、該当のプライバシーポリシーにアプリの名称の記載がなかったので困りました。結論、私達はサービス固有のプライバシーポリシーを用意して審査に臨むことにしました。そのため、アプリ名称が記載されていないことでリジェクトされるかどうかは実際にはわからないですが、リスクを可能な限り回避するためには対応しておく方が良いと思います。アプリで使用している第三者サービスのプライバシーポリシーを調査する必要があったり、法務に内容を相談する必要があったり、一朝一夕で用意できるものではないと思うので可能な限り早めに対応しておくと良さそうです。 すべてのデベロッパーは、すべてのアプリについて、ユーザーデータの収集、使用、共有に関する詳細な説明を、データセーフティセクションに明瞭かつ正確に記載する必要があります。 こちらに詳細記載されていますが、データセーフティセクションというものが新設され2022年4月までに内容を申告する必要があるそうです。PlayConsoleにて自身のサービスのプライバシーポリシーをもとにいくつかの質問に回答する形なので、物量はありましたが内容自体そこまで大変なものではありませんでした。 こちらのプライバシーに関する情報提供についてですが、iOSにも似たようなセクションがあり2020年12月より提出が必須になっています。詳細はこちらに記載がありますのでご参照ください。 2. 審査に必要な準備を知る 審査に提出するには何をする必要があるのかチェックリストのようなものがあれば一番良いのですが、残念ながらそういったリストの用意はありません。※Androidの場合はPlayConsoleのダッシュボードの画面にチェックリストが表示されています。 前述のガイドラインをよく読んで審査基準を満たしているか確認するとともに、スクリーンショットや掲載文などのアプリのメタ情報を用意します。公式のヘルプページを見つつ用意する形になると思いますが、実際にデベロッパーコンソールやアプリストアを見つつ、何が必要かどのように使われるのかイメージを掴みながら用意するのが手っ取り早くかつ最も分かりやすいと思います。 iOS https://developer.apple.com/jp/app-store/product-page/ Android https://support.google.com/googleplay/android-developer/answer/9859455?hl=ja&ref_topic=7072031 https://support.google.com/googleplay/android-developer/topic/3450987?hl=ja&ref_topic=7072031 ここで忘れがちだったり後回しにしがちだったりするので注意しておきたい点なのですが、審査に提出する(審査をしていただく)ということは審査を行うことのできる環境が必要です。ECなどアプリ上で金銭のやりとりが発生する場合や、WEBが先行で既に本番稼働していてサーバーサイドはアプリと共通といった場合などは、審査の際に実際に操作されてしまうと困るという事情があると思います。私達は後者の例にあてはまったのですが、レビュー時に操作しないでほしいという旨の注意書きと、YouTubeに限定公開した機能説明の動画のリンクを提出するという手法で乗り切りました。実際、審査中に該当の操作を行ったログはなかったですし、審査も無事に通過したので有効な手段ということが言えると思います。MacがあればiMovieなどを使って手軽に動画作成もできるのでおすすめです。 また、アプリ内にアカウントの作成機能がある場合は、審査用にログイン可能なデモアカウントを提出する必要がありますのでご注意ください。私たちの場合、SMS認証が必要なサービスなのでどのように対応するか困ったのですが、FirebaseAuthを使っていたので架空の電話番号と認証コードを用意して対応しました。便利! Ref: https://firebase.google.com/docs/auth/web/phone-auth?hl=ja#:~:text=Firebase Authentication では、実際の,番号として使用します。 3. 最後に いかがでしたでしょうか?アプリエンジニアの方からすれば知っていて当然のことかもしれないですが、初見の人間からすると知らない、見えない分非常に神経を使う作業でした。 アプリのスクリーンショットは熟練のデザイナーさんが対応してくださったり、掲載文は企画の方が他サービスの調査を踏まえつつ用意してくださったり、品質はQAエンジニアの方が綿密なテストを実施して担保してくださったりと色々な方の協力があったので、私は漠然とした不安を抱えながらも、安心して全体のチェックに時間を割くことができました。アプリの要件としても、金銭のやりとりやユーザーに寄るコンテンツの作成だったり基準の厳しい機能がなかったのも初心者としては対応しやすかったという面もあったと思います。 稚拙な文で大変恐縮ですが、ここまで読んでくださりありがとうございました。私と同じように、これから世の中にアプリを出していこうという方の少しでも手助けとなれば幸いです。また、こちらの文章に記載している記事や公式の審査基準等は今後も更新されていくはずなので、常にApple/Googleの最新の公式ページを確認したり、情報をウォッチしていく必要があると思います。他にも気をつけるべき点などが思い浮かんだ方はぜひ実体験なども踏まえてコメントしていただけると大変ありがたいです。
- 投稿日:2022-02-24T13:32:30+09:00
ネイティブアプリの初回審査通過に向けて気をつけたポイント(2022年2月版)
0. 概要 この度、新規のネイティブアプリをiOS/Androidの両プラットフォームにてスケジュール通りにリリース可能な(Apple/Googleによる審査が通過した)状態にすることができました! ※審査時間がとても早かった(通常、初回は2週間ほどを見るのが良いと言われていますが、提出から通過までなんと1営業日…!)というラッキーはありましたが、間違いなく開発チームの努力の成果だと思っています! チームの中でも私個人は今回、技術的な側面ではなく、アプリが審査基準を満たせているか?審査提出に必要なタスクは何か?といった側面において、リスク回避に努めました。スケジュール通りに何かを成し遂げる際は「不確定要素」をどれだけ減らしていくかといったことが重要だと思いますが、アプリのサービスリリースにおいて最大の不確定要素は「審査でのリジェクト」になるかと思います。今回得た知見で、どなたかの「不確定要素」を減らす手助けが出来れば…!という気持ちです。 1. 公式のガイドラインを読む 兎にも角にもまずは公式のガイドラインを読みました。入り口が分かりづらかったり、各所に情報が散らばっていたり、色々と思うところはありますがまずは一読しておいた方が良いと思います。 iOS https://developer.apple.com/jp/app-store/review/ https://developer.apple.com/jp/ios/submit/ 特に注視したのは、App Store Reviewガイドラインです。審査はこちらの基準に則って行われるはずなので、少々文量はありますが、端から端までしっかり読むのが良いと思います。中でも気になった点を以下に紹介しておきます。 アカウントの作成に対応したAppの場合は、App内でアカウントの削除もできるようにする必要があります。 こちらに公式のプレスが載っていますが、アプリ内にてアカウント作成機能を提供している場合は、2022年1月31日よりApp内のアカウント削除機能の提供が必須要件になっています。引用した文章は太字にもなっておらずしれっと記載されています。ググるといくつか記事も見当たりますので、iOSエンジニアの方からすると知っていて当然のニュースという感じかもしれませんが、アプリ開発未経験者からするとあまりにも不親切…と思いました。 ユーザーコンテンツやアプリ内課金がある場合などアプリの要件に合わせて、各項目をしっかりチェックする方が良いと思います。上記のように機能開発が必要なのにも関わらず、審査でリジェクトされるまで気づけないと精神的にかなりきついところがあると思います。当然リリース日は伸びてしまいますし、急ぎで作った機能は品質の面などで不安になってしまうでしょう。今回は他の開発メンバーがプレスに気づき比較的早い段階で対応できましたが、不安要素は早め早めに潰しておくと良いなと改めて感じました。 Android https://play.google.com/about/developer-content-policy/?hl=ja https://support.google.com/googleplay/android-developer/answer/9859152?hl=ja こんなことを言うと怒られてしまうかもしれませんが、個人的にAndroidはiOSほど情報が上手くまとまっていないように思いました。昔はそもそも審査がなかったり、審査基準がAppleと比較すると緩いという話もあったりしますし、整備がまだまだ行き届いていないのかもしれません。 私は特に1つ目のデベロッパーポリシーの方を注視しました。こちらもかなりの文量ですが、iOS同様しっかり読むことをおすすめします。中でも気になった点をいくつかご紹介します。 著作権で保護されているコンテンツを使用する場合は、その権利の証拠を示すよう求められることがあります。 例えば、他社からアプリ開発の委託を受けている場合や他社とアライアンスを組んでいる場合など、デベロッパーアカウントの情報と直接に関係のないロゴを使用していると、権限を保有しているのか審査で尋ねられることがあるそうです。私達のアプリは前述の例でいうところの後者に該当するサービスなのですが、幸いなことに今回は指摘がありませんでした。こういった権利周りのセンシティブな情報の外部公開にはそれなりに時間がかかると思います。Googleの審査チームへの事前フォームがあり、ファイルを添付してメッセージを送信できるようになっているので、用意可能な場合は必要書類をフォームで提出しておくと良さそうです。 アプリの Google Play 掲載情報に記載されている主体(デベロッパーや会社等)がプライバシー ポリシーに明記されている、もしくはアプリ名がプライバシーポリシーに明記されている必要があります。 1つの会社でいくつもサービスを持っている場合、全社で共通のプライバシーポリシーを使用しているという場合があると思います。私達が正に同じ状況にあり、該当のプライバシーポリシーにアプリの名称の記載がなかったので困りました。結論、私達はサービス固有のプライバシーポリシーを用意して審査に臨むことにしました。そのため、アプリ名称が記載されていないことでリジェクトされるかどうかは実際にはわからないですが、リスクを可能な限り回避するためには対応しておく方が良いと思います。アプリで使用している第三者サービスのプライバシーポリシーを調査する必要があったり、法務に内容を相談する必要があったり、一朝一夕で用意できるものではないと思うので可能な限り早めに対応しておくと良さそうです。 すべてのデベロッパーは、すべてのアプリについて、ユーザーデータの収集、使用、共有に関する詳細な説明を、データセーフティセクションに明瞭かつ正確に記載する必要があります。 こちらに詳細記載されていますが、データセーフティセクションというものが新設され2022年4月までに内容を申告する必要があるそうです。PlayConsoleにて自身のサービスのプライバシーポリシーをもとにいくつかの質問に回答する形なので、物量はありましたが内容自体そこまで大変なものではありませんでした。 こちらのプライバシーに関する情報提供についてですが、iOSにも似たようなセクションがあり2020年12月より提出が必須になっています。詳細はこちらに記載がありますのでご参照ください。 2. 審査に必要な準備を知る 審査に提出するには何をする必要があるのかチェックリストのようなものがあれば一番良いのですが、残念ながらそういったリストの用意はありません。※Androidの場合はPlayConsoleのダッシュボードの画面にチェックリストが表示されています。 前述のガイドラインをよく読んで審査基準を満たしているか確認するとともに、スクリーンショットや掲載文などのアプリのメタ情報を用意します。公式のヘルプページを見つつ用意する形になると思いますが、実際にデベロッパーコンソールやアプリストアを見つつ、何が必要かどのように使われるのかイメージを掴みながら用意するのが手っ取り早くかつ最も分かりやすいと思います。 iOS https://developer.apple.com/jp/app-store/product-page/ Android https://support.google.com/googleplay/android-developer/answer/9859455?hl=ja&ref_topic=7072031 https://support.google.com/googleplay/android-developer/topic/3450987?hl=ja&ref_topic=7072031 ここで忘れがちだったり後回しにしがちだったりするので注意しておきたい点なのですが、審査に提出する(審査をしていただく)ということは審査を行うことのできる環境が必要です。ECなどアプリ上で金銭のやりとりが発生する場合や、WEBが先行で既に本番稼働していてサーバーサイドはアプリと共通といった場合などは、審査の際に実際に操作されてしまうと困るという事情があると思います。私達は後者の例にあてはまったのですが、レビュー時に操作しないでほしいという旨の注意書きと、YouTubeに限定公開した機能説明の動画のリンクを提出するという手法で乗り切りました。実際、審査中に該当の操作を行ったログはなかったですし、審査も無事に通過したので有効な手段ということが言えると思います。MacがあればiMovieなどを使って手軽に動画作成もできるのでおすすめです。 また、アプリ内にアカウントの作成機能がある場合は、審査用にログイン可能なデモアカウントを提出する必要がありますのでご注意ください。私たちの場合、SMS認証が必要なサービスなのでどのように対応するか困ったのですが、FirebaseAuthを使っていたので架空の電話番号と認証コードを用意して対応しました。便利! Ref: https://firebase.google.com/docs/auth/web/phone-auth?hl=ja#:~:text=Firebase Authentication では、実際の,番号として使用します。 3. 最後に いかがでしたでしょうか?アプリエンジニアの方からすれば知っていて当然のことかもしれないですが、初見の人間からすると知らない、見えない分非常に神経を使う作業でした。 アプリのスクリーンショットは熟練のデザイナーさんが対応してくださったり、掲載文は企画の方が他サービスの調査を踏まえつつ用意してくださったり、品質はQAエンジニアの方が綿密なテストを実施して担保してくださったりと色々な方の協力があったので、私は漠然とした不安を抱えながらも、安心して全体のチェックに時間を割くことができました。アプリの要件としても、金銭のやりとりやユーザーに寄るコンテンツの作成だったり基準の厳しい機能がなかったのも初心者としては対応しやすかったという面もあったと思います。 稚拙な文で大変恐縮ですが、ここまで読んでくださりありがとうございました。私と同じように、これから世の中にアプリを出していこうという方の少しでも手助けとなれば幸いです。また、こちらの文章に記載している記事や公式の審査基準等は今後も更新されていくはずなので、常にApple/Googleの最新の公式ページを確認したり、情報をウォッチしていく必要があると思います。他にも気をつけるべき点などが思い浮かんだ方はぜひ実体験なども踏まえてコメントしていただけると大変ありがたいです。