FlutterでURL Schemeを扱う方法としてはuni_linksをよく使うと思います。
今回、FlutterアプリにFlutterのパッケージでなくネイティブのGoogle Sign Inを追加した所、uni_linksが動かないという状況になりました。
直接的な原因はAppDelegate.swiftに,GoogleSignInのコールバックを受けるために、以下の関数を追加してしまったことです。(公式ドキュメント通りの手順)
override func application(
_ app: UIApplication,
open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]
) -> Bool {
var handled: Bool
handled = GIDSignIn.sharedInstance.handle(url)
if handled {
return true
} else {
return
}
// Handle other custom URL types.
// If not handled by this app, return false.
return false
}
しかし、この関数をオーバーライドしてしまうと、uni_linksが動かなくなります。
理由はAppDelegate
のスーパークラスであるFlutterAppDelegate
の方の、関数が動かなくなってしまうからpluginで呼ばれるはずの、uni_links関数が実行されなくなってしまうからです。
正しく修正するには、AppDelegate.swift
にこの関数を追加せずに、この関数自体をpluginで実行するようにします。
public class AppDelegatePlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let instance = AppDelegatePlugin()
registrar.addApplicationDelegate(instance)
}
public func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
var handled: Bool
handled = GIDSignIn.sharedInstance.handle(url)
if handled {
return true
}
// ここでハンドルしない場合はuni_linksでハンドルできるようにfalseを返す
return false
}
}
application
関数の戻り値はGoogleSignInのURLを処理した場合のみtrueを返し、それ以外の場合はfalseを返します。これは複数のPluginからこの関数が登録された場合に、あとに実行されるapplication
関数を実行するためです。ちなみにuni_linksを使うとこの関数の戻り値は常にtrueになります。参考。そのためプラグインの追加順は以下のようにする必要があります。
// uni_linksより先に実行させるためこの位置に追加
AppDelegatePlugin.register(with: registrar(forPlugin: "com.example.AppDelegatePlugin")!)
// uni_linksを含む追加されたライブラリのプラグインが追加される
GeneratedPluginRegistrant.register(with: self)
いかがでしたか?今回はやりたいことがニッチ過ぎましたが、Flutterプラグインの理解が少し深まりました。
例えばURLスキーマを扱うライブラリが複数追加された場合にも、片方が機能しないなどの問題が起きそうな気がします。その場合、プラグインの追加順を調整したり、application
関数の戻り値を制御するなどの対応が取れるかもしれません。