Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/firebase_dynamic_links/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 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).
`retrieveDynamicLink` has been replaced with two different functions:
- `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+6

* Update google-services Android gradle plugin to 4.3.0 in documentation and examples.
Expand Down
27 changes: 21 additions & 6 deletions packages/firebase_dynamic_links/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `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
void main() {
Expand All @@ -117,24 +118,38 @@ class MyHomeWidgetState extends State<MyHomeWidget> {
@override
void initState() {
super.initState();
_retrieveDynamicLink();
this.initDynamicLinks();
}

Future<void> _retrieveDynamicLink() async {
final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.retrieveDynamicLink();
void initDynamicLinks() async {
final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.getInitialLink();
final Uri deepLink = data?.link;

if (deepLink != null) {
Navigator.pushNamed(context, deepLink.path); // deeplink.path == '/helloworld'
Navigator.pushNamed(context, deepLink.path);
}

FirebaseDynamicLinks.instance.onLink(
onSuccess: (PendingDynamicLinkData dynamicLink) async {
final Uri deepLink = dynamicLink?.link;

if (deepLink != null) {
Navigator.pushNamed(context, deepLink.path);
}
},
onError: (OnLinkErrorException e) async {
print('onLinkError');
print(e.message);
}
);
}
.
.
.
}
```

If your app did not open from a dynamic link, `retrieveDynamicLink()` will return `null`.
If your app did not open from a dynamic link, `getInitialLink()` will return `null`.

## Getting Started

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -14,38 +15,61 @@
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;
import java.util.List;
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<PendingDynamicLinkData>() {
@Override
public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
if (pendingDynamicLinkData != null) {
Map<String, Object> dynamicLink =
getMapFromPendingDynamicLinkData(pendingDynamicLinkData);
channel.invokeMethod("onLinkSuccess", dynamicLink);
}
}
})
.addOnFailureListener(
registrar.activity(),
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Map<String, Object> 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
Expand All @@ -66,49 +90,47 @@ public void onMethodCall(MethodCall call, Result result) {
builder.setLongLink(url);
buildShortDynamicLink(builder, call, createShortLinkListener(result));
break;
case "FirebaseDynamicLinks#retrieveDynamicLink":
handleRetrieveDynamicLink(result);
case "FirebaseDynamicLinks#getInitialLink":
handleGetInitialDynamicLink(result);
break;
default:
result.notImplemented();
break;
}
}

private void handleRetrieveDynamicLink(final Result result) {
if (latestIntent == null) {
result.success(null);
return;
}
private Map<String, Object> getMapFromPendingDynamicLinkData(
PendingDynamicLinkData pendingDynamicLinkData) {
Map<String, Object> dynamicLink = new HashMap<>();
dynamicLink.put("link", pendingDynamicLinkData.getLink().toString());

Map<String, Object> androidData = new HashMap<>();
androidData.put("clickTimestamp", pendingDynamicLinkData.getClickTimestamp());
androidData.put("minimumVersion", pendingDynamicLinkData.getMinimumAppVersion());

dynamicLink.put("android", androidData);
return dynamicLink;
}

private void handleGetInitialDynamicLink(final Result result) {
FirebaseDynamicLinks.getInstance()
.getDynamicLink(latestIntent)
.addOnCompleteListener(
.getDynamicLink(registrar.activity().getIntent())
.addOnSuccessListener(
registrar.activity(),
new OnCompleteListener<PendingDynamicLinkData>() {
new OnSuccessListener<PendingDynamicLinkData>() {
@Override
public void onComplete(@NonNull Task<PendingDynamicLinkData> task) {
if (task.isSuccessful()) {
PendingDynamicLinkData data = task.getResult();
if (data != null) {
Map<String, Object> dynamicLink = new HashMap<>();
dynamicLink.put("link", data.getLink().toString());

Map<String, Object> 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<String, Object> dynamicLink =
getMapFromPendingDynamicLinkData(pendingDynamicLinkData);
result.success(dynamicLink);
return;
}
result.success(null);
}
})
.addOnFailureListener(
registrar.activity(),
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Expand Down
34 changes: 16 additions & 18 deletions packages/firebase_dynamic_links/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class _MainScreen extends StatefulWidget {
State<StatefulWidget> createState() => _MainScreenState();
}

class _MainScreenState extends State<_MainScreen> with WidgetsBindingObserver {
class _MainScreenState extends State<_MainScreen> {
String _linkMessage;
bool _isCreatingLink = false;
String _testString =
Expand All @@ -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<void> _retrieveDynamicLink() async {
void initDynamicLinks() async {
final PendingDynamicLinkData data =
await FirebaseDynamicLinks.instance.retrieveDynamicLink();
await FirebaseDynamicLinks.instance.getInitialLink();
final Uri deepLink = data?.link;

if (deepLink != null) {
Navigator.pushNamed(context, deepLink.path);
}

FirebaseDynamicLinks.instance.onLink(
onSuccess: (PendingDynamicLinkData dynamicLink) async {
final Uri deepLink = dynamicLink?.link;

if (deepLink != null) {
Navigator.pushNamed(context, deepLink.path);
}
}, onError: (OnLinkErrorException e) async {
print('onLinkError');
print(e.message);
});
}

Future<void> _createDynamicLink(bool short) async {
Expand Down
Loading