fix #732, fix #759, Fixed Android ChromeSafariBrowser menu item callback not called because of PendingIntents extra were cached

This commit is contained in:
Lorenzo Pichilli 2021-03-28 04:17:09 +02:00
parent a0e3bc2de7
commit 71a8fe23ea
36 changed files with 411 additions and 290 deletions

View File

@ -1,8 +1,6 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Flutter Plugins"> <library name="Flutter Plugins">
<CLASSES> <CLASSES />
<root url="file://$PROJECT_DIR$" />
</CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES /> <SOURCES />
</library> </library>

View File

@ -7,6 +7,9 @@
- Removed `final` keyword for all `HeadlessInAppWebView` events - Removed `final` keyword for all `HeadlessInAppWebView` events
- Fixed wrong usage of Android WebView scale property - Fixed wrong usage of Android WebView scale property
- Fixed "java.lang.NullPointerException: com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebViewRenderProcessClient$1.success(InAppWebViewRenderProcessClient.java:37)" [#757](https://github.com/pichillilorenzo/flutter_inappwebview/issues/757) - Fixed "java.lang.NullPointerException: com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebViewRenderProcessClient$1.success(InAppWebViewRenderProcessClient.java:37)" [#757](https://github.com/pichillilorenzo/flutter_inappwebview/issues/757)
- Fixed "In a multi-activity app, the plugin doesn't reattach to the first activity" [#732](https://github.com/pichillilorenzo/flutter_inappwebview/issues/732)
- Fixed "ChromeSafariBrowser isn't calling its events, and not keeping track of isOpen properly" [#759](https://github.com/pichillilorenzo/flutter_inappwebview/issues/759)
- Fixed Android ChromeSafariBrowser menu item callback not called because of PendingIntents extra were cached
## 5.2.1+1 ## 5.2.1+1

View File

@ -24,64 +24,76 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
protected static final String LOG_TAG = "InAppWebViewFlutterPL"; protected static final String LOG_TAG = "InAppWebViewFlutterPL";
public static PlatformUtil platformUtil; public PlatformUtil platformUtil;
public static InAppBrowserManager inAppBrowserManager; public InAppBrowserManager inAppBrowserManager;
public static HeadlessInAppWebViewManager headlessInAppWebViewManager; public HeadlessInAppWebViewManager headlessInAppWebViewManager;
public static ChromeSafariBrowserManager chromeSafariBrowserManager; public ChromeSafariBrowserManager chromeSafariBrowserManager;
public static InAppWebViewStatic inAppWebViewStatic; public InAppWebViewStatic inAppWebViewStatic;
public static MyCookieManager myCookieManager; public MyCookieManager myCookieManager;
public static CredentialDatabaseHandler credentialDatabaseHandler; public CredentialDatabaseHandler credentialDatabaseHandler;
public static MyWebStorage myWebStorage; public MyWebStorage myWebStorage;
public static ServiceWorkerManager serviceWorkerManager; public ServiceWorkerManager serviceWorkerManager;
public static WebViewFeatureManager webViewFeatureManager; public WebViewFeatureManager webViewFeatureManager;
public FlutterWebViewFactory flutterWebViewFactory;
public static ValueCallback<Uri> filePathCallbackLegacy; public static ValueCallback<Uri> filePathCallbackLegacy;
public static ValueCallback<Uri[]> filePathCallback; public static ValueCallback<Uri[]> filePathCallback;
public Context applicationContext;
public PluginRegistry.Registrar registrar;
public BinaryMessenger messenger;
public FlutterPlugin.FlutterAssets flutterAssets;
public ActivityPluginBinding activityPluginBinding;
public Activity activity;
@SuppressWarnings("deprecation")
public FlutterView flutterView;
public InAppWebViewFlutterPlugin() {} public InAppWebViewFlutterPlugin() {}
@SuppressWarnings("deprecation")
public static void registerWith(PluginRegistry.Registrar registrar) { public static void registerWith(PluginRegistry.Registrar registrar) {
final InAppWebViewFlutterPlugin instance = new InAppWebViewFlutterPlugin(); final InAppWebViewFlutterPlugin instance = new InAppWebViewFlutterPlugin();
Shared.registrar = registrar; instance.registrar = registrar;
instance.onAttachedToEngine( instance.onAttachedToEngine(
registrar.context(), registrar.messenger(), registrar.activity(), registrar.platformViewRegistry(), registrar.view()); registrar.context(), registrar.messenger(), registrar.activity(), registrar.platformViewRegistry(), registrar.view());
} }
@Override @Override
public void onAttachedToEngine(FlutterPluginBinding binding) { public void onAttachedToEngine(FlutterPluginBinding binding) {
Shared.flutterAssets = binding.getFlutterAssets(); this.flutterAssets = binding.getFlutterAssets();
// Shared.activity could be null or not. // Shared.activity could be null or not.
// It depends on who is called first between onAttachedToEngine event and onAttachedToActivity event. // It depends on who is called first between onAttachedToEngine event and onAttachedToActivity event.
// //
// See https://github.com/pichillilorenzo/flutter_inappwebview/issues/390#issuecomment-647039084 // See https://github.com/pichillilorenzo/flutter_inappwebview/issues/390#issuecomment-647039084
onAttachedToEngine( onAttachedToEngine(
binding.getApplicationContext(), binding.getBinaryMessenger(), Shared.activity, binding.getPlatformViewRegistry(), null); binding.getApplicationContext(), binding.getBinaryMessenger(), this.activity, binding.getPlatformViewRegistry(), null);
} }
@SuppressWarnings("deprecation")
private void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger, Activity activity, PlatformViewRegistry platformViewRegistry, FlutterView flutterView) { private void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger, Activity activity, PlatformViewRegistry platformViewRegistry, FlutterView flutterView) {
this.applicationContext = applicationContext;
this.activity = activity;
this.messenger = messenger;
this.flutterView = flutterView;
Shared.applicationContext = applicationContext; inAppBrowserManager = new InAppBrowserManager(this);
Shared.activity = activity; headlessInAppWebViewManager = new HeadlessInAppWebViewManager(this);
Shared.messenger = messenger; chromeSafariBrowserManager = new ChromeSafariBrowserManager(this);
flutterWebViewFactory = new FlutterWebViewFactory(this);
inAppBrowserManager = new InAppBrowserManager(messenger);
headlessInAppWebViewManager = new HeadlessInAppWebViewManager(messenger);
chromeSafariBrowserManager = new ChromeSafariBrowserManager(messenger);
platformViewRegistry.registerViewFactory( platformViewRegistry.registerViewFactory(
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(messenger, flutterView)); "com.pichillilorenzo/flutter_inappwebview", flutterWebViewFactory);
platformUtil = new PlatformUtil(messenger); platformUtil = new PlatformUtil(this);
inAppWebViewStatic = new InAppWebViewStatic(messenger); inAppWebViewStatic = new InAppWebViewStatic(this);
myCookieManager = new MyCookieManager(messenger); myCookieManager = new MyCookieManager(this);
myWebStorage = new MyWebStorage(messenger); myWebStorage = new MyWebStorage(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
serviceWorkerManager = new ServiceWorkerManager(messenger); serviceWorkerManager = new ServiceWorkerManager(this);
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
credentialDatabaseHandler = new CredentialDatabaseHandler(messenger); credentialDatabaseHandler = new CredentialDatabaseHandler(this);
} }
webViewFeatureManager = new WebViewFeatureManager(messenger); webViewFeatureManager = new WebViewFeatureManager(this);
} }
@Override @Override
@ -132,25 +144,25 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
@Override @Override
public void onAttachedToActivity(ActivityPluginBinding activityPluginBinding) { public void onAttachedToActivity(ActivityPluginBinding activityPluginBinding) {
Shared.activityPluginBinding = activityPluginBinding; this.activityPluginBinding = activityPluginBinding;
Shared.activity = activityPluginBinding.getActivity(); this.activity = activityPluginBinding.getActivity();
} }
@Override @Override
public void onDetachedFromActivityForConfigChanges() { public void onDetachedFromActivityForConfigChanges() {
Shared.activityPluginBinding = null; this.activityPluginBinding = null;
Shared.activity = null; this.activity = null;
} }
@Override @Override
public void onReattachedToActivityForConfigChanges(ActivityPluginBinding activityPluginBinding) { public void onReattachedToActivityForConfigChanges(ActivityPluginBinding activityPluginBinding) {
Shared.activityPluginBinding = activityPluginBinding; this.activityPluginBinding = activityPluginBinding;
Shared.activity = activityPluginBinding.getActivity(); this.activity = activityPluginBinding.getActivity();
} }
@Override @Override
public void onDetachedFromActivity() { public void onDetachedFromActivity() {
Shared.activityPluginBinding = null; this.activityPluginBinding = null;
Shared.activity = null; this.activity = null;
} }
} }

View File

@ -548,7 +548,7 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
case "addWebMessageListener": case "addWebMessageListener":
if (webView != null && WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) { if (webView != null && WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
Map<String, Object> webMessageListenerMap = (Map<String, Object>) call.argument("webMessageListener"); Map<String, Object> webMessageListenerMap = (Map<String, Object>) call.argument("webMessageListener");
WebMessageListener webMessageListener = WebMessageListener.fromMap(webMessageListenerMap); WebMessageListener webMessageListener = WebMessageListener.fromMap(webView.plugin.messenger, webMessageListenerMap);
try { try {
webView.addWebMessageListener(webMessageListener); webView.addWebMessageListener(webMessageListener);
result.success(true); result.success(true);

View File

@ -1,12 +1,12 @@
package com.pichillilorenzo.flutter_inappwebview; package com.pichillilorenzo.flutter_inappwebview;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build; import android.os.Build;
import android.webkit.ValueCallback; import android.webkit.ValueCallback;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import android.webkit.WebView; import android.webkit.WebView;
import androidx.annotation.Nullable;
import androidx.webkit.WebViewCompat; import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewFeature; import androidx.webkit.WebViewFeature;
@ -17,17 +17,19 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
public class InAppWebViewStatic implements MethodChannel.MethodCallHandler { public class InAppWebViewStatic implements MethodChannel.MethodCallHandler {
public MethodChannel channel;
protected static final String LOG_TAG = "InAppWebViewStatic"; protected static final String LOG_TAG = "InAppWebViewStatic";
public MethodChannel channel;
@Nullable
public InAppWebViewFlutterPlugin plugin;
public InAppWebViewStatic(BinaryMessenger messenger) { public InAppWebViewStatic(final InAppWebViewFlutterPlugin plugin) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_static"); this.plugin = plugin;
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_static");
channel.setMethodCallHandler(this); channel.setMethodCallHandler(this);
} }
@ -35,7 +37,7 @@ public class InAppWebViewStatic implements MethodChannel.MethodCallHandler {
public void onMethodCall(MethodCall call, final MethodChannel.Result result) { public void onMethodCall(MethodCall call, final MethodChannel.Result result) {
switch (call.method) { switch (call.method) {
case "getDefaultUserAgent": case "getDefaultUserAgent":
result.success(WebSettings.getDefaultUserAgent(Shared.applicationContext)); result.success(WebSettings.getDefaultUserAgent(plugin.applicationContext));
break; break;
case "clearClientCertPreferences": case "clearClientCertPreferences":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@ -78,7 +80,7 @@ public class InAppWebViewStatic implements MethodChannel.MethodCallHandler {
break; break;
case "getCurrentWebViewPackage": case "getCurrentWebViewPackage":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
result.success(convertWebViewPackageToMap(WebViewCompat.getCurrentWebViewPackage(Shared.activity))); result.success(convertWebViewPackageToMap(WebViewCompat.getCurrentWebViewPackage(plugin.activity)));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//with Android Lollipop (API 21) they started to update the WebView //with Android Lollipop (API 21) they started to update the WebView
//as a separate APK with the PlayStore and they added the //as a separate APK with the PlayStore and they added the
@ -122,5 +124,6 @@ public class InAppWebViewStatic implements MethodChannel.MethodCallHandler {
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
plugin = null;
} }
} }

View File

@ -23,8 +23,7 @@ public class JavaScriptBridgeInterface {
private static final String LOG_TAG = "JSBridgeInterface"; private static final String LOG_TAG = "JSBridgeInterface";
private InAppWebView inAppWebView; private InAppWebView inAppWebView;
private final MethodChannel channel; private final MethodChannel channel;
public JavaScriptBridgeInterface(InAppWebView inAppWebView) { public JavaScriptBridgeInterface(InAppWebView inAppWebView) {
this.inAppWebView = inAppWebView; this.inAppWebView = inAppWebView;
this.channel = this.inAppWebView.channel; this.channel = this.inAppWebView.channel;

View File

@ -16,7 +16,6 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.TimeZone; import java.util.TimeZone;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
@ -24,11 +23,14 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
static final String LOG_TAG = "MyCookieManager"; static final String LOG_TAG = "MyCookieManager";
public static MethodChannel channel; public MethodChannel channel;
public static CookieManager cookieManager; public static CookieManager cookieManager;
@Nullable
public InAppWebViewFlutterPlugin plugin;
public MyCookieManager(BinaryMessenger messenger) { public MyCookieManager(final InAppWebViewFlutterPlugin plugin) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_cookiemanager"); this.plugin = plugin;
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_cookiemanager");
channel.setMethodCallHandler(this); channel.setMethodCallHandler(this);
cookieManager = getCookieManager(); cookieManager = getCookieManager();
} }
@ -49,7 +51,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
Boolean isSecure = (Boolean) call.argument("isSecure"); Boolean isSecure = (Boolean) call.argument("isSecure");
Boolean isHttpOnly = (Boolean) call.argument("isHttpOnly"); Boolean isHttpOnly = (Boolean) call.argument("isHttpOnly");
String sameSite = (String) call.argument("sameSite"); String sameSite = (String) call.argument("sameSite");
MyCookieManager.setCookie(url, setCookie(url,
name, name,
value, value,
domain, domain,
@ -63,7 +65,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
} }
break; break;
case "getCookies": case "getCookies":
result.success(MyCookieManager.getCookies((String) call.argument("url"))); result.success(getCookies((String) call.argument("url")));
break; break;
case "deleteCookie": case "deleteCookie":
{ {
@ -71,7 +73,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
String name = (String) call.argument("name"); String name = (String) call.argument("name");
String domain = (String) call.argument("domain"); String domain = (String) call.argument("domain");
String path = (String) call.argument("path"); String path = (String) call.argument("path");
MyCookieManager.deleteCookie(url, name, domain, path, result); deleteCookie(url, name, domain, path, result);
} }
break; break;
case "deleteCookies": case "deleteCookies":
@ -79,11 +81,11 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
String url = (String) call.argument("url"); String url = (String) call.argument("url");
String domain = (String) call.argument("domain"); String domain = (String) call.argument("domain");
String path = (String) call.argument("path"); String path = (String) call.argument("path");
MyCookieManager.deleteCookies(url, domain, path, result); deleteCookies(url, domain, path, result);
} }
break; break;
case "deleteAllCookies": case "deleteAllCookies":
MyCookieManager.deleteAllCookies(result); deleteAllCookies(result);
break; break;
default: default:
result.notImplemented(); result.notImplemented();
@ -124,7 +126,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
return cookieManager; return cookieManager;
} }
public static void setCookie(String url, public void setCookie(String url,
String name, String name,
String value, String value,
String domain, String domain,
@ -167,7 +169,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
cookieManager.flush(); cookieManager.flush();
} }
else { else {
CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(Shared.applicationContext); CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(plugin.applicationContext);
cookieSyncMngr.startSync(); cookieSyncMngr.startSync();
cookieManager.setCookie(url, cookieValue); cookieManager.setCookie(url, cookieValue);
result.success(true); result.success(true);
@ -176,7 +178,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
} }
} }
public static List<Map<String, Object>> getCookies(final String url) { public List<Map<String, Object>> getCookies(final String url) {
final List<Map<String, Object>> cookieListMap = new ArrayList<>(); final List<Map<String, Object>> cookieListMap = new ArrayList<>();
@ -209,7 +211,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
} }
public static void deleteCookie(String url, String name, String domain, String path, final MethodChannel.Result result) { public void deleteCookie(String url, String name, String domain, String path, final MethodChannel.Result result) {
cookieManager = getCookieManager(); cookieManager = getCookieManager();
if (cookieManager == null) return; if (cookieManager == null) return;
@ -225,7 +227,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
cookieManager.flush(); cookieManager.flush();
} }
else { else {
CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(Shared.applicationContext); CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(plugin.applicationContext);
cookieSyncMngr.startSync(); cookieSyncMngr.startSync();
cookieManager.setCookie(url, cookieValue); cookieManager.setCookie(url, cookieValue);
result.success(true); result.success(true);
@ -234,7 +236,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
} }
} }
public static void deleteCookies(String url, String domain, String path, final MethodChannel.Result result) { public void deleteCookies(String url, String domain, String path, final MethodChannel.Result result) {
cookieManager = getCookieManager(); cookieManager = getCookieManager();
if (cookieManager == null) return; if (cookieManager == null) return;
@ -244,7 +246,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
if (cookiesString != null) { if (cookiesString != null) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
cookieSyncMngr = CookieSyncManager.createInstance(Shared.applicationContext); cookieSyncMngr = CookieSyncManager.createInstance(plugin.applicationContext);
cookieSyncMngr.startSync(); cookieSyncMngr.startSync();
} }
@ -268,7 +270,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
result.success(true); result.success(true);
} }
public static void deleteAllCookies(final MethodChannel.Result result) { public void deleteAllCookies(final MethodChannel.Result result) {
cookieManager = getCookieManager(); cookieManager = getCookieManager();
if (cookieManager == null) return; if (cookieManager == null) return;
@ -282,7 +284,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
cookieManager.flush(); cookieManager.flush();
} }
else { else {
CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(Shared.applicationContext); CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(plugin.applicationContext);
cookieSyncMngr.startSync(); cookieSyncMngr.startSync();
cookieManager.removeAllCookie(); cookieManager.removeAllCookie();
result.success(true); result.success(true);
@ -299,5 +301,6 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
plugin = null;
} }
} }

View File

@ -1,15 +1,15 @@
package com.pichillilorenzo.flutter_inappwebview; package com.pichillilorenzo.flutter_inappwebview;
import android.util.Log;
import android.webkit.ValueCallback; import android.webkit.ValueCallback;
import android.webkit.WebStorage; import android.webkit.WebStorage;
import androidx.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
@ -17,11 +17,14 @@ public class MyWebStorage implements MethodChannel.MethodCallHandler {
static final String LOG_TAG = "MyWebStorage"; static final String LOG_TAG = "MyWebStorage";
public static MethodChannel channel; public MethodChannel channel;
public static WebStorage webStorageManager; public static WebStorage webStorageManager;
@Nullable
public InAppWebViewFlutterPlugin plugin;
public MyWebStorage(BinaryMessenger messenger) { public MyWebStorage(final InAppWebViewFlutterPlugin plugin) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_webstoragemanager"); this.plugin = plugin;
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_webstoragemanager");
channel.setMethodCallHandler(this); channel.setMethodCallHandler(this);
webStorageManager = WebStorage.getInstance(); webStorageManager = WebStorage.getInstance();
} }
@ -100,5 +103,6 @@ public class MyWebStorage implements MethodChannel.MethodCallHandler {
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
plugin = null;
} }
} }

View File

@ -14,12 +14,15 @@ import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
public class PlatformUtil implements MethodChannel.MethodCallHandler { public class PlatformUtil implements MethodChannel.MethodCallHandler {
public MethodChannel channel;
protected static final String LOG_TAG = "PlatformUtil"; protected static final String LOG_TAG = "PlatformUtil";
public MethodChannel channel;
@Nullable
public InAppWebViewFlutterPlugin plugin;
public PlatformUtil(BinaryMessenger messenger) { public PlatformUtil(final InAppWebViewFlutterPlugin plugin) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_platformutil"); this.plugin = plugin;
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_platformutil");
channel.setMethodCallHandler(this); channel.setMethodCallHandler(this);
} }
@ -63,5 +66,6 @@ public class PlatformUtil implements MethodChannel.MethodCallHandler {
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
plugin = null;
} }
} }

View File

@ -26,12 +26,15 @@ public class ServiceWorkerManager implements MethodChannel.MethodCallHandler {
static final String LOG_TAG = "ServiceWorkerManager"; static final String LOG_TAG = "ServiceWorkerManager";
public static MethodChannel channel; public MethodChannel channel;
@Nullable @Nullable
public static ServiceWorkerControllerCompat serviceWorkerController; public static ServiceWorkerControllerCompat serviceWorkerController;
@Nullable
public InAppWebViewFlutterPlugin plugin;
public ServiceWorkerManager(BinaryMessenger messenger) { public ServiceWorkerManager(final InAppWebViewFlutterPlugin plugin) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_android_serviceworkercontroller"); this.plugin = plugin;
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_android_serviceworkercontroller");
channel.setMethodCallHandler(this); channel.setMethodCallHandler(this);
if (WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_BASIC_USAGE)) { if (WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_BASIC_USAGE)) {
serviceWorkerController = ServiceWorkerControllerCompat.getInstance(); serviceWorkerController = ServiceWorkerControllerCompat.getInstance();
@ -152,5 +155,6 @@ public class ServiceWorkerManager implements MethodChannel.MethodCallHandler {
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
plugin = null;
} }
} }

View File

@ -1,18 +0,0 @@
package com.pichillilorenzo.flutter_inappwebview;
import android.app.Activity;
import android.content.Context;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry;
public class Shared {
public static Context applicationContext;
public static PluginRegistry.Registrar registrar;
public static BinaryMessenger messenger;
public static FlutterPlugin.FlutterAssets flutterAssets;
public static ActivityPluginBinding activityPluginBinding;
public static Activity activity;
}

View File

@ -6,9 +6,7 @@ import android.net.http.SslCertificate;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.os.Parcelable;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@ -16,13 +14,11 @@ import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Serializable;
import java.security.Key; import java.security.Key;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.PrivateKey; import java.security.PrivateKey;
@ -30,7 +26,6 @@ import java.security.cert.Certificate;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -57,13 +52,13 @@ public class Util {
private Util() {} private Util() {}
public static String getUrlAsset(String assetFilePath) throws IOException { public static String getUrlAsset(InAppWebViewFlutterPlugin plugin, String assetFilePath) throws IOException {
String key = (Shared.registrar != null) ? Shared.registrar.lookupKeyForAsset(assetFilePath) : Shared.flutterAssets.getAssetFilePathByName(assetFilePath); String key = (plugin.registrar != null) ? plugin.registrar.lookupKeyForAsset(assetFilePath) : plugin.flutterAssets.getAssetFilePathByName(assetFilePath);
InputStream is = null; InputStream is = null;
IOException e = null; IOException e = null;
try { try {
is = getFileAsset(assetFilePath); is = getFileAsset(plugin, assetFilePath);
} catch (IOException ex) { } catch (IOException ex) {
e = ex; e = ex;
} finally { } finally {
@ -82,9 +77,9 @@ public class Util {
return ANDROID_ASSET_URL + key; return ANDROID_ASSET_URL + key;
} }
public static InputStream getFileAsset(String assetFilePath) throws IOException { public static InputStream getFileAsset(InAppWebViewFlutterPlugin plugin,String assetFilePath) throws IOException {
String key = (Shared.registrar != null) ? Shared.registrar.lookupKeyForAsset(assetFilePath) : Shared.flutterAssets.getAssetFilePathByName(assetFilePath); String key = (plugin.registrar != null) ? plugin.registrar.lookupKeyForAsset(assetFilePath) : plugin.flutterAssets.getAssetFilePathByName(assetFilePath);
AssetManager mg = Shared.applicationContext.getResources().getAssets(); AssetManager mg = plugin.applicationContext.getResources().getAssets();
return mg.open(key); return mg.open(key);
} }
@ -136,12 +131,12 @@ public class Util {
} }
} }
public static PrivateKeyAndCertificates loadPrivateKeyAndCertificate(String certificatePath, String certificatePassword, String keyStoreType) { public static PrivateKeyAndCertificates loadPrivateKeyAndCertificate(InAppWebViewFlutterPlugin plugin, String certificatePath, String certificatePassword, String keyStoreType) {
PrivateKeyAndCertificates privateKeyAndCertificates = null; PrivateKeyAndCertificates privateKeyAndCertificates = null;
try { try {
InputStream certificateFileStream = getFileAsset(certificatePath); InputStream certificateFileStream = getFileAsset(plugin, certificatePath);
KeyStore keyStore = KeyStore.getInstance(keyStoreType); KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(certificateFileStream, certificatePassword != null ? certificatePassword.toCharArray() : null); keyStore.load(certificateFileStream, certificatePassword != null ? certificatePassword.toCharArray() : null);

View File

@ -1,5 +1,6 @@
package com.pichillilorenzo.flutter_inappwebview; package com.pichillilorenzo.flutter_inappwebview;
import androidx.annotation.Nullable;
import androidx.webkit.WebViewFeature; import androidx.webkit.WebViewFeature;
import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.BinaryMessenger;
@ -10,10 +11,13 @@ public class WebViewFeatureManager implements MethodChannel.MethodCallHandler {
static final String LOG_TAG = "WebViewFeatureManager"; static final String LOG_TAG = "WebViewFeatureManager";
public static MethodChannel channel; public MethodChannel channel;
@Nullable
public InAppWebViewFlutterPlugin plugin;
public WebViewFeatureManager(BinaryMessenger messenger) { public WebViewFeatureManager(final InAppWebViewFlutterPlugin plugin) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_android_webviewfeature"); this.plugin = plugin;
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_android_webviewfeature");
channel.setMethodCallHandler(this); channel.setMethodCallHandler(this);
} }
@ -31,5 +35,6 @@ public class WebViewFeatureManager implements MethodChannel.MethodCallHandler {
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
plugin = null;
} }
} }

View File

@ -5,8 +5,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -16,6 +14,7 @@ public class ActionBroadcastReceiver extends BroadcastReceiver {
protected static final String LOG_TAG = "ActionBroadcastReceiver"; protected static final String LOG_TAG = "ActionBroadcastReceiver";
public static final String KEY_ACTION_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_ID"; public static final String KEY_ACTION_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_ID";
public static final String KEY_ACTION_VIEW_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_VIEW_ID"; public static final String KEY_ACTION_VIEW_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_VIEW_ID";
public static final String CHROME_MANAGER_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.CHROME_MANAGER_ID";
public static final String KEY_URL_TITLE = "android.intent.extra.SUBJECT"; public static final String KEY_URL_TITLE = "android.intent.extra.SUBJECT";
@Override @Override
@ -27,7 +26,10 @@ public class ActionBroadcastReceiver extends BroadcastReceiver {
int id = b.getInt(KEY_ACTION_ID); int id = b.getInt(KEY_ACTION_ID);
String title = b.getString(KEY_URL_TITLE); String title = b.getString(KEY_URL_TITLE);
MethodChannel channel = new MethodChannel(Shared.messenger, "com.pichillilorenzo/flutter_chromesafaribrowser_" + viewId); String managerId = b.getString(CHROME_MANAGER_ID);
ChromeSafariBrowserManager manager = (ChromeSafariBrowserManager) ChromeSafariBrowserManager.shared.get(managerId);
MethodChannel channel = new MethodChannel(manager.plugin.messenger, "com.pichillilorenzo/flutter_chromesafaribrowser_" + viewId);
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
obj.put("url", url); obj.put("url", url);
obj.put("title", title); obj.put("title", title);

View File

@ -6,6 +6,7 @@ import android.content.Intent;
import android.graphics.Color; import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import androidx.browser.customtabs.CustomTabsCallback; import androidx.browser.customtabs.CustomTabsCallback;
import androidx.browser.customtabs.CustomTabsIntent; import androidx.browser.customtabs.CustomTabsIntent;
@ -13,7 +14,6 @@ import androidx.browser.customtabs.CustomTabsService;
import androidx.browser.customtabs.CustomTabsSession; import androidx.browser.customtabs.CustomTabsSession;
import com.pichillilorenzo.flutter_inappwebview.R; import com.pichillilorenzo.flutter_inappwebview.R;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -34,6 +34,7 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
protected final int CHROME_CUSTOM_TAB_REQUEST_CODE = 100; protected final int CHROME_CUSTOM_TAB_REQUEST_CODE = 100;
protected boolean onChromeSafariBrowserOpened = false; protected boolean onChromeSafariBrowserOpened = false;
protected boolean onChromeSafariBrowserCompletedInitialLoad = false; protected boolean onChromeSafariBrowserCompletedInitialLoad = false;
public ChromeSafariBrowserManager manager;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -45,7 +46,10 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
assert b != null; assert b != null;
id = b.getString("id"); id = b.getString("id");
channel = new MethodChannel(Shared.messenger, "com.pichillilorenzo/flutter_chromesafaribrowser_" + id); String managerId = b.getString("managerId");
manager = (ChromeSafariBrowserManager) ChromeSafariBrowserManager.shared.get(managerId);
channel = new MethodChannel(manager.plugin.messenger, "com.pichillilorenzo/flutter_chromesafaribrowser_" + id);
channel.setMethodCallHandler(this); channel.setMethodCallHandler(this);
final String url = b.getString("url"); final String url = b.getString("url");
@ -77,6 +81,7 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
@Override @Override
public void onCustomTabsDisconnected() { public void onCustomTabsDisconnected() {
chromeCustomTabsActivity.close(); chromeCustomTabsActivity.close();
dispose();
} }
}); });
@ -128,10 +133,13 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
this.close(); this.close();
// https://stackoverflow.com/a/41596629/4637638 // https://stackoverflow.com/a/41596629/4637638
Intent myIntent = new Intent(Shared.activity, Shared.activity.getClass()); Intent myIntent = new Intent(manager.plugin.activity, manager.plugin.activity.getClass());
myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
myIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); myIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Shared.activity.startActivity(myIntent); manager.plugin.activity.startActivity(myIntent);
dispose();
result.success(true); result.success(true);
break; break;
default: default:
@ -186,25 +194,32 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CHROME_CUSTOM_TAB_REQUEST_CODE) { if (requestCode == CHROME_CUSTOM_TAB_REQUEST_CODE) {
close(); close();
dispose();
} }
} }
public void close() {
customTabsSession = null;
finish();
Map<String, Object> obj = new HashMap<>();
channel.invokeMethod("onChromeSafariBrowserClosed", obj);
}
private PendingIntent createPendingIntent(int actionSourceId) { private PendingIntent createPendingIntent(int actionSourceId) {
Intent actionIntent = new Intent(this, ActionBroadcastReceiver.class); Intent actionIntent = new Intent(this, ActionBroadcastReceiver.class);
Bundle extras = new Bundle(); Bundle extras = new Bundle();
extras.putInt(ActionBroadcastReceiver.KEY_ACTION_ID, actionSourceId); extras.putInt(ActionBroadcastReceiver.KEY_ACTION_ID, actionSourceId);
extras.putString(ActionBroadcastReceiver.KEY_ACTION_VIEW_ID, id); extras.putString(ActionBroadcastReceiver.KEY_ACTION_VIEW_ID, id);
extras.putString(ActionBroadcastReceiver.CHROME_MANAGER_ID, manager.id);
actionIntent.putExtras(extras); actionIntent.putExtras(extras);
return PendingIntent.getBroadcast( return PendingIntent.getBroadcast(
this, actionSourceId, actionIntent, 0); this, actionSourceId, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public void dispose() {
channel.setMethodCallHandler(null);
manager = null;
}
public void close() {
customTabsSession = null;
finish();
Map<String, Object> obj = new HashMap<>();
channel.invokeMethod("onChromeSafariBrowserClosed", obj);
} }
} }

View File

@ -4,30 +4,38 @@ import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import com.pichillilorenzo.flutter_inappwebview.Shared; import androidx.annotation.Nullable;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandler { public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandler {
public MethodChannel channel;
protected static final String LOG_TAG = "ChromeBrowserManager"; protected static final String LOG_TAG = "ChromeBrowserManager";
public MethodChannel channel;
@Nullable
public InAppWebViewFlutterPlugin plugin;
public String id;
public static final Map<String, ChromeSafariBrowserManager> shared = new HashMap<>();
public ChromeSafariBrowserManager(BinaryMessenger messenger) { public ChromeSafariBrowserManager(final InAppWebViewFlutterPlugin plugin) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_chromesafaribrowser"); this.id = UUID.randomUUID().toString();
this.plugin = plugin;
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_chromesafaribrowser");
channel.setMethodCallHandler(this); channel.setMethodCallHandler(this);
shared.put(this.id, this);
} }
@Override @Override
public void onMethodCall(final MethodCall call, final MethodChannel.Result result) { public void onMethodCall(final MethodCall call, final MethodChannel.Result result) {
final Activity activity = Shared.activity;
final String id = (String) call.argument("id"); final String id = (String) call.argument("id");
switch (call.method) { switch (call.method) {
@ -36,11 +44,11 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
String url = (String) call.argument("url"); String url = (String) call.argument("url");
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options"); HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
List<HashMap<String, Object>> menuItemList = (List<HashMap<String, Object>>) call.argument("menuItemList"); List<HashMap<String, Object>> menuItemList = (List<HashMap<String, Object>>) call.argument("menuItemList");
open(activity, id, url, options, menuItemList, result); open(plugin.activity, id, url, options, menuItemList, result);
} }
break; break;
case "isAvailable": case "isAvailable":
result.success(CustomTabActivityHelper.isAvailable(activity)); result.success(CustomTabActivityHelper.isAvailable(plugin.activity));
break; break;
default: default:
result.notImplemented(); result.notImplemented();
@ -52,10 +60,10 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
Intent intent = null; Intent intent = null;
Bundle extras = new Bundle(); Bundle extras = new Bundle();
extras.putString("fromActivity", activity.getClass().getName());
extras.putString("url", url); extras.putString("url", url);
extras.putBoolean("isData", false); extras.putBoolean("isData", false);
extras.putString("id", id); extras.putString("id", id);
extras.putString("managerId", this.id);
extras.putSerializable("options", options); extras.putSerializable("options", options);
extras.putSerializable("menuItemList", (Serializable) menuItemList); extras.putSerializable("menuItemList", (Serializable) menuItemList);
@ -72,5 +80,7 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
shared.remove(this.id);
plugin = null;
} }
} }

View File

@ -4,9 +4,10 @@ import android.os.Build;
import android.webkit.WebViewDatabase; import android.webkit.WebViewDatabase;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import com.pichillilorenzo.flutter_inappwebview.Shared; import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.types.URLCredential; import com.pichillilorenzo.flutter_inappwebview.types.URLCredential;
import com.pichillilorenzo.flutter_inappwebview.types.URLProtectionSpace; import com.pichillilorenzo.flutter_inappwebview.types.URLProtectionSpace;
@ -15,7 +16,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
@ -24,13 +24,16 @@ public class CredentialDatabaseHandler implements MethodChannel.MethodCallHandle
static final String LOG_TAG = "CredentialDatabaseHandler"; static final String LOG_TAG = "CredentialDatabaseHandler";
public static MethodChannel channel; public MethodChannel channel;
public static CredentialDatabase credentialDatabase; public static CredentialDatabase credentialDatabase;
@Nullable
public InAppWebViewFlutterPlugin plugin;
public CredentialDatabaseHandler(BinaryMessenger messenger) { public CredentialDatabaseHandler(final InAppWebViewFlutterPlugin plugin) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_credential_database"); this.plugin = plugin;
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_credential_database");
channel.setMethodCallHandler(this); channel.setMethodCallHandler(this);
credentialDatabase = CredentialDatabase.getInstance(Shared.applicationContext); credentialDatabase = CredentialDatabase.getInstance(plugin.applicationContext);
} }
@Override @Override
@ -109,7 +112,7 @@ public class CredentialDatabaseHandler implements MethodChannel.MethodCallHandle
break; break;
case "clearAllAuthCredentials": case "clearAllAuthCredentials":
credentialDatabase.clearAllAuthCredentials(); credentialDatabase.clearAllAuthCredentials();
WebViewDatabase.getInstance(Shared.applicationContext).clearHttpAuthUsernamePassword(); WebViewDatabase.getInstance(plugin.applicationContext).clearHttpAuthUsernamePassword();
result.success(true); result.success(true);
break; break;
default: default:
@ -119,6 +122,7 @@ public class CredentialDatabaseHandler implements MethodChannel.MethodCallHandle
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
plugin = null;
} }
} }

View File

@ -7,7 +7,7 @@ import android.widget.FrameLayout;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.pichillilorenzo.flutter_inappwebview.Shared; import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.Util; import com.pichillilorenzo.flutter_inappwebview.Util;
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.FlutterWebView; import com.pichillilorenzo.flutter_inappwebview.in_app_webview.FlutterWebView;
import com.pichillilorenzo.flutter_inappwebview.types.Size2D; import com.pichillilorenzo.flutter_inappwebview.types.Size2D;
@ -15,7 +15,6 @@ import com.pichillilorenzo.flutter_inappwebview.types.Size2D;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
@ -27,11 +26,14 @@ public class HeadlessInAppWebView implements MethodChannel.MethodCallHandler {
public final MethodChannel channel; public final MethodChannel channel;
@Nullable @Nullable
public FlutterWebView flutterWebView; public FlutterWebView flutterWebView;
@Nullable
public InAppWebViewFlutterPlugin plugin;
public HeadlessInAppWebView(BinaryMessenger messenger, @NonNull String id, @NonNull FlutterWebView flutterWebView) { public HeadlessInAppWebView(@NonNull final InAppWebViewFlutterPlugin plugin, @NonNull String id, @NonNull FlutterWebView flutterWebView) {
this.id = id; this.id = id;
this.plugin = plugin;
this.flutterWebView = flutterWebView; this.flutterWebView = flutterWebView;
this.channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_headless_inappwebview_" + id); this.channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_headless_inappwebview_" + id);
channel.setMethodCallHandler(this); channel.setMethodCallHandler(this);
} }
@ -70,7 +72,7 @@ public class HeadlessInAppWebView implements MethodChannel.MethodCallHandler {
public void prepare(Map<String, Object> params) { public void prepare(Map<String, Object> params) {
// Add the headless WebView to the view hierarchy. // Add the headless WebView to the view hierarchy.
// This way is also possible to take screenshots. // This way is also possible to take screenshots.
ViewGroup contentView = (ViewGroup) Shared.activity.findViewById(android.R.id.content); ViewGroup contentView = (ViewGroup) plugin.activity.findViewById(android.R.id.content);
ViewGroup mainView = (ViewGroup) (contentView).getChildAt(0); ViewGroup mainView = (ViewGroup) (contentView).getChildAt(0);
if (mainView != null) { if (mainView != null) {
View view = flutterWebView.getView(); View view = flutterWebView.getView();
@ -108,12 +110,13 @@ public class HeadlessInAppWebView implements MethodChannel.MethodCallHandler {
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
HeadlessInAppWebViewManager.webViews.remove(id); HeadlessInAppWebViewManager.webViews.remove(id);
ViewGroup contentView = (ViewGroup) Shared.activity.findViewById(android.R.id.content); ViewGroup contentView = (ViewGroup) plugin.activity.findViewById(android.R.id.content);
ViewGroup mainView = (ViewGroup) (contentView).getChildAt(0); ViewGroup mainView = (ViewGroup) (contentView).getChildAt(0);
if (mainView != null) { if (mainView != null) {
mainView.removeView(flutterWebView.getView()); mainView.removeView(flutterWebView.getView());
} }
flutterWebView.dispose(); flutterWebView.dispose();
flutterWebView = null; flutterWebView = null;
plugin = null;
} }
} }

View File

@ -21,13 +21,14 @@
package com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview; package com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview;
import com.pichillilorenzo.flutter_inappwebview.Shared; import androidx.annotation.Nullable;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.FlutterWebView; import com.pichillilorenzo.flutter_inappwebview.in_app_webview.FlutterWebView;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.MethodChannel.Result;
@ -37,9 +38,12 @@ public class HeadlessInAppWebViewManager implements MethodChannel.MethodCallHand
protected static final String LOG_TAG = "HeadlessInAppWebViewManager"; protected static final String LOG_TAG = "HeadlessInAppWebViewManager";
public MethodChannel channel; public MethodChannel channel;
public static final Map<String, HeadlessInAppWebView> webViews = new HashMap<>(); public static final Map<String, HeadlessInAppWebView> webViews = new HashMap<>();
@Nullable
public InAppWebViewFlutterPlugin plugin;
public HeadlessInAppWebViewManager(BinaryMessenger messenger) { public HeadlessInAppWebViewManager(final InAppWebViewFlutterPlugin plugin) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_headless_inappwebview"); this.plugin = plugin;
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_headless_inappwebview");
channel.setMethodCallHandler(this); channel.setMethodCallHandler(this);
} }
@ -51,7 +55,7 @@ public class HeadlessInAppWebViewManager implements MethodChannel.MethodCallHand
case "run": case "run":
{ {
HashMap<String, Object> params = (HashMap<String, Object>) call.argument("params"); HashMap<String, Object> params = (HashMap<String, Object>) call.argument("params");
HeadlessInAppWebViewManager.run(id, params); run(id, params);
} }
result.success(true); result.success(true);
break; break;
@ -61,9 +65,9 @@ public class HeadlessInAppWebViewManager implements MethodChannel.MethodCallHand
} }
public static void run(String id, HashMap<String, Object> params) { public void run(String id, HashMap<String, Object> params) {
FlutterWebView flutterWebView = new FlutterWebView(Shared.messenger, Shared.activity, id, params, null); FlutterWebView flutterWebView = new FlutterWebView(plugin, plugin.activity, id, params);
HeadlessInAppWebView headlessInAppWebView = new HeadlessInAppWebView(Shared.messenger, id, flutterWebView); HeadlessInAppWebView headlessInAppWebView = new HeadlessInAppWebView(plugin, id, flutterWebView);
HeadlessInAppWebViewManager.webViews.put(id, headlessInAppWebView); HeadlessInAppWebViewManager.webViews.put(id, headlessInAppWebView);
headlessInAppWebView.prepare(params); headlessInAppWebView.prepare(params);
@ -72,7 +76,7 @@ public class HeadlessInAppWebViewManager implements MethodChannel.MethodCallHand
} }
public void dispose() { public void dispose() {
HeadlessInAppWebViewManager.webViews.clear();
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
webViews.clear();
} }
} }

View File

@ -23,17 +23,16 @@ import android.widget.SearchView;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewMethodHandler;
import com.pichillilorenzo.flutter_inappwebview.R;
import com.pichillilorenzo.flutter_inappwebview.Util;
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebView; import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebView;
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebViewChromeClient; import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebViewChromeClient;
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebViewOptions; import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebViewOptions;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewMethodHandler;
import com.pichillilorenzo.flutter_inappwebview.R;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import com.pichillilorenzo.flutter_inappwebview.pull_to_refresh.PullToRefreshLayout; import com.pichillilorenzo.flutter_inappwebview.pull_to_refresh.PullToRefreshLayout;
import com.pichillilorenzo.flutter_inappwebview.pull_to_refresh.PullToRefreshOptions; import com.pichillilorenzo.flutter_inappwebview.pull_to_refresh.PullToRefreshOptions;
import com.pichillilorenzo.flutter_inappwebview.types.URLRequest; import com.pichillilorenzo.flutter_inappwebview.types.URLRequest;
import com.pichillilorenzo.flutter_inappwebview.types.UserScript; import com.pichillilorenzo.flutter_inappwebview.types.UserScript;
import com.pichillilorenzo.flutter_inappwebview.Util;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -60,7 +59,8 @@ public class InAppBrowserActivity extends AppCompatActivity implements InAppBrow
public String fromActivity; public String fromActivity;
private List<ActivityResultListener> activityResultListeners = new ArrayList<>(); private List<ActivityResultListener> activityResultListeners = new ArrayList<>();
public InAppWebViewMethodHandler methodCallDelegate; public InAppWebViewMethodHandler methodCallDelegate;
public InAppBrowserManager manager;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -68,14 +68,18 @@ public class InAppBrowserActivity extends AppCompatActivity implements InAppBrow
Bundle b = getIntent().getExtras(); Bundle b = getIntent().getExtras();
assert b != null; assert b != null;
id = b.getString("id"); id = b.getString("id");
String managerId = b.getString("managerId");
manager = (InAppBrowserManager) InAppBrowserManager.shared.get(managerId);
windowId = b.getInt("windowId"); windowId = b.getInt("windowId");
channel = new MethodChannel(Shared.messenger, "com.pichillilorenzo/flutter_inappbrowser_" + id); channel = new MethodChannel(manager.plugin.messenger, "com.pichillilorenzo/flutter_inappbrowser_" + id);
setContentView(R.layout.activity_web_view); setContentView(R.layout.activity_web_view);
Map<String, Object> pullToRefreshInitialOptions = (Map<String, Object>) b.getSerializable("pullToRefreshInitialOptions"); Map<String, Object> pullToRefreshInitialOptions = (Map<String, Object>) b.getSerializable("pullToRefreshInitialOptions");
MethodChannel pullToRefreshLayoutChannel = new MethodChannel(Shared.messenger, "com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_" + id); MethodChannel pullToRefreshLayoutChannel = new MethodChannel(manager.plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_" + id);
PullToRefreshOptions pullToRefreshOptions = new PullToRefreshOptions(); PullToRefreshOptions pullToRefreshOptions = new PullToRefreshOptions();
pullToRefreshOptions.parse(pullToRefreshInitialOptions); pullToRefreshOptions.parse(pullToRefreshInitialOptions);
pullToRefreshLayout = findViewById(R.id.pullToRefresh); pullToRefreshLayout = findViewById(R.id.pullToRefresh);
@ -87,6 +91,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements InAppBrow
webView.windowId = windowId; webView.windowId = windowId;
webView.inAppBrowserDelegate = this; webView.inAppBrowserDelegate = this;
webView.channel = channel; webView.channel = channel;
webView.plugin = manager.plugin;
methodCallDelegate = new InAppWebViewMethodHandler(webView); methodCallDelegate = new InAppWebViewMethodHandler(webView);
channel.setMethodCallHandler(methodCallDelegate); channel.setMethodCallHandler(methodCallDelegate);
@ -488,8 +493,8 @@ public class InAppBrowserActivity extends AppCompatActivity implements InAppBrow
methodCallDelegate = null; methodCallDelegate = null;
} }
if (webView != null) { if (webView != null) {
if (Shared.activityPluginBinding != null) { if (manager.plugin.activityPluginBinding != null) {
Shared.activityPluginBinding.removeActivityResultListener(webView.inAppWebViewChromeClient); manager.plugin.activityPluginBinding.removeActivityResultListener(webView.inAppWebViewChromeClient);
} }
ViewGroup vg = (ViewGroup) (webView.getParent()); ViewGroup vg = (ViewGroup) (webView.getParent());
if (vg != null) { if (vg != null) {
@ -501,6 +506,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements InAppBrow
webView.dispose(); webView.dispose();
webView.destroy(); webView.destroy();
webView = null; webView = null;
manager = null;
} }
}); });
webView.loadUrl("about:blank"); webView.loadUrl("about:blank");

View File

@ -25,23 +25,25 @@ import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.os.Parcelable;
import android.provider.Browser;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.webkit.MimeTypeMap; import android.os.Parcelable;
import android.provider.Browser;
import android.util.Log; import android.util.Log;
import android.webkit.MimeTypeMap;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.pichillilorenzo.flutter_inappwebview.Shared; import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.MethodChannel.Result;
@ -51,33 +53,37 @@ import io.flutter.plugin.common.MethodChannel.Result;
*/ */
public class InAppBrowserManager implements MethodChannel.MethodCallHandler { public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
public MethodChannel channel;
protected static final String LOG_TAG = "InAppBrowserManager"; protected static final String LOG_TAG = "InAppBrowserManager";
public MethodChannel channel;
@Nullable
public InAppWebViewFlutterPlugin plugin;
public String id;
public static final Map<String, InAppBrowserManager> shared = new HashMap<>();
public InAppBrowserManager(BinaryMessenger messenger) { public InAppBrowserManager(final InAppWebViewFlutterPlugin plugin) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappbrowser"); this.id = UUID.randomUUID().toString();
this.plugin = plugin;
channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappbrowser");
channel.setMethodCallHandler(this); channel.setMethodCallHandler(this);
shared.put(this.id, this);
} }
@Override @Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
final Activity activity = Shared.activity;
switch (call.method) { switch (call.method) {
case "open": case "open":
open(activity, (Map<String, Object>) call.arguments()); open(plugin.activity, (Map<String, Object>) call.arguments());
result.success(true); result.success(true);
break; break;
case "openWithSystemBrowser": case "openWithSystemBrowser":
{ {
String url = (String) call.argument("url"); String url = (String) call.argument("url");
openWithSystemBrowser(activity, url, result); openWithSystemBrowser(plugin.activity, url, result);
} }
break; break;
default: default:
result.notImplemented(); result.notImplemented();
} }
} }
public static String getMimeType(String url) { public static String getMimeType(String url) {
@ -180,6 +186,7 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
extras.putString("initialBaseUrl", baseUrl); extras.putString("initialBaseUrl", baseUrl);
extras.putString("initialHistoryUrl", historyUrl); extras.putString("initialHistoryUrl", historyUrl);
extras.putString("id", id); extras.putString("id", id);
extras.putString("managerId", this.id);
extras.putSerializable("options", (Serializable) options); extras.putSerializable("options", (Serializable) options);
extras.putSerializable("contextMenu", (Serializable) contextMenu); extras.putSerializable("contextMenu", (Serializable) contextMenu);
extras.putInt("windowId", windowId != null ? windowId : -1); extras.putInt("windowId", windowId != null ? windowId : -1);
@ -197,5 +204,7 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
shared.remove(this.id);
plugin = null;
} }
} }

View File

@ -17,8 +17,8 @@ import androidx.annotation.NonNull;
import androidx.webkit.WebViewCompat; import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewFeature; import androidx.webkit.WebViewFeature;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewMethodHandler; import com.pichillilorenzo.flutter_inappwebview.InAppWebViewMethodHandler;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js.JavaScriptBridgeJS; import com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js.JavaScriptBridgeJS;
import com.pichillilorenzo.flutter_inappwebview.pull_to_refresh.PullToRefreshLayout; import com.pichillilorenzo.flutter_inappwebview.pull_to_refresh.PullToRefreshLayout;
import com.pichillilorenzo.flutter_inappwebview.pull_to_refresh.PullToRefreshOptions; import com.pichillilorenzo.flutter_inappwebview.pull_to_refresh.PullToRefreshOptions;
@ -31,7 +31,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.platform.PlatformView; import io.flutter.plugin.platform.PlatformView;
@ -44,9 +43,9 @@ public class FlutterWebView implements PlatformView {
public InAppWebViewMethodHandler methodCallDelegate; public InAppWebViewMethodHandler methodCallDelegate;
public PullToRefreshLayout pullToRefreshLayout; public PullToRefreshLayout pullToRefreshLayout;
public FlutterWebView(BinaryMessenger messenger, final Context context, Object id, public FlutterWebView(final InAppWebViewFlutterPlugin plugin, final Context context, Object id,
HashMap<String, Object> params, View containerView) { HashMap<String, Object> params) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_" + id); channel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_" + id);
DisplayListenerProxy displayListenerProxy = new DisplayListenerProxy(); DisplayListenerProxy displayListenerProxy = new DisplayListenerProxy();
DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
@ -61,11 +60,11 @@ public class FlutterWebView implements PlatformView {
InAppWebViewOptions options = new InAppWebViewOptions(); InAppWebViewOptions options = new InAppWebViewOptions();
options.parse(initialOptions); options.parse(initialOptions);
if (Shared.activity == null) { if (plugin.activity == null) {
Log.e(LOG_TAG, "\n\n\nERROR: Shared.activity is null!!!\n\n" + Log.e(LOG_TAG, "\n\n\nERROR: You need to upgrade your Flutter project to use the new Java Embedding API:\n\n" +
"You need to upgrade your Flutter project to use the new Java Embedding API:\n\n" +
"- Take a look at the \"IMPORTANT Note for Android\" section here: https://github.com/pichillilorenzo/flutter_inappwebview#important-note-for-android\n" + "- Take a look at the \"IMPORTANT Note for Android\" section here: https://github.com/pichillilorenzo/flutter_inappwebview#important-note-for-android\n" +
"- See the official wiki here: https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects\n\n\n"); "- See the official wiki here: https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects\n\n\n");
return;
} }
List<UserScript> userScripts = new ArrayList<>(); List<UserScript> userScripts = new ArrayList<>();
@ -75,13 +74,13 @@ public class FlutterWebView implements PlatformView {
} }
} }
webView = new InAppWebView(context, channel, id, windowId, options, contextMenu, options.useHybridComposition ? null : containerView, userScripts); webView = new InAppWebView(context, plugin, channel, id, windowId, options, contextMenu, options.useHybridComposition ? null : plugin.flutterView, userScripts);
displayListenerProxy.onPostWebViewInitialization(displayManager); displayListenerProxy.onPostWebViewInitialization(displayManager);
if (options.useHybridComposition) { if (options.useHybridComposition) {
// set MATCH_PARENT layout params to the WebView, otherwise it won't take all the available space! // set MATCH_PARENT layout params to the WebView, otherwise it won't take all the available space!
webView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); webView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
MethodChannel pullToRefreshLayoutChannel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_" + id); MethodChannel pullToRefreshLayoutChannel = new MethodChannel(plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_" + id);
PullToRefreshOptions pullToRefreshOptions = new PullToRefreshOptions(); PullToRefreshOptions pullToRefreshOptions = new PullToRefreshOptions();
pullToRefreshOptions.parse(pullToRefreshInitialOptions); pullToRefreshOptions.parse(pullToRefreshInitialOptions);
pullToRefreshLayout = new PullToRefreshLayout(context, pullToRefreshLayoutChannel, pullToRefreshOptions); pullToRefreshLayout = new PullToRefreshLayout(context, pullToRefreshLayoutChannel, pullToRefreshOptions);

View File

@ -3,6 +3,8 @@ package com.pichillilorenzo.flutter_inappwebview.in_app_webview;
import android.content.Context; import android.content.Context;
import android.view.View; import android.view.View;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import java.util.HashMap; import java.util.HashMap;
import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.BinaryMessenger;
@ -11,19 +13,17 @@ import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory; import io.flutter.plugin.platform.PlatformViewFactory;
public class FlutterWebViewFactory extends PlatformViewFactory { public class FlutterWebViewFactory extends PlatformViewFactory {
private final View containerView; private final InAppWebViewFlutterPlugin plugin;
private final BinaryMessenger messenger;
public FlutterWebViewFactory(BinaryMessenger messenger, View containerView) { public FlutterWebViewFactory(final InAppWebViewFlutterPlugin plugin) {
super(StandardMessageCodec.INSTANCE); super(StandardMessageCodec.INSTANCE);
this.containerView = containerView; this.plugin = plugin;
this.messenger = messenger;
} }
@Override @Override
public PlatformView create(Context context, int id, Object args) { public PlatformView create(Context context, int id, Object args) {
HashMap<String, Object> params = (HashMap<String, Object>) args; HashMap<String, Object> params = (HashMap<String, Object>) args;
FlutterWebView flutterWebView = new FlutterWebView(messenger, context, id, params, containerView); FlutterWebView flutterWebView = new FlutterWebView(plugin, context, id, params);
flutterWebView.makeInitialLoad(params); flutterWebView.makeInitialLoad(params);
return flutterWebView; return flutterWebView;
} }

View File

@ -51,9 +51,9 @@ import androidx.annotation.RequiresApi;
import androidx.webkit.WebViewCompat; import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewFeature; import androidx.webkit.WebViewFeature;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.JavaScriptBridgeInterface; import com.pichillilorenzo.flutter_inappwebview.JavaScriptBridgeInterface;
import com.pichillilorenzo.flutter_inappwebview.R; import com.pichillilorenzo.flutter_inappwebview.R;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import com.pichillilorenzo.flutter_inappwebview.Util; import com.pichillilorenzo.flutter_inappwebview.Util;
import com.pichillilorenzo.flutter_inappwebview.content_blocker.ContentBlocker; import com.pichillilorenzo.flutter_inappwebview.content_blocker.ContentBlocker;
import com.pichillilorenzo.flutter_inappwebview.content_blocker.ContentBlockerAction; import com.pichillilorenzo.flutter_inappwebview.content_blocker.ContentBlockerAction;
@ -102,6 +102,8 @@ final public class InAppWebView extends InputAwareWebView {
static final String LOG_TAG = "InAppWebView"; static final String LOG_TAG = "InAppWebView";
@Nullable
public InAppWebViewFlutterPlugin plugin;
@Nullable @Nullable
public InAppBrowserDelegate inAppBrowserDelegate; public InAppBrowserDelegate inAppBrowserDelegate;
public MethodChannel channel; public MethodChannel channel;
@ -155,18 +157,20 @@ final public class InAppWebView extends InputAwareWebView {
super(context, attrs, defaultStyle); super(context, attrs, defaultStyle);
} }
public InAppWebView(Context context, MethodChannel channel, Object id, public InAppWebView(Context context, InAppWebViewFlutterPlugin plugin,
MethodChannel channel, Object id,
@Nullable Integer windowId, InAppWebViewOptions options, @Nullable Integer windowId, InAppWebViewOptions options,
@Nullable Map<String, Object> contextMenu, View containerView, @Nullable Map<String, Object> contextMenu, View containerView,
List<UserScript> userScripts) { List<UserScript> userScripts) {
super(context, containerView, options.useHybridComposition); super(context, containerView, options.useHybridComposition);
this.plugin = plugin;
this.channel = channel; this.channel = channel;
this.id = id; this.id = id;
this.windowId = windowId; this.windowId = windowId;
this.options = options; this.options = options;
this.contextMenu = contextMenu; this.contextMenu = contextMenu;
this.userContentController.addUserOnlyScripts(userScripts); this.userContentController.addUserOnlyScripts(userScripts);
Shared.activity.registerForContextMenu(this); plugin.activity.registerForContextMenu(this);
} }
@Override @Override
@ -181,7 +185,7 @@ final public class InAppWebView extends InputAwareWebView {
javaScriptBridgeInterface = new JavaScriptBridgeInterface(this); javaScriptBridgeInterface = new JavaScriptBridgeInterface(this);
addJavascriptInterface(javaScriptBridgeInterface, JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME); addJavascriptInterface(javaScriptBridgeInterface, JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME);
inAppWebViewChromeClient = new InAppWebViewChromeClient(channel, inAppBrowserDelegate); inAppWebViewChromeClient = new InAppWebViewChromeClient(plugin, channel, inAppBrowserDelegate);
setWebChromeClient(inAppWebViewChromeClient); setWebChromeClient(inAppWebViewChromeClient);
inAppWebViewClient = new InAppWebViewClient(channel, inAppBrowserDelegate); inAppWebViewClient = new InAppWebViewClient(channel, inAppBrowserDelegate);
@ -551,7 +555,7 @@ final public class InAppWebView extends InputAwareWebView {
} }
public void loadFile(String assetFilePath) throws IOException { public void loadFile(String assetFilePath) throws IOException {
loadUrl(Util.getUrlAsset(assetFilePath)); loadUrl(Util.getUrlAsset(plugin, assetFilePath));
} }
public boolean isLoading() { public boolean isLoading() {
@ -1208,7 +1212,7 @@ final public class InAppWebView extends InputAwareWebView {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void printCurrentPage() { public void printCurrentPage() {
// Get a PrintManager instance // Get a PrintManager instance
PrintManager printManager = (PrintManager) Shared.activity.getSystemService(Context.PRINT_SERVICE); PrintManager printManager = (PrintManager) plugin.activity.getSystemService(Context.PRINT_SERVICE);
if (printManager != null) { if (printManager != null) {
String jobName = getTitle() + " Document"; String jobName = getTitle() + " Document";
@ -1665,6 +1669,7 @@ final public class InAppWebView extends InputAwareWebView {
inAppWebViewClient = null; inAppWebViewClient = null;
javaScriptBridgeInterface = null; javaScriptBridgeInterface = null;
inAppWebViewRenderProcessClient = null; inAppWebViewRenderProcessClient = null;
plugin = null;
super.dispose(); super.dispose();
} }

View File

@ -8,7 +8,6 @@ import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor; import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color; import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
@ -45,7 +44,6 @@ import com.pichillilorenzo.flutter_inappwebview.in_app_browser.ActivityResultLis
import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserDelegate; import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserDelegate;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin; import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.R; import com.pichillilorenzo.flutter_inappwebview.R;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import com.pichillilorenzo.flutter_inappwebview.types.URLRequest; import com.pichillilorenzo.flutter_inappwebview.types.URLRequest;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -100,20 +98,22 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
private WebChromeClient.CustomViewCallback mCustomViewCallback; private WebChromeClient.CustomViewCallback mCustomViewCallback;
private int mOriginalOrientation; private int mOriginalOrientation;
private int mOriginalSystemUiVisibility; private int mOriginalSystemUiVisibility;
@Nullable
public InAppWebViewFlutterPlugin plugin;
public InAppWebViewChromeClient(MethodChannel channel, InAppBrowserDelegate inAppBrowserDelegate) { public InAppWebViewChromeClient(final InAppWebViewFlutterPlugin plugin, MethodChannel channel, InAppBrowserDelegate inAppBrowserDelegate) {
super(); super();
this.plugin = plugin;
this.channel = channel; this.channel = channel;
this.inAppBrowserDelegate = inAppBrowserDelegate; this.inAppBrowserDelegate = inAppBrowserDelegate;
if (this.inAppBrowserDelegate != null) { if (this.inAppBrowserDelegate != null) {
this.inAppBrowserDelegate.getActivityResultListeners().add(this); this.inAppBrowserDelegate.getActivityResultListeners().add(this);
} }
if (Shared.registrar != null) if (plugin.registrar != null)
Shared.registrar.addActivityResultListener(this); plugin.registrar.addActivityResultListener(this);
else else
Shared.activityPluginBinding.addActivityResultListener(this); plugin.activityPluginBinding.addActivityResultListener(this);
} }
@Override @Override
@ -123,7 +123,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
@Override @Override
public void onHideCustomView() { public void onHideCustomView() {
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
View decorView = getRootView(); View decorView = getRootView();
((FrameLayout) decorView).removeView(this.mCustomView); ((FrameLayout) decorView).removeView(this.mCustomView);
@ -144,7 +144,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
return; return;
} }
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
View decorView = getRootView(); View decorView = getRootView();
this.mCustomView = paramView; this.mCustomView = paramView;
@ -228,7 +228,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
}; };
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity, R.style.Theme_AppCompat_Dialog_Alert); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity, R.style.Theme_AppCompat_Dialog_Alert);
alertDialogBuilder.setMessage(alertMessage); alertDialogBuilder.setMessage(alertMessage);
@ -321,7 +321,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
}; };
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity, R.style.Theme_AppCompat_Dialog_Alert); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity, R.style.Theme_AppCompat_Dialog_Alert);
alertDialogBuilder.setMessage(alertMessage); alertDialogBuilder.setMessage(alertMessage);
@ -440,7 +440,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
}; };
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity, R.style.Theme_AppCompat_Dialog_Alert); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity, R.style.Theme_AppCompat_Dialog_Alert);
alertDialogBuilder.setMessage(alertMessage); alertDialogBuilder.setMessage(alertMessage);
@ -538,7 +538,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
}; };
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity, R.style.Theme_AppCompat_Dialog_Alert); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity, R.style.Theme_AppCompat_Dialog_Alert);
alertDialogBuilder.setMessage(alertMessage); alertDialogBuilder.setMessage(alertMessage);
@ -733,7 +733,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
protected ViewGroup getRootView() { protected ViewGroup getRootView() {
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
return (ViewGroup) activity.findViewById(android.R.id.content); return (ViewGroup) activity.findViewById(android.R.id.content);
} }
@ -827,7 +827,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
private boolean isFileNotEmpty(Uri uri) { private boolean isFileNotEmpty(Uri uri) {
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
long length; long length;
try { try {
@ -868,7 +868,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents.toArray(new Parcelable[]{})); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents.toArray(new Parcelable[]{}));
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
if (chooserIntent.resolveActivity(activity.getPackageManager()) != null) { if (chooserIntent.resolveActivity(activity.getPackageManager()) != null) {
activity.startActivityForResult(chooserIntent, PICKER_LEGACY); activity.startActivityForResult(chooserIntent, PICKER_LEGACY);
} else { } else {
@ -896,7 +896,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
chooserIntent.putExtra(Intent.EXTRA_INTENT, fileSelectionIntent); chooserIntent.putExtra(Intent.EXTRA_INTENT, fileSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents.toArray(new Parcelable[]{})); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents.toArray(new Parcelable[]{}));
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
if (chooserIntent.resolveActivity(activity.getPackageManager()) != null) { if (chooserIntent.resolveActivity(activity.getPackageManager()) != null) {
activity.startActivityForResult(chooserIntent, PICKER); activity.startActivityForResult(chooserIntent, PICKER);
} else { } else {
@ -909,7 +909,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
protected boolean needsCameraPermission() { protected boolean needsCameraPermission() {
boolean needed = false; boolean needed = false;
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
PackageManager packageManager = activity.getPackageManager(); PackageManager packageManager = activity.getPackageManager();
try { try {
String[] requestedPermissions = packageManager.getPackageInfo(activity.getApplicationContext().getPackageName(), PackageManager.GET_PERMISSIONS).requestedPermissions; String[] requestedPermissions = packageManager.getPackageInfo(activity.getApplicationContext().getPackageName(), PackageManager.GET_PERMISSIONS).requestedPermissions;
@ -1051,7 +1051,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
return Uri.fromFile(capturedFile); return Uri.fromFile(capturedFile);
} }
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
// for versions 6.0+ (23) we use the FileProvider to avoid runtime permissions // for versions 6.0+ (23) we use the FileProvider to avoid runtime permissions
String packageName = activity.getApplicationContext().getPackageName(); String packageName = activity.getApplicationContext().getPackageName();
return FileProvider.getUriForFile(activity.getApplicationContext(), packageName + "." + fileProviderAuthorityExtension, capturedFile); return FileProvider.getUriForFile(activity.getApplicationContext(), packageName + "." + fileProviderAuthorityExtension, capturedFile);
@ -1081,7 +1081,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
return new File(storageDir, filename); return new File(storageDir, filename);
} }
Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : Shared.activity; Activity activity = inAppBrowserDelegate != null ? inAppBrowserDelegate.getActivity() : plugin.activity;
File storageDir = activity.getApplicationContext().getExternalFilesDir(null); File storageDir = activity.getApplicationContext().getExternalFilesDir(null);
return File.createTempFile(prefix, suffix, storageDir); return File.createTempFile(prefix, suffix, storageDir);
} }
@ -1140,12 +1140,13 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
public void dispose() { public void dispose() {
if (Shared.activityPluginBinding != null) { if (plugin != null && plugin.activityPluginBinding != null) {
Shared.activityPluginBinding.removeActivityResultListener(this); plugin.activityPluginBinding.removeActivityResultListener(this);
} }
if (inAppBrowserDelegate != null) { if (inAppBrowserDelegate != null) {
inAppBrowserDelegate.getActivityResultListeners().clear(); inAppBrowserDelegate.getActivityResultListeners().clear();
inAppBrowserDelegate = null; inAppBrowserDelegate = null;
} }
plugin = null;
} }
} }

View File

@ -23,7 +23,6 @@ import android.webkit.WebViewClient;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import com.pichillilorenzo.flutter_inappwebview.Util; import com.pichillilorenzo.flutter_inappwebview.Util;
import com.pichillilorenzo.flutter_inappwebview.credential_database.CredentialDatabase; import com.pichillilorenzo.flutter_inappwebview.credential_database.CredentialDatabase;
import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserDelegate; import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserDelegate;
@ -444,6 +443,8 @@ public class InAppWebViewClient extends WebViewClient {
@Override @Override
public void onReceivedClientCertRequest(final WebView view, final ClientCertRequest request) { public void onReceivedClientCertRequest(final WebView view, final ClientCertRequest request) {
InAppWebView webView = (InAppWebView) view;
URI uri; URI uri;
try { try {
uri = new URI(view.getUrl()); uri = new URI(view.getUrl());
@ -475,7 +476,7 @@ public class InAppWebViewClient extends WebViewClient {
String certificatePath = (String) responseMap.get("certificatePath"); String certificatePath = (String) responseMap.get("certificatePath");
String certificatePassword = (String) responseMap.get("certificatePassword"); String certificatePassword = (String) responseMap.get("certificatePassword");
String androidKeyStoreType = (String) responseMap.get("androidKeyStoreType"); String androidKeyStoreType = (String) responseMap.get("androidKeyStoreType");
Util.PrivateKeyAndCertificates privateKeyAndCertificates = Util.loadPrivateKeyAndCertificate(certificatePath, certificatePassword, androidKeyStoreType); Util.PrivateKeyAndCertificates privateKeyAndCertificates = Util.loadPrivateKeyAndCertificate(webView.plugin, certificatePath, certificatePassword, androidKeyStoreType);
request.proceed(privateKeyAndCertificates.privateKey, privateKeyAndCertificates.certificates); request.proceed(privateKeyAndCertificates.privateKey, privateKeyAndCertificates.certificates);
} }
return; return;

View File

@ -7,7 +7,6 @@ import androidx.webkit.WebMessagePortCompat;
import androidx.webkit.WebViewCompat; import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewFeature; import androidx.webkit.WebViewFeature;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebView; import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebView;
import java.util.ArrayList; import java.util.ArrayList;
@ -29,7 +28,7 @@ public class WebMessageChannel implements MethodChannel.MethodCallHandler {
public WebMessageChannel(@NonNull String id, @NonNull InAppWebView webView) { public WebMessageChannel(@NonNull String id, @NonNull InAppWebView webView) {
this.id = id; this.id = id;
this.channel = new MethodChannel(Shared.messenger, "com.pichillilorenzo/flutter_inappwebview_web_message_channel_" + id); this.channel = new MethodChannel(webView.plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_web_message_channel_" + id);
this.channel.setMethodCallHandler(this); this.channel.setMethodCallHandler(this);
this.ports = new ArrayList<>(Arrays.asList(WebViewCompat.createWebMessageChannel(webView))); this.ports = new ArrayList<>(Arrays.asList(WebViewCompat.createWebMessageChannel(webView)));
this.webView = webView; this.webView = webView;

View File

@ -10,14 +10,13 @@ import androidx.webkit.WebMessageCompat;
import androidx.webkit.WebViewCompat; import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewFeature; import androidx.webkit.WebViewFeature;
import com.pichillilorenzo.flutter_inappwebview.Shared;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
@ -30,10 +29,10 @@ public class WebMessageListener implements MethodChannel.MethodCallHandler {
public JavaScriptReplyProxy replyProxy; public JavaScriptReplyProxy replyProxy;
public MethodChannel channel; public MethodChannel channel;
public WebMessageListener(@NonNull String jsObjectName, @NonNull Set<String> allowedOriginRules) { public WebMessageListener(@NonNull BinaryMessenger messenger, @NonNull String jsObjectName, @NonNull Set<String> allowedOriginRules) {
this.jsObjectName = jsObjectName; this.jsObjectName = jsObjectName;
this.allowedOriginRules = allowedOriginRules; this.allowedOriginRules = allowedOriginRules;
this.channel = new MethodChannel(Shared.messenger, "com.pichillilorenzo/flutter_inappwebview_web_message_listener_" + this.jsObjectName); this.channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_web_message_listener_" + this.jsObjectName);
this.channel.setMethodCallHandler(this); this.channel.setMethodCallHandler(this);
this.listener = new WebViewCompat.WebMessageListener() { this.listener = new WebViewCompat.WebMessageListener() {
@Override @Override
@ -49,7 +48,7 @@ public class WebMessageListener implements MethodChannel.MethodCallHandler {
} }
@Nullable @Nullable
public static WebMessageListener fromMap(@Nullable Map<String, Object> map) { public static WebMessageListener fromMap(@NonNull BinaryMessenger messenger, @Nullable Map<String, Object> map) {
if (map == null) { if (map == null) {
return null; return null;
} }
@ -58,7 +57,7 @@ public class WebMessageListener implements MethodChannel.MethodCallHandler {
List<String> allowedOriginRuleList = (List<String>) map.get("allowedOriginRules"); List<String> allowedOriginRuleList = (List<String>) map.get("allowedOriginRules");
assert allowedOriginRuleList != null; assert allowedOriginRuleList != null;
Set<String> allowedOriginRules = new HashSet<>(allowedOriginRuleList); Set<String> allowedOriginRules = new HashSet<>(allowedOriginRuleList);
return new WebMessageListener(jsObjectName, allowedOriginRules); return new WebMessageListener(messenger, jsObjectName, allowedOriginRules);
} }
@Override @Override

View File

@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.1.0-10.0.pre/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.1.0-10.0.pre/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-03-25 11:56:12.905923","version":"2.1.0-10.0.pre"} {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.1.0-10.0.pre/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.1.0-10.0.pre/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-03-28 04:12:52.120913","version":"2.1.0-10.0.pre"}

View File

@ -5455,10 +5455,10 @@ setTimeout(function() {
onWebViewCreated: (controller) { onWebViewCreated: (controller) {
controllerCompleter.complete(controller); controllerCompleter.complete(controller);
}, },
onLoadStop: (controller, url) async {
pageLoaded.complete();
},
); );
headlessWebView.onLoadStop = (controller, url) async {
pageLoaded.complete();
};
await headlessWebView.run(); await headlessWebView.run();
expect(headlessWebView.isRunning(), true); expect(headlessWebView.isRunning(), true);
@ -5472,8 +5472,70 @@ setTimeout(function() {
await headlessWebView.dispose(); await headlessWebView.dispose();
expect(() async => await headlessWebView.webViewController.getUrl(), expect(headlessWebView.isRunning(), false);
throwsA(isInstanceOf<MissingPluginException>())); });
test('take screenshot', () async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
final Completer<void> pageLoaded = Completer<void>();
var headlessWebView = new HeadlessInAppWebView(
initialUrlRequest: URLRequest(url: Uri.parse("https://github.com/flutter")),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
onLoadStop: (controller, url) async {
pageLoaded.complete();
}
);
await headlessWebView.run();
expect(headlessWebView.isRunning(), true);
final InAppWebViewController controller =
await controllerCompleter.future;
await pageLoaded.future;
final String? url = (await controller.getUrl())?.toString();
expect(url, 'https://github.com/flutter');
final Size? size = await headlessWebView.getSize();
expect(size, isNotNull);
final Uint8List? screenshot = await controller.takeScreenshot();
expect(screenshot, isNotNull);
await headlessWebView.dispose();
expect(headlessWebView.isRunning(), false);
});
test('set and get custom size', () async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
var headlessWebView = new HeadlessInAppWebView(
initialUrlRequest: URLRequest(url: Uri.parse("https://github.com/flutter")),
initialSize: Size(600, 800),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
);
await headlessWebView.run();
expect(headlessWebView.isRunning(), true);
final Size? size = await headlessWebView.getSize();
expect(size, isNotNull);
expect(size, Size(600, 800));
await headlessWebView.setSize(Size(1080, 1920));
final Size? newSize = await headlessWebView.getSize();
expect(newSize, isNotNull);
expect(newSize, Size(1080, 1920));
await headlessWebView.dispose();
expect(headlessWebView.isRunning(), false);
}); });
test('set/get options', () async { test('set/get options', () async {
@ -5569,7 +5631,7 @@ setTimeout(function() {
throwsA(isInstanceOf<MissingPluginException>())); throwsA(isInstanceOf<MissingPluginException>()));
}); });
test('openFile and close', () async { test('openData and close', () async {
var inAppBrowser = new MyInAppBrowser(); var inAppBrowser = new MyInAppBrowser();
expect(inAppBrowser.isOpened(), false); expect(inAppBrowser.isOpened(), false);
expect(() async { expect(() async {

View File

@ -80,5 +80,6 @@
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart SDK" level="project" /> <orderEntry type="library" name="Dart SDK" level="project" />
<orderEntry type="library" name="Flutter Plugins" level="project" /> <orderEntry type="library" name="Flutter Plugins" level="project" />
<orderEntry type="library" name="Dart Packages" level="project" />
</component> </component>
</module> </module>

View File

@ -25,7 +25,8 @@ class HeadlessInAppWebView implements WebView {
bool _started = false; bool _started = false;
bool _running = false; bool _running = false;
static const MethodChannel _sharedChannel = const MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview'); static const MethodChannel _sharedChannel =
const MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview');
late MethodChannel _channel; late MethodChannel _channel;
///WebView Controller that can be used to access the [InAppWebViewController] API. ///WebView Controller that can be used to access the [InAppWebViewController] API.
@ -97,7 +98,7 @@ class HeadlessInAppWebView implements WebView {
this.androidOnRenderProcessUnresponsive, this.androidOnRenderProcessUnresponsive,
this.androidOnFormResubmission, this.androidOnFormResubmission,
@Deprecated('Use `onZoomScaleChanged` instead') @Deprecated('Use `onZoomScaleChanged` instead')
this.androidOnScaleChanged, this.androidOnScaleChanged,
this.androidOnReceivedIcon, this.androidOnReceivedIcon,
this.androidOnReceivedTouchIconUrl, this.androidOnReceivedTouchIconUrl,
this.androidOnJsBeforeUnload, this.androidOnJsBeforeUnload,
@ -108,8 +109,8 @@ class HeadlessInAppWebView implements WebView {
this.iosShouldAllowDeprecatedTLS}) { this.iosShouldAllowDeprecatedTLS}) {
id = IdGenerator.generate(); id = IdGenerator.generate();
webViewController = new InAppWebViewController(id, this); webViewController = new InAppWebViewController(id, this);
this._channel = MethodChannel( this._channel =
'com.pichillilorenzo/flutter_headless_inappwebview_$id'); MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview_$id');
this._channel.setMethodCallHandler(handleMethod); this._channel.setMethodCallHandler(handleMethod);
} }
@ -188,7 +189,8 @@ class HeadlessInAppWebView implements WebView {
///Gets the current size in pixels of the WebView. ///Gets the current size in pixels of the WebView.
Future<Size?> getSize() async { Future<Size?> getSize() async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
Map<String, dynamic> sizeMap = (await _channel.invokeMethod('getSize', args))?.cast<String, dynamic>(); Map<String, dynamic> sizeMap =
(await _channel.invokeMethod('getSize', args))?.cast<String, dynamic>();
return MapSize.fromMap(sizeMap); return MapSize.fromMap(sizeMap);
} }
@ -223,16 +225,12 @@ class HeadlessInAppWebView implements WebView {
androidOnGeolocationPermissionsShowPrompt; androidOnGeolocationPermissionsShowPrompt;
@override @override
Future<PermissionRequestResponse?> Function( Future<PermissionRequestResponse?> Function(InAppWebViewController controller,
InAppWebViewController controller, String origin, List<String> resources)? androidOnPermissionRequest;
String origin,
List<String> resources)? androidOnPermissionRequest;
@override @override
Future<SafeBrowsingResponse?> Function( Future<SafeBrowsingResponse?> Function(InAppWebViewController controller,
InAppWebViewController controller, Uri url, SafeBrowsingThreat? threatType)? androidOnSafeBrowsingHit;
Uri url,
SafeBrowsingThreat? threatType)? androidOnSafeBrowsingHit;
@override @override
void Function(InAppWebViewController controller, Uri? url)? void Function(InAppWebViewController controller, Uri? url)?
@ -289,8 +287,7 @@ class HeadlessInAppWebView implements WebView {
void Function(InAppWebViewController controller)? onWindowBlur; void Function(InAppWebViewController controller)? onWindowBlur;
@override @override
void Function(InAppWebViewController controller, Uri url)? void Function(InAppWebViewController controller, Uri url)? onDownloadStart;
onDownloadStart;
@override @override
void Function(InAppWebViewController controller, int activeMatchOrdinal, void Function(InAppWebViewController controller, int activeMatchOrdinal,
@ -316,12 +313,11 @@ class HeadlessInAppWebView implements WebView {
String message)? onLoadError; String message)? onLoadError;
@override @override
void Function(InAppWebViewController controller, Uri? url, void Function(InAppWebViewController controller, Uri? url, int statusCode,
int statusCode, String description)? onLoadHttpError; String description)? onLoadHttpError;
@override @override
void Function( void Function(InAppWebViewController controller, LoadedResource resource)?
InAppWebViewController controller, LoadedResource resource)?
onLoadResource; onLoadResource;
@override @override
@ -354,8 +350,7 @@ class HeadlessInAppWebView implements WebView {
URLAuthenticationChallenge challenge)? onReceivedHttpAuthRequest; URLAuthenticationChallenge challenge)? onReceivedHttpAuthRequest;
@override @override
Future<ServerTrustAuthResponse?> Function( Future<ServerTrustAuthResponse?> Function(InAppWebViewController controller,
InAppWebViewController controller,
URLAuthenticationChallenge challenge)? onReceivedServerTrustAuthRequest; URLAuthenticationChallenge challenge)? onReceivedServerTrustAuthRequest;
@override @override
@ -392,13 +387,13 @@ class HeadlessInAppWebView implements WebView {
void Function(InAppWebViewController controller)? onExitFullscreen; void Function(InAppWebViewController controller)? onExitFullscreen;
@override @override
void Function(InAppWebViewController controller, int x, int y, void Function(InAppWebViewController controller, int x, int y, bool clampedX,
bool clampedX, bool clampedY)? onOverScrolled; bool clampedY)? onOverScrolled;
@override @override
void Function( void Function(
InAppWebViewController controller, double oldScale, double newScale)? InAppWebViewController controller, double oldScale, double newScale)?
onZoomScaleChanged; onZoomScaleChanged;
@override @override
Future<WebResourceResponse?> Function( Future<WebResourceResponse?> Function(
@ -436,17 +431,14 @@ class HeadlessInAppWebView implements WebView {
androidOnReceivedIcon; androidOnReceivedIcon;
@override @override
void Function( void Function(InAppWebViewController controller, Uri url, bool precomposed)?
InAppWebViewController controller, Uri url, bool precomposed)?
androidOnReceivedTouchIconUrl; androidOnReceivedTouchIconUrl;
@override @override
Future<JsBeforeUnloadResponse?> Function( Future<JsBeforeUnloadResponse?> Function(InAppWebViewController controller,
InAppWebViewController controller,
JsBeforeUnloadRequest jsBeforeUnloadRequest)? androidOnJsBeforeUnload; JsBeforeUnloadRequest jsBeforeUnloadRequest)? androidOnJsBeforeUnload;
@override @override
void Function( void Function(InAppWebViewController controller, LoginRequest loginRequest)?
InAppWebViewController controller, LoginRequest loginRequest)?
androidOnReceivedLoginRequest; androidOnReceivedLoginRequest;
} }

View File

@ -87,8 +87,7 @@ class InAppWebView extends StatefulWidget implements WebView {
this.androidOnRenderProcessResponsive, this.androidOnRenderProcessResponsive,
this.androidOnRenderProcessUnresponsive, this.androidOnRenderProcessUnresponsive,
this.androidOnFormResubmission, this.androidOnFormResubmission,
@Deprecated('Use `onZoomScaleChanged` instead') @Deprecated('Use `onZoomScaleChanged` instead') this.androidOnScaleChanged,
this.androidOnScaleChanged,
this.androidOnReceivedIcon, this.androidOnReceivedIcon,
this.androidOnReceivedTouchIconUrl, this.androidOnReceivedTouchIconUrl,
this.androidOnJsBeforeUnload, this.androidOnJsBeforeUnload,
@ -317,8 +316,8 @@ class InAppWebView extends StatefulWidget implements WebView {
@override @override
final void Function( final void Function(
InAppWebViewController controller, double oldScale, double newScale)? InAppWebViewController controller, double oldScale, double newScale)?
onZoomScaleChanged; onZoomScaleChanged;
@override @override
final Future<WebResourceResponse?> Function( final Future<WebResourceResponse?> Function(

View File

@ -356,7 +356,9 @@ class InAppWebViewController {
} }
break; break;
case "onZoomScaleChanged": case "onZoomScaleChanged":
if ((_webview != null && (_webview!.androidOnScaleChanged != null || _webview!.onZoomScaleChanged != null)) || if ((_webview != null &&
(_webview!.androidOnScaleChanged != null ||
_webview!.onZoomScaleChanged != null)) ||
_inAppBrowser != null) { _inAppBrowser != null) {
double oldScale = call.arguments["oldScale"]; double oldScale = call.arguments["oldScale"];
double newScale = call.arguments["newScale"]; double newScale = call.arguments["newScale"];
@ -365,8 +367,7 @@ class InAppWebViewController {
_webview!.onZoomScaleChanged!(this, oldScale, newScale); _webview!.onZoomScaleChanged!(this, oldScale, newScale);
else else
_webview!.androidOnScaleChanged!(this, oldScale, newScale); _webview!.androidOnScaleChanged!(this, oldScale, newScale);
} } else
else
_inAppBrowser!.androidOnScaleChanged(oldScale, newScale); _inAppBrowser!.androidOnScaleChanged(oldScale, newScale);
} }
break; break;

View File

@ -413,8 +413,8 @@ abstract class WebView {
/// ///
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollviewdelegate/1619409-scrollviewdidzoom ///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollviewdelegate/1619409-scrollviewdidzoom
final void Function( final void Function(
InAppWebViewController controller, double oldScale, double newScale)? InAppWebViewController controller, double oldScale, double newScale)?
onZoomScaleChanged; onZoomScaleChanged;
///Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing. ///Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing.
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible. ///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
@ -721,7 +721,7 @@ abstract class WebView {
this.androidOnRenderProcessUnresponsive, this.androidOnRenderProcessUnresponsive,
this.androidOnFormResubmission, this.androidOnFormResubmission,
@Deprecated('Use `onZoomScaleChanged` instead') @Deprecated('Use `onZoomScaleChanged` instead')
this.androidOnScaleChanged, this.androidOnScaleChanged,
this.androidOnReceivedIcon, this.androidOnReceivedIcon,
this.androidOnReceivedTouchIconUrl, this.androidOnReceivedTouchIconUrl,
this.androidOnJsBeforeUnload, this.androidOnJsBeforeUnload,

View File

@ -499,9 +499,6 @@ extension MapSize on Size {
} }
Map<String, double> toMap() { Map<String, double> toMap() {
return { return {'width': width, 'height': height};
'width': width,
'height': height
};
} }
} }