環境
Flutter 3.19.6
Dart 3.3.4
M2 mac Sonoma 14.5
xcode Version 15.3
課題
どうしてもアプリ起動時にAppdelegate.swiftにdart-define-from-fileで定義している環境変数を渡したかった。ただし.envとか使った方が圧倒的に楽そうではある。
↓この記事が非常に参考になった。chatGPTが相決してくれなかったことを解決してくれた。AIばっかりに頼っていてはいけないかもしれない。
解決方法
/libディレクトリ内の任意の場所に環境変数の橋渡しをするためのファイルを作る(別にmain.dartに直接書いても構わない)。
MethodChannel()
には任意の文字列を渡す。これはAppDelegateでも同じ文字列を使うのでわかりやすい名前をつけるのがいい。
platform.invokeMethod(methodName, arguments)
でAppDelegateから関数を呼ぶ。channelと同様methodName
はわかりやすい名前をつける。arguments
に値を渡すことでAppDelegate内でその値を利用することができる。
ただし、MapかListを渡す時はそれぞれinvokeMapMethod()
、invokeListMethod()
と別の関数を使う。
import 'package:flutter/services.dart';
import 'package:flutter/foundation.dart';
class EnvBridge {
// AppDelegate.swiftから処理を実行するためのchannelを宣言
static const platform = MethodChannel('envBridgeChannel');
// main.dartから呼ぶ
static Future<void> sendEnvironmentVariableToAppDelegate() async {
const key =
String.fromEnvironment('key', defaultValue: 'noSuchKey');
try {
// AppDelegateで登録した処理を行う
await platform.invokeMethod('setEnvironmentVariable', key);
} catch (e) {
debugPrint('failed to set googlemaps api: $e');
}
}
}
flutterコードか実行するための処理をAppDelegateに登録する。
FlutterMethodChannel()
のnameにはEnvBrigde
に書いたものと同じものを書く。
channel.setMethodCallHandler()
で任意の処理を登録する。methodCall.arguments
でFlutterで渡された引数を受け取ることができる。ビルド時に怒られるのでas! String
でキャストする。数値などを渡す時は適宜対応する。
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
+ let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
+ let channel = FlutterMethodChannel(
+ name: "envBridgeChannel",
+ binaryMessenger: controller.binaryMessenger
+ )
+ channel.setMethodCallHandler({
+ (methodCall: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
+ if (methodCall.method == "setEnvironmentVariable") {
+ let value = methodCall.arguments as! String
+ // 環境変数を受け取って何かする。
+ print(value)
+ }
+ })
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
main関数からEnvBridgeで定義した関数を呼ぶことで、AppDelegateの処理を実行する。結果としてFlutterから値を渡してSwiftで環境変数を使った処理を実行することができる。
Androidの時に不測の処理をすると困るので一応iosの時だけ実行するようにしておく。
+ import 'package:flutter/services.dart';
+ import 'env_bridge.dart';
- void main() {
+ Future<void> main() async {
+ if (Platform.isIOS) {
+ await EnvBridge.sendEnvironmentVariableToAppDelegate();
+ }
runApp(const MyApp())
}