20240425 Flutterからネイティブコードにアクセスする

1.1K Views

April 25, 24

スライド概要

profile-image

いとーけー@そらかぜ

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

Flutterから ネイティブコードに アクセスする 2024.4.25 関西モバイルアプリ研究会A #3 itok@そらかぜ

2.

itok@そらかぜ • いとうけい(itok) • の中の人 • モバイルアプリエンジニア 兼 CEO • 副業でフリーランス的 • https://itok.jp/, https://sorakaze.co.jp/, @itokjp

3.

所在地:京都市中京区 社員1人=自分 2015年創業9期目

4.

実績 自社 受託 公私合わせて200件ほどのアプリ開発に携わる

5.

iOS / Android / macOS / Windows / サーバ 一人でやってます(デザイン以外)

6.

Flutterから ネイティブコードに アクセスする

7.

pub.dev

8.

ここを作る話

9.

どんなシーン? • ネイティブに実装されたOSの新機能をいち早く使 いたい時 • Flutterサポートのないライブラリを使いたい時 • • 広告SDKとか (Flutterへの移行途中とか?)

10.

非UIでの処理

11.

MethodChannel MessageChannel

12.

MethodChannel • ネイティブのメソッドを呼び出すイメージ • ネイティブからは非同期で返す

13.

MessageChannel • Flutter - ネイティブの双方向通信 • どちらからもchannel越しにメッセージを送れる

14.

MethodChannel Battery Levelを取得するサンプル

15.
[beta]
Flutter側
チャンネル作成
static const channel = MethodChannel("jp.itok.kanmoba_a3/battery");
Future<int> _getBatteryLevel() async {

メソッド名指定で実行
int level = await channel.invokeMethod<int>("getBatteryLevel");
...
}

16.
[beta]
iOS側
// @objc class AppDelegate: FlutterAppDelegate
// didFinishLaunchingWithOptions内
let controller = window?.rootViewController as! FlutterViewController

チャンネル作成
let batteryChannel = FlutterMethodChannel(name: "jp.itok.kanmoba_a3/battery",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler {
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in

メソッド名指定で受け取って処理
if call.method == "getBatteryLevel" {
let level = self.getBatteryLevel()
result(level)
} else {
result(FlutterMethodNotImplemented)
}
}
)

17.

ちなみに

18.
[beta]
Future<int> _getBatteryLevel() async {
int level;
...
}

private fun getBatteryLevel(): Int {
var level: Int
...
}

private func getBatteryLevel() -> Int {
var level: Int
...
}

19.
[beta]
Flutter
Dart

Future<int> _getBatteryLevel() async {
int level;
...
}

Android
Kotlin

private fun getBatteryLevel(): Int {
var level: Int
...
}

iOS
Swift

private func getBatteryLevel() -> Int {
var level: Int
...
}

20.

😵💫

21.

ネイティブUI

22.

Flutter UiKitView AndroidView PlatformViewLink PlatformViewFactory ネイティブ PlatformView

23.

Flutter側 UiKitView( viewType: "jp.itok.kanmoba_a3/nativeView", 引数 creationParams: creationParams, 引数のエンコード/デコード方式 creationParamsCodec: const StandardMessageCodec(), )

24.
[beta]
iOS側: PlatformView
class NativeView: NSObject, FlutterPlatformView {
private var _view: UIView
init(frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?) {
_view = UIView()
super.init()
createNativeView(frame: frame,
viewIdentifier: viewId,
arguments: args)
}

ここで実際のViewを返す
func view() -> UIView {
_view
}
}

25.

iOS側: PlatformViewFactory class NativeViewFactory: NSObject, FlutterPlatformViewFactory { func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView { Viewを生成 return NativeView(frame: frame, viewIdentifier: viewId, arguments: args) } 引数のエンコード/デコード方式 func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol { return FlutterStandardMessageCodec() } }

26.

iOS側: 登録 // @objc class AppDelegate: FlutterAppDelegate // didFinishLaunchingWithOptions内 Factoryを登録 let factory = NativeViewFactory(messenger: registrar!.messenger()) registrar(forPlugin: "pluginName")! .register(factory, withId: "jp.itok.kanmoba_a3/nativeView")

28.

既存のネイティブプロジェクト ViewControllerまるごと Flutterで使えるのでは?

29.

雑感 • UIViewの配下という位置づけなので UIViewControllerをchildViewControllerとしては 扱ってくれない • SwiftUIもUIHostingController経由で使えるが・・・

30.

まとめ • 3プラットフォームを行き来するので一人で全部や るとちょっと大変 • 簡単なものならpub.devに頼るよりメンテが楽な場 合もあるかも • ネイティブプロジェクトからの移行としては微妙