diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d991822..302de33d 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,9 @@ - Fixed error caused by `pauseTimers` on iOS when the WebView has been disposed - Fixed `ignoresViewportScaleLimits`, `dataDetectorTypes`, `suppressesIncrementalRendering`, `selectionGranularity` iOS-specific option when used in `initialOptions` - Fixed `getFavicons` method +- Fixed `HttpAuthCredentialDatabase.removeHttpAuthCredential` on Android +- Fixed some cases where `takeScreenshot` was not working on Android +- Fixed `After upgrade to Android embedding V2, still get Shared.activity is null / NullPointerException on android.content.Context.getResources()` [#390](https://github.com/pichillilorenzo/flutter_inappwebview/issues/390) ### BREAKING CHANGES @@ -27,6 +30,7 @@ - `builtInZoomControls` android webview options changed default value to `true` - Updated `ServerTrustChallenge` class used by the `onReceivedServerTrustAuthRequest` event - The method `getOptions` could return null now +- Updated `HttpAuthCredentialDatabase.getAllAuthCredentials` method return type ## 3.3.0+3 diff --git a/README.md b/README.md index 1761c632..1e283b34 100755 --- a/README.md +++ b/README.md @@ -495,7 +495,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly: * `useOnDownloadStart`: Set to `true` to be able to listen at the `onDownloadStart` event. The default value is `false`. * `useShouldInterceptAjaxRequest`: Set to `true` to be able to listen at the `shouldInterceptAjaxRequest` event. The default value is `false`. * `useShouldInterceptFetchRequest`: Set to `true` to be able to listen at the `shouldInterceptFetchRequest` event. The default value is `false`. -* `clearCache`: Set to `true` to have all the browser's cache cleared before the new window is opened. The default value is `false`. +* `clearCache`: Set to `true` to have all the browser's cache cleared before the new WebView is opened. The default value is `false`. * `userAgent`: Sets the user-agent for the WebView. * `applicationNameForUserAgent`: Append to the existing user-agent. Setting userAgent will override this. * `javaScriptEnabled`: Set to `true` to enable JavaScript. The default value is `true`. diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/CredentialDatabase/CredentialDatabase.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/CredentialDatabase/CredentialDatabase.java index 6279fd8c..9b02fba9 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/CredentialDatabase/CredentialDatabase.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/CredentialDatabase/CredentialDatabase.java @@ -57,7 +57,8 @@ public class CredentialDatabase { public void removeHttpAuthCredential(String host, String protocol, String realm, Integer port, String username, String password) { ProtectionSpace protectionSpace = protectionSpaceDao.find(host, protocol, realm, port); if (protectionSpace != null) { - credentialDao.find(username, password, protectionSpace.id); + Credential credential = credentialDao.find(username, password, protectionSpace.id); + credentialDao.delete(credential); } } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/CredentialDatabaseHandler.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/CredentialDatabaseHandler.java index 8a8b272b..54ef1e5e 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/CredentialDatabaseHandler.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/CredentialDatabaseHandler.java @@ -1,6 +1,7 @@ package com.pichillilorenzo.flutter_inappwebview; import android.os.Build; +import android.webkit.WebViewDatabase; import androidx.annotation.RequiresApi; @@ -108,6 +109,7 @@ public class CredentialDatabaseHandler implements MethodChannel.MethodCallHandle break; case "clearAllAuthCredentials": credentialDatabase.clearAllAuthCredentials(); + WebViewDatabase.getInstance(Shared.applicationContext).clearHttpAuthUsernamePassword(); result.success(true); break; default: diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebView.java index 51abda3f..c8eb0ad7 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebView.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebView.java @@ -1056,10 +1056,20 @@ final public class InAppWebView extends InputAwareWebView { Canvas c = new Canvas(b); draw(c); - int scrollOffset = (getScrollY() + getMeasuredHeight() > b.getHeight()) - ? b.getHeight() : getScrollY(); + + int scrollY = getScrollY(); + int measuredHeight = getMeasuredHeight(); + int bitmapHeight = b.getHeight(); + + int scrollOffset = (scrollY + measuredHeight > bitmapHeight) + ? (bitmapHeight - measuredHeight) : scrollY; + + if (scrollOffset < 0) { + scrollOffset = 0; + } + Bitmap resized = Bitmap.createBitmap( - b, 0, scrollOffset, b.getWidth(), getMeasuredHeight()); + b, 0, scrollOffset, b.getWidth(), measuredHeight); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); @@ -1610,6 +1620,7 @@ final public class InAppWebView extends InputAwareWebView { InputMethodManager imm = (InputMethodManager) getContext().getSystemService(INPUT_METHOD_SERVICE); if (imm != null && !imm.isAcceptingText()) { + imm.hideSoftInputFromWindow( containerView.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java index 4eac0713..3d4c5416 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java @@ -224,10 +224,6 @@ public class InAppWebViewClient extends WebViewClient { CookieSyncManager.getInstance().sync(); } - // https://issues.apache.org/jira/browse/CB-11248 - view.clearFocus(); - view.requestFocus(); - String js = InAppWebView.platformReadyJS.replaceAll("[\r\n]+", ""); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewFlutterPlugin.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewFlutterPlugin.java index 6708e625..9f4c85df 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewFlutterPlugin.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewFlutterPlugin.java @@ -15,6 +15,7 @@ import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.PluginRegistry; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.plugin.platform.PlatformViewRegistry; +import io.flutter.view.FlutterMain; import io.flutter.view.FlutterView; public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware { @@ -34,6 +35,8 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware { public InAppWebViewFlutterPlugin() {} public static void registerWith(PluginRegistry.Registrar registrar) { + Log.d(LOG_TAG, "\n\n\nregisterWith\n\n\n"); + final InAppWebViewFlutterPlugin instance = new InAppWebViewFlutterPlugin(); Shared.registrar = registrar; instance.onAttachedToEngine( @@ -43,11 +46,17 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware { @Override public void onAttachedToEngine(FlutterPluginBinding binding) { Shared.flutterAssets = binding.getFlutterAssets(); + + // Shared.activity could be null or not. + // It depends on who is called first between onAttachedToEngine event and onAttachedToActivity event. + // + // See https://github.com/pichillilorenzo/flutter_inappwebview/issues/390#issuecomment-647039084 onAttachedToEngine( - binding.getApplicationContext(), binding.getBinaryMessenger(), null, binding.getPlatformViewRegistry(), null); + binding.getApplicationContext(), binding.getBinaryMessenger(), Shared.activity, binding.getPlatformViewRegistry(), null); } private void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger, Activity activity, PlatformViewRegistry platformViewRegistry, FlutterView flutterView) { + Shared.applicationContext = applicationContext; Shared.activity = activity; Shared.messenger = messenger; diff --git a/ios/Classes/InAppWebView.swift b/ios/Classes/InAppWebView.swift index ca10c3bb..39188156 100755 --- a/ios/Classes/InAppWebView.swift +++ b/ios/Classes/InAppWebView.swift @@ -2962,4 +2962,12 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi deinit { print("InAppWebView - dealloc") } + +// var accessoryView: UIView? +// +// // https://stackoverflow.com/a/58001395/4637638 +// public override var inputAccessoryView: UIView? { +// // remove/replace the default accessory view +// return accessoryView +// } } diff --git a/lib/src/http_auth_credentials_database.dart b/lib/src/http_auth_credentials_database.dart index 2977c2b8..3ea2283b 100755 --- a/lib/src/http_auth_credentials_database.dart +++ b/lib/src/http_auth_credentials_database.dart @@ -31,26 +31,30 @@ class HttpAuthCredentialDatabase { ///Gets a map list of all HTTP auth credentials saved. ///Each map contains the key `protectionSpace` of type [ProtectionSpace] ///and the key `credentials` of type `List` that contains all the HTTP auth credentials saved for that `protectionSpace`. - Future>> getAllAuthCredentials() async { + Future> getAllAuthCredentials() async { Map args = {}; List allCredentials = await _channel.invokeMethod('getAllAuthCredentials', args); - List> result = []; + + List result = []; + for (Map map in allCredentials) { Map protectionSpace = map["protectionSpace"]; List credentials = map["credentials"]; - result.add({ - "protectionSpace": ProtectionSpace( - host: protectionSpace["host"], - protocol: protectionSpace["protocol"], - realm: protectionSpace["realm"], - port: protectionSpace["port"]), - "credentials": credentials - .map((credential) => HttpAuthCredential( - username: credential["username"], - password: credential["password"])) - .toList() - }); + result.add( + ProtectionSpaceHttpAuthCredentials( + protectionSpace: ProtectionSpace( + host: protectionSpace["host"], + protocol: protectionSpace["protocol"], + realm: protectionSpace["realm"], + port: protectionSpace["port"]), + credentials: credentials + .map((credential) => HttpAuthCredential( + username: credential["username"], + password: credential["password"])) + .toList() + ) + ); } return result; } diff --git a/lib/src/types.dart b/lib/src/types.dart index b4c228d8..938cd2eb 100755 --- a/lib/src/types.dart +++ b/lib/src/types.dart @@ -874,6 +874,29 @@ class HttpAuthCredential { } } +class ProtectionSpaceHttpAuthCredentials { + ProtectionSpace protectionSpace; + List credentials; + + ProtectionSpaceHttpAuthCredentials({this.protectionSpace, this.credentials}); + + Map toMap() { + return { + "protectionSpace": protectionSpace?.toMap(), + "credentials": credentials?.map((credential) => credential?.toMap())?.toList() + }; + } + + Map toJson() { + return this.toMap(); + } + + @override + String toString() { + return toMap().toString(); + } +} + ///Class used by [ServerTrustAuthResponse] class. class ServerTrustAuthResponseAction { final int _value; diff --git a/lib/src/webview_options.dart b/lib/src/webview_options.dart index e96fdec4..78bf04fb 100755 --- a/lib/src/webview_options.dart +++ b/lib/src/webview_options.dart @@ -89,7 +89,7 @@ class InAppWebViewOptions ///Set to `true` to be able to listen at the [onDownloadStart] event. The default value is `false`. bool useOnDownloadStart; - ///Set to `true` to have all the browser's cache cleared before the new window is opened. The default value is `false`. + ///Set to `true` to have all the browser's cache cleared before the new WebView is opened. The default value is `false`. bool clearCache; ///Sets the user-agent for the WebView.