diff --git a/packages/firebase_dynamic_links/CHANGELOG.md b/packages/firebase_dynamic_links/CHANGELOG.md
index d70d789ffdbc..fb72d7fcc133 100644
--- a/packages/firebase_dynamic_links/CHANGELOG.md
+++ b/packages/firebase_dynamic_links/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.5.0+8
+
+* Support v2 embedding. This will remain compatible with the original embedding and won't require app migration.
+
## 0.5.0+7
* Add `getDynamicLink` to support expanding from short links.
diff --git a/packages/firebase_dynamic_links/android/build.gradle b/packages/firebase_dynamic_links/android/build.gradle
index 8e5b53c6f334..8a84add378d6 100644
--- a/packages/firebase_dynamic_links/android/build.gradle
+++ b/packages/firebase_dynamic_links/android/build.gradle
@@ -34,8 +34,33 @@ android {
dependencies {
api 'com.google.firebase:firebase-dynamic-links:16.1.8'
implementation 'com.google.firebase:firebase-common:16.1.0'
- implementation 'androidx.annotation:annotation:1.0.0'
}
}
apply from: file("./user-agent.gradle")
+
+// TODO(bparrishMines): Remove this hack once androidx.lifecycle is included on stable. https://github.com/flutter/flutter/issues/42348
+afterEvaluate {
+ def containsEmbeddingDependencies = false
+ for (def configuration : configurations.all) {
+ for (def dependency : configuration.dependencies) {
+ if (dependency.group == 'io.flutter' &&
+ dependency.name.startsWith('flutter_embedding') &&
+ dependency.isTransitive())
+ {
+ containsEmbeddingDependencies = true
+ break
+ }
+ }
+ }
+ if (!containsEmbeddingDependencies) {
+ android {
+ dependencies {
+ def lifecycle_version = "1.1.1"
+ compileOnly "android.arch.lifecycle:runtime:$lifecycle_version"
+ compileOnly "android.arch.lifecycle:common:$lifecycle_version"
+ compileOnly "android.arch.lifecycle:common-java8:$lifecycle_version"
+ }
+ }
+ }
+}
diff --git a/packages/firebase_dynamic_links/android/gradle.properties b/packages/firebase_dynamic_links/android/gradle.properties
deleted file mode 100644
index 8bd86f680510..000000000000
--- a/packages/firebase_dynamic_links/android/gradle.properties
+++ /dev/null
@@ -1 +0,0 @@
-org.gradle.jvmargs=-Xmx1536M
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 ef7a0263b39e..31e2567349fe 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
@@ -4,9 +4,9 @@
package io.flutter.plugins.firebasedynamiclinks;
+import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
-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;
@@ -15,6 +15,10 @@
import com.google.firebase.dynamiclinks.FirebaseDynamicLinks;
import com.google.firebase.dynamiclinks.PendingDynamicLinkData;
import com.google.firebase.dynamiclinks.ShortDynamicLink;
+import io.flutter.embedding.engine.plugins.FlutterPlugin;
+import io.flutter.embedding.engine.plugins.activity.ActivityAware;
+import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
+import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
@@ -26,16 +30,50 @@
import java.util.List;
import java.util.Map;
-/** FirebaseDynamicLinksPlugin */
-public class FirebaseDynamicLinksPlugin implements MethodCallHandler, NewIntentListener {
- private final Registrar registrar;
- private final MethodChannel channel;
-
- private FirebaseDynamicLinksPlugin(Registrar registrar, MethodChannel channel) {
- this.registrar = registrar;
+/**
+ * Flutter plugin accessing for Firebase Dynamic Links API.
+ *
+ *
Instantiate this in an add to app scenario to gracefully handle activity and context changes.
+ */
+public class FirebaseDynamicLinksPlugin
+ implements FlutterPlugin, ActivityAware, MethodCallHandler, NewIntentListener {
+ private Activity activity;
+ private MethodChannel channel;
+
+ private FirebaseDynamicLinksPlugin(Activity activity, MethodChannel channel) {
+ this.activity = activity;
this.channel = channel;
}
+ /**
+ * Default Constructor.
+ *
+ *
Use this when adding the plugin to your FlutterEngine
+ */
+ public FirebaseDynamicLinksPlugin() {}
+
+ /**
+ * Registers a plugin with the v1 embedding api {@code io.flutter.plugin.common}.
+ *
+ *
Calling this will register the plugin with the passed registrar. However, plugins
+ * initialized this way won't react to changes in activity or context.
+ *
+ * @param registrar attaches this plugin's {@link
+ * io.flutter.plugin.common.MethodChannel.MethodCallHandler} to the registrar's {@link
+ * io.flutter.plugin.common.BinaryMessenger}.
+ */
+ public static void registerWith(Registrar registrar) {
+ final MethodChannel channel = createChannel(registrar.messenger());
+ final FirebaseDynamicLinksPlugin plugin =
+ new FirebaseDynamicLinksPlugin(registrar.activity(), channel);
+ registrar.addNewIntentListener(plugin);
+ channel.setMethodCallHandler(plugin);
+ }
+
+ private static MethodChannel createChannel(final BinaryMessenger messenger) {
+ return new MethodChannel(messenger, "plugins.flutter.io/firebase_dynamic_links");
+ }
+
@Override
public boolean onNewIntent(Intent intent) {
FirebaseDynamicLinks.getInstance()
@@ -54,7 +92,7 @@ public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
.addOnFailureListener(
new OnFailureListener() {
@Override
- public void onFailure(@NonNull Exception e) {
+ public void onFailure(Exception e) {
Map exception = new HashMap<>();
exception.put("code", e.getClass().getSimpleName());
exception.put("message", e.getMessage());
@@ -66,12 +104,37 @@ public void onFailure(@NonNull Exception e) {
return false;
}
- public static void registerWith(Registrar registrar) {
- final MethodChannel channel =
- new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_dynamic_links");
- final FirebaseDynamicLinksPlugin plugin = new FirebaseDynamicLinksPlugin(registrar, channel);
- registrar.addNewIntentListener(plugin);
- channel.setMethodCallHandler(plugin);
+ @Override
+ public void onAttachedToEngine(FlutterPluginBinding binding) {
+ channel = createChannel(binding.getFlutterEngine().getDartExecutor());
+ channel.setMethodCallHandler(this);
+ }
+
+ @Override
+ public void onDetachedFromEngine(FlutterPluginBinding binding) {
+ channel.setMethodCallHandler(null);
+ }
+
+ @Override
+ public void onAttachedToActivity(ActivityPluginBinding binding) {
+ activity = binding.getActivity();
+ binding.addOnNewIntentListener(this);
+ }
+
+ @Override
+ public void onDetachedFromActivityForConfigChanges() {
+ activity = null;
+ }
+
+ @Override
+ public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
+ activity = binding.getActivity();
+ binding.addOnNewIntentListener(this);
+ }
+
+ @Override
+ public void onDetachedFromActivity() {
+ activity = null;
}
@Override
@@ -134,7 +197,7 @@ public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
.addOnFailureListener(
new OnFailureListener() {
@Override
- public void onFailure(@NonNull Exception e) {
+ public void onFailure(Exception e) {
result.error(e.getClass().getSimpleName(), e.getMessage(), null);
}
});
@@ -146,20 +209,19 @@ private void handleGetDynamicLink(final Result result, Uri uri) {
private void handleGetInitialDynamicLink(final Result result) {
// If there's no activity, then there's no initial dynamic link.
- if (registrar.activity() == null) {
+ if (activity == null) {
result.success(null);
return;
}
addDynamicLinkListener(
- FirebaseDynamicLinks.getInstance().getDynamicLink(registrar.activity().getIntent()),
- result);
+ FirebaseDynamicLinks.getInstance().getDynamicLink(activity.getIntent()), result);
}
private OnCompleteListener createShortLinkListener(final Result result) {
return new OnCompleteListener() {
@Override
- public void onComplete(@NonNull Task task) {
+ public void onComplete(Task task) {
if (task.isSuccessful()) {
Map url = new HashMap<>();
url.put("url", task.getResult().getShortLink().toString());
diff --git a/packages/firebase_dynamic_links/example/android/app/build.gradle b/packages/firebase_dynamic_links/example/android/app/build.gradle
index 75ab78059c1c..f620169bc756 100644
--- a/packages/firebase_dynamic_links/example/android/app/build.gradle
+++ b/packages/firebase_dynamic_links/example/android/app/build.gradle
@@ -52,6 +52,9 @@ flutter {
}
dependencies {
+ androidTestImplementation 'androidx.test:runner:1.2.0'
+ androidTestImplementation 'androidx.test:rules:1.2.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
apply plugin: 'com.google.gms.google-services'
diff --git a/packages/firebase_dynamic_links/example/android/app/src/androidTest/java/io/flutter/plugins/firebasedynamiclinks/EmbeddingV1ActivityTest.java b/packages/firebase_dynamic_links/example/android/app/src/androidTest/java/io/flutter/plugins/firebasedynamiclinks/EmbeddingV1ActivityTest.java
new file mode 100644
index 000000000000..e46c9dea4e3c
--- /dev/null
+++ b/packages/firebase_dynamic_links/example/android/app/src/androidTest/java/io/flutter/plugins/firebasedynamiclinks/EmbeddingV1ActivityTest.java
@@ -0,0 +1,14 @@
+package io.flutter.plugins.firebasedynamiclinks;
+
+import androidx.test.rule.ActivityTestRule;
+import dev.flutter.plugins.e2e.FlutterRunner;
+import io.flutter.plugins.firebasedynamiclinksexample.EmbeddingV1Activity;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+
+@RunWith(FlutterRunner.class)
+public class EmbeddingV1ActivityTest {
+ @Rule
+ public ActivityTestRule rule =
+ new ActivityTestRule<>(EmbeddingV1Activity.class);
+}
diff --git a/packages/firebase_dynamic_links/example/android/app/src/androidTest/java/io/flutter/plugins/firebasedynamiclinks/MainActivityTest.java b/packages/firebase_dynamic_links/example/android/app/src/androidTest/java/io/flutter/plugins/firebasedynamiclinks/MainActivityTest.java
new file mode 100644
index 000000000000..da558649436f
--- /dev/null
+++ b/packages/firebase_dynamic_links/example/android/app/src/androidTest/java/io/flutter/plugins/firebasedynamiclinks/MainActivityTest.java
@@ -0,0 +1,12 @@
+package io.flutter.plugins.firebasedynamiclinks;
+
+import androidx.test.rule.ActivityTestRule;
+import dev.flutter.plugins.e2e.FlutterRunner;
+import io.flutter.plugins.firebasedynamiclinksexample.MainActivity;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+
+@RunWith(FlutterRunner.class)
+public class MainActivityTest {
+ @Rule public ActivityTestRule rule = new ActivityTestRule<>(MainActivity.class);
+}
diff --git a/packages/firebase_dynamic_links/example/android/app/src/main/AndroidManifest.xml b/packages/firebase_dynamic_links/example/android/app/src/main/AndroidManifest.xml
index ed3cca73d5d3..9f2179a23235 100644
--- a/packages/firebase_dynamic_links/example/android/app/src/main/AndroidManifest.xml
+++ b/packages/firebase_dynamic_links/example/android/app/src/main/AndroidManifest.xml
@@ -14,13 +14,17 @@
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
-
+
+
diff --git a/packages/firebase_dynamic_links/example/android/app/src/main/java/io/flutter/plugins/firebasedynamiclinksexample/EmbeddingV1Activity.java b/packages/firebase_dynamic_links/example/android/app/src/main/java/io/flutter/plugins/firebasedynamiclinksexample/EmbeddingV1Activity.java
new file mode 100644
index 000000000000..1d8a55dae484
--- /dev/null
+++ b/packages/firebase_dynamic_links/example/android/app/src/main/java/io/flutter/plugins/firebasedynamiclinksexample/EmbeddingV1Activity.java
@@ -0,0 +1,13 @@
+package io.flutter.plugins.firebasedynamiclinksexample;
+
+import android.os.Bundle;
+import io.flutter.app.FlutterActivity;
+import io.flutter.plugins.GeneratedPluginRegistrant;
+
+public class EmbeddingV1Activity extends FlutterActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ GeneratedPluginRegistrant.registerWith(this);
+ }
+}
diff --git a/packages/firebase_dynamic_links/example/android/app/src/main/java/io/flutter/plugins/firebasedynamiclinksexample/MainActivity.java b/packages/firebase_dynamic_links/example/android/app/src/main/java/io/flutter/plugins/firebasedynamiclinksexample/MainActivity.java
index 885f28ec4efc..4b1e59618568 100644
--- a/packages/firebase_dynamic_links/example/android/app/src/main/java/io/flutter/plugins/firebasedynamiclinksexample/MainActivity.java
+++ b/packages/firebase_dynamic_links/example/android/app/src/main/java/io/flutter/plugins/firebasedynamiclinksexample/MainActivity.java
@@ -1,13 +1,17 @@
package io.flutter.plugins.firebasedynamiclinksexample;
-import android.os.Bundle;
-import io.flutter.app.FlutterActivity;
-import io.flutter.plugins.GeneratedPluginRegistrant;
+import dev.flutter.plugins.e2e.E2EPlugin;
+import io.flutter.embedding.android.FlutterActivity;
+import io.flutter.embedding.engine.FlutterEngine;
+import io.flutter.plugins.firebasedynamiclinks.FirebaseDynamicLinksPlugin;
+import io.flutter.plugins.urllauncher.UrlLauncherPlugin;
public class MainActivity extends FlutterActivity {
+ // TODO(bparrishMines): Remove this once v2 of GeneratedPluginRegistrant rolls to stable. https://github.com/flutter/flutter/issues/42694
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- GeneratedPluginRegistrant.registerWith(this);
+ public void configureFlutterEngine(FlutterEngine flutterEngine) {
+ flutterEngine.getPlugins().add(new FirebaseDynamicLinksPlugin());
+ flutterEngine.getPlugins().add(new E2EPlugin());
+ flutterEngine.getPlugins().add(new UrlLauncherPlugin());
}
}
diff --git a/packages/firebase_dynamic_links/example/android/gradle.properties b/packages/firebase_dynamic_links/example/android/gradle.properties
index 7be3d8b46841..38c8d4544ff1 100644
--- a/packages/firebase_dynamic_links/example/android/gradle.properties
+++ b/packages/firebase_dynamic_links/example/android/gradle.properties
@@ -1,2 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/packages/firebase_dynamic_links/example/pubspec.yaml b/packages/firebase_dynamic_links/example/pubspec.yaml
index a2b3297b1452..bb7c5ce9b2ea 100644
--- a/packages/firebase_dynamic_links/example/pubspec.yaml
+++ b/packages/firebase_dynamic_links/example/pubspec.yaml
@@ -11,5 +11,10 @@ dependencies:
url_launcher: ^5.1.6
+dev_dependencies:
+ e2e: ^0.2.1
+ flutter_driver:
+ sdk: flutter
+
flutter:
uses-material-design: true
diff --git a/packages/firebase_dynamic_links/pubspec.yaml b/packages/firebase_dynamic_links/pubspec.yaml
index 032659e93a4d..417256abfe97 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.5.0+7
+version: 0.5.0+8
author: Flutter Team
homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_dynamic_links
@@ -11,6 +11,9 @@ dependencies:
sdk: flutter
dev_dependencies:
+ e2e: ^0.2.1
+ flutter_driver:
+ sdk: flutter
flutter_test:
sdk: flutter
url_launcher: ^4.2.0
@@ -24,4 +27,4 @@ flutter:
environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0"
- flutter: ">=1.5.0 <2.0.0"
+ flutter: ">=1.9.1+hotfix.4 <2.0.0"
diff --git a/packages/firebase_dynamic_links/test/firebase_dynamic_links_e2e.dart b/packages/firebase_dynamic_links/test/firebase_dynamic_links_e2e.dart
new file mode 100644
index 000000000000..e2927d8e500c
--- /dev/null
+++ b/packages/firebase_dynamic_links/test/firebase_dynamic_links_e2e.dart
@@ -0,0 +1,32 @@
+import 'package:flutter_test/flutter_test.dart';
+import 'package:e2e/e2e.dart';
+
+import '../lib/firebase_dynamic_links.dart';
+
+void main() {
+ E2EWidgetsFlutterBinding.ensureInitialized();
+
+ testWidgets('buildUrl', (WidgetTester tester) async {
+ final DynamicLinkParameters parameters = DynamicLinkParameters(
+ uriPrefix: 'https://cx4k7.app.goo.gl',
+ link: Uri.parse('https://dynamic.link.example/helloworld'),
+ androidParameters: AndroidParameters(
+ packageName: 'io.flutter.plugins.firebasedynamiclinksexample',
+ minimumVersion: 0,
+ ),
+ dynamicLinkParametersOptions: DynamicLinkParametersOptions(
+ shortDynamicLinkPathLength: ShortDynamicLinkPathLength.short,
+ ),
+ iosParameters: IosParameters(
+ bundleId: 'com.google.FirebaseCppDynamicLinksTestApp.dev',
+ minimumVersion: '0',
+ ),
+ );
+
+ final Uri uri = await parameters.buildUrl();
+ expect(
+ uri.toString(),
+ 'https://cx4k7.app.goo.gl?amv=0&apn=io.flutter.plugins.firebasedynamiclinksexample&ibi=com.google.FirebaseCppDynamicLinksTestApp.dev&imv=0&link=https%3A%2F%2Fdynamic.link.example%2Fhelloworld',
+ );
+ });
+}