Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
How to handle 3rd-Party Apps in a plugin packag...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Katsumi Onishi
August 28, 2018
Technology
1.2k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
How to handle 3rd-Party Apps in a plugin packages in Flutter
Katsumi Onishi
August 28, 2018
More Decks by Katsumi Onishi
See All by Katsumi Onishi
Material Design と Product UI Design
katsummy
2
880
Flutter at Google I/O 2019
katsummy
8
1.5k
TechCon Official App on Flutter
katsummy
1
1.1k
Other Decks in Technology
See All in Technology
1週間、Opus封印でお願いします
kintotechdev
0
370
AI時代のエンジニアの情報発信〜個人の発信を組織の力に変える〜
ryo_kawamata
0
380
AIコーディングエージェント開発_全体像
happysamurai294
0
120
AIエージェントに 権限と鍵をどこまで渡すか
nrinetcom
PRO
2
150
Microsoft のサポート ライフサイクルを理解する
murachiakira
PRO
0
230
キヨさん、67歳。AIコーディングエージェントに挑む
happysamurai294
0
120
AIに任せられるFlutterコードベースを作る 〜仕様をコードで表し、ハーネスで守る〜
myohei
1
410
Lint の層を組み直した話
bengo4com
1
190
Flutter Widget Previewerで始めるUIプレビューとVRTの自動化
sakusaku3939
0
170
デザインレビューは自動化できるのか?─ Flutter × Figma で UI 品質保証を考える
techiro
2
570
200人の配信コメント、 全部Jevが仕分けます 〜 マサカリガードを作ってみた 〜
katayamatg
1
440
仕様駆動開発の、その先へ。決める力と確かめる仕組み
inariku
1
130
Featured
See All Featured
How to Talk to Developers About Accessibility
jct
2
600
WCS-LA-2024
lcolladotor
0
930
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
610
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.2k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3.1k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.4k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
540
Designing for humans not robots
tammielis
254
26k
Music & Morning Musume
bryan
48
7.5k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
570
Game over? The fight for quality and originality in the time of robots
wayneb77
1
320
Transcript
Handling 3rd-Party Apps in a plugin packages @katsummy - Android
Engineer
Flutter Plugin Package Plugin Package iOS Host FlutterViewController AppDelegate iOS
platform APIs 3rd-Party App Android Host FlutterView Activity Android platform APIs 3rd-Party App App Platform Channels
App / Package / Plugin app : アプリケーション package :
共有モジュール(Dart) plugin : プラットフォームの実装を持つ共有モジュール
Platform Channels プラットフォーム固有のAPIと通信する - Method Channel - Event Channel
Method Channel ホストのメソッドを呼び出してプラットフォームのAPIを実行し、結 果を戻り値として受け取ります。 Flutter App iOS/Android Call Method Return
Value (Synchronous)
Event Channel ブロードキャストストームの受信者をホストに登録し、コールバッ クで非同期にプラットフォームイベントを受信します。 Flutter App iOS/Android BroadcastStream Listener Event
(Asynchronous) Event
Method Channel Implementation
Method Channel - Android Implement (1/2) public class HelloPlugin implements
MethodCallHandler { // static method. public static void registerWith(Registrar registrar) { // 1. MethodChannelを作成 final MethodChannel channel = new MethodChannel(registrar.messenger(), "hello"); // 2. MethodChannelにPluginを登録 HelloPlugin instance = new HelloPlugin(); channel.setMethodCallHandler(instance); } $ flutter create --template=plugin hello
Method Channel - Android Implement (2/2) @Override public void onMethodCall(MethodCall
call, Result result) { // 3. FlutterからのMethodCallを受け取る if (call.method.equals("getPlatformVersion")) { // 4. Flutterへ結果をコールバックする if (/*condition*/) { // 4-1. Success result.success("Android " + android.os.Build.VERSION.RELEASE); } else { // 4-2. Error result.error("ERROR", "errorMessage", null): } } else { // 4-2. NotImplemented Error result.notImplemented(); } } }
Method Channel - iOS Implement (1/2) @interface HelloPlugin : NSObject<FlutterPlugin>
@end @implementation HelloPlugin // Implemented by the iOS part of a FlutterPlugin. + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { // 1. MethodChannelを作成 FlutterMethodChannel* channel = [FlutterMethodChannel methodChannelWithName:@"hello" binaryMessenger:[registrar messenger]]; // 2. MethodChannelにPluginを登録 HelloPlugin* instance = [[HelloPlugin alloc] init]; [registrar addMethodCallDelegate:instance channel:channel]; }
Method Channel - iOS Implement (2/2) - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
// 3. FlutterからのMethodCallを受け取る if ([@"getPlatformVersion" isEqualToString:call.method]) { // 4. Flutterへ結果をコールバックする if (/*condition*/) { // 4-1. Success result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]); } else { // 4-2. Error result([FlutterError errorWithCode:@"ERROR" message:"errorMessage" details:nil]); } } else { // 4-2. NotImplemented Error result(FlutterMethodNotImplemented); }
Method Channel - Flutter Implement class Hello { // 1.
MethodChannelを作成 static const MethodChannel _channel = const MethodChannel('hello'); static Future<String> get platformVersion async { // Platform messages may fail, so we use a try/catch PlatformException. try { // 2. メソッドの呼び出し final String version = await _channel.invokeMethod('getPlatformVersion'); return version; } on PlatformException catch (e) { debugPrint(${e}); return null; } } }
Event Channel Implementation
Event Channel - Android Implement (1/4) public class HelloPlugin implements
EventChannel.StreamHandler { // 1. StreamHandlerのメソッドを実装 @Override public void onListen(Object arguments, EventChannel.EventSink events) { } @Override public void onCancel(Object arguments) { }
Event Channel - Android Implement (2/4) public class HelloPlugin implements
EventChannel.StreamHandler { private EventChannel.EventSink _eventSink; public static void registerWith(Registrar registrar) { // 2. EventChannelの作成 final EventChannel eventChannel = EventChannel(registrar.messenger(), "hello"); // 3. EventChannelにPluginを登録 HelloPlugin instance = new HelloPlugin(); eventChannel.setStreamHandler(instance); }
Event Channel - Android Implement (3/4) public class HelloPlugin implements
EventChannel.StreamHandler { // 1. StreamHandlerのメソッドを実装 @Override public void onListen(Object arguments, EventChannel.EventSink events) { // 4. イベントストリームを設定 _eventSink = events; } @Override public void onCancel(Object arguments) { _eventSink = null; }
Event Channel - Android Implement (4/4) final Runnable runnable =
new Runnable() { @Override public void run() { if(_eventSink != null) { // 5. イベントをFlutterにエミット if (/*condition*/) { // 5-1. Success _eventSink.success("Hello"); } else { // 5-2. Error _eventSink.error("ERROR", "errorMessage", null); } } } };
Event Channel - iOS Implement (1/4) @interface HelloPlugin : NSObject<FlutterPlugin,
FlutterStreamHandler> @end // Implemented by the iOS part of a FlutterPlugin and FlutterStreamHandler. @implementation HelloPlugin // 1. StreamHandlerのメソッドを実装 // イベントストリームの設定する要求を処理 - (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink { return nil; } // イベントストリームを破棄する要求を処理 - (FlutterError *)onCancelWithArguments:(id)arguments { return nil; }
Event Channel - iOS Implement (2/4) // Implemented by the
iOS part of a FlutterPlugin and FlutterStreamHandler. @implementation HelloPlugin + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { // 2. EventChannelの作成 FlutterEventChannel* channel = [FlutterEventChannel eventChannelWithName:@"hello" binaryMessenger:[registrar messenger]]; // 3. EventChannelにPluginを登録 HelloPlugin* instance = [[HelloPlugin alloc] init]; [registrar addMethodCallDelegate:instance channel:methodChannel]; }
Event Channel - iOS Implement (3/4) // イベントストリームの設定する要求を処理 - (FlutterError
*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink { // 4. イベントストリームを設定 _eventSink = eventSink; return nil; } // イベントストリームを破棄する要求を処理 - (FlutterError *)onCancelWithArguments:(id)arguments { _eventSink = nil; return nil; }
Event Channel - iOS Implement (4/4) - (void)emit { [[[NSOperationQueue
alloc] init] addOperationWithBlock:^{ if(_eventSink != null) { // 5. イベントをFlutterにエミット if (/*condition*/) { // 5-1. Success _eventSink("Hello"); } else { // 5-2. Error _eventSink([FlutterError errorWithCode:@"ERROR" message:"errorMessage" details:nil]); } } }]; } @end
Event Channel - Flutter Implement class Hello { // 1.
EventChannelの作成 static const EventChannel _channel = const EventChannel('hello'); Hello() { // 2. ブロードキャストストリームのリスナーを設定 _eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError); } // 3. イベントストリームの処理 void _onEvent(Object event) { debugPrint(${event}); } // 4. エラーストリームの処理 void _onError(Object error) { debugPrint(${error}); }
How to handle 3rd-Party Apps in a plugin packages
Flutter Plugin Package Plugin Package iOS Host FlutterViewController AppDelegate iOS
platform APIs 3rd-Party App Android Host FlutterView Activity Android platform APIs 3rd-Party App App Platform Channels
3rd-Party App Login App Package Login Requeste Plugin 3rd-Party App
startActivityForResult Result Login Result Result <Method Channel> <Event Channel>
Start Activity of 3rd-Party App in Plugin (1/4) class FlutterLineLoginPlugin(registrar:
Registrar) : MethodCallHandler, EventChannel.StreamHandler, PluginRegistry.ActivityResultListener { companion object { // static method. @JvmStatic fun registerWith(registrar: Registrar): Unit { FlutterLineLoginPlugin(registrar) } } Registrar + activeContext() + activity() + addActivityResultListener()
Start Activity of 3rd-Party App in Plugin (2/4) init {
// 1. MethodChannelの作成 val methodChannel = MethodChannel(registrar.messenger(), "net.granoeste/flutter_line_login") // 2. EventChannelの作成 val eventChannel = EventChannel(registrar.messenger(), "net.granoeste/flutter_line_login_result") // 3. MethodChannelとEventChannelにPluginを登録 methodChannel.setMethodCallHandler(this) eventChannel.setStreamHandler(this) // 4. ActivityResultListenerにPluginを登録 registrar.addActivityResultListener(this) }
Start Activity of 3rd-Party App in Plugin (3/4) override fun
onMethodCall(call: MethodCall, result: Result) { // 5. FlutterからのMethodCallを受け取る when (call.method) { "startLogin" -> { // 6. Activityの起動 val loginIntent = LineLoginApi.getLoginIntent(activity, channelId) activity.startActivityForResult(loginIntent, REQUEST_CODE) // 7. Flutterへは成功を返す result.success(null) } // 8. StreamHandlerのメソッドを実装 override fun onListen(arguments: Any?, events: EventChannel.EventSink) { // 9. EventSinkを保管 _eventSink = events }
Start Activity of 3rd-Party App in Plugin (4/4) // 10.
onActivityResultを実装 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { val result = LineLoginApi.getLoginResultFromIntent(data) when (result.responseCode) { LineApiResponseCode.SUCCESS -> { // 10. EventSinkに成功を流す eventSink.success(null) } else -> { // 11. EventSinkにエラーを流す eventSink.error(result.responseCode.toString(), result.errorData.message, result.errorData.toString()) } } return true
Start Activity of 3rd-Party App in Package (1/3) class FlutterLineLogin
{ // 1. MethodChannelを作成 static const MethodChannel _methodChannel = const MethodChannel('net.granoeste/flutter_line_login'); // 2. EventChannelの作成 static const EventChannel _eventChannel = const EventChannel('net.granoeste/flutter_line_login_result');
Start Activity of 3rd-Party App in Package (2/3) FlutterLineLogin() {
// 3. ブロードキャストストリームのリスナーを設定 _eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError); } // 4. イベントストリームの処理 void _onEvent(Object event) { _onLoginSuccess(event); } // 5. エラーストリームの処理 void _onError(Object error) { _onLoginError(error); }
Start Activity of 3rd-Party App in Package (3/3) Function _onLoginSuccess;
Function _onLoginError; // 6. ログインメソッド startLogin(Function onSuccess, Function onError) async { _onLoginSuccess = onSuccess; _onLoginError = onError; await _methodChannel.invokeMethod('startLogin'); }
Start Activity of 3rd-Party App in App (1/3) // 1.
インスタンス作成 var _flutterLineLogin = new FlutterLineLogin(); // 2. ログイン await _flutterLineLogin.startLogin( (data) => { // LoginSuccess }, (error) => { // LoginError });
flutter_line_login | Flutter Package https://pub.dartlang.org/packages/flutter_line_login FirebaseSignInWithLine https://github.com/granoeste/FirebaseSignInWithLine