Introduction
備忘録。
前提として、Flutter (dart) を使って App Clip のアプリを作るのは推奨できない。
何故なら
- App Clip アプリにはサイズの上限があり、Flutter と統合するとサイズが上限に到達してしまう
- iOS 17 以降 50MB (ただし、条件あり)
- iOS 16 15MB
- iOS 15 以前 10MB
- Flutter 公式のサポートが薄い
- Adding an iOS App Clip target の説明における Xcode が古い
- App Clip uncompressed size is larger than 10MB #71098 にあるように、何もカスタマイズしていない状態で 10MB を超える問題が Close されない
と前途多難。
しかも、Anroid における App Clip の対となる Google Play Instant では、
- 現時点でサイズの上限が 15MB
- Flutter 公式で一切言及がない
- NFC 等大部分の機能が使えない
と致命的。
それでも、仕事のネタなので試してみる。
環境は
- macOS Sequoia 15.3
- Xcode 16.2
- Flutter 3.27.4
とする。
How to do?
App Clip を作る
基本は Adding an iOS App Clip target 従えば良い。
- Xcode から App Clip を追加 (Step 2 - Add an App Clip target に該当)
- App Clip の BundleID は必ず、末尾が
.Clip
で終わること (大文字小文字を区別する)
- App Clip の BundleID は必ず、末尾が
- ビルド設定を統合 (Step 4 - Share build configurations に該当)
- 親アプリ、App Clip に対して、 Associated Domains 機能を追加し、 appclips:<ドメイン> を追加 (Step 6 - Add App Clip associated domains に該当)
- App Clip 用の Profile (Distribution等) を Apple Developer Program 上で作成し、Xcode 上で紐づける
- apple-app-site-association ファイルの設定
を実施すれば、最低限の基盤はできる。
下記はスキップした
- Step 3 - Remove unneeded files
- サイズ上限問題もあり、Flutter と統合しない道を選んだのと Swift で実装する覚悟を決めたため
- Step 5 - Share code and assets
- ここはオプション。親アプリと Storyboard とかを共有するか、という話だが自分はスキップ
- Step 7 - Integrate Flutter、Step 8 - Integrate plugins
- 試してはいないが、Flutter で親アプリをビルドすると、App Clip 側もビルドする等の設定だと思うが、サイズの上限の問題もあるので実施しない
apple-app-site-association の設定
下記のような appclips
セクションを追加する。
1 | { |
App Clip を起動するだけなら、 applinks
側の設定は不要。appclips
側に親アプリ側を加える必要もない。
高度なApp Clip体験
App Clip カードに対して詳細な設定ができる。
高度な体験を編集 をクリック
次へ をクリック
apple-app-site-association を配置したサイトのドメインを入力し、App Clip のバンドル ID を選択。
ここで apple-app-site-association の設定が上手くいっていなかったり、Apple の CDN にキャッシュされていないと、エラーになる。
ヘッダー画像を付与したりタイトルを入力する。
ここでの画像は https://flutter.dev/ のヘッダー画像を使わせてもらった。
どっちでもいいと思うので割愛。
確認。
戻ってくると、リストに先程作成した App Clip 体験 が追加されている。
App Clip コードを取得する… を選択し、リストのチェックボックスをチェックをつける。
続ける を選択。
App Clip コードの作成処理に入る。
なお、別に App Clip コードでなくても、apple-app-site-association を配置したサイトの url を示す QR コードでも App Clip は起動する。
複数生成する予定もないので、 いいえ を選択し、 次へ。
お好みのカラーを選択し、 次へ。
ユースケースを選択し、 次へ。
App Clip ロゴを含めるかどうかを選択し、 次へ。
作成完了。
App Clip コードをダウンロードする を選択し、zip ファイルをダウンロード。
完了 を選択して終了。
出来上がった zip ファイルの中には SVG 形式で App Clip コードが入っている。
なお、同じ内容を QR コードにすると下記になる。
TestFlight で配信
ここまでくれば後は普通に TestFlight で配信できる。
従来のアプリの下に App Clip が出現し、開く から App Clip が起動する。
カメラから起動
TestFlight が内部テストからなのか上手く起動しない。
とりあえずはここまで。
Trouble shooting
App Clip のストアへの提出
個別に実施する必要はなくて、親アプリを App Store Connect にアップロードすれば自動的に App Clip がアップロードされる。
The CFBundleShortVersionString of an App Clip (null) must match that of its containing parent app
親アプリ (Flutter の場合 Runner) とバージョンが一致していない、というエラー。
この問題は Swift で 0 から作った場合は遭遇しなかった問題。
単純に修正するだけなら、 App Clip 側のプロジェクトの General タブ配下の Identity - Version に値を設定するだけだが、固定の値を設定すると、親アプリのバージョンを変える度に手動での変更が必要になる。
そのため、まず、上で述べたように固定値 (ここでは 1.0.0 とする) を入力しし、親アプリの project.pbxproj ファイル (Flutter なら Runner.xcodeproj/project.pbxproj) をテキストで開く。
そうすると MARKETING_VERSION = "1.0.0";
という記述があるので、それを MARKETING_VERSION = "$(FLUTTER_BUILD_NAME)";
で置換する。
これで問題が解決する。
App Clipのサイズを知りたい
極端に言えば、App Store Connect にアップロードを実行し、失敗すればサイズ上限を超えたことになるが、流石にそれはあれだ。
App Store Connect でサイズを調べるには、 TestFlight タブに移動し、対象のバージョンのビルドを選択、ビルドのメタデータを選択し、アプリのファイルサイズを開くと、各デバイスにおけるインストールサイズを把握できる。
ダウンロードサイズは App Clip の上限ではない点に注意。
では、App Store Connect へのアップロード前にアプリのサイズを調べるには、Ad Hoc でアプリをエクスポートし、ログを見ることで調べることになる。
親アプリを Archive し、Distribute App を選択し、 Custom を選ぶ。
Release Testing を選択。
App Clip 側を選択。
All compatible device variants を選択。
AdHoc 対応したプロファイルを選択。
Export を選択。
出力先を選択。
エクスポートが完了し、出力先の App Thinning Size Report.txt
を開き内容を確認。
All compatible device variants を選択してエクスポートしたため、複数のデバイス向けの非圧縮サイズ (インストールサイズ) が表示されているが、おおよそのサイズは掴める。
下記の場合は 142 KB になる。
1 | Variant: DemoAppClip-AEDDFF66-BE28-4961-81AF-B52B72039985.ipa |
App Clip コードから App Clip が起動しない
標準のカメラアプリ、QR コードスキャンアプリの双方で、 使用可能なデータが見つかりません と言われる。
デベロッパ -> APP CLIPテスト の 診断 から
No Advanced Experience is registered for this URL.
と表示される。
色々試していたが、冒頭で述べた App Clip の BundleID は必ず、末尾が .Clip
で終わること (大文字小文字を区別する) が重要。
最初は末尾を .clip
のように小文字から始めていたが、どうやっても App Clip コードから起動しなかったので、ダメもとで変えてみたら動いた次第。
とは言え、それでも動くようになるまで Apple Store Connect や Apple CDN までの反映に遅延があったのか、起動するまでにまた時間がかかった。