From d14828d4c4607e3bc5634180b5985c5f97fac9ae Mon Sep 17 00:00:00 2001 From: Mosc Date: Sat, 11 Jun 2022 12:39:00 +0200 Subject: [PATCH 1/8] Add non-browser URL launch mode for Android --- .../lib/src/url_launcher_uri.dart | 6 +-- .../urllauncher/MethodCallHandlerImpl.java | 4 +- .../plugins/urllauncher/UrlLauncher.java | 49 ++++++++++++++++++- .../MethodCallHandlerImplTest.java | 27 ++++++++-- 4 files changed, 78 insertions(+), 8 deletions(-) diff --git a/packages/url_launcher/url_launcher/lib/src/url_launcher_uri.dart b/packages/url_launcher/url_launcher/lib/src/url_launcher_uri.dart index fc33f05e5afb..47b6a8af27c2 100644 --- a/packages/url_launcher/url_launcher/lib/src/url_launcher_uri.dart +++ b/packages/url_launcher/url_launcher/lib/src/url_launcher_uri.dart @@ -25,9 +25,9 @@ import 'package:url_launcher_platform_interface/url_launcher_platform_interface. /// On iOS, this should be used in cases where sharing the cookies of the /// user's browser is important, such as SSO flows, since Safari View /// Controller does not share the browser's context. -/// - [LaunchMode.externalNonBrowserApplication] is supported on iOS 10+. -/// This setting is used to require universal links to open in a non-browser -/// application. +/// - [LaunchMode.externalNonBrowserApplication] is supported on iOS 10+ and +/// Android. This setting is used to require universal links to open in a +/// non-browser application. /// /// For web, [webOnlyWindowName] specifies a target for the launch. This /// supports the standard special link target names. For example: diff --git a/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/MethodCallHandlerImpl.java b/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/MethodCallHandlerImpl.java index f7bed8648872..c3d67feed613 100644 --- a/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/MethodCallHandlerImpl.java +++ b/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/MethodCallHandlerImpl.java @@ -88,11 +88,13 @@ private void onLaunch(MethodCall call, Result result, String url) { final boolean useWebView = call.argument("useWebView"); final boolean enableJavaScript = call.argument("enableJavaScript"); final boolean enableDomStorage = call.argument("enableDomStorage"); + final boolean universalLinksOnly = call.argument("universalLinksOnly"); final Map headersMap = call.argument("headers"); final Bundle headersBundle = extractBundle(headersMap); LaunchStatus launchStatus = - urlLauncher.launch(url, headersBundle, useWebView, enableJavaScript, enableDomStorage); + urlLauncher.launch( + url, headersBundle, useWebView, enableJavaScript, enableDomStorage, universalLinksOnly); if (launchStatus == LaunchStatus.NO_ACTIVITY) { result.error("NO_ACTIVITY", "Launching a URL requires a foreground activity.", null); diff --git a/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java b/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java index c3a563a9c137..6f0bd8d561b9 100644 --- a/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java +++ b/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java @@ -9,12 +9,19 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.provider.Browser; import android.util.Log; import androidx.annotation.Nullable; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + /** Launches components for URLs. */ class UrlLauncher { private static final String TAG = "UrlLauncher"; @@ -60,6 +67,9 @@ boolean canLaunch(String url) { * @param useWebView when true, the URL is launched inside of {@link WebViewActivity}. * @param enableJavaScript Only used if {@param useWebView} is true. Enables JS in the WebView. * @param enableDomStorage Only used if {@param useWebView} is true. Enables DOM storage in the + * WebView. + * @param universalLinksOnly Only used if {@param useWebView} is false. When true, will only + * launch if an app is available that is not a browser. * @return {@link LaunchStatus#NO_ACTIVITY} if there's no available {@code applicationContext}. * {@link LaunchStatus#ACTIVITY_NOT_FOUND} if there's no activity found to handle {@code * launchIntent}. {@link LaunchStatus#OK} otherwise. @@ -69,7 +79,8 @@ LaunchStatus launch( Bundle headersBundle, boolean useWebView, boolean enableJavaScript, - boolean enableDomStorage) { + boolean enableDomStorage, + boolean universalLinksOnly) { if (activity == null) { return LaunchStatus.NO_ACTIVITY; } @@ -84,6 +95,17 @@ LaunchStatus launch( new Intent(Intent.ACTION_VIEW) .setData(Uri.parse(url)) .putExtra(Browser.EXTRA_HEADERS, headersBundle); + + if (universalLinksOnly) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + launchIntent = launchIntent.addFlags(Intent.FLAG_ACTIVITY_REQUIRE_NON_BROWSER); + } else { + Set nonBrowserPackageNames = getNonBrowserPackageNames(launchIntent); + if (nonBrowserPackageNames.isEmpty()) { + return LaunchStatus.ACTIVITY_NOT_FOUND; + } + } + } } try { @@ -95,6 +117,31 @@ LaunchStatus launch( return LaunchStatus.OK; } + private Set getNonBrowserPackageNames(Intent specializedIntent) { + PackageManager packageManager = activity.getPackageManager(); + + // Get all apps that resolve the specific URL. + Set specializedPackageNames = queryPackageNames(packageManager, specializedIntent); + + // Get all apps that resolve a generic URL. + Intent genericIntent = + new Intent().setAction(Intent.ACTION_VIEW).setData(Uri.fromParts("https", "", null)); + Set genericPackageNames = queryPackageNames(packageManager, genericIntent); + + // Keep only the apps that resolve the specific, but not the generic URLs. + specializedPackageNames.removeAll(genericPackageNames); + return specializedPackageNames; + } + + private Set queryPackageNames(PackageManager packageManager, Intent intent) { + List intentActivities = packageManager.queryIntentActivities(intent, 0); + Set packageNames = new HashSet<>(); + for (ResolveInfo intentActivity : intentActivities) { + packageNames.add(intentActivity.activityInfo.packageName); + } + return packageNames; + } + /** Closes any activities started with {@link #launch} {@code useWebView=true}. */ void closeWebView() { applicationContext.sendBroadcast(new Intent(WebViewActivity.ACTION_CLOSE)); diff --git a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/MethodCallHandlerImplTest.java b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/MethodCallHandlerImplTest.java index b60192531dbd..74524a53ce6e 100644 --- a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/MethodCallHandlerImplTest.java +++ b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/MethodCallHandlerImplTest.java @@ -120,16 +120,23 @@ public void onMethodCall_launchReturnsNoActivityError() { boolean useWebView = false; boolean enableJavaScript = false; boolean enableDomStorage = false; + boolean universalLinksOnly = false; // Setup arguments map send on the method channel Map args = new HashMap<>(); args.put("url", url); args.put("useWebView", useWebView); args.put("enableJavaScript", enableJavaScript); args.put("enableDomStorage", enableDomStorage); + args.put("universalLinksOnly", universalLinksOnly); args.put("headers", new HashMap<>()); // Mock the launch method on the urlLauncher class when(urlLauncher.launch( - eq(url), any(Bundle.class), eq(useWebView), eq(enableJavaScript), eq(enableDomStorage))) + eq(url), + any(Bundle.class), + eq(useWebView), + eq(enableJavaScript), + eq(enableDomStorage), + eq(universalLinksOnly))) .thenReturn(UrlLauncher.LaunchStatus.NO_ACTIVITY); // Act by calling the "launch" method on the method channel methodCallHandler = new MethodCallHandlerImpl(urlLauncher); @@ -149,16 +156,23 @@ public void onMethodCall_launchReturnsActivityNotFoundError() { boolean useWebView = false; boolean enableJavaScript = false; boolean enableDomStorage = false; + boolean universalLinksOnly = false; // Setup arguments map send on the method channel Map args = new HashMap<>(); args.put("url", url); args.put("useWebView", useWebView); args.put("enableJavaScript", enableJavaScript); args.put("enableDomStorage", enableDomStorage); + args.put("universalLinksOnly", universalLinksOnly); args.put("headers", new HashMap<>()); // Mock the launch method on the urlLauncher class when(urlLauncher.launch( - eq(url), any(Bundle.class), eq(useWebView), eq(enableJavaScript), eq(enableDomStorage))) + eq(url), + any(Bundle.class), + eq(useWebView), + eq(enableJavaScript), + eq(enableDomStorage), + eq(universalLinksOnly))) .thenReturn(UrlLauncher.LaunchStatus.ACTIVITY_NOT_FOUND); // Act by calling the "launch" method on the method channel methodCallHandler = new MethodCallHandlerImpl(urlLauncher); @@ -181,16 +195,23 @@ public void onMethodCall_launchReturnsTrue() { boolean useWebView = false; boolean enableJavaScript = false; boolean enableDomStorage = false; + boolean universalLinksOnly = false; // Setup arguments map send on the method channel Map args = new HashMap<>(); args.put("url", url); args.put("useWebView", useWebView); args.put("enableJavaScript", enableJavaScript); args.put("enableDomStorage", enableDomStorage); + args.put("universalLinksOnly", universalLinksOnly); args.put("headers", new HashMap<>()); // Mock the launch method on the urlLauncher class when(urlLauncher.launch( - eq(url), any(Bundle.class), eq(useWebView), eq(enableJavaScript), eq(enableDomStorage))) + eq(url), + any(Bundle.class), + eq(useWebView), + eq(enableJavaScript), + eq(enableDomStorage), + eq(universalLinksOnly))) .thenReturn(UrlLauncher.LaunchStatus.OK); // Act by calling the "launch" method on the method channel methodCallHandler = new MethodCallHandlerImpl(urlLauncher); From 96d7b94032559f8c129fd84b1039535fa9696557 Mon Sep 17 00:00:00 2001 From: Mosc Date: Sat, 11 Jun 2022 13:17:34 +0200 Subject: [PATCH 2/8] Use application context to access package manager --- .../main/java/io/flutter/plugins/urllauncher/UrlLauncher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java b/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java index 6f0bd8d561b9..f5c288782ddd 100644 --- a/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java +++ b/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java @@ -118,7 +118,7 @@ LaunchStatus launch( } private Set getNonBrowserPackageNames(Intent specializedIntent) { - PackageManager packageManager = activity.getPackageManager(); + PackageManager packageManager = applicationContext.getPackageManager(); // Get all apps that resolve the specific URL. Set specializedPackageNames = queryPackageNames(packageManager, specializedIntent); From 6888d86ef283bb8e3220f96f5ec75c23f81bcc0a Mon Sep 17 00:00:00 2001 From: Mosc Date: Sat, 11 Jun 2022 21:34:36 +0200 Subject: [PATCH 3/8] Add tests --- .../plugins/urllauncher/UrlLauncherTest.java | 127 ++++++++++++++++++ .../urllauncher/utils/IntentDataMatcher.java | 22 +++ .../plugins/urllauncher/utils/TestUtils.java | 26 ++++ 3 files changed, 175 insertions(+) create mode 100644 packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/UrlLauncherTest.java create mode 100644 packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/IntentDataMatcher.java create mode 100644 packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/TestUtils.java diff --git a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/UrlLauncherTest.java b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/UrlLauncherTest.java new file mode 100644 index 000000000000..1447cdfc76b7 --- /dev/null +++ b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/UrlLauncherTest.java @@ -0,0 +1,127 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.urllauncher; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Build; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatcher; +import org.mockito.Matchers; +import org.robolectric.RobolectricTestRunner; + +import java.util.Arrays; +import java.util.Collections; + +import io.flutter.plugins.urllauncher.utils.IntentDataMatcher; +import io.flutter.plugins.urllauncher.utils.TestUtils; + +@RunWith(RobolectricTestRunner.class) +public class UrlLauncherTest { + private Context applicationContext; + private UrlLauncher urlLauncher; + + private static final String LAUNCH_URL = "https://www.google.com"; + + @Before + public void setUp() { + applicationContext = mock(Context.class); + Activity activity = mock(Activity.class); + urlLauncher = new UrlLauncher(applicationContext, activity); + } + + @Test + public void launch_shouldNotQueryPackageManagerWhenUniversalLinksOnlyOnAndroidR() { + updateSdkVersion(Build.VERSION_CODES.R); + + try { + PackageManager mockPackageManager = mock(PackageManager.class); + when(applicationContext.getPackageManager()).thenReturn(mockPackageManager); + + urlLauncher.launch(LAUNCH_URL, null, false, false, false, true); + + verify(mockPackageManager, never()).queryIntentActivities(any(Intent.class), anyInt()); + } finally { + updateSdkVersion(0); + } + } + + @Test + public void launch_shouldReturnOkWhenUniversalLinksOnlyBelowAndroidRAndNonBrowserPresent() { + updateSdkVersion(Build.VERSION_CODES.Q); + + try { + PackageManager mockPackageManager = mock(PackageManager.class); + when(applicationContext.getPackageManager()).thenReturn(mockPackageManager); + ResolveInfo browserIntentActivity = stubResolveInfo("browser"); + ResolveInfo nonBrowserIntentActivity = stubResolveInfo("nonBrowser"); + when(mockPackageManager.queryIntentActivities(any(Intent.class), anyInt())) + .thenReturn(Collections.singletonList(browserIntentActivity)); + when(mockPackageManager.queryIntentActivities( + Matchers.argThat(new IntentDataMatcher(LAUNCH_URL)), anyInt())) + .thenReturn(Arrays.asList(nonBrowserIntentActivity, browserIntentActivity)); + + UrlLauncher.LaunchStatus launchStatus = + urlLauncher.launch(LAUNCH_URL, null, false, false, false, true); + + verify(mockPackageManager, times(2)).queryIntentActivities(any(Intent.class), anyInt()); + assertEquals(launchStatus, UrlLauncher.LaunchStatus.OK); + } finally { + updateSdkVersion(0); + } + } + + @Test + public void + launch_shouldReturnActivityNotFoundWhenUniversalLinksOnlyBelowAndroidRAndNonBrowserNotPresent() { + updateSdkVersion(Build.VERSION_CODES.Q); + + try { + PackageManager mockPackageManager = mock(PackageManager.class); + when(applicationContext.getPackageManager()).thenReturn(mockPackageManager); + ResolveInfo browserIntentActivity = stubResolveInfo("browser"); + when(mockPackageManager.queryIntentActivities(any(Intent.class), anyInt())) + .thenReturn(Collections.singletonList(browserIntentActivity)); + when(mockPackageManager.queryIntentActivities( + Matchers.argThat(new IntentDataMatcher(LAUNCH_URL)), anyInt())) + .thenReturn(Collections.singletonList(browserIntentActivity)); + + UrlLauncher.LaunchStatus launchStatus = + urlLauncher.launch(LAUNCH_URL, null, false, false, false, true); + + verify(mockPackageManager, times(2)).queryIntentActivities(any(Intent.class), anyInt()); + assertEquals(launchStatus, UrlLauncher.LaunchStatus.ACTIVITY_NOT_FOUND); + } finally { + updateSdkVersion(0); + } + } + + private static ResolveInfo stubResolveInfo(String packageName) { + ResolveInfo resolveInfo = new ResolveInfo(); + resolveInfo.activityInfo = new ActivityInfo(); + resolveInfo.activityInfo.packageName = packageName; + return resolveInfo; + } + + private static void updateSdkVersion(int version) { + TestUtils.setFinalStatic(Build.VERSION.class, "SDK_INT", version); + } +} diff --git a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/IntentDataMatcher.java b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/IntentDataMatcher.java new file mode 100644 index 000000000000..eaf5cd20b1ac --- /dev/null +++ b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/IntentDataMatcher.java @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.urllauncher.utils; + +import android.content.Intent; + +import org.mockito.ArgumentMatcher; + +public class IntentDataMatcher extends ArgumentMatcher { + public IntentDataMatcher(String dataString) { + this.dataString = dataString; + } + + private final String dataString; + + @Override + public boolean matches(Object intent) { + return ((Intent) intent).getDataString().equals(dataString); + } +} diff --git a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/TestUtils.java b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/TestUtils.java new file mode 100644 index 000000000000..f67707b362d3 --- /dev/null +++ b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/TestUtils.java @@ -0,0 +1,26 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.urllauncher.utils; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import org.junit.Assert; + +public class TestUtils { + public static void setFinalStatic(Class classToModify, String fieldName, Object newValue) { + try { + Field field = classToModify.getField(fieldName); + field.setAccessible(true); + + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + + field.set(null, newValue); + } catch (Exception e) { + Assert.fail("Unable to mock static field: " + fieldName); + } + } +} From 327480cf0b4106180f9ec1d94654566a671b78ce Mon Sep 17 00:00:00 2001 From: Mosc Date: Sat, 11 Jun 2022 23:36:57 +0200 Subject: [PATCH 4/8] Bump version --- packages/url_launcher/url_launcher_android/CHANGELOG.md | 5 +++++ packages/url_launcher/url_launcher_android/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/url_launcher/url_launcher_android/CHANGELOG.md b/packages/url_launcher/url_launcher_android/CHANGELOG.md index 887178c479e4..890053edae79 100644 --- a/packages/url_launcher/url_launcher_android/CHANGELOG.md +++ b/packages/url_launcher/url_launcher_android/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.0.18 + +* Adds support for requiring links to open in a non-browser app in `launch` + through the `universalLinksOnly` parameter. + ## 6.0.17 * Fixes library_private_types_in_public_api, sort_child_properties_last and use_key_in_widget_constructors diff --git a/packages/url_launcher/url_launcher_android/pubspec.yaml b/packages/url_launcher/url_launcher_android/pubspec.yaml index 3c80170f1422..040ba9917d7f 100644 --- a/packages/url_launcher/url_launcher_android/pubspec.yaml +++ b/packages/url_launcher/url_launcher_android/pubspec.yaml @@ -2,7 +2,7 @@ name: url_launcher_android description: Android implementation of the url_launcher plugin. repository: https://github.com/flutter/plugins/tree/main/packages/url_launcher/url_launcher_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22 -version: 6.0.17 +version: 6.0.18 environment: sdk: ">=2.14.0 <3.0.0" From 56a6d82c97312d22bc0395b969f0871329fded63 Mon Sep 17 00:00:00 2001 From: Mosc Date: Sat, 11 Jun 2022 23:50:08 +0200 Subject: [PATCH 5/8] Fix formatting --- .../urllauncher/utils/IntentDataMatcher.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/IntentDataMatcher.java b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/IntentDataMatcher.java index eaf5cd20b1ac..389748f78e2f 100644 --- a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/IntentDataMatcher.java +++ b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/IntentDataMatcher.java @@ -9,14 +9,14 @@ import org.mockito.ArgumentMatcher; public class IntentDataMatcher extends ArgumentMatcher { - public IntentDataMatcher(String dataString) { - this.dataString = dataString; - } + public IntentDataMatcher(String dataString) { + this.dataString = dataString; + } - private final String dataString; + private final String dataString; - @Override - public boolean matches(Object intent) { - return ((Intent) intent).getDataString().equals(dataString); - } + @Override + public boolean matches(Object intent) { + return ((Intent) intent).getDataString().equals(dataString); + } } From 99c3c8e29cf1a2dc7610aa3d2bf531a63207de97 Mon Sep 17 00:00:00 2001 From: Mosc Date: Sat, 11 Jun 2022 23:57:56 +0200 Subject: [PATCH 6/8] Fix imports --- .../io/flutter/plugins/urllauncher/UrlLauncher.java | 1 - .../flutter/plugins/urllauncher/UrlLauncherTest.java | 12 ++++-------- .../plugins/urllauncher/utils/IntentDataMatcher.java | 1 - 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java b/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java index f5c288782ddd..b012b9b59bfb 100644 --- a/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java +++ b/packages/url_launcher/url_launcher_android/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java @@ -17,7 +17,6 @@ import android.provider.Browser; import android.util.Log; import androidx.annotation.Nullable; - import java.util.HashSet; import java.util.List; import java.util.Set; diff --git a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/UrlLauncherTest.java b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/UrlLauncherTest.java index 1447cdfc76b7..15edf507ce37 100644 --- a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/UrlLauncherTest.java +++ b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/UrlLauncherTest.java @@ -20,20 +20,16 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Build; - +import io.flutter.plugins.urllauncher.utils.IntentDataMatcher; +import io.flutter.plugins.urllauncher.utils.TestUtils; +import java.util.Arrays; +import java.util.Collections; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentMatcher; import org.mockito.Matchers; import org.robolectric.RobolectricTestRunner; -import java.util.Arrays; -import java.util.Collections; - -import io.flutter.plugins.urllauncher.utils.IntentDataMatcher; -import io.flutter.plugins.urllauncher.utils.TestUtils; - @RunWith(RobolectricTestRunner.class) public class UrlLauncherTest { private Context applicationContext; diff --git a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/IntentDataMatcher.java b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/IntentDataMatcher.java index 389748f78e2f..21fa5bbadeb0 100644 --- a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/IntentDataMatcher.java +++ b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/utils/IntentDataMatcher.java @@ -5,7 +5,6 @@ package io.flutter.plugins.urllauncher.utils; import android.content.Intent; - import org.mockito.ArgumentMatcher; public class IntentDataMatcher extends ArgumentMatcher { From cfd4412d6b08cca6518a034aba2e4172c0a506be Mon Sep 17 00:00:00 2001 From: Mosc Date: Sun, 12 Jun 2022 12:45:42 +0200 Subject: [PATCH 7/8] Bump version --- packages/url_launcher/url_launcher/CHANGELOG.md | 4 +++- packages/url_launcher/url_launcher/pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/url_launcher/url_launcher/CHANGELOG.md b/packages/url_launcher/url_launcher/CHANGELOG.md index 182119345ccc..9a38b855eee0 100644 --- a/packages/url_launcher/url_launcher/CHANGELOG.md +++ b/packages/url_launcher/url_launcher/CHANGELOG.md @@ -1,6 +1,8 @@ -## NEXT +## 6.1.4 * Ignores unnecessary import warnings in preparation for [upcoming Flutter changes](https://github.com/flutter/flutter/pull/105648). +* Updates documentation to mention `LaunchMode.externalNonBrowserApplication` + now being supported for Android in `launchUrl`. ## 6.1.3 diff --git a/packages/url_launcher/url_launcher/pubspec.yaml b/packages/url_launcher/url_launcher/pubspec.yaml index 2a7ddcdb1dbe..9a93b2080df6 100644 --- a/packages/url_launcher/url_launcher/pubspec.yaml +++ b/packages/url_launcher/url_launcher/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for launching a URL. Supports web, phone, SMS, and email schemes. repository: https://github.com/flutter/plugins/tree/main/packages/url_launcher/url_launcher issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22 -version: 6.1.3 +version: 6.1.4 environment: sdk: ">=2.14.0 <3.0.0" From 2b91cc0b82f7daa8ec9bfab8f5712de9429aa380 Mon Sep 17 00:00:00 2001 From: Mosc Date: Sun, 12 Jun 2022 12:51:00 +0200 Subject: [PATCH 8/8] Simplify test --- .../java/io/flutter/plugins/urllauncher/UrlLauncherTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/UrlLauncherTest.java b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/UrlLauncherTest.java index 15edf507ce37..85f935b9ab57 100644 --- a/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/UrlLauncherTest.java +++ b/packages/url_launcher/url_launcher_android/android/src/test/java/io/flutter/plugins/urllauncher/UrlLauncherTest.java @@ -96,9 +96,6 @@ public void launch_shouldReturnOkWhenUniversalLinksOnlyBelowAndroidRAndNonBrowse ResolveInfo browserIntentActivity = stubResolveInfo("browser"); when(mockPackageManager.queryIntentActivities(any(Intent.class), anyInt())) .thenReturn(Collections.singletonList(browserIntentActivity)); - when(mockPackageManager.queryIntentActivities( - Matchers.argThat(new IntentDataMatcher(LAUNCH_URL)), anyInt())) - .thenReturn(Collections.singletonList(browserIntentActivity)); UrlLauncher.LaunchStatus launchStatus = urlLauncher.launch(LAUNCH_URL, null, false, false, false, true);