Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit f8d9022

Browse files
committed
[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.
1 parent c83f670 commit f8d9022

File tree

8 files changed

+231
-102
lines changed

8 files changed

+231
-102
lines changed

packages/firebase_dynamic_links/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.5.0
2+
3+
* **Breaking change**. Changed architecture and method names to be able to difference between
4+
the dynamic link which opened the app and links clicked during app execution (active and background).
5+
16
## 0.4.0+1
27

38
* Fixed bug where link persists after starting an app with a Dynamic Link.

packages/firebase_dynamic_links/README.md

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ Receiving dynamic links on *iOS* requires a couple more steps than *Android*. If
9797
applinks:YOUR_SUBDOMAIN.page.link
9898
```
9999

100-
4. To receive a dynamic link, call the `retrieveDynamicLink()` method from `FirebaseDynamicLinks`:
100+
4. To receive a dynamic link, call the `getLaunchLink()` method from `FirebaseDynamicLinks` and
101+
configure listeners for link handlers when the application is active or in background.
101102

102103
```dart
103104
void main() {
@@ -117,24 +118,38 @@ class MyHomeWidgetState extends State<MyHomeWidget> {
117118
@override
118119
void initState() {
119120
super.initState();
120-
_retrieveDynamicLink();
121+
this.initDynamicLinks();
121122
}
122123
123-
Future<void> _retrieveDynamicLink() async {
124-
final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.retrieveDynamicLink();
124+
void initDynamicLinks() async {
125+
final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.getLaunchLink();
125126
final Uri deepLink = data?.link;
126127
127128
if (deepLink != null) {
128-
Navigator.pushNamed(context, deepLink.path); // deeplink.path == '/helloworld'
129+
Navigator.pushNamed(context, deepLink.path);
129130
}
131+
132+
FirebaseDynamicLinks.instance.configure(
133+
onLinkSuccess: (PendingDynamicLinkData dynamicLink) async {
134+
final Uri deepLink = dynamicLink?.link;
135+
136+
if (deepLink != null) {
137+
Navigator.pushNamed(context, deepLink.path);
138+
}
139+
},
140+
onLinkError: (OnLinkErrorException e) async {
141+
print('onLinkError');
142+
print(e.message);
143+
}
144+
);
130145
}
131146
.
132147
.
133148
.
134149
}
135150
```
136151

137-
If your app did not open from a dynamic link, `retrieveDynamicLink()` will return `null`.
152+
If your app did not open from a dynamic link, `getLaunchLink()` will return `null`.
138153

139154
## Getting Started
140155

packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java

Lines changed: 65 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import androidx.annotation.NonNull;
66
import com.google.android.gms.tasks.OnCompleteListener;
77
import com.google.android.gms.tasks.OnFailureListener;
8+
import com.google.android.gms.tasks.OnSuccessListener;
89
import com.google.android.gms.tasks.Task;
910
import com.google.firebase.dynamiclinks.DynamicLink;
1011
import com.google.firebase.dynamiclinks.FirebaseDynamicLinks;
@@ -14,36 +15,59 @@
1415
import io.flutter.plugin.common.MethodChannel;
1516
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
1617
import io.flutter.plugin.common.MethodChannel.Result;
17-
import io.flutter.plugin.common.PluginRegistry;
18+
import io.flutter.plugin.common.PluginRegistry.NewIntentListener;
1819
import io.flutter.plugin.common.PluginRegistry.Registrar;
1920
import java.util.ArrayList;
2021
import java.util.HashMap;
2122
import java.util.List;
2223
import java.util.Map;
2324

2425
/** FirebaseDynamicLinksPlugin */
25-
public class FirebaseDynamicLinksPlugin implements MethodCallHandler {
26-
private Registrar registrar;
27-
private Intent latestIntent;
26+
public class FirebaseDynamicLinksPlugin implements MethodCallHandler, NewIntentListener {
27+
private final Registrar registrar;
28+
private final MethodChannel channel;
2829

29-
private FirebaseDynamicLinksPlugin(Registrar registrar) {
30+
private FirebaseDynamicLinksPlugin(Registrar registrar, MethodChannel channel) {
3031
this.registrar = registrar;
31-
latestIntent = registrar.activity().getIntent();
32-
33-
registrar.addNewIntentListener(
34-
new PluginRegistry.NewIntentListener() {
35-
@Override
36-
public boolean onNewIntent(Intent intent) {
37-
latestIntent = intent;
38-
return false;
39-
}
40-
});
32+
this.channel = channel;
33+
}
34+
35+
@Override
36+
public boolean onNewIntent(Intent intent) {
37+
FirebaseDynamicLinks.getInstance()
38+
.getDynamicLink(intent)
39+
.addOnSuccessListener(
40+
registrar.activity(),
41+
new OnSuccessListener<PendingDynamicLinkData>() {
42+
@Override
43+
public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
44+
if (pendingDynamicLinkData != null) {
45+
Map<String, Object> dynamicLink =
46+
getMapFromPendingDynamicLinkData(pendingDynamicLinkData);
47+
channel.invokeMethod("onLinkSuccess", dynamicLink);
48+
}
49+
}
50+
})
51+
.addOnFailureListener(
52+
registrar.activity(),
53+
new OnFailureListener() {
54+
@Override
55+
public void onFailure(@NonNull Exception e) {
56+
Map<String, Object> exception = new HashMap<>();
57+
exception.put("code", e.getClass().getSimpleName());
58+
exception.put("message", e.getMessage());
59+
exception.put("details", null);
60+
channel.invokeMethod("onLinkError", exception);
61+
}
62+
});
63+
64+
return false;
4165
}
4266

4367
public static void registerWith(Registrar registrar) {
4468
final MethodChannel channel =
4569
new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_dynamic_links");
46-
channel.setMethodCallHandler(new FirebaseDynamicLinksPlugin(registrar));
70+
channel.setMethodCallHandler(new FirebaseDynamicLinksPlugin(registrar, channel));
4771
}
4872

4973
@Override
@@ -64,49 +88,47 @@ public void onMethodCall(MethodCall call, Result result) {
6488
builder.setLongLink(url);
6589
buildShortDynamicLink(builder, call, createShortLinkListener(result));
6690
break;
67-
case "FirebaseDynamicLinks#retrieveDynamicLink":
68-
handleRetrieveDynamicLink(result);
91+
case "FirebaseDynamicLinks#getLaunchLink":
92+
handleGetLaunchDynamicLink(result);
6993
break;
7094
default:
7195
result.notImplemented();
7296
break;
7397
}
7498
}
7599

76-
private void handleRetrieveDynamicLink(final Result result) {
77-
if (latestIntent == null) {
78-
result.success(null);
79-
return;
80-
}
100+
private Map<String, Object> getMapFromPendingDynamicLinkData(
101+
PendingDynamicLinkData pendingDynamicLinkData) {
102+
Map<String, Object> dynamicLink = new HashMap<>();
103+
dynamicLink.put("link", pendingDynamicLinkData.getLink().toString());
104+
105+
Map<String, Object> androidData = new HashMap<>();
106+
androidData.put("clickTimestamp", pendingDynamicLinkData.getClickTimestamp());
107+
androidData.put("minimumVersion", pendingDynamicLinkData.getMinimumAppVersion());
81108

109+
dynamicLink.put("android", androidData);
110+
return dynamicLink;
111+
}
112+
113+
private void handleGetLaunchDynamicLink(final Result result) {
82114
FirebaseDynamicLinks.getInstance()
83-
.getDynamicLink(latestIntent)
84-
.addOnCompleteListener(
115+
.getDynamicLink(registrar.activity().getIntent())
116+
.addOnSuccessListener(
85117
registrar.activity(),
86-
new OnCompleteListener<PendingDynamicLinkData>() {
118+
new OnSuccessListener<PendingDynamicLinkData>() {
87119
@Override
88-
public void onComplete(@NonNull Task<PendingDynamicLinkData> task) {
89-
if (task.isSuccessful()) {
90-
PendingDynamicLinkData data = task.getResult();
91-
if (data != null) {
92-
Map<String, Object> dynamicLink = new HashMap<>();
93-
dynamicLink.put("link", data.getLink().toString());
94-
95-
Map<String, Object> androidData = new HashMap<>();
96-
androidData.put("clickTimestamp", data.getClickTimestamp());
97-
androidData.put("minimumVersion", data.getMinimumAppVersion());
98-
99-
dynamicLink.put("android", androidData);
100-
101-
latestIntent = null;
102-
result.success(dynamicLink);
103-
return;
104-
}
120+
public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
121+
if (pendingDynamicLinkData != null) {
122+
Map<String, Object> dynamicLink =
123+
getMapFromPendingDynamicLinkData(pendingDynamicLinkData);
124+
result.success(dynamicLink);
125+
return;
105126
}
106127
result.success(null);
107128
}
108129
})
109130
.addOnFailureListener(
131+
registrar.activity(),
110132
new OnFailureListener() {
111133
@Override
112134
public void onFailure(@NonNull Exception e) {

packages/firebase_dynamic_links/example/lib/main.dart

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class _MainScreen extends StatefulWidget {
2424
State<StatefulWidget> createState() => _MainScreenState();
2525
}
2626

27-
class _MainScreenState extends State<_MainScreen> with WidgetsBindingObserver {
27+
class _MainScreenState extends State<_MainScreen> {
2828
String _linkMessage;
2929
bool _isCreatingLink = false;
3030
String _testString =
@@ -36,31 +36,29 @@ class _MainScreenState extends State<_MainScreen> with WidgetsBindingObserver {
3636
@override
3737
void initState() {
3838
super.initState();
39-
_retrieveDynamicLink();
40-
WidgetsBinding.instance.addObserver(this);
39+
initDynamicLinks();
4140
}
4241

43-
@override
44-
void dispose() {
45-
super.dispose();
46-
WidgetsBinding.instance.removeObserver(this);
47-
}
48-
49-
@override
50-
void didChangeAppLifecycleState(AppLifecycleState state) {
51-
if (state == AppLifecycleState.resumed) {
52-
_retrieveDynamicLink();
53-
}
54-
}
55-
56-
Future<void> _retrieveDynamicLink() async {
42+
void initDynamicLinks() async {
5743
final PendingDynamicLinkData data =
58-
await FirebaseDynamicLinks.instance.retrieveDynamicLink();
44+
await FirebaseDynamicLinks.instance.getLaunchLink();
5945
final Uri deepLink = data?.link;
6046

6147
if (deepLink != null) {
6248
Navigator.pushNamed(context, deepLink.path);
6349
}
50+
51+
FirebaseDynamicLinks.instance.configure(
52+
onLinkSuccess: (PendingDynamicLinkData dynamicLink) async {
53+
final Uri deepLink = dynamicLink?.link;
54+
55+
if (deepLink != null) {
56+
Navigator.pushNamed(context, deepLink.path);
57+
}
58+
}, onLinkError: (OnLinkErrorException e) async {
59+
print('onLinkError');
60+
print(e.message);
61+
});
6462
}
6563

6664
Future<void> _createDynamicLink(bool short) async {

0 commit comments

Comments
 (0)