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..e418ab8ebd00 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 @@ -17,6 +17,7 @@ import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugin.platform.PlatformView; import java.util.Collections; import java.util.List; @@ -33,11 +34,11 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { @SuppressWarnings("unchecked") FlutterWebView( final Context context, - BinaryMessenger messenger, int id, Map params, - final View containerView) { - + PluginRegistry.Registrar registrar) { + BinaryMessenger messenger = registrar.messenger(); + final View containerView = registrar.view(); DisplayListenerProxy displayListenerProxy = new DisplayListenerProxy(); DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); @@ -48,6 +49,11 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { platformThreadHandler = new Handler(context.getMainLooper()); // Allow local storage. webView.getSettings().setDomStorageEnabled(true); + // choose file + webView.getSettings().setAllowFileAccess(true); + final FlutterWebViewChromeClient webViewChromeClient = + new FlutterWebViewChromeClient(registrar); + webView.setWebChromeClient(webViewChromeClient); methodChannel = new MethodChannel(messenger, "plugins.flutter.io/webview_" + id); methodChannel.setMethodCallHandler(this); diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewChromeClient.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewChromeClient.java new file mode 100644 index 000000000000..dae2a9d6f4f0 --- /dev/null +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewChromeClient.java @@ -0,0 +1,209 @@ +package io.flutter.plugins.webviewflutter; + +import static android.app.Activity.RESULT_CANCELED; +import static android.app.Activity.RESULT_OK; + +import android.annotation.TargetApi; +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Build; +import android.os.Message; +import android.view.View; +import android.webkit.ConsoleMessage; +import android.webkit.GeolocationPermissions; +import android.webkit.JsPromptResult; +import android.webkit.JsResult; +import android.webkit.PermissionRequest; +import android.webkit.ValueCallback; +import android.webkit.WebChromeClient; +import android.webkit.WebStorage; +import android.webkit.WebView; +import androidx.annotation.Nullable; +import io.flutter.plugin.common.PluginRegistry; + +public class FlutterWebViewChromeClient extends WebChromeClient + implements PluginRegistry.ActivityResultListener { + private static final int REQUEST_CODE_FILE_CHOOSER = 0x12; + + private ValueCallback filePathCallback; + + private PluginRegistry.Registrar registrar; + + public FlutterWebViewChromeClient(PluginRegistry.Registrar registrar) { + super(); + this.registrar = registrar; + registrar.addActivityResultListener(this); + } + + @Override + public void onProgressChanged(WebView view, int newProgress) { + super.onProgressChanged(view, newProgress); + } + + @Override + public void onReceivedTitle(WebView view, String title) { + super.onReceivedTitle(view, title); + } + + @Override + public void onReceivedIcon(WebView view, Bitmap icon) { + super.onReceivedIcon(view, icon); + } + + @Override + public void onReceivedTouchIconUrl(WebView view, String url, boolean precomposed) { + super.onReceivedTouchIconUrl(view, url, precomposed); + } + + @Override + public void onShowCustomView(View view, CustomViewCallback callback) { + super.onShowCustomView(view, callback); + } + + @Override + public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) { + super.onShowCustomView(view, requestedOrientation, callback); + } + + @Override + public void onHideCustomView() { + super.onHideCustomView(); + } + + @Override + public boolean onCreateWindow( + WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { + return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg); + } + + @Override + public void onRequestFocus(WebView view) { + super.onRequestFocus(view); + } + + @Override + public void onCloseWindow(WebView window) { + super.onCloseWindow(window); + } + + @Override + public boolean onJsAlert(WebView view, String url, String message, JsResult result) { + return super.onJsAlert(view, url, message, result); + } + + @Override + public boolean onJsConfirm(WebView view, String url, String message, JsResult result) { + return super.onJsConfirm(view, url, message, result); + } + + @Override + public boolean onJsPrompt( + WebView view, String url, String message, String defaultValue, JsPromptResult result) { + return super.onJsPrompt(view, url, message, defaultValue, result); + } + + @Override + public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result) { + return super.onJsBeforeUnload(view, url, message, result); + } + + @Override + public void onExceededDatabaseQuota( + String url, + String databaseIdentifier, + long quota, + long estimatedDatabaseSize, + long totalQuota, + WebStorage.QuotaUpdater quotaUpdater) { + super.onExceededDatabaseQuota( + url, databaseIdentifier, quota, estimatedDatabaseSize, totalQuota, quotaUpdater); + } + + @Override + public void onReachedMaxAppCacheSize( + long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater) { + super.onReachedMaxAppCacheSize(requiredStorage, quota, quotaUpdater); + } + + @Override + public void onGeolocationPermissionsShowPrompt( + String origin, GeolocationPermissions.Callback callback) { + super.onGeolocationPermissionsShowPrompt(origin, callback); + } + + @Override + public void onGeolocationPermissionsHidePrompt() { + super.onGeolocationPermissionsHidePrompt(); + } + + @Override + public void onPermissionRequest(PermissionRequest request) { + super.onPermissionRequest(request); + } + + @Override + public void onPermissionRequestCanceled(PermissionRequest request) { + super.onPermissionRequestCanceled(request); + } + + @Override + public boolean onJsTimeout() { + return super.onJsTimeout(); + } + + @Override + public void onConsoleMessage(String message, int lineNumber, String sourceID) { + super.onConsoleMessage(message, lineNumber, sourceID); + } + + @Override + public boolean onConsoleMessage(ConsoleMessage consoleMessage) { + return super.onConsoleMessage(consoleMessage); + } + + @Nullable + @Override + public Bitmap getDefaultVideoPoster() { + return super.getDefaultVideoPoster(); + } + + @Nullable + @Override + public View getVideoLoadingProgressView() { + return super.getVideoLoadingProgressView(); + } + + @Override + public void getVisitedHistory(ValueCallback callback) { + super.getVisitedHistory(callback); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public boolean onShowFileChooser( + WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) { + this.filePathCallback = filePathCallback; + Intent intent = fileChooserParams.createIntent(); + intent.addCategory(Intent.CATEGORY_OPENABLE); + try { + registrar.activity().startActivityForResult(intent, REQUEST_CODE_FILE_CHOOSER); + } catch (ActivityNotFoundException e) { + e.printStackTrace(); + return false; + } + return true; + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public boolean onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == REQUEST_CODE_FILE_CHOOSER + && (resultCode == RESULT_OK || resultCode == RESULT_CANCELED)) { + filePathCallback.onReceiveValue( + WebChromeClient.FileChooserParams.parseResult(resultCode, data)); + } + return false; + } +} 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..8b60ecf31ed0 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 @@ -5,27 +5,24 @@ package io.flutter.plugins.webviewflutter; import android.content.Context; -import android.view.View; -import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugin.common.StandardMessageCodec; import io.flutter.plugin.platform.PlatformView; import io.flutter.plugin.platform.PlatformViewFactory; import java.util.Map; public final class WebViewFactory extends PlatformViewFactory { - private final BinaryMessenger messenger; - private final View containerView; + private final PluginRegistry.Registrar registrar; - WebViewFactory(BinaryMessenger messenger, View containerView) { + WebViewFactory(PluginRegistry.Registrar registrar) { super(StandardMessageCodec.INSTANCE); - this.messenger = messenger; - this.containerView = containerView; + this.registrar = registrar; } @SuppressWarnings("unchecked") @Override public PlatformView create(Context context, int id, Object args) { Map params = (Map) args; - return new FlutterWebView(context, messenger, id, params, containerView); + return new FlutterWebView(context, id, params, registrar); } } 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..bea232d4d817 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 @@ -12,9 +12,7 @@ public class WebViewFlutterPlugin { public static void registerWith(Registrar registrar) { registrar .platformViewRegistry() - .registerViewFactory( - "plugins.flutter.io/webview", - new WebViewFactory(registrar.messenger(), registrar.view())); + .registerViewFactory("plugins.flutter.io/webview", new WebViewFactory(registrar)); FlutterCookieManager.registerWith(registrar.messenger()); } }