From ae65d47ebc3a750cbf90830a59c46f92a59e1231 Mon Sep 17 00:00:00 2001 From: Jaime Herencia Date: Mon, 15 Jul 2019 01:55:39 +0200 Subject: [PATCH 1/4] [firebase_dynamic_links] Changed architecture to be able to difference between the dynamic link which opened the app and links clicked on app active or in background. --- packages/firebase_dynamic_links/CHANGELOG.md | 5 + packages/firebase_dynamic_links/README.md | 27 ++++- .../FirebaseDynamicLinksPlugin.java | 110 +++++++++++------- .../example/lib/main.dart | 34 +++--- .../ios/Classes/FirebaseDynamicLinksPlugin.m | 96 ++++++++++----- .../lib/src/firebase_dynamic_links.dart | 56 ++++++++- packages/firebase_dynamic_links/pubspec.yaml | 2 +- .../test/firebase_dynamic_links_test.dart | 8 +- 8 files changed, 233 insertions(+), 105 deletions(-) diff --git a/packages/firebase_dynamic_links/CHANGELOG.md b/packages/firebase_dynamic_links/CHANGELOG.md index 64b41dc9ee3a..8d847e7de470 100644 --- a/packages/firebase_dynamic_links/CHANGELOG.md +++ b/packages/firebase_dynamic_links/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.5.0 + +* **Breaking change**. Changed architecture and method names to be able to differentiate between +the dynamic link which opened the app and links clicked during app execution (active and background). + ## 0.4.0+5 * Fix the bug below properly by allowing the activity to be null (but still registering the plugin). If activity is null, we don't get a latestIntent, instead we expect the intent listener to grab it. diff --git a/packages/firebase_dynamic_links/README.md b/packages/firebase_dynamic_links/README.md index b3250deb6a56..6a4388185694 100644 --- a/packages/firebase_dynamic_links/README.md +++ b/packages/firebase_dynamic_links/README.md @@ -97,7 +97,8 @@ Receiving dynamic links on *iOS* requires a couple more steps than *Android*. If applinks:YOUR_SUBDOMAIN.page.link ``` -4. To receive a dynamic link, call the `retrieveDynamicLink()` method from `FirebaseDynamicLinks`: +4. To receive a dynamic link, call the `getLaunchLink()` method from `FirebaseDynamicLinks` and +configure listeners for link handlers when the application is active or in background. ```dart void main() { @@ -117,16 +118,30 @@ class MyHomeWidgetState extends State { @override void initState() { super.initState(); - _retrieveDynamicLink(); + this.initDynamicLinks(); } - Future _retrieveDynamicLink() async { - final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.retrieveDynamicLink(); + void initDynamicLinks() async { + final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.getLaunchLink(); final Uri deepLink = data?.link; if (deepLink != null) { - Navigator.pushNamed(context, deepLink.path); // deeplink.path == '/helloworld' + Navigator.pushNamed(context, deepLink.path); } + + FirebaseDynamicLinks.instance.configure( + onLinkSuccess: (PendingDynamicLinkData dynamicLink) async { + final Uri deepLink = dynamicLink?.link; + + if (deepLink != null) { + Navigator.pushNamed(context, deepLink.path); + } + }, + onLinkError: (OnLinkErrorException e) async { + print('onLinkError'); + print(e.message); + } + ); } . . @@ -134,7 +149,7 @@ class MyHomeWidgetState extends State { } ``` -If your app did not open from a dynamic link, `retrieveDynamicLink()` will return `null`. +If your app did not open from a dynamic link, `getLaunchLink()` will return `null`. ## Getting Started diff --git a/packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java b/packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java index c4ed3a5903f6..782c865a8b3f 100644 --- a/packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java +++ b/packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java @@ -5,6 +5,7 @@ import androidx.annotation.NonNull; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; import com.google.android.gms.tasks.Task; import com.google.firebase.dynamiclinks.DynamicLink; import com.google.firebase.dynamiclinks.FirebaseDynamicLinks; @@ -14,7 +15,7 @@ import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; -import io.flutter.plugin.common.PluginRegistry; +import io.flutter.plugin.common.PluginRegistry.NewIntentListener; import io.flutter.plugin.common.PluginRegistry.Registrar; import java.util.ArrayList; import java.util.HashMap; @@ -22,30 +23,53 @@ import java.util.Map; /** FirebaseDynamicLinksPlugin */ -public class FirebaseDynamicLinksPlugin implements MethodCallHandler { - private Registrar registrar; - private Intent latestIntent; +public class FirebaseDynamicLinksPlugin implements MethodCallHandler, NewIntentListener { + private final Registrar registrar; + private final MethodChannel channel; - private FirebaseDynamicLinksPlugin(Registrar registrar) { + private FirebaseDynamicLinksPlugin(Registrar registrar, MethodChannel channel) { this.registrar = registrar; - if (registrar.activity() != null) { - latestIntent = registrar.activity().getIntent(); - } + this.channel = channel; + } - registrar.addNewIntentListener( - new PluginRegistry.NewIntentListener() { - @Override - public boolean onNewIntent(Intent intent) { - latestIntent = intent; - return false; - } - }); + @Override + public boolean onNewIntent(Intent intent) { + FirebaseDynamicLinks.getInstance() + .getDynamicLink(intent) + .addOnSuccessListener( + registrar.activity(), + new OnSuccessListener() { + @Override + public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) { + if (pendingDynamicLinkData != null) { + Map dynamicLink = + getMapFromPendingDynamicLinkData(pendingDynamicLinkData); + channel.invokeMethod("onLinkSuccess", dynamicLink); + } + } + }) + .addOnFailureListener( + registrar.activity(), + new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + Map exception = new HashMap<>(); + exception.put("code", e.getClass().getSimpleName()); + exception.put("message", e.getMessage()); + exception.put("details", null); + channel.invokeMethod("onLinkError", exception); + } + }); + + return false; } public static void registerWith(Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_dynamic_links"); - channel.setMethodCallHandler(new FirebaseDynamicLinksPlugin(registrar)); + final FirebaseDynamicLinksPlugin plugin = new FirebaseDynamicLinksPlugin(registrar, channel); + registrar.addNewIntentListener(plugin); + channel.setMethodCallHandler(plugin); } @Override @@ -66,8 +90,8 @@ public void onMethodCall(MethodCall call, Result result) { builder.setLongLink(url); buildShortDynamicLink(builder, call, createShortLinkListener(result)); break; - case "FirebaseDynamicLinks#retrieveDynamicLink": - handleRetrieveDynamicLink(result); + case "FirebaseDynamicLinks#getLaunchLink": + handleGetLaunchDynamicLink(result); break; default: result.notImplemented(); @@ -75,40 +99,38 @@ public void onMethodCall(MethodCall call, Result result) { } } - private void handleRetrieveDynamicLink(final Result result) { - if (latestIntent == null) { - result.success(null); - return; - } + private Map getMapFromPendingDynamicLinkData( + PendingDynamicLinkData pendingDynamicLinkData) { + Map dynamicLink = new HashMap<>(); + dynamicLink.put("link", pendingDynamicLinkData.getLink().toString()); + + Map androidData = new HashMap<>(); + androidData.put("clickTimestamp", pendingDynamicLinkData.getClickTimestamp()); + androidData.put("minimumVersion", pendingDynamicLinkData.getMinimumAppVersion()); + dynamicLink.put("android", androidData); + return dynamicLink; + } + + private void handleGetLaunchDynamicLink(final Result result) { FirebaseDynamicLinks.getInstance() - .getDynamicLink(latestIntent) - .addOnCompleteListener( + .getDynamicLink(registrar.activity().getIntent()) + .addOnSuccessListener( registrar.activity(), - new OnCompleteListener() { + new OnSuccessListener() { @Override - public void onComplete(@NonNull Task task) { - if (task.isSuccessful()) { - PendingDynamicLinkData data = task.getResult(); - if (data != null) { - Map dynamicLink = new HashMap<>(); - dynamicLink.put("link", data.getLink().toString()); - - Map androidData = new HashMap<>(); - androidData.put("clickTimestamp", data.getClickTimestamp()); - androidData.put("minimumVersion", data.getMinimumAppVersion()); - - dynamicLink.put("android", androidData); - - latestIntent = null; - result.success(dynamicLink); - return; - } + public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) { + if (pendingDynamicLinkData != null) { + Map dynamicLink = + getMapFromPendingDynamicLinkData(pendingDynamicLinkData); + result.success(dynamicLink); + return; } result.success(null); } }) .addOnFailureListener( + registrar.activity(), new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { diff --git a/packages/firebase_dynamic_links/example/lib/main.dart b/packages/firebase_dynamic_links/example/lib/main.dart index 443b79d986db..84b48492902d 100644 --- a/packages/firebase_dynamic_links/example/lib/main.dart +++ b/packages/firebase_dynamic_links/example/lib/main.dart @@ -24,7 +24,7 @@ class _MainScreen extends StatefulWidget { State createState() => _MainScreenState(); } -class _MainScreenState extends State<_MainScreen> with WidgetsBindingObserver { +class _MainScreenState extends State<_MainScreen> { String _linkMessage; bool _isCreatingLink = false; String _testString = @@ -36,31 +36,29 @@ class _MainScreenState extends State<_MainScreen> with WidgetsBindingObserver { @override void initState() { super.initState(); - _retrieveDynamicLink(); - WidgetsBinding.instance.addObserver(this); + initDynamicLinks(); } - @override - void dispose() { - super.dispose(); - WidgetsBinding.instance.removeObserver(this); - } - - @override - void didChangeAppLifecycleState(AppLifecycleState state) { - if (state == AppLifecycleState.resumed) { - _retrieveDynamicLink(); - } - } - - Future _retrieveDynamicLink() async { + void initDynamicLinks() async { final PendingDynamicLinkData data = - await FirebaseDynamicLinks.instance.retrieveDynamicLink(); + await FirebaseDynamicLinks.instance.getLaunchLink(); final Uri deepLink = data?.link; if (deepLink != null) { Navigator.pushNamed(context, deepLink.path); } + + FirebaseDynamicLinks.instance.configure( + onLinkSuccess: (PendingDynamicLinkData dynamicLink) async { + final Uri deepLink = dynamicLink?.link; + + if (deepLink != null) { + Navigator.pushNamed(context, deepLink.path); + } + }, onLinkError: (OnLinkErrorException e) async { + print('onLinkError'); + print(e.message); + }); } Future _createDynamicLink(bool short) async { diff --git a/packages/firebase_dynamic_links/ios/Classes/FirebaseDynamicLinksPlugin.m b/packages/firebase_dynamic_links/ios/Classes/FirebaseDynamicLinksPlugin.m index a98b382cc09a..e3488aaebdff 100644 --- a/packages/firebase_dynamic_links/ios/Classes/FirebaseDynamicLinksPlugin.m +++ b/packages/firebase_dynamic_links/ios/Classes/FirebaseDynamicLinksPlugin.m @@ -9,9 +9,39 @@ details:error.localizedDescription]; } +static NSMutableDictionary *getDictionaryFromDynamicLink(FIRDynamicLink *dynamicLink) { + if (dynamicLink != nil) { + NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; + dictionary[@"link"] = dynamicLink.url.absoluteString; + + NSMutableDictionary *iosData = [[NSMutableDictionary alloc] init]; + if (dynamicLink.minimumAppVersion) { + iosData[@"minimumVersion"] = dynamicLink.minimumAppVersion; + } + dictionary[@"ios"] = iosData; + return dictionary; + } else { + return nil; + } +} + +static NSMutableDictionary *getDictionaryFromFlutterError(FlutterError *error) { + if (error == nil) { + return nil; + } + + NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; + dictionary[@"code"] = error.code; + dictionary[@"message"] = error.message; + dictionary[@"details"] = error.details; + return dictionary; +} + @interface FLTFirebaseDynamicLinksPlugin () -@property(nonatomic, retain) FIRDynamicLink *dynamicLink; +@property(nonatomic, retain) FlutterMethodChannel *channel; +@property(nonatomic, retain) FIRDynamicLink *launchLink; @property(nonatomic, retain) FlutterError *flutterError; +@property(nonatomic) BOOL initiated; @end @implementation FLTFirebaseDynamicLinksPlugin @@ -19,7 +49,8 @@ + (void)registerWithRegistrar:(NSObject *)registrar { FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_dynamic_links" binaryMessenger:[registrar messenger]]; - FLTFirebaseDynamicLinksPlugin *instance = [[FLTFirebaseDynamicLinksPlugin alloc] init]; + FLTFirebaseDynamicLinksPlugin *instance = + [[FLTFirebaseDynamicLinksPlugin alloc] initWithChannel:channel]; [registrar addMethodCallDelegate:instance channel:channel]; [registrar addApplicationDelegate:instance]; @@ -29,9 +60,11 @@ + (void)registerWithRegistrar:(NSObject *)registrar { } } -- (instancetype)init { +- (instancetype)initWithChannel:(FlutterMethodChannel *)channel { self = [super init]; if (self) { + _initiated = NO; + _channel = channel; if (![FIRApp appNamed:@"__FIRAPP_DEFAULT"]) { NSLog(@"Configuring the default Firebase app..."); [FIRApp configure]; @@ -54,11 +87,11 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [FIRDynamicLinkComponents shortenURL:url options:options completion:[self createShortLinkCompletion:result]]; - } else if ([@"FirebaseDynamicLinks#retrieveDynamicLink" isEqualToString:call.method]) { - NSMutableDictionary *dict = [self retrieveDynamicLink]; + } else if ([@"FirebaseDynamicLinks#getLaunchLink" isEqualToString:call.method]) { + _initiated = YES; + NSMutableDictionary *dict = [self getLaunchLink]; if (dict == nil && self.flutterError) { result(self.flutterError); - self.flutterError = nil; } else { result(dict); } @@ -67,21 +100,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } } -- (NSMutableDictionary *)retrieveDynamicLink { - if (_dynamicLink != nil) { - NSMutableDictionary *dynamicLink = [[NSMutableDictionary alloc] init]; - dynamicLink[@"link"] = _dynamicLink.url.absoluteString; - - NSMutableDictionary *iosData = [[NSMutableDictionary alloc] init]; - if (_dynamicLink.minimumAppVersion) { - iosData[@"minimumVersion"] = _dynamicLink.minimumAppVersion; - } - _dynamicLink = nil; - dynamicLink[@"ios"] = iosData; - return dynamicLink; - } else { - return nil; - } +- (NSMutableDictionary *)getLaunchLink { + return getDictionaryFromDynamicLink(_launchLink); } - (BOOL)application:(UIApplication *)application @@ -100,27 +120,49 @@ - (BOOL)application:(UIApplication *)application - (BOOL)checkForDynamicLink:(NSURL *)url { FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url]; if (dynamicLink) { - if (dynamicLink.url) _dynamicLink = dynamicLink; + if (dynamicLink.url) _launchLink = dynamicLink; return YES; } return NO; } -- (BOOL)application:(UIApplication *)application - continueUserActivity:(NSUserActivity *)userActivity - restorationHandler:(void (^)(NSArray *))restorationHandler { - usleep(50000); +- (BOOL)onLink:(NSUserActivity *)userActivity { + BOOL handled = [[FIRDynamicLinks dynamicLinks] + handleUniversalLink:userActivity.webpageURL + completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) { + if (error) { + FlutterError *flutterError = getFlutterError(error); + [self.channel invokeMethod:@"onLinkError" + arguments:getDictionaryFromFlutterError(flutterError)]; + } else { + NSMutableDictionary *dictionary = getDictionaryFromDynamicLink(dynamicLink); + [self.channel invokeMethod:@"onLinkSuccess" arguments:dictionary]; + } + }]; + return handled; +} + +- (BOOL)onLaunchLink:(NSUserActivity *)userActivity { BOOL handled = [[FIRDynamicLinks dynamicLinks] handleUniversalLink:userActivity.webpageURL completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) { if (error) { self.flutterError = getFlutterError(error); } - self.dynamicLink = dynamicLink; + self.launchLink = dynamicLink; }]; return handled; } +- (BOOL)application:(UIApplication *)application + continueUserActivity:(NSUserActivity *)userActivity + restorationHandler:(void (^)(NSArray *))restorationHandler { + if (_initiated) { + return [self onLink:userActivity]; + } + return [self onLaunchLink:userActivity]; +} + - (FIRDynamicLinkShortenerCompletion)createShortLinkCompletion:(FlutterResult)result { return ^(NSURL *_Nullable shortURL, NSArray *_Nullable warnings, NSError *_Nullable error) { if (error) { diff --git a/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart b/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart index 647cb8c267d0..35a86f904943 100644 --- a/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart +++ b/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart @@ -4,6 +4,9 @@ part of firebase_dynamic_links; +typedef Future OnLinkSuccessHandler(PendingDynamicLinkData linkData); +typedef Future OnLinkErrorHandler(OnLinkErrorException error); + /// Firebase Dynamic Links API. /// /// You can get an instance by calling [FirebaseDynamicLinks.instance]. @@ -17,16 +20,22 @@ class FirebaseDynamicLinks { /// Singleton of [FirebaseDynamicLinks]. static final FirebaseDynamicLinks instance = FirebaseDynamicLinks._(); - /// Attempts to retrieve a pending dynamic link. + OnLinkSuccessHandler _onLinkSuccess; + OnLinkErrorHandler _onLinkError; + + /// Attempts to retrieve the dynamic link which launched the app. /// /// This method always returns a Future. That Future completes to null if /// there is no pending dynamic link or any call to this method after the /// the first attempt. - Future retrieveDynamicLink() async { - final Map linkData = - await channel.invokeMapMethod( - 'FirebaseDynamicLinks#retrieveDynamicLink'); + Future getLaunchLink() async { + final Map linkData = await channel + .invokeMapMethod('FirebaseDynamicLinks#getLaunchLink'); + return getPendingDynamicLinkDataFromMap(linkData); + } + PendingDynamicLinkData getPendingDynamicLinkDataFromMap( + Map linkData) { if (linkData == null) return null; PendingDynamicLinkDataAndroid androidData; @@ -50,6 +59,33 @@ class FirebaseDynamicLinks { iosData, ); } + + /// Configures onLink listeners: it has two methods for success and failure. + void configure({ + OnLinkSuccessHandler onLinkSuccess, + OnLinkErrorHandler onLinkError, + }) { + _onLinkSuccess = onLinkSuccess; + _onLinkError = onLinkError; + channel.setMethodCallHandler(_handleMethod); + } + + Future _handleMethod(MethodCall call) async { + switch (call.method) { + case "onLinkSuccess": + final Map data = + call.arguments.cast(); + final PendingDynamicLinkData linkData = + getPendingDynamicLinkDataFromMap(data); + return _onLinkSuccess(linkData); + case "onLinkError": + final Map data = + call.arguments.cast(); + final OnLinkErrorException e = OnLinkErrorException._( + data['code'], data['message'], data['details']); + return _onLinkError(e); + } + } } /// Provides data from received dynamic link. @@ -104,3 +140,13 @@ class PendingDynamicLinkDataIOS { /// declares higher [minimumVersion] than currently installed. final String minimumVersion; } + +class OnLinkErrorException { + OnLinkErrorException._(this.code, this.message, this.details); + + final String code; + + final String message; + + final dynamic details; +} diff --git a/packages/firebase_dynamic_links/pubspec.yaml b/packages/firebase_dynamic_links/pubspec.yaml index 587bcbcfcbf3..73848496a15b 100644 --- a/packages/firebase_dynamic_links/pubspec.yaml +++ b/packages/firebase_dynamic_links/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_dynamic_links description: Flutter plugin for Google Dynamic Links for Firebase, an app solution for creating and handling links across multiple platforms. -version: 0.4.0+5 +version: 0.5.0 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_dynamic_links diff --git a/packages/firebase_dynamic_links/test/firebase_dynamic_links_test.dart b/packages/firebase_dynamic_links/test/firebase_dynamic_links_test.dart index acf7121c7f22..6adeaace10db 100644 --- a/packages/firebase_dynamic_links/test/firebase_dynamic_links_test.dart +++ b/packages/firebase_dynamic_links/test/firebase_dynamic_links_test.dart @@ -26,7 +26,7 @@ void main() { return returnUrl; case 'DynamicLinkParameters#shortenUrl': return returnUrl; - case 'FirebaseDynamicLinks#retrieveDynamicLink': + case 'FirebaseDynamicLinks#getLaunchLink': return { 'link': 'https://google.com', 'android': { @@ -44,9 +44,9 @@ void main() { log.clear(); }); - test('retrieveDynamicLink', () async { + test('getLaunchLink', () async { final PendingDynamicLinkData data = - await FirebaseDynamicLinks.instance.retrieveDynamicLink(); + await FirebaseDynamicLinks.instance.getLaunchLink(); expect(data.link, Uri.parse('https://google.com')); @@ -57,7 +57,7 @@ void main() { expect(log, [ isMethodCall( - 'FirebaseDynamicLinks#retrieveDynamicLink', + 'FirebaseDynamicLinks#getLaunchLink', arguments: null, ) ]); From 23e49936fef2f2347af4d4cf8395c58c61adf53c Mon Sep 17 00:00:00 2001 From: Jaime Herencia Date: Mon, 15 Jul 2019 02:37:21 +0200 Subject: [PATCH 2/4] [firebase_dynamic_links] Improvements provided by @bparrishMines --- packages/firebase_dynamic_links/CHANGELOG.md | 3 +++ packages/firebase_dynamic_links/README.md | 4 ++-- .../lib/src/firebase_dynamic_links.dart | 14 ++++++++------ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/firebase_dynamic_links/CHANGELOG.md b/packages/firebase_dynamic_links/CHANGELOG.md index 8d847e7de470..4c3d1a4d6179 100644 --- a/packages/firebase_dynamic_links/CHANGELOG.md +++ b/packages/firebase_dynamic_links/CHANGELOG.md @@ -2,6 +2,9 @@ * **Breaking change**. Changed architecture and method names to be able to differentiate between the dynamic link which opened the app and links clicked during app execution (active and background). +`retrieveDynamicLink` has been replaced with two different functions: +- `getLaunchLink` a future to retrieve the link that opened the app +- `configure` a callback to listen to links opened while the app is active or in background ## 0.4.0+5 diff --git a/packages/firebase_dynamic_links/README.md b/packages/firebase_dynamic_links/README.md index 6a4388185694..4022a11b84f7 100644 --- a/packages/firebase_dynamic_links/README.md +++ b/packages/firebase_dynamic_links/README.md @@ -97,8 +97,8 @@ Receiving dynamic links on *iOS* requires a couple more steps than *Android*. If applinks:YOUR_SUBDOMAIN.page.link ``` -4. To receive a dynamic link, call the `getLaunchLink()` method from `FirebaseDynamicLinks` and -configure listeners for link handlers when the application is active or in background. +4. To receive a dynamic link, call the `getLaunchLink()` method from `FirebaseDynamicLinks` which gets the link that opened the app (or null if it was not opened via a dynamic link) +and configure listeners for link callbacks when the application is active or in background calling `configure`. ```dart void main() { diff --git a/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart b/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart index 35a86f904943..71322bbb339a 100644 --- a/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart +++ b/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart @@ -4,8 +4,10 @@ part of firebase_dynamic_links; -typedef Future OnLinkSuccessHandler(PendingDynamicLinkData linkData); -typedef Future OnLinkErrorHandler(OnLinkErrorException error); +typedef OnLinkSuccessCallback = Future Function( + PendingDynamicLinkData linkData); +typedef OnLinkErrorCallback = Future Function( + OnLinkErrorException error); /// Firebase Dynamic Links API. /// @@ -20,8 +22,8 @@ class FirebaseDynamicLinks { /// Singleton of [FirebaseDynamicLinks]. static final FirebaseDynamicLinks instance = FirebaseDynamicLinks._(); - OnLinkSuccessHandler _onLinkSuccess; - OnLinkErrorHandler _onLinkError; + OnLinkSuccessCallback _onLinkSuccess; + OnLinkErrorCallback _onLinkError; /// Attempts to retrieve the dynamic link which launched the app. /// @@ -62,8 +64,8 @@ class FirebaseDynamicLinks { /// Configures onLink listeners: it has two methods for success and failure. void configure({ - OnLinkSuccessHandler onLinkSuccess, - OnLinkErrorHandler onLinkError, + OnLinkSuccessCallback onLinkSuccess, + OnLinkErrorCallback onLinkError, }) { _onLinkSuccess = onLinkSuccess; _onLinkError = onLinkError; From 5fa9cb31215f05f7a8c7c572356591a9f176ce36 Mon Sep 17 00:00:00 2001 From: Jaime Herencia Date: Mon, 15 Jul 2019 02:41:55 +0200 Subject: [PATCH 3/4] [firebase_dynamic_links] Renaming configure to onLink --- packages/firebase_dynamic_links/CHANGELOG.md | 2 +- packages/firebase_dynamic_links/README.md | 8 ++++---- packages/firebase_dynamic_links/example/lib/main.dart | 6 +++--- .../lib/src/firebase_dynamic_links.dart | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/firebase_dynamic_links/CHANGELOG.md b/packages/firebase_dynamic_links/CHANGELOG.md index 4c3d1a4d6179..d97c290b0a50 100644 --- a/packages/firebase_dynamic_links/CHANGELOG.md +++ b/packages/firebase_dynamic_links/CHANGELOG.md @@ -4,7 +4,7 @@ the dynamic link which opened the app and links clicked during app execution (active and background). `retrieveDynamicLink` has been replaced with two different functions: - `getLaunchLink` a future to retrieve the link that opened the app -- `configure` a callback to listen to links opened while the app is active or in background +- `onLink` a callback to listen to links opened while the app is active or in background ## 0.4.0+5 diff --git a/packages/firebase_dynamic_links/README.md b/packages/firebase_dynamic_links/README.md index 4022a11b84f7..ddb0fa6c6369 100644 --- a/packages/firebase_dynamic_links/README.md +++ b/packages/firebase_dynamic_links/README.md @@ -98,7 +98,7 @@ applinks:YOUR_SUBDOMAIN.page.link ``` 4. To receive a dynamic link, call the `getLaunchLink()` method from `FirebaseDynamicLinks` which gets the link that opened the app (or null if it was not opened via a dynamic link) -and configure listeners for link callbacks when the application is active or in background calling `configure`. +and configure listeners for link callbacks when the application is active or in background calling `onLink`. ```dart void main() { @@ -129,15 +129,15 @@ class MyHomeWidgetState extends State { Navigator.pushNamed(context, deepLink.path); } - FirebaseDynamicLinks.instance.configure( - onLinkSuccess: (PendingDynamicLinkData dynamicLink) async { + FirebaseDynamicLinks.instance.onLink( + onSuccess: (PendingDynamicLinkData dynamicLink) async { final Uri deepLink = dynamicLink?.link; if (deepLink != null) { Navigator.pushNamed(context, deepLink.path); } }, - onLinkError: (OnLinkErrorException e) async { + onError: (OnLinkErrorException e) async { print('onLinkError'); print(e.message); } diff --git a/packages/firebase_dynamic_links/example/lib/main.dart b/packages/firebase_dynamic_links/example/lib/main.dart index 84b48492902d..d123514b9a68 100644 --- a/packages/firebase_dynamic_links/example/lib/main.dart +++ b/packages/firebase_dynamic_links/example/lib/main.dart @@ -48,14 +48,14 @@ class _MainScreenState extends State<_MainScreen> { Navigator.pushNamed(context, deepLink.path); } - FirebaseDynamicLinks.instance.configure( - onLinkSuccess: (PendingDynamicLinkData dynamicLink) async { + FirebaseDynamicLinks.instance.onLink( + onSuccess: (PendingDynamicLinkData dynamicLink) async { final Uri deepLink = dynamicLink?.link; if (deepLink != null) { Navigator.pushNamed(context, deepLink.path); } - }, onLinkError: (OnLinkErrorException e) async { + }, onError: (OnLinkErrorException e) async { print('onLinkError'); print(e.message); }); diff --git a/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart b/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart index 71322bbb339a..f332ca182ba7 100644 --- a/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart +++ b/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart @@ -63,12 +63,12 @@ class FirebaseDynamicLinks { } /// Configures onLink listeners: it has two methods for success and failure. - void configure({ - OnLinkSuccessCallback onLinkSuccess, - OnLinkErrorCallback onLinkError, + void onLink({ + OnLinkSuccessCallback onSuccess, + OnLinkErrorCallback onError, }) { - _onLinkSuccess = onLinkSuccess; - _onLinkError = onLinkError; + _onLinkSuccess = onSuccess; + _onLinkError = onError; channel.setMethodCallHandler(_handleMethod); } From b3bb0eebea3185971e1f9d999437c6e04c929ef5 Mon Sep 17 00:00:00 2001 From: Jaime Herencia Date: Tue, 23 Jul 2019 01:27:00 +0200 Subject: [PATCH 4/4] [firebase_dynamic_links] Renaming getLaunchLink to getInitialLink --- packages/firebase_dynamic_links/CHANGELOG.md | 2 +- packages/firebase_dynamic_links/README.md | 6 +++--- .../FirebaseDynamicLinksPlugin.java | 6 +++--- .../example/lib/main.dart | 2 +- .../ios/Classes/FirebaseDynamicLinksPlugin.m | 18 +++++++++--------- .../lib/src/firebase_dynamic_links.dart | 7 ++++--- .../test/firebase_dynamic_links_test.dart | 8 ++++---- 7 files changed, 25 insertions(+), 24 deletions(-) diff --git a/packages/firebase_dynamic_links/CHANGELOG.md b/packages/firebase_dynamic_links/CHANGELOG.md index d97c290b0a50..08740e681a00 100644 --- a/packages/firebase_dynamic_links/CHANGELOG.md +++ b/packages/firebase_dynamic_links/CHANGELOG.md @@ -3,7 +3,7 @@ * **Breaking change**. Changed architecture and method names to be able to differentiate between the dynamic link which opened the app and links clicked during app execution (active and background). `retrieveDynamicLink` has been replaced with two different functions: -- `getLaunchLink` a future to retrieve the link that opened the app +- `getInitialLink` a future to retrieve the link that opened the app - `onLink` a callback to listen to links opened while the app is active or in background ## 0.4.0+5 diff --git a/packages/firebase_dynamic_links/README.md b/packages/firebase_dynamic_links/README.md index ddb0fa6c6369..e5b755d6f421 100644 --- a/packages/firebase_dynamic_links/README.md +++ b/packages/firebase_dynamic_links/README.md @@ -97,7 +97,7 @@ Receiving dynamic links on *iOS* requires a couple more steps than *Android*. If applinks:YOUR_SUBDOMAIN.page.link ``` -4. To receive a dynamic link, call the `getLaunchLink()` method from `FirebaseDynamicLinks` which gets the link that opened the app (or null if it was not opened via a dynamic link) +4. To receive a dynamic link, call the `getInitialLink()` method from `FirebaseDynamicLinks` which gets the link that opened the app (or null if it was not opened via a dynamic link) and configure listeners for link callbacks when the application is active or in background calling `onLink`. ```dart @@ -122,7 +122,7 @@ class MyHomeWidgetState extends State { } void initDynamicLinks() async { - final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.getLaunchLink(); + final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.getInitialLink(); final Uri deepLink = data?.link; if (deepLink != null) { @@ -149,7 +149,7 @@ class MyHomeWidgetState extends State { } ``` -If your app did not open from a dynamic link, `getLaunchLink()` will return `null`. +If your app did not open from a dynamic link, `getInitialLink()` will return `null`. ## Getting Started diff --git a/packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java b/packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java index 782c865a8b3f..5cc4debaa404 100644 --- a/packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java +++ b/packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java @@ -90,8 +90,8 @@ public void onMethodCall(MethodCall call, Result result) { builder.setLongLink(url); buildShortDynamicLink(builder, call, createShortLinkListener(result)); break; - case "FirebaseDynamicLinks#getLaunchLink": - handleGetLaunchDynamicLink(result); + case "FirebaseDynamicLinks#getInitialLink": + handleGetInitialDynamicLink(result); break; default: result.notImplemented(); @@ -112,7 +112,7 @@ private Map getMapFromPendingDynamicLinkData( return dynamicLink; } - private void handleGetLaunchDynamicLink(final Result result) { + private void handleGetInitialDynamicLink(final Result result) { FirebaseDynamicLinks.getInstance() .getDynamicLink(registrar.activity().getIntent()) .addOnSuccessListener( diff --git a/packages/firebase_dynamic_links/example/lib/main.dart b/packages/firebase_dynamic_links/example/lib/main.dart index d123514b9a68..6784e2d0e2ef 100644 --- a/packages/firebase_dynamic_links/example/lib/main.dart +++ b/packages/firebase_dynamic_links/example/lib/main.dart @@ -41,7 +41,7 @@ class _MainScreenState extends State<_MainScreen> { void initDynamicLinks() async { final PendingDynamicLinkData data = - await FirebaseDynamicLinks.instance.getLaunchLink(); + await FirebaseDynamicLinks.instance.getInitialLink(); final Uri deepLink = data?.link; if (deepLink != null) { diff --git a/packages/firebase_dynamic_links/ios/Classes/FirebaseDynamicLinksPlugin.m b/packages/firebase_dynamic_links/ios/Classes/FirebaseDynamicLinksPlugin.m index e3488aaebdff..4ab04a4e8723 100644 --- a/packages/firebase_dynamic_links/ios/Classes/FirebaseDynamicLinksPlugin.m +++ b/packages/firebase_dynamic_links/ios/Classes/FirebaseDynamicLinksPlugin.m @@ -39,7 +39,7 @@ @interface FLTFirebaseDynamicLinksPlugin () @property(nonatomic, retain) FlutterMethodChannel *channel; -@property(nonatomic, retain) FIRDynamicLink *launchLink; +@property(nonatomic, retain) FIRDynamicLink *initialLink; @property(nonatomic, retain) FlutterError *flutterError; @property(nonatomic) BOOL initiated; @end @@ -87,9 +87,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [FIRDynamicLinkComponents shortenURL:url options:options completion:[self createShortLinkCompletion:result]]; - } else if ([@"FirebaseDynamicLinks#getLaunchLink" isEqualToString:call.method]) { + } else if ([@"FirebaseDynamicLinks#getInitialLink" isEqualToString:call.method]) { _initiated = YES; - NSMutableDictionary *dict = [self getLaunchLink]; + NSMutableDictionary *dict = [self getInitialLink]; if (dict == nil && self.flutterError) { result(self.flutterError); } else { @@ -100,8 +100,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } } -- (NSMutableDictionary *)getLaunchLink { - return getDictionaryFromDynamicLink(_launchLink); +- (NSMutableDictionary *)getInitialLink { + return getDictionaryFromDynamicLink(_initialLink); } - (BOOL)application:(UIApplication *)application @@ -120,7 +120,7 @@ - (BOOL)application:(UIApplication *)application - (BOOL)checkForDynamicLink:(NSURL *)url { FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url]; if (dynamicLink) { - if (dynamicLink.url) _launchLink = dynamicLink; + if (dynamicLink.url) _initialLink = dynamicLink; return YES; } return NO; @@ -142,14 +142,14 @@ - (BOOL)onLink:(NSUserActivity *)userActivity { return handled; } -- (BOOL)onLaunchLink:(NSUserActivity *)userActivity { +- (BOOL)onInitialLink:(NSUserActivity *)userActivity { BOOL handled = [[FIRDynamicLinks dynamicLinks] handleUniversalLink:userActivity.webpageURL completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) { if (error) { self.flutterError = getFlutterError(error); } - self.launchLink = dynamicLink; + self.initialLink = dynamicLink; }]; return handled; } @@ -160,7 +160,7 @@ - (BOOL)application:(UIApplication *)application if (_initiated) { return [self onLink:userActivity]; } - return [self onLaunchLink:userActivity]; + return [self onInitialLink:userActivity]; } - (FIRDynamicLinkShortenerCompletion)createShortLinkCompletion:(FlutterResult)result { diff --git a/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart b/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart index f332ca182ba7..c247fe82bb28 100644 --- a/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart +++ b/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart @@ -30,9 +30,10 @@ class FirebaseDynamicLinks { /// This method always returns a Future. That Future completes to null if /// there is no pending dynamic link or any call to this method after the /// the first attempt. - Future getLaunchLink() async { - final Map linkData = await channel - .invokeMapMethod('FirebaseDynamicLinks#getLaunchLink'); + Future getInitialLink() async { + final Map linkData = + await channel.invokeMapMethod( + 'FirebaseDynamicLinks#getInitialLink'); return getPendingDynamicLinkDataFromMap(linkData); } diff --git a/packages/firebase_dynamic_links/test/firebase_dynamic_links_test.dart b/packages/firebase_dynamic_links/test/firebase_dynamic_links_test.dart index 6adeaace10db..e89dfef03df3 100644 --- a/packages/firebase_dynamic_links/test/firebase_dynamic_links_test.dart +++ b/packages/firebase_dynamic_links/test/firebase_dynamic_links_test.dart @@ -26,7 +26,7 @@ void main() { return returnUrl; case 'DynamicLinkParameters#shortenUrl': return returnUrl; - case 'FirebaseDynamicLinks#getLaunchLink': + case 'FirebaseDynamicLinks#getInitialLink': return { 'link': 'https://google.com', 'android': { @@ -44,9 +44,9 @@ void main() { log.clear(); }); - test('getLaunchLink', () async { + test('getInitialLink', () async { final PendingDynamicLinkData data = - await FirebaseDynamicLinks.instance.getLaunchLink(); + await FirebaseDynamicLinks.instance.getInitialLink(); expect(data.link, Uri.parse('https://google.com')); @@ -57,7 +57,7 @@ void main() { expect(log, [ isMethodCall( - 'FirebaseDynamicLinks#getLaunchLink', + 'FirebaseDynamicLinks#getInitialLink', arguments: null, ) ]);