Introduction

備忘録。

前提として、Flutter (dart) を使って App Clip のアプリを作るのは推奨できない。
何故なら

  • App Clip アプリにはサイズの上限があり、Flutter と統合するとサイズが上限に到達してしまう
    • iOS 17 以降 50MB (ただし、条件あり)
    • iOS 16 15MB
    • iOS 15 以前 10MB
  • Flutter 公式のサポートが薄い

と前途多難。

しかも、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 従えば良い。

  1. Xcode から App Clip を追加 (Step 2 - Add an App Clip target に該当)
    • App Clip の BundleID は必ず、末尾が .Clip で終わること (大文字小文字を区別する)
  2. ビルド設定を統合 (Step 4 - Share build configurations に該当)
  3. 親アプリ、App Clip に対して、 Associated Domains 機能を追加し、 appclips:<ドメイン> を追加 (Step 6 - Add App Clip associated domains に該当)
  4. App Clip 用の Profile (Distribution等) を Apple Developer Program 上で作成し、Xcode 上で紐づける
  5. 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
2
3
4
5
6
7
8
{
"appclips": {
"apps": [
"U27JXXX492.jp.taktak.demo.flutter.ios.Clip"
]
},
"applinks": {
"details": [

App Clip を起動するだけなら、 applinks 側の設定は不要。
appclips 側に親アプリ側を加える必要もない。

高度なApp Clip体験

App Clip カードに対して詳細な設定ができる。

高度な体験を編集 をクリック

appclip experience

次へ をクリック

appclip experience

apple-app-site-association を配置したサイトのドメインを入力し、App Clip のバンドル ID を選択。
ここで apple-app-site-association の設定が上手くいっていなかったり、Apple の CDN にキャッシュされていないと、エラーになる。

appclip experience

ヘッダー画像を付与したりタイトルを入力する。
ここでの画像は https://flutter.dev/ のヘッダー画像を使わせてもらった。

appclip experience

どっちでもいいと思うので割愛。

appclip experience

確認。

appclip experience

戻ってくると、リストに先程作成した App Clip 体験 が追加されている。

appclip experience

App Clip コードを取得する… を選択し、リストのチェックボックスをチェックをつける。
続ける を選択。

appclip experience

App Clip コードの作成処理に入る。
なお、別に App Clip コードでなくても、apple-app-site-association を配置したサイトの url を示す QR コードでも App Clip は起動する。

appclip experience

複数生成する予定もないので、 いいえ を選択し、 次へ

appclip experience

お好みのカラーを選択し、 次へ

appclip experience

ユースケースを選択し、 次へ

appclip experience

App Clip ロゴを含めるかどうかを選択し、 次へ

appclip experience

作成完了。
App Clip コードをダウンロードする を選択し、zip ファイルをダウンロード。
完了 を選択して終了。

appclip experience

出来上がった zip ファイルの中には SVG 形式で App Clip コードが入っている。

appclip code

なお、同じ内容を QR コードにすると下記になる。

qr code

TestFlight で配信

ここまでくれば後は普通に TestFlight で配信できる。
従来のアプリの下に App Clip が出現し、開く から App Clip が起動する。

appclip

カメラから起動

appclip

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 から作った場合は遭遇しなかった問題。

appclip

単純に修正するだけなら、 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 を選ぶ。

appclip

Release Testing を選択。

appclip

App Clip 側を選択。

appclip

All compatible device variants を選択。

appclip

AdHoc 対応したプロファイルを選択。

appclip

Export を選択。

appclip

出力先を選択。

appclip

エクスポートが完了し、出力先の App Thinning Size Report.txt を開き内容を確認。

appclip

All compatible device variants を選択してエクスポートしたため、複数のデバイス向けの非圧縮サイズ (インストールサイズ) が表示されているが、おおよそのサイズは掴める。
下記の場合は 142 KB になる。

1
2
3
4
5
Variant: DemoAppClip-AEDDFF66-BE28-4961-81AF-B52B72039985.ipa
Supported variant descriptors: [device: iPhone14,6, os-version: 17.4], [device: iPhone14,6, os-version: 18.0], [device: iPhone12,8, os-version: 17.4], and [device: iPhone12,8, os-version: 18.0]
App + On Demand Resources size: 35 KB compressed, 142 KB uncompressed
App size: 35 KB compressed, 142 KB uncompressed
On Demand Resources size: Zero KB compressed, Zero KB uncompressed

App Clip コードから App Clip が起動しない

標準のカメラアプリ、QR コードスキャンアプリの双方で、 使用可能なデータが見つかりません と言われる。

appclip

デベロッパ -> APP CLIPテスト の 診断 から

No Advanced Experience is registered for this URL.

appclip

と表示される。

色々試していたが、冒頭で述べた App Clip の BundleID は必ず、末尾が .Clip で終わること (大文字小文字を区別する) が重要。
最初は末尾を .clip のように小文字から始めていたが、どうやっても App Clip コードから起動しなかったので、ダメもとで変えてみたら動いた次第。
とは言え、それでも動くようになるまで Apple Store Connect や Apple CDN までの反映に遅延があったのか、起動するまでにまた時間がかかった。