From ceb4cfa9f8b3f4fed42707c2032c93cf69056f90 Mon Sep 17 00:00:00 2001 From: Michael Klimushyn Date: Thu, 17 Oct 2019 10:25:32 -0700 Subject: [PATCH 1/7] Revert "[flutter_webview] Revert v2 embedder support (#2200)" This reverts commit 2ca7b52bf8b463eae743f3a92861547c817dac9e. --- packages/webview_flutter/CHANGELOG.md | 5 -- packages/webview_flutter/android/build.gradle | 25 ++++++ .../webview_flutter/android/gradle.properties | 2 + .../webviewflutter/FlutterCookieManager.java | 18 ++--- .../webviewflutter/FlutterWebView.java | 14 +++- .../webviewflutter/InputAwareWebView.java | 38 ++++++++- .../webviewflutter/WebViewFactory.java | 5 +- .../webviewflutter/WebViewFlutterPlugin.java | 64 ++++++++++++++- .../example/android/app/build.gradle | 5 +- .../EmbeddingV1ActivityTest.java | 13 +++ .../MainActivityTest.java | 11 +++ .../android/app/src/main/AndroidManifest.xml | 79 +++++++++++-------- .../EmbeddingV1Activity.java | 17 ++++ .../webviewflutterexample/MainActivity.java | 20 +++-- .../example/android/gradle.properties | 4 +- packages/webview_flutter/example/pubspec.yaml | 4 +- ...{webview.dart => webview_flutter_e2e.dart} | 65 +++++++-------- ...est.dart => webview_flutter_e2e_test.dart} | 5 +- packages/webview_flutter/pubspec.yaml | 4 +- 19 files changed, 290 insertions(+), 108 deletions(-) create mode 100644 packages/webview_flutter/example/android/app/src/androidTestDebug/java/io/flutter/plugins/webviewflutterexample/EmbeddingV1ActivityTest.java create mode 100644 packages/webview_flutter/example/android/app/src/androidTestDebug/java/io/flutter/plugins/webviewflutterexample/MainActivityTest.java create mode 100644 packages/webview_flutter/example/android/app/src/main/java/io/flutter/plugins/webviewflutterexample/EmbeddingV1Activity.java rename packages/webview_flutter/example/test_driver/{webview.dart => webview_flutter_e2e.dart} (92%) rename packages/webview_flutter/example/test_driver/{webview_test.dart => webview_flutter_e2e_test.dart} (72%) diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md index 313b29cda9fb..7710f748fca5 100644 --- a/packages/webview_flutter/CHANGELOG.md +++ b/packages/webview_flutter/CHANGELOG.md @@ -1,8 +1,3 @@ -## 0.3.15+1 - -* Revert the prior embedding support add since it requires an API that hasn't - rolled to stable. - ## 0.3.15 * Add support for the v2 Android embedding. This shouldn't affect existing diff --git a/packages/webview_flutter/android/build.gradle b/packages/webview_flutter/android/build.gradle index 4fe7629b5f76..0104ede0a418 100644 --- a/packages/webview_flutter/android/build.gradle +++ b/packages/webview_flutter/android/build.gradle @@ -50,3 +50,28 @@ android { implementation 'androidx.webkit:webkit:1.0.0' } } + +// TODO(mklim): 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 = "2.1.0" + api "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" + api "androidx.lifecycle:lifecycle-runtime:$lifecycle_version" + } + } + } +} \ No newline at end of file diff --git a/packages/webview_flutter/android/gradle.properties b/packages/webview_flutter/android/gradle.properties index 8bd86f680510..08f2b5f91bff 100644 --- a/packages/webview_flutter/android/gradle.properties +++ b/packages/webview_flutter/android/gradle.properties @@ -1 +1,3 @@ org.gradle.jvmargs=-Xmx1536M +android.enableJetifier=true +android.useAndroidX=true diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterCookieManager.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterCookieManager.java index 908f877fb922..86b4fd412a29 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterCookieManager.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterCookieManager.java @@ -15,17 +15,11 @@ import io.flutter.plugin.common.MethodChannel.Result; class FlutterCookieManager implements MethodCallHandler { + private final MethodChannel methodChannel; - private FlutterCookieManager() { - // Do not instantiate. - // This class should only be used in context of a BinaryMessenger. - // Use FlutterCookieManager#registerWith instead. - } - - static void registerWith(BinaryMessenger messenger) { - MethodChannel methodChannel = new MethodChannel(messenger, "plugins.flutter.io/cookie_manager"); - FlutterCookieManager cookieManager = new FlutterCookieManager(); - methodChannel.setMethodCallHandler(cookieManager); + FlutterCookieManager(BinaryMessenger messenger) { + methodChannel = new MethodChannel(messenger, "plugins.flutter.io/cookie_manager"); + methodChannel.setMethodCallHandler(this); } @Override @@ -39,6 +33,10 @@ public void onMethodCall(MethodCall methodCall, Result result) { } } + void dispose() { + methodChannel.setMethodCallHandler(null); + } + private static void clearCookies(final Result result) { CookieManager cookieManager = CookieManager.getInstance(); final boolean hasCookies = cookieManager.hasCookies(); diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java index a7f2db308e15..ac326ed7f27b 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java @@ -12,6 +12,8 @@ import android.view.View; import android.webkit.WebStorage; import android.webkit.WebViewClient; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; @@ -36,7 +38,7 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { BinaryMessenger messenger, int id, Map params, - final View containerView) { + @Nullable View containerView) { DisplayListenerProxy displayListenerProxy = new DisplayListenerProxy(); DisplayManager displayManager = @@ -95,6 +97,16 @@ public void onInputConnectionLocked() { webView.lockInputConnection(); } + @Override + public void onFlutterViewAttached(@NonNull View flutterView) { + webView.setContainerView(flutterView); + } + + @Override + public void onFlutterViewDetached() { + webView.setContainerView(null); + } + @Override public void onMethodCall(MethodCall methodCall, Result result) { switch (methodCall.method) { diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java index 9275c380fb56..e04d566bdc92 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java @@ -7,9 +7,11 @@ import static android.content.Context.INPUT_METHOD_SERVICE; import android.content.Context; +import android.util.Log; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.webkit.WebView; +import androidx.annotation.Nullable; /** * A WebView subclass that mirrors the same implementation hacks that the system WebView does in @@ -22,16 +24,29 @@ *

See also {@link ThreadedInputConnectionProxyAdapterView}. */ final class InputAwareWebView extends WebView { - private final View containerView; - + private static final String TAG = "InputAwareWebView"; private View threadedInputConnectionProxyView; private ThreadedInputConnectionProxyAdapterView proxyAdapterView; + private @Nullable View containerView; - InputAwareWebView(Context context, View containerView) { + InputAwareWebView(Context context, @Nullable View containerView) { super(context); this.containerView = containerView; } + void setContainerView(@Nullable View containerView) { + this.containerView = containerView; + + if (proxyAdapterView == null) { + return; + } + + Log.w(TAG, "The containerView has changed while the proxyAdapterView exists."); + if (containerView != null) { + setInputConnectionTarget(proxyAdapterView); + } + } + /** * Set our proxy adapter view to use its cached input connection instead of creating new ones. * @@ -81,6 +96,12 @@ public boolean checkInputConnectionProxy(final View view) { // This isn't a new ThreadedInputConnectionProxyView. Ignore it. return super.checkInputConnectionProxy(view); } + if (containerView == null) { + Log.e( + TAG, + "Can't create a proxy view because there's no container view. Text input may not work."); + return super.checkInputConnectionProxy(view); + } // We've never seen this before, so we make the assumption that this is WebView's // ThreadedInputConnectionProxyView. We are making the assumption that the only view that could @@ -120,6 +141,10 @@ private void resetInputConnection() { // No need to reset the InputConnection to the default thread if we've never changed it. return; } + if (containerView == null) { + Log.e(TAG, "Can't reset the input connection to the container view because there is none."); + return; + } setInputConnectionTarget(/*targetView=*/ containerView); } @@ -132,6 +157,13 @@ private void resetInputConnection() { * InputConnections should be created on. */ private void setInputConnectionTarget(final View targetView) { + if (containerView == null) { + Log.e( + TAG, + "Can't set the input connection target because there is no containerView to use as a handler."); + return; + } + targetView.requestFocus(); containerView.post( new Runnable() { diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFactory.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFactory.java index 6fdc36fbe545..fe62e3a35540 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFactory.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFactory.java @@ -6,6 +6,7 @@ import android.content.Context; import android.view.View; +import androidx.annotation.Nullable; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.StandardMessageCodec; import io.flutter.plugin.platform.PlatformView; @@ -14,9 +15,9 @@ public final class WebViewFactory extends PlatformViewFactory { private final BinaryMessenger messenger; - private final View containerView; + private @Nullable final View containerView; - WebViewFactory(BinaryMessenger messenger, View containerView) { + WebViewFactory(BinaryMessenger messenger, @Nullable View containerView) { super(StandardMessageCodec.INSTANCE); this.messenger = messenger; this.containerView = containerView; diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java index 17177541222c..0284f20115f8 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java @@ -4,17 +4,73 @@ package io.flutter.plugins.webviewflutter; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.PluginRegistry.Registrar; -/** WebViewFlutterPlugin */ -public class WebViewFlutterPlugin { - /** Plugin registration. */ +/** + * Java platform implementation of the webview_flutter plugin. + * + *

Register this in an add to app scenario to gracefully handle activity and context changes. + * + *

Call {@link #registerWith(Registrar)} to use the stable {@code io.flutter.plugin.common} + * package instead. + */ +public class WebViewFlutterPlugin implements FlutterPlugin { + + private @Nullable FlutterCookieManager flutterCookieManager; + + /** + * Add an instance of this to {@link io.flutter.embedding.engine.plugins.PluginRegistry} to + * register it. + * + *

THIS PLUGIN CODE PATH DEPENDS ON A NEWER VERSION OF FLUTTER THAN THE ONE DEFINED IN THE + * PUBSPEC.YAML. Text input will fail on some Android devices unless this is used with at least + * flutter/flutter@1d4d63ace1f801a022ea9ec737bf8c15395588b9. Use the V1 embedding with {@link + * #registerWith(Registrar)} to use this plugin with older Flutter versions. + * + *

Registration should eventually be handled automatically by v2 of the + * GeneratedPluginRegistrant. https://github.com/flutter/flutter/issues/42694 + */ + public WebViewFlutterPlugin() {} + + /** + * Registers a plugin implementation that uses the stable {@code io.flutter.plugin.common} + * package. + * + *

Calling this automatically initializes the plugin. However plugins initialized this way + * won't react to changes in activity or context, unlike {@link CameraPlugin}. + */ public static void registerWith(Registrar registrar) { registrar .platformViewRegistry() .registerViewFactory( "plugins.flutter.io/webview", new WebViewFactory(registrar.messenger(), registrar.view())); - FlutterCookieManager.registerWith(registrar.messenger()); + new FlutterCookieManager(registrar.messenger()); + } + + @Override + public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { + BinaryMessenger messenger = binding.getFlutterEngine().getDartExecutor(); + binding + .getFlutterEngine() + .getPlatformViewsController() + .getRegistry() + .registerViewFactory( + "plugins.flutter.io/webview", new WebViewFactory(messenger, /*containerView=*/ null)); + flutterCookieManager = new FlutterCookieManager(messenger); + } + + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + if (flutterCookieManager == null) { + return; + } + + flutterCookieManager.dispose(); + flutterCookieManager = null; } } diff --git a/packages/webview_flutter/example/android/app/build.gradle b/packages/webview_flutter/example/android/app/build.gradle index 79a69ac3e4d7..706d501c4060 100644 --- a/packages/webview_flutter/example/android/app/build.gradle +++ b/packages/webview_flutter/example/android/app/build.gradle @@ -56,6 +56,7 @@ flutter { dependencies { testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test:rules:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } diff --git a/packages/webview_flutter/example/android/app/src/androidTestDebug/java/io/flutter/plugins/webviewflutterexample/EmbeddingV1ActivityTest.java b/packages/webview_flutter/example/android/app/src/androidTestDebug/java/io/flutter/plugins/webviewflutterexample/EmbeddingV1ActivityTest.java new file mode 100644 index 000000000000..fe10c6155e5a --- /dev/null +++ b/packages/webview_flutter/example/android/app/src/androidTestDebug/java/io/flutter/plugins/webviewflutterexample/EmbeddingV1ActivityTest.java @@ -0,0 +1,13 @@ +package io.flutter.plugins.webviewflutterexample; + +import androidx.test.rule.ActivityTestRule; +import dev.flutter.plugins.e2e.FlutterRunner; +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/webview_flutter/example/android/app/src/androidTestDebug/java/io/flutter/plugins/webviewflutterexample/MainActivityTest.java b/packages/webview_flutter/example/android/app/src/androidTestDebug/java/io/flutter/plugins/webviewflutterexample/MainActivityTest.java new file mode 100644 index 000000000000..a0bd4fe1a7f5 --- /dev/null +++ b/packages/webview_flutter/example/android/app/src/androidTestDebug/java/io/flutter/plugins/webviewflutterexample/MainActivityTest.java @@ -0,0 +1,11 @@ +package io.flutter.plugins.webviewflutterexample; + +import androidx.test.rule.ActivityTestRule; +import dev.flutter.plugins.e2e.FlutterRunner; +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/webview_flutter/example/android/app/src/main/AndroidManifest.xml b/packages/webview_flutter/example/android/app/src/main/AndroidManifest.xml index 8fcbcd3908ba..fd570acc8959 100644 --- a/packages/webview_flutter/example/android/app/src/main/AndroidManifest.xml +++ b/packages/webview_flutter/example/android/app/src/main/AndroidManifest.xml @@ -1,39 +1,48 @@ + package="io.flutter.plugins.webviewflutterexample"> - - + + + + + + + + + + + + + - - - - - - - - - - - + + diff --git a/packages/webview_flutter/example/android/app/src/main/java/io/flutter/plugins/webviewflutterexample/EmbeddingV1Activity.java b/packages/webview_flutter/example/android/app/src/main/java/io/flutter/plugins/webviewflutterexample/EmbeddingV1Activity.java new file mode 100644 index 000000000000..9b868934cc10 --- /dev/null +++ b/packages/webview_flutter/example/android/app/src/main/java/io/flutter/plugins/webviewflutterexample/EmbeddingV1Activity.java @@ -0,0 +1,17 @@ +// Copyright 2019 The Chromium 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.webviewflutterexample; + +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/webview_flutter/example/android/app/src/main/java/io/flutter/plugins/webviewflutterexample/MainActivity.java b/packages/webview_flutter/example/android/app/src/main/java/io/flutter/plugins/webviewflutterexample/MainActivity.java index f935d0030483..2f3b7edd3d9f 100644 --- a/packages/webview_flutter/example/android/app/src/main/java/io/flutter/plugins/webviewflutterexample/MainActivity.java +++ b/packages/webview_flutter/example/android/app/src/main/java/io/flutter/plugins/webviewflutterexample/MainActivity.java @@ -4,14 +4,22 @@ package io.flutter.plugins.webviewflutterexample; -import android.os.Bundle; -import io.flutter.app.FlutterActivity; -import io.flutter.plugins.GeneratedPluginRegistrant; +import io.flutter.embedding.android.FlutterActivity; +import io.flutter.embedding.engine.FlutterEngine; +import io.flutter.plugins.webviewflutter.WebViewFlutterPlugin; +/** + * THIS PLUGIN CODE PATH DEPENDS ON A NEWER VERSION OF FLUTTER THAN THE ONE DEFINED IN THE + * PUBSPEC.YAML. Text input will fail on some Android devices unless this is used with at least + * flutter/flutter@1d4d63ace1f801a022ea9ec737bf8c15395588b9. + * + *

Use the V1 embedding as seen in {@link EmbeddingV1Activity} to use this plugin on older + * Flutter versions. + */ public class MainActivity extends FlutterActivity { + // TODO(mklim): 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 WebViewFlutterPlugin()); } } diff --git a/packages/webview_flutter/example/android/gradle.properties b/packages/webview_flutter/example/android/gradle.properties index ad8917e962e5..a6738207fd15 100644 --- a/packages/webview_flutter/example/android/gradle.properties +++ b/packages/webview_flutter/example/android/gradle.properties @@ -1,2 +1,4 @@ org.gradle.jvmargs=-Xmx1536M -android.useAndroidX=true \ No newline at end of file +android.useAndroidX=true +android.enableJetifier=true +android.enableR8=true diff --git a/packages/webview_flutter/example/pubspec.yaml b/packages/webview_flutter/example/pubspec.yaml index 3a73afaffa44..0e24333cfc0b 100644 --- a/packages/webview_flutter/example/pubspec.yaml +++ b/packages/webview_flutter/example/pubspec.yaml @@ -1,10 +1,11 @@ name: webview_flutter_example description: Demonstrates how to use the webview_flutter plugin. -version: 1.0.3 +version: 1.0.2 environment: sdk: ">=2.0.0-dev.68.0 <3.0.0" + flutter: ">=1.9.1+hotfix.4 <2.0.0" dependencies: flutter: @@ -17,6 +18,7 @@ dev_dependencies: sdk: flutter flutter_driver: sdk: flutter + e2e: "^0.2.0" flutter: uses-material-design: true diff --git a/packages/webview_flutter/example/test_driver/webview.dart b/packages/webview_flutter/example/test_driver/webview_flutter_e2e.dart similarity index 92% rename from packages/webview_flutter/example/test_driver/webview.dart rename to packages/webview_flutter/example/test_driver/webview_flutter_e2e.dart index e24afd73f557..a5d4d7de66fe 100644 --- a/packages/webview_flutter/example/test_driver/webview.dart +++ b/packages/webview_flutter/example/test_driver/webview_flutter_e2e.dart @@ -9,19 +9,17 @@ import 'dart:typed_data'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:webview_flutter/webview_flutter.dart'; +import 'package:e2e/e2e.dart'; void main() { - final Completer allTestsCompleter = Completer(); - enableFlutterDriverExtension(handler: (_) => allTestsCompleter.future); - tearDownAll(() => allTestsCompleter.complete(null)); + E2EWidgetsFlutterBinding.ensureInitialized(); - test('initalUrl', () async { + testWidgets('initalUrl', (WidgetTester tester) async { final Completer controllerCompleter = Completer(); - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -38,10 +36,10 @@ void main() { expect(currentUrl, 'https://flutter.dev/'); }); - test('loadUrl', () async { + testWidgets('loadUrl', (WidgetTester tester) async { final Completer controllerCompleter = Completer(); - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -61,11 +59,11 @@ void main() { // enable this once https://github.com/flutter/flutter/issues/31510 // is resolved. - test('loadUrl with headers', () async { + testWidgets('loadUrl with headers', (WidgetTester tester) async { final Completer controllerCompleter = Completer(); final StreamController pageLoads = StreamController(); - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -96,12 +94,12 @@ void main() { expect(content.contains('flutter_test_header'), isTrue); }); - test('JavaScriptChannel', () async { + testWidgets('JavaScriptChannel', (WidgetTester tester) async { final Completer controllerCompleter = Completer(); final Completer pageLoaded = Completer(); final List messagesReceived = []; - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -137,7 +135,7 @@ void main() { expect(messagesReceived, equals(['hello'])); }); - test('resize webview', () async { + testWidgets('resize webview', (WidgetTester tester) async { final String resizeTest = ''' Resize test @@ -184,7 +182,7 @@ void main() { javascriptMode: JavascriptMode.unrestricted, ); - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Column( @@ -204,7 +202,7 @@ void main() { expect(resizeCompleter.isCompleted, false); - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Column( @@ -222,11 +220,11 @@ void main() { await resizeCompleter.future; }); - test('set custom userAgent', () async { + testWidgets('set custom userAgent', (WidgetTester tester) async { final Completer controllerCompleter1 = Completer(); final GlobalKey _globalKey = GlobalKey(); - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -244,7 +242,7 @@ void main() { final String customUserAgent1 = await _getUserAgent(controller1); expect(customUserAgent1, 'Custom_User_Agent1'); // rebuild the WebView with a different user agent. - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -260,12 +258,13 @@ void main() { expect(customUserAgent2, 'Custom_User_Agent2'); }); - test('use default platform userAgent after webView is rebuilt', () async { + testWidgets('use default platform userAgent after webView is rebuilt', + (WidgetTester tester) async { final Completer controllerCompleter = Completer(); final GlobalKey _globalKey = GlobalKey(); // Build the webView with no user agent to get the default platform user agent. - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -281,7 +280,7 @@ void main() { final WebViewController controller = await controllerCompleter.future; final String defaultPlatformUserAgent = await _getUserAgent(controller); // rebuild the WebView with a custom user agent. - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -295,7 +294,7 @@ void main() { final String customUserAgent = await _getUserAgent(controller); expect(customUserAgent, 'Custom_User_Agent'); // rebuilds the WebView with no user agent. - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -341,12 +340,12 @@ void main() { audioTestBase64 = base64Encode(const Utf8Encoder().convert(audioTest)); }); - test('Auto media playback', () async { + testWidgets('Auto media playback', (WidgetTester tester) async { Completer controllerCompleter = Completer(); Completer pageLoaded = Completer(); - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -373,7 +372,7 @@ void main() { pageLoaded = Completer(); // We change the key to re-create a new webview as we change the initialMediaPlaybackPolicy - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -399,13 +398,14 @@ void main() { expect(isPaused, _webviewBool(true)); }); - test('Changes to initialMediaPlaybackPolocy are ignored', () async { + testWidgets('Changes to initialMediaPlaybackPolocy are ignored', + (WidgetTester tester) async { final Completer controllerCompleter = Completer(); Completer pageLoaded = Completer(); final GlobalKey key = GlobalKey(); - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -430,7 +430,7 @@ void main() { pageLoaded = Completer(); - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -458,7 +458,7 @@ void main() { }); }); - test('getTitle', () async { + testWidgets('getTitle', (WidgetTester tester) async { final String getTitleTest = ''' Some title @@ -473,7 +473,7 @@ void main() { final Completer controllerCompleter = Completer(); - await pumpWidget( + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( @@ -496,11 +496,6 @@ void main() { }); } -Future pumpWidget(Widget widget) { - runApp(widget); - return WidgetsBinding.instance.endOfFrame; -} - // JavaScript booleans evaluate to different string values on Android and iOS. // This utility method returns the string boolean value of the current platform. String _webviewBool(bool value) { diff --git a/packages/webview_flutter/example/test_driver/webview_test.dart b/packages/webview_flutter/example/test_driver/webview_flutter_e2e_test.dart similarity index 72% rename from packages/webview_flutter/example/test_driver/webview_test.dart rename to packages/webview_flutter/example/test_driver/webview_flutter_e2e_test.dart index b0d3305cd652..2e5c27fd402e 100644 --- a/packages/webview_flutter/example/test_driver/webview_test.dart +++ b/packages/webview_flutter/example/test_driver/webview_flutter_e2e_test.dart @@ -3,11 +3,14 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'dart:io'; import 'package:flutter_driver/flutter_driver.dart'; Future main() async { final FlutterDriver driver = await FlutterDriver.connect(); - await driver.requestData(null, timeout: const Duration(minutes: 1)); + final String result = + await driver.requestData(null, timeout: const Duration(minutes: 1)); driver.close(); + exit(result == 'pass' ? 0 : 1); } diff --git a/packages/webview_flutter/pubspec.yaml b/packages/webview_flutter/pubspec.yaml index cd8bfb5d4044..efddfd3b7aec 100644 --- a/packages/webview_flutter/pubspec.yaml +++ b/packages/webview_flutter/pubspec.yaml @@ -1,12 +1,12 @@ name: webview_flutter description: A Flutter plugin that provides a WebView widget on Android and iOS. -version: 0.3.15+1 +version: 0.3.15 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/webview_flutter environment: sdk: ">=2.0.0-dev.68.0 <3.0.0" - flutter: ">=1.5.0 <2.0.0" + flutter: ">=1.6.7 <2.0.0" dependencies: flutter: From e518d6732003dfd2bb52defacc8a44a02a0805da Mon Sep 17 00:00:00 2001 From: Michael Klimushyn Date: Thu, 17 Oct 2019 10:32:47 -0700 Subject: [PATCH 2/7] [webview_flutter] Re-land v2 embedding support This correctly sets the minimum SDK to the latest stable and avoid any compile errors. *WARNING:* the V2 embedding itself still requires the current Flutter master channel (flutter/flutter@1d4d63a) for text input to work properly on all Android versions. --- packages/webview_flutter/CHANGELOG.md | 13 +++++++++++++ .../plugins/webviewflutter/FlutterWebView.java | 14 ++++++++++++-- packages/webview_flutter/example/pubspec.yaml | 3 +-- packages/webview_flutter/pubspec.yaml | 4 ++-- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md index 7710f748fca5..9dab62c83eaf 100644 --- a/packages/webview_flutter/CHANGELOG.md +++ b/packages/webview_flutter/CHANGELOG.md @@ -1,3 +1,16 @@ +## 0.3.15+2 + +* Re-land support for the v2 Android embedding. This correctly sets the minimum + SDK to the latest stable and avoid any compile errors. *WARNING:* the V2 + embedding itself still requires the current Flutter master channel + (flutter/flutter@1d4d63a) for text input to work properly on all Android + versions. + +## 0.3.15+1 + +* Revert the prior embedding support add since it requires an API that hasn't + rolled to stable. + ## 0.3.15 * Add support for the v2 Android embedding. This shouldn't affect existing diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java index ac326ed7f27b..6922745907bf 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java @@ -97,12 +97,22 @@ public void onInputConnectionLocked() { webView.lockInputConnection(); } - @Override + // @Override + // This is overriding a method that hasn't rolled into stable Flutter yet. Including the + // annotation would cause compile time failures in versions of Flutter too old to include the new + // method. However leaving it raw like this means that the method will be ignored in old versions + // of Flutter but used as an override anyway wherever it's actually defined. + // TODO(mklim): Add the @Override annotation once stable passes v1.10.9. public void onFlutterViewAttached(@NonNull View flutterView) { webView.setContainerView(flutterView); } - @Override + // @Override + // This is overriding a method that hasn't rolled into stable Flutter yet. Including the + // annotation would cause compile time failures in versions of Flutter too old to include the new + // method. However leaving it raw like this means that the method will be ignored in old versions + // of Flutter but used as an override anyway wherever it's actually defined. + // TODO(mklim): Add the @Override annotation once stable passes v1.10.9. public void onFlutterViewDetached() { webView.setContainerView(null); } diff --git a/packages/webview_flutter/example/pubspec.yaml b/packages/webview_flutter/example/pubspec.yaml index 0e24333cfc0b..ae1d71c1cade 100644 --- a/packages/webview_flutter/example/pubspec.yaml +++ b/packages/webview_flutter/example/pubspec.yaml @@ -1,11 +1,10 @@ name: webview_flutter_example description: Demonstrates how to use the webview_flutter plugin. -version: 1.0.2 +version: 1.0.4 environment: sdk: ">=2.0.0-dev.68.0 <3.0.0" - flutter: ">=1.9.1+hotfix.4 <2.0.0" dependencies: flutter: diff --git a/packages/webview_flutter/pubspec.yaml b/packages/webview_flutter/pubspec.yaml index efddfd3b7aec..0188cd1744ef 100644 --- a/packages/webview_flutter/pubspec.yaml +++ b/packages/webview_flutter/pubspec.yaml @@ -1,12 +1,12 @@ name: webview_flutter description: A Flutter plugin that provides a WebView widget on Android and iOS. -version: 0.3.15 +version: 0.3.15+2 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/webview_flutter environment: sdk: ">=2.0.0-dev.68.0 <3.0.0" - flutter: ">=1.6.7 <2.0.0" + flutter: ">=1.9.1+hotfix.5 <2.0.0" dependencies: flutter: From a59a6da10c4268d4c40ab8d06e7cf7a92f8eb786 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Thu, 31 Oct 2019 16:01:15 -0700 Subject: [PATCH 3/7] Changed Gradle deps and removed nullability annotations. --- packages/webview_flutter/android/build.gradle | 6 +++--- .../io/flutter/plugins/webviewflutter/FlutterWebView.java | 6 ++---- .../plugins/webviewflutter/FlutterWebViewClient.java | 3 +-- .../flutter/plugins/webviewflutter/InputAwareWebView.java | 7 +++---- .../io/flutter/plugins/webviewflutter/WebViewFactory.java | 5 ++--- .../plugins/webviewflutter/WebViewFlutterPlugin.java | 8 +++----- 6 files changed, 14 insertions(+), 21 deletions(-) diff --git a/packages/webview_flutter/android/build.gradle b/packages/webview_flutter/android/build.gradle index 0104ede0a418..a0661d6b7bc6 100644 --- a/packages/webview_flutter/android/build.gradle +++ b/packages/webview_flutter/android/build.gradle @@ -68,9 +68,9 @@ afterEvaluate { if (!containsEmbeddingDependencies) { android { dependencies { - def lifecycle_version = "2.1.0" - api "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" - api "androidx.lifecycle:lifecycle-runtime:$lifecycle_version" + def lifecycle_version = "1.1.1" + compileOnly "android.arch.lifecycle:common-java8:$lifecycle_version" + compileOnly "android.arch.lifecycle:runtime:$lifecycle_version" } } } diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java index 6922745907bf..83a7ed6340f8 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java @@ -12,8 +12,6 @@ import android.view.View; import android.webkit.WebStorage; import android.webkit.WebViewClient; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; @@ -38,7 +36,7 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { BinaryMessenger messenger, int id, Map params, - @Nullable View containerView) { + View containerView) { DisplayListenerProxy displayListenerProxy = new DisplayListenerProxy(); DisplayManager displayManager = @@ -103,7 +101,7 @@ public void onInputConnectionLocked() { // method. However leaving it raw like this means that the method will be ignored in old versions // of Flutter but used as an override anyway wherever it's actually defined. // TODO(mklim): Add the @Override annotation once stable passes v1.10.9. - public void onFlutterViewAttached(@NonNull View flutterView) { + public void onFlutterViewAttached(View flutterView) { webView.setContainerView(flutterView); } diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java index bdd6abb66282..8925fbdc919d 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java @@ -11,7 +11,6 @@ import android.webkit.WebResourceRequest; import android.webkit.WebView; import android.webkit.WebViewClient; -import androidx.annotation.NonNull; import androidx.webkit.WebViewClientCompat; import io.flutter.plugin.common.MethodChannel; import java.util.HashMap; @@ -125,7 +124,7 @@ private WebViewClientCompat internalCreateWebViewClientCompat() { return new WebViewClientCompat() { @Override public boolean shouldOverrideUrlLoading( - @NonNull WebView view, @NonNull WebResourceRequest request) { + WebView view, WebResourceRequest request) { return FlutterWebViewClient.this.shouldOverrideUrlLoading(view, request); } diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java index e04d566bdc92..477eefc3565a 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java @@ -11,7 +11,6 @@ import android.view.View; import android.view.inputmethod.InputMethodManager; import android.webkit.WebView; -import androidx.annotation.Nullable; /** * A WebView subclass that mirrors the same implementation hacks that the system WebView does in @@ -27,14 +26,14 @@ final class InputAwareWebView extends WebView { private static final String TAG = "InputAwareWebView"; private View threadedInputConnectionProxyView; private ThreadedInputConnectionProxyAdapterView proxyAdapterView; - private @Nullable View containerView; + private View containerView; - InputAwareWebView(Context context, @Nullable View containerView) { + InputAwareWebView(Context context, View containerView) { super(context); this.containerView = containerView; } - void setContainerView(@Nullable View containerView) { + void setContainerView(View containerView) { this.containerView = containerView; if (proxyAdapterView == null) { diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFactory.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFactory.java index fe62e3a35540..6fdc36fbe545 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFactory.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFactory.java @@ -6,7 +6,6 @@ import android.content.Context; import android.view.View; -import androidx.annotation.Nullable; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.StandardMessageCodec; import io.flutter.plugin.platform.PlatformView; @@ -15,9 +14,9 @@ public final class WebViewFactory extends PlatformViewFactory { private final BinaryMessenger messenger; - private @Nullable final View containerView; + private final View containerView; - WebViewFactory(BinaryMessenger messenger, @Nullable View containerView) { + WebViewFactory(BinaryMessenger messenger, View containerView) { super(StandardMessageCodec.INSTANCE); this.messenger = messenger; this.containerView = containerView; diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java index 0284f20115f8..3acbe97c5cec 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java @@ -4,8 +4,6 @@ package io.flutter.plugins.webviewflutter; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.PluginRegistry.Registrar; @@ -20,7 +18,7 @@ */ public class WebViewFlutterPlugin implements FlutterPlugin { - private @Nullable FlutterCookieManager flutterCookieManager; + private FlutterCookieManager flutterCookieManager; /** * Add an instance of this to {@link io.flutter.embedding.engine.plugins.PluginRegistry} to @@ -53,7 +51,7 @@ public static void registerWith(Registrar registrar) { } @Override - public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { + public void onAttachedToEngine(FlutterPluginBinding binding) { BinaryMessenger messenger = binding.getFlutterEngine().getDartExecutor(); binding .getFlutterEngine() @@ -65,7 +63,7 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { } @Override - public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + public void onDetachedFromEngine(FlutterPluginBinding binding) { if (flutterCookieManager == null) { return; } From 6e1aeb4452a9c6527b20534c811e1c5f119bccf1 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Thu, 31 Oct 2019 16:45:03 -0700 Subject: [PATCH 4/7] Updated CHANGELOG --- packages/webview_flutter/CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md index 9dab62c83eaf..17a4eb0b0916 100644 --- a/packages/webview_flutter/CHANGELOG.md +++ b/packages/webview_flutter/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.3.15+2 +## 0.3.15+3 * Re-land support for the v2 Android embedding. This correctly sets the minimum SDK to the latest stable and avoid any compile errors. *WARNING:* the V2 @@ -6,6 +6,10 @@ (flutter/flutter@1d4d63a) for text input to work properly on all Android versions. +## 0.3.15+2 + +* Remove AndroidX warnings. + ## 0.3.15+1 * Revert the prior embedding support add since it requires an API that hasn't From d5ed3c5fff5bb337aba780003ea4778d06c8452a Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Thu, 31 Oct 2019 16:53:16 -0700 Subject: [PATCH 5/7] Incremented release version in pubspec. --- packages/webview_flutter/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/pubspec.yaml b/packages/webview_flutter/pubspec.yaml index 0188cd1744ef..4d4df2676f03 100644 --- a/packages/webview_flutter/pubspec.yaml +++ b/packages/webview_flutter/pubspec.yaml @@ -1,6 +1,6 @@ name: webview_flutter description: A Flutter plugin that provides a WebView widget on Android and iOS. -version: 0.3.15+2 +version: 0.3.15+3 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/webview_flutter From 1bba48ba22d54bf777eb330be0ed00cee6f72bef Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Thu, 31 Oct 2019 17:09:12 -0700 Subject: [PATCH 6/7] Formatting --- .../flutter/plugins/webviewflutter/FlutterWebViewClient.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java index 8925fbdc919d..37ec1c992e26 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java @@ -123,8 +123,7 @@ public void onUnhandledKeyEvent(WebView view, KeyEvent event) { private WebViewClientCompat internalCreateWebViewClientCompat() { return new WebViewClientCompat() { @Override - public boolean shouldOverrideUrlLoading( - WebView view, WebResourceRequest request) { + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { return FlutterWebViewClient.this.shouldOverrideUrlLoading(view, request); } From 79069cedf8828433d8a0a4109a52e08ffe9e0ad9 Mon Sep 17 00:00:00 2001 From: Michael Klimushyn Date: Fri, 1 Nov 2019 11:24:52 -0700 Subject: [PATCH 7/7] Remove plugin gradle.properties This can have negative side affects for apps and isn't needed. --- packages/webview_flutter/android/gradle.properties | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 packages/webview_flutter/android/gradle.properties diff --git a/packages/webview_flutter/android/gradle.properties b/packages/webview_flutter/android/gradle.properties deleted file mode 100644 index 08f2b5f91bff..000000000000 --- a/packages/webview_flutter/android/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M -android.enableJetifier=true -android.useAndroidX=true