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.1k
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
870
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
ADKで始める業務改善 - AIエージェント開発時の考えと設計
harappa80
2
160
開発投資の期待値を上げるプロダクトロードマップづくり ~プロダクトエンジニアが越境して事業を伸ばす~
kekekenta
1
190
作って終わりじゃないサーバーレス 〜9年運用する大規模EC物流API基盤の設計・運用のリアル〜
zozotech
PRO
0
110
バイブコーディング時代のWebアプリ開発入門~Cloud Runで学ぶセキュアなビルドとデプロイ
waiwai2111
1
130
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
3
510
Snowflakeのコスト最適化を支えるアーキテクチャ設計
ktatsuya
1
1.6k
AI de Idea
kawaguti
PRO
2
120
AIによるクリエイティブ生成を行う上での試行錯誤
plaidtech
PRO
0
160
あるけみー式LTスライド作成術
alchemy1115
2
220
Railsのように考える: See through the Master
snoozer05
PRO
4
950
Screen Lens - 今見てる画面を翻訳する
komagata
0
320
俺の仕事は AIに奪われないし、たぶんその BIも要らない
hikaruri
0
500
Featured
See All Featured
4 Signs Your Business is Dying
shpigford
187
23k
Become a Pro
speakerdeck
PRO
31
6.3k
Six Lessons from altMBA
skipperchong
29
4.5k
Raft: Consensus for Rubyists
vanstee
142
7.7k
KATA
mclloyd
PRO
35
15k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
200
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
410
A Soul's Torment
seathinner
8
3.6k
The agentic SEO stack - context over prompts
schlessera
0
940
Agile that works and the tools we love
rasmusluckow
331
22k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
68
57k
The SEO Collaboration Effect
kristinabergwall1
1
570
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