From 3c4bbd604e317b88a29ddeb8293c362e6c97e957 Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Thu, 27 Aug 2020 16:41:40 +0200 Subject: [PATCH] Added Android Hybrid Composition support, fix #218 --- CHANGELOG.md | 5 +++++ README.md | 10 ++++++---- .../InAppWebView/InAppWebViewClient.java | 15 ++++++++++++--- example/.flutter-plugins-dependencies | 2 +- example/ios/Flutter/flutter_export_environment.sh | 4 ++++ example/lib/in_app_webiew_example.screen.dart | 10 ++++++++-- lib/src/in_app_webview.dart | 2 +- lib/src/webview_options.dart | 6 ++++-- pubspec.yaml | 2 +- 9 files changed, 42 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1827bf2f..1a7e85cf 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 5.0.0 + +- Added Android Hybrid Composition support "Use PlatformViewLink widget for Android WebView" [#462](https://github.com/pichillilorenzo/flutter_inappwebview/pull/462) (thanks to [plateaukao](https://github.com/plateaukao) and [tneotia](https://github.com/tneotia)) +- Fixed `window.flutter_inappwebview.callHandler is not a function` [#218](https://github.com/pichillilorenzo/flutter_inappwebview/issues/218) + ## 4.0.0+4 - Reverted calling `handler.post` on Android when a WebView is created diff --git a/README.md b/README.md index 18c3f425..d398a02e 100755 --- a/README.md +++ b/README.md @@ -68,7 +68,8 @@ as mentioned in the 6th step of [Full-Flutter app migration](https://github.com/ Because of [Flutter AndroidX compatibility](https://flutter.dev/docs/development/packages-and-plugins/androidx-compatibility), the latest version that doesn't use `AndroidX` is `0.6.0`. -Also, note that to use the `InAppWebView` widget on Android, it requires **Android API 20+** (see [AndroidView](https://api.flutter.dev/flutter/widgets/AndroidView-class.html)). +Also, note that to use the `InAppWebView` widget on Android, it requires **Android API 20+** (see [AndroidView](https://api.flutter.dev/flutter/widgets/AndroidView-class.html)) +or **Android API 19+** if you enable the `useHybridComposition` Android-specific option. **Support HTTP request**: Starting with Android 9 (API level 28), cleartext support is disabled by default: - Check the official [Network security configuration - "Opt out of cleartext traffic"](https://developer.android.com/training/articles/security-config#CleartextTrafficPermitted) section. @@ -181,7 +182,7 @@ First, add `flutter_inappwebview` as a [dependency in your pubspec.yaml file](ht ## Usage Classes: -- [InAppWebView](#inappwebview-class): Flutter Widget for adding an **inline native WebView** integrated into the flutter widget tree. To use `InAppWebView` class on iOS you need to opt-in for the embedded views preview by adding a boolean property to the app's `Info.plist` file, with the key `io.flutter.embedded_views_preview` and the value `YES`. Also, note that on Android it requires **Android API 20+** (see [AndroidView](https://api.flutter.dev/flutter/widgets/AndroidView-class.html)). +- [InAppWebView](#inappwebview-class): Flutter Widget for adding an **inline native WebView** integrated into the flutter widget tree. To use `InAppWebView` class on iOS you need to opt-in for the embedded views preview by adding a boolean property to the app's `Info.plist` file, with the key `io.flutter.embedded_views_preview` and the value `YES`. Also, note that on Android it requires **Android API 20+** (see [AndroidView](https://api.flutter.dev/flutter/widgets/AndroidView-class.html)) or **Android API 19+** if you enable the `useHybridComposition` Android-specific option. - [ContextMenu](#contextmenu-class): This class represents the WebView context menu. - [HeadlessInAppWebView](#headlessinappwebview-class): Class that represents a WebView in headless mode. It can be used to run a WebView in background without attaching an `InAppWebView` to the widget tree. - [InAppBrowser](#inappbrowser-class): In-App Browser using native WebView. @@ -233,7 +234,8 @@ Keyboard support within webviews is also experimental. To use `InAppWebView` class on iOS you need to opt-in for the embedded views preview by adding a boolean property to the app's `Info.plist` file, with the key `io.flutter.embedded_views_preview` and the value `YES`. -Also, note that on Android it requires **Android API 20+** (see [AndroidView](https://api.flutter.dev/flutter/widgets/AndroidView-class.html)). +Also, note that on Android it requires **Android API 20+** (see [AndroidView](https://api.flutter.dev/flutter/widgets/AndroidView-class.html)) +or **Android API 19+** if you enable the `useHybridComposition` Android-specific option. Use `InAppWebViewController` to control the WebView instance. Example: @@ -545,7 +547,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly: ##### `InAppWebView` Android-specific options -* `useHybridComposition`: Set to `true` to use Flutter's new Hybrid Composition rendering method, which fixes all issues [here](https://github.com/flutter/flutter/issues/61133). The default value is `false`. Note that this option requires Flutter v1.20+ and should only be used on Android 10+ for release apps, as animations will drop frames on < Android 10. +* `useHybridComposition`: Set to `true` to use Flutter's new Hybrid Composition rendering method, which fixes all issues [here](https://github.com/flutter/flutter/issues/61133). The default value is `false`. Note that this option requires Flutter v1.20+ and should only be used on Android 10+ for release apps, as animations will drop frames on < Android 10 (see [Hybrid-Composition#performance](https://github.com/flutter/flutter/wiki/Hybrid-Composition#performance)). * `useShouldInterceptRequest`: Set to `true` to be able to listen at the `androidShouldInterceptRequest` event. The default value is `false`. * `useOnRenderProcessGone`: Set to `true` to be able to listen at the `androidOnRenderProcessGone` event. The default value is `false`. * `textZoom`: Sets the text zoom of the page in percent. The default value is `100`. diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java index 324220d7..f9507809 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java @@ -162,9 +162,7 @@ public class InAppWebViewClient extends WebViewClient { }); } - @Override - public void onPageStarted(WebView view, String url, Bitmap favicon) { - + private void loadCustomJavaScript(WebView view) { InAppWebView webView = (InAppWebView) view; String js = InAppWebView.consoleLogJS.replaceAll("[\r\n]+", ""); @@ -192,6 +190,14 @@ public class InAppWebViewClient extends WebViewClient { } else { webView.loadUrl("javascript:" + js); } + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + + InAppWebView webView = (InAppWebView) view; + + loadCustomJavaScript(webView); super.onPageStarted(view, url, favicon); @@ -211,6 +217,9 @@ public class InAppWebViewClient extends WebViewClient { public void onPageFinished(WebView view, String url) { final InAppWebView webView = (InAppWebView) view; + // try to reload custom javascript if they were not loaded during the onPageStarted event + loadCustomJavaScript(webView); + super.onPageFinished(view, url); webView.isLoading = false; diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies index 15f8cb9c..39aabb31 100755 --- a/example/.flutter-plugins-dependencies +++ b/example/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.11/","dependencies":[]}],"android":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.11/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+7/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+1/","dependencies":[]}],"windows":[],"web":[{"name":"url_launcher_web","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-0.1.2/","dependencies":[]}]},"dependencyGraph":[{"name":"e2e","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_web","url_launcher_macos"]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]}],"date_created":"2020-08-04 10:25:55.458926","version":"1.17.5"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.11/","dependencies":[]}],"android":[{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.11/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+7/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+1/","dependencies":[]}],"windows":[],"web":[{"name":"url_launcher_web","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-0.1.2/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_inappwebview","dependencies":[]},{"name":"e2e","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_web","url_launcher_macos"]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]}],"date_created":"2020-08-27 16:35:52.128453","version":"1.20.2"} \ No newline at end of file diff --git a/example/ios/Flutter/flutter_export_environment.sh b/example/ios/Flutter/flutter_export_environment.sh index 4882a9e9..10c6e0c2 100755 --- a/example/ios/Flutter/flutter_export_environment.sh +++ b/example/ios/Flutter/flutter_export_environment.sh @@ -9,3 +9,7 @@ export "OTHER_LDFLAGS=$(inherited) -framework Flutter" export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=false" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.packages" diff --git a/example/lib/in_app_webiew_example.screen.dart b/example/lib/in_app_webiew_example.screen.dart index 29c68a75..1dc03d5d 100755 --- a/example/lib/in_app_webiew_example.screen.dart +++ b/example/lib/in_app_webiew_example.screen.dart @@ -80,7 +80,7 @@ class _InAppWebViewExampleScreenState extends State { decoration: BoxDecoration(border: Border.all(color: Colors.blueAccent)), child: InAppWebView( - contextMenu: contextMenu, + // contextMenu: contextMenu, initialUrl: "https://github.com/flutter", // initialFile: "assets/index.html", initialHeaders: {}, @@ -89,6 +89,9 @@ class _InAppWebViewExampleScreenState extends State { debuggingEnabled: true, useShouldOverrideUrlLoading: true, ), + android: AndroidInAppWebViewOptions( + useHybridComposition: true + ) ), onWebViewCreated: (InAppWebViewController controller) { webView = controller; @@ -135,7 +138,10 @@ class _InAppWebViewExampleScreenState extends State { setState(() { this.url = url; }); - } + }, + onConsoleMessage: (controller, consoleMessage) { + print(consoleMessage); + }, ), ), ), diff --git a/lib/src/in_app_webview.dart b/lib/src/in_app_webview.dart index f211b3f6..d9fbbebf 100755 --- a/lib/src/in_app_webview.dart +++ b/lib/src/in_app_webview.dart @@ -340,7 +340,7 @@ class _InAppWebViewState extends State { @override Widget build(BuildContext context) { if (defaultTargetPlatform == TargetPlatform.android) { - if (widget.initialOptions.android.useHybridComposition) { + if (widget.initialOptions?.android?.useHybridComposition ?? false) { return PlatformViewLink( viewType: 'com.pichillilorenzo/flutter_inappwebview', surfaceFactory: ( diff --git a/lib/src/webview_options.dart b/lib/src/webview_options.dart index 046f9908..b467e3e7 100755 --- a/lib/src/webview_options.dart +++ b/lib/src/webview_options.dart @@ -471,8 +471,10 @@ class AndroidInAppWebViewOptions String regexToCancelSubFramesLoading; ///Set to `true` to enable Flutter's new Hybrid Composition. The default value is `false`. - ///Hybrid Composition is supported starting with Flutter v1.20. - ///**NOTE**: It is recommended to use Hybrid Composition only on Android 10+ for a release app, as it can cause framerate drops on animations in Android 9 and lower. + ///Hybrid Composition is supported starting with Flutter v1.20+. + /// + ///**NOTE**: It is recommended to use Hybrid Composition only on Android 10+ for a release app, + ///as it can cause framerate drops on animations in Android 9 and lower (see [Hybrid-Composition#performance](https://github.com/flutter/flutter/wiki/Hybrid-Composition#performance)). bool useHybridComposition; ///Set to `true` to be able to listen at the [WebView.androidShouldInterceptRequest] event. The default value is `false`. diff --git a/pubspec.yaml b/pubspec.yaml index 0cac4754..88111d5a 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_inappwebview description: A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window. -version: 4.0.0+4 +version: 5.0.0 homepage: https://github.com/pichillilorenzo/flutter_inappwebview environment: