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
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
1k
Other Decks in Technology
See All in Technology
しろおびから始める!ログ活用の第一歩
shumei_ito
0
690
FactoryBotアンチパターン / factory_bot anti-patterns
toshimaru
0
140
二歩目のフロントエンド・ウェブアクセシビリティ
camiha
2
150
「Docker Desktop不要の時代」は 来たのか?
ueponx
0
250
私の推しは「聞いてから進む」AIです -AI-DLCに一人でアプリを作らせた話
yama3133
1
180
今こそ知りたいAmplifyGen2
mkdev10
2
160
初対面のメンバーがチームを組み、Claude Codeでゼロからサービスをリリース
mkdev10
1
110
味覇で作るパスタが美味い - 20261001_yabaubuki.dev
livesense
PRO
0
110
生成AIで高い生産性を求められて、 悩み、乗り越えた話
mot_techtalk
2
130
LLM機能を自作して分かるSnowflake Cortex AIの強み
nayuts
0
330
不可逆な意思決定を避けながら10億超の顧客データを AI Ready にするデータ基盤設計
baseballyama
1
180
3つのアプローチで目指す チームを強くするAI駆動開発
thkt
0
130
Featured
See All Featured
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
KATA
mclloyd
PRO
35
16k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
[RailsConf 2023] Rails as a piece of cake
palkan
59
7.1k
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
390
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
4
4.3k
Code Reviewing Like a Champion
maltzj
529
40k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.4k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.7k
Fireside Chat
paigeccino
43
4.1k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
480
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
50
10k
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