🔔

Flutter で環境を分けつつ iOS の AppExtension を利用する

2023/03/13に公開

ハマりどころが多かったので、備忘録として残しておく

AppExtension とは

iOSにおいて、アプリ外の部分で機能を提供したい場合に利用するもの

  • ウィジェット
  • 通知領域のカスタマイズ
  • ...

https://developer.apple.com/jp/app-extensions/

AppExtension をアプリに追加する

該当する Extension のターゲットを追加する

例 Notification Service Extension の導入
https://developer.apple.com/documentation/usernotifications/modifying_content_in_newly_delivered_notifications

Flutter の環境分けについて(Flutter3.7以上)

dart-define-from-file オプションを利用し、 BundleId やアプリ名を環境ごとに切り替える事ができる

参考↓
https://zenn.dev/altiveinc/articles/separating-environments-in-flutter

AppExtension で環境毎の値を読み取る

AppExtension の BundleId はアプリ本体の BundleId をベースに作成する必要がある(環境ごとの値を読み取る必要がある)。が、単に AppExtension を追加しただけでは dart-define-from-file の値を読み取れないため、追加で作業が必要になる

前提: dart-define-from-file オプションがやっていること

  1. ios/Flutter/Generated.xcconfig に値を埋め込む
  2. 1 の内容を ios/Flutter/Release.xcconfig 及び ios/Flutter/Debug.xcconfig から参照する
  3. 2 の xcconfig を Runner ターゲットに紐付ける ( Xcode の Project -> Configrations から確認できる)

ここまでは Flutter 側が勝手にやってくれているが、 AppExtension への紐付けは行ってくれないため自力で設定する。

  1. AppExtension 側のターゲット用に xcconfig を作成する (例: ios/${ExtensionTarget}/Debug.xcconfig
  2. 1 で作成した xcconfig から、 ios/Flutter 配下で生成された xcconfig を参照する
ios/${ExtensionTarget}/Debug.xcconfig
#include "../Flutter/Generated.xcconfig"
  1. 2 の xcconfig を AppExtension ターゲットに紐付ける ( Xcode の Project -> Configrations から設定する)

これにより、 dart-define-from-file で渡した値も AppExtension 側で利用することができる

その他ハマりポイント

Flutter... とは関係なく AppExtension を利用するにあたって、いくつかハマった部分があったのでメモしておく

Profile の設定

ProvisioningProfile も AppExtension 用に別で作成するので、手動で Profile を設定する場合は ExportOptions に追記する必要がある

Before
<key>provisioningProfiles</key>
<dict>
	<key>com.example.app</key>
	<string>{アプリ本体用の Profile 名}</string>
</dict>
After
<key>provisioningProfiles</key>
<dict>
	<key>com.example.app</key>
	<string>{アプリ本体用の Profile 名}</string>
	<key>com.example.app.extension</key>
	<string>{AppExtension 用の Profile 名}</string>
</dict>

Development Target の設定

AppExtension を作成する際、デフォルトだとアプリ本体の Development Target に追従しないため、後から手動で設定する必要がある。

例: アプリ本体の Development Target を 11.0 にしていても、新規作成した AppExtension の Development Target が 16.0 になっている

自分は Notification Service を使うために AppExtension を追加したが、上記の問題のせいで通知に画像を添付することができず、丸一日溶かした。(ビルド自体は通るため原因に気づきにくい)

https://developer.apple.com/forums/thread/674620

おわりに

資料も少なくハマりどころも多かったため、今後この実装を行う人の助けになれば幸いです。

Discussion