[webview_flutter] Create WebView client depending on version and hasDelegate (#1360)
diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md
index 813ab33..81801b8 100644
--- a/packages/webview_flutter/CHANGELOG.md
+++ b/packages/webview_flutter/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.3.5+2
+
+* Fix crash from `NavigationDelegate` on later versions of Android.
+
## 0.3.5+1
* Fix a bug where updates to onPageFinished were ignored.
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 070ba74..9db7d5e 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
@@ -10,6 +10,7 @@
import android.view.View;
import android.webkit.WebStorage;
import android.webkit.WebView;
+import android.webkit.WebViewClient;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
@@ -41,8 +42,6 @@
registerJavaScriptChannelNames((List<String>) params.get(JS_CHANNEL_NAMES_FIELD));
}
- webView.setWebViewClient(flutterWebViewClient);
-
if (params.containsKey("initialUrl")) {
String url = (String) params.get("initialUrl");
webView.loadUrl(url);
@@ -186,7 +185,12 @@
updateJsMode((Integer) settings.get(key));
break;
case "hasNavigationDelegate":
- flutterWebViewClient.setHasNavigationDelegate((boolean) settings.get(key));
+ final boolean hasNavigationDelegate = (boolean) settings.get(key);
+
+ final WebViewClient webViewClient =
+ flutterWebViewClient.createWebViewClient(hasNavigationDelegate);
+
+ webView.setWebViewClient(webViewClient);
break;
default:
throw new IllegalArgumentException("Unknown WebView setting: " + key);
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 fef2258..e7b10ce 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
@@ -9,6 +9,8 @@
import android.util.Log;
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;
@@ -18,7 +20,7 @@
// shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
// invoked by the webview on older Android devices, without it pages that use iframes will
// be broken when a navigationDelegate is set on Android version earlier than N.
-class FlutterWebViewClient extends WebViewClientCompat {
+class FlutterWebViewClient {
private static final String TAG = "FlutterWebViewClient";
private final MethodChannel methodChannel;
private boolean hasNavigationDelegate;
@@ -27,13 +29,8 @@
this.methodChannel = methodChannel;
}
- void setHasNavigationDelegate(boolean hasNavigationDelegate) {
- this.hasNavigationDelegate = hasNavigationDelegate;
- }
-
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
+ private boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
if (!hasNavigationDelegate) {
return false;
}
@@ -53,8 +50,7 @@
return request.isForMainFrame();
}
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ private boolean shouldOverrideUrlLoading(WebView view, String url) {
if (!hasNavigationDelegate) {
return false;
}
@@ -70,8 +66,7 @@
return true;
}
- @Override
- public void onPageFinished(WebView view, String url) {
+ private void onPageFinished(WebView view, String url) {
Map<String, Object> args = new HashMap<>();
args.put("url", url);
methodChannel.invokeMethod("onPageFinished", args);
@@ -90,6 +85,54 @@
}
}
+ // This method attempts to avoid using WebViewClientCompat due to bug
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=925887. Also, see
+ // https://github.com/flutter/flutter/issues/29446.
+ WebViewClient createWebViewClient(boolean hasNavigationDelegate) {
+ this.hasNavigationDelegate = hasNavigationDelegate;
+
+ if (!hasNavigationDelegate || android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ return internalCreateWebViewClient();
+ }
+
+ return internalCreateWebViewClientCompat();
+ }
+
+ private WebViewClient internalCreateWebViewClient() {
+ return new WebViewClient() {
+ @TargetApi(Build.VERSION_CODES.N)
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
+ return FlutterWebViewClient.this.shouldOverrideUrlLoading(view, request);
+ }
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ FlutterWebViewClient.this.onPageFinished(view, url);
+ }
+ };
+ }
+
+ private WebViewClientCompat internalCreateWebViewClientCompat() {
+ return new WebViewClientCompat() {
+ @Override
+ public boolean shouldOverrideUrlLoading(
+ @NonNull WebView view, @NonNull WebResourceRequest request) {
+ return FlutterWebViewClient.this.shouldOverrideUrlLoading(view, request);
+ }
+
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ return FlutterWebViewClient.this.shouldOverrideUrlLoading(view, url);
+ }
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ FlutterWebViewClient.this.onPageFinished(view, url);
+ }
+ };
+ }
+
private static class OnNavigationRequestResult implements MethodChannel.Result {
private final String url;
private final Map<String, String> headers;
diff --git a/packages/webview_flutter/pubspec.yaml b/packages/webview_flutter/pubspec.yaml
index e21da55..bf707a8 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.5+1
+version: 0.3.5+2
author: Flutter Team <flutter-dev@googlegroups.com>
homepage: https://github.com/flutter/plugins/tree/master/packages/webview_flutter