From 449bfd06ef845314844bcbc5ef983b554dbece6b Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Sun, 1 May 2022 04:03:17 +0200 Subject: [PATCH] added isInFullscreen method --- CHANGELOG.md | 2 +- .../InAppWebViewMethodHandler.java | 7 +++ .../in_app_webview/InAppWebView.java | 13 ++++- .../InAppWebViewChromeClient.java | 19 +++++- .../types/InAppWebViewInterface.java | 2 + .../ios/Flutter/flutter_export_environment.sh | 4 +- example/lib/in_app_webiew_example.screen.dart | 11 +--- example/lib/main.dart | 2 +- ios/Classes/InAppWebView/InAppWebView.swift | 58 ++++++++++++++----- ios/Classes/InAppWebViewMethodHandler.swift | 11 ++++ .../in_app_webview_controller.dart | 10 ++++ 11 files changed, 110 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7914bbaa..2b802923 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ - Deprecated old classes/properties/methods to make them eventually compatible with other Platforms and WebView engines. - Added Web support -- Added `pauseAllMediaPlayback`, `setAllMediaPlaybackSuspended`, `closeAllMediaPresentations`, `requestMediaPlaybackState` WebView controller methods +- Added `pauseAllMediaPlayback`, `setAllMediaPlaybackSuspended`, `closeAllMediaPresentations`, `requestMediaPlaybackState`, `isInFullscreen` WebView controller methods - Added `underPageBackgroundColor`, `isTextInteractionEnabled`, `isSiteSpecificQuirksModeEnabled`, `upgradeKnownHostsToHTTPS` WebView settings - Added support for `onPermissionRequest` event on iOS 15.0+ - Updated `getMetaThemeColor` on iOS 15.0+ diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewMethodHandler.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewMethodHandler.java index 5c9e1641..4ebf9b46 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewMethodHandler.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewMethodHandler.java @@ -598,6 +598,13 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle result.success(false); } break; + case "isInFullscreen": + if (webView != null) { + result.success(webView.isInFullscreen()); + } else { + result.success(false); + } + break; default: result.notImplemented(); } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/InAppWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/InAppWebView.java index 1ec9b347..f4f222af 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/InAppWebView.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/InAppWebView.java @@ -121,6 +121,7 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie public JavaScriptBridgeInterface javaScriptBridgeInterface; public InAppWebViewSettings customSettings; public boolean isLoading = false; + private boolean inFullscreen = false; public OkHttpClient httpClient; public float zoomScale = 1.0f; int okHttpClientCacheSize = 10 * 1024 * 1024; // 10MB @@ -187,7 +188,7 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie javaScriptBridgeInterface = new JavaScriptBridgeInterface(this); addJavascriptInterface(javaScriptBridgeInterface, JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME); - inAppWebViewChromeClient = new InAppWebViewChromeClient(plugin, channel, inAppBrowserDelegate); + inAppWebViewChromeClient = new InAppWebViewChromeClient(plugin, channel, this, inAppBrowserDelegate); setWebChromeClient(inAppWebViewChromeClient); inAppWebViewClient = new InAppWebViewClient(channel, inAppBrowserDelegate); @@ -1691,6 +1692,16 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie return Looper.getMainLooper(); } + @Override + public boolean isInFullscreen() { + return inFullscreen; + } + + @Override + public void setInFullscreen(boolean inFullscreen) { + this.inFullscreen = inFullscreen; + } + @Override public void postWebMessage(com.pichillilorenzo.flutter_inappwebview.types.WebMessage message, Uri targetOrigin, ValueCallback callback) throws Exception { throw new UnsupportedOperationException(); diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/InAppWebViewChromeClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/InAppWebViewChromeClient.java index e24b35b2..25ecfa32 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/InAppWebViewChromeClient.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/InAppWebViewChromeClient.java @@ -34,6 +34,7 @@ import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AlertDialog; @@ -45,6 +46,7 @@ import com.pichillilorenzo.flutter_inappwebview.in_app_browser.ActivityResultLis import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserDelegate; import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin; import com.pichillilorenzo.flutter_inappwebview.R; +import com.pichillilorenzo.flutter_inappwebview.types.InAppWebViewInterface; import com.pichillilorenzo.flutter_inappwebview.types.URLRequest; import java.io.ByteArrayOutputStream; @@ -101,11 +103,15 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR private int mOriginalSystemUiVisibility; @Nullable public InAppWebViewFlutterPlugin plugin; + @Nullable + public InAppWebViewInterface inAppWebView; - public InAppWebViewChromeClient(final InAppWebViewFlutterPlugin plugin, MethodChannel channel, InAppBrowserDelegate inAppBrowserDelegate) { + public InAppWebViewChromeClient(@NonNull final InAppWebViewFlutterPlugin plugin, MethodChannel channel, + @NonNull InAppWebViewInterface inAppWebView, InAppBrowserDelegate inAppBrowserDelegate) { super(); this.plugin = plugin; this.channel = channel; + this.inAppWebView = inAppWebView; this.inAppBrowserDelegate = inAppBrowserDelegate; if (this.inAppBrowserDelegate != null) { this.inAppBrowserDelegate.getActivityResultListeners().add(this); @@ -142,6 +148,10 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); Map obj = new HashMap<>(); channel.invokeMethod("onExitFullscreen", obj); + + if (inAppWebView != null) { + inAppWebView.setInFullscreen(false); + } } @Override @@ -173,9 +183,13 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR } activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); ((FrameLayout) decorView).addView(this.mCustomView, FULLSCREEN_LAYOUT_PARAMS); - + Map obj = new HashMap<>(); channel.invokeMethod("onEnterFullscreen", obj); + + if (inAppWebView != null) { + inAppWebView.setInFullscreen(true); + } } @Override @@ -1221,5 +1235,6 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR inAppBrowserDelegate = null; } plugin = null; + inAppWebView = null; } } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/InAppWebViewInterface.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/InAppWebViewInterface.java index cc8c9333..aedaccdd 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/InAppWebViewInterface.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/InAppWebViewInterface.java @@ -100,4 +100,6 @@ public interface InAppWebViewInterface { void disposeWebMessageChannels(); void disposeWebMessageListeners(); Looper getWebViewLooper(); + boolean isInFullscreen(); + void setInFullscreen(boolean inFullscreen); } diff --git a/example/ios/Flutter/flutter_export_environment.sh b/example/ios/Flutter/flutter_export_environment.sh index 03bce7c9..9e98dd5e 100755 --- a/example/ios/Flutter/flutter_export_environment.sh +++ b/example/ios/Flutter/flutter_export_environment.sh @@ -3,11 +3,11 @@ export "FLUTTER_ROOT=/Users/lorenzopichilli/fvm/versions/2.10.4" export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example" export "COCOAPODS_PARALLEL_CODE_SIGN=true" -export "FLUTTER_TARGET=integration_test/webview_flutter_test.dart" +export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart" export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" -export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==" +export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false" diff --git a/example/lib/in_app_webiew_example.screen.dart b/example/lib/in_app_webiew_example.screen.dart index ba8418da..b2e567d7 100755 --- a/example/lib/in_app_webiew_example.screen.dart +++ b/example/lib/in_app_webiew_example.screen.dart @@ -21,8 +21,7 @@ class _InAppWebViewExampleScreenState extends State { mediaPlaybackRequiresUserGesture: false, allowsInlineMediaPlayback: true, iframeAllow: "camera; microphone", - iframeAllowFullscreen: true, - javaScriptEnabled: false + iframeAllowFullscreen: true ); PullToRefreshController? pullToRefreshController; @@ -115,7 +114,7 @@ class _InAppWebViewExampleScreenState extends State { InAppWebView( key: webViewKey, initialUrlRequest: - URLRequest(url: Uri.parse("https://flutter.dev")), + URLRequest(url: Uri.parse("https://www.youtube.com/watch?v=CylXr3AF3uU")), // initialUrlRequest: // URLRequest(url: Uri.parse(Uri.base.toString().replaceFirst("/#/", "/") + 'page.html')), // initialFile: "assets/index.html", @@ -218,12 +217,6 @@ class _InAppWebViewExampleScreenState extends State { webViewController?.reload(); }, ), - ElevatedButton( - child: Icon(Icons.refresh), - onPressed: () { - webViewController?.evaluateJavascript(source: "document.title='test';"); - }, - ), ], ), ]))); diff --git a/example/lib/main.dart b/example/lib/main.dart index f453b613..5da8fb6a 100755 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -19,7 +19,7 @@ Future main() async { // await Permission.microphone.request(); // await Permission.storage.request(); - WebView.debugLogging = true; + WebView.debugLogging = false; if (defaultTargetPlatform == TargetPlatform.android) { await InAppWebViewController.setWebContentsDebuggingEnabled(true); diff --git a/ios/Classes/InAppWebView/InAppWebView.swift b/ios/Classes/InAppWebView/InAppWebView.swift index 62d5594d..1fbcabe7 100755 --- a/ios/Classes/InAppWebView/InAppWebView.swift +++ b/ios/Classes/InAppWebView/InAppWebView.swift @@ -23,6 +23,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, var webMessageChannels: [String:WebMessageChannel] = [:] var webMessageListeners: [WebMessageListener] = [] var currentOriginalUrl: URL? + var inFullscreen = false static var sslCertificatesMap: [String: SslCertificate] = [:] // [URL host name : SslCertificate] static var credentialsProposed: [URLCredential] = [] @@ -320,17 +321,24 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, name: UIMenuController.didHideMenuNotification, object: nil) - // listen for videos playing in fullscreen - NotificationCenter.default.addObserver(self, - selector: #selector(onEnterFullscreen(_:)), - name: UIWindow.didBecomeVisibleNotification, - object: window) +// if #available(iOS 15.0, *) { +// addObserver(self, +// forKeyPath: #keyPath(WKWebView.fullscreenState), +// options: .new, +// context: nil) +// } else { + // listen for videos playing in fullscreen + NotificationCenter.default.addObserver(self, + selector: #selector(onEnterFullscreen(_:)), + name: UIWindow.didBecomeVisibleNotification, + object: window) - // listen for videos stopping to play in fullscreen - NotificationCenter.default.addObserver(self, - selector: #selector(onExitFullscreen(_:)), - name: UIWindow.didBecomeHiddenNotification, - object: window) + // listen for videos stopping to play in fullscreen + NotificationCenter.default.addObserver(self, + selector: #selector(onExitFullscreen(_:)), + name: UIWindow.didBecomeHiddenNotification, + object: window) +// } if let settings = settings { if settings.transparentBackground { @@ -639,6 +647,15 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, } } } +// else if #available(iOS 15.0, *) { +// if keyPath == #keyPath(WKWebView.fullscreenState) { +// if fullscreenState == .enteringFullscreen { +// onEnterFullscreen() +// } else if fullscreenState == .exitingFullscreen { +// onExitFullscreen() +// } +// } +// } replaceGestureHandlerIfNeeded() } @@ -2676,7 +2693,9 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { public func isVideoPlayerWindow(_ notificationObject: AnyObject?) -> Bool { let nonVideoClasses = ["_UIAlertControllerShimPresenterWindow", "UITextEffectsWindow", - "UIRemoteKeyboardWindow"] + "UIRemoteKeyboardWindow", + "PGHostedWindow"] + var isVideo = true if let obj = notificationObject { for nonVideoClass in nonVideoClasses { @@ -2690,16 +2709,26 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { @objc func onEnterFullscreen(_ notification: Notification) { if (isVideoPlayerWindow(notification.object as AnyObject?)) { - channel?.invokeMethod("onEnterFullscreen", arguments: []) + onEnterFullscreen() + inFullscreen = true } } + public func onEnterFullscreen() { + channel?.invokeMethod("onEnterFullscreen", arguments: []) + } + @objc func onExitFullscreen(_ notification: Notification) { if (isVideoPlayerWindow(notification.object as AnyObject?)) { - channel?.invokeMethod("onExitFullscreen", arguments: []) + onExitFullscreen() + inFullscreen = false } } + public func onExitFullscreen() { + channel?.invokeMethod("onExitFullscreen", arguments: []) + } + // public func onContextMenuConfigurationForElement(linkURL: String?, result: FlutterResult?) { // let arguments: [String: Any?] = ["linkURL": linkURL] // channel?.invokeMethod("onContextMenuConfigurationForElement", arguments: arguments, result: result) @@ -3074,6 +3103,9 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { removeObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress)) removeObserver(self, forKeyPath: #keyPath(WKWebView.url)) removeObserver(self, forKeyPath: #keyPath(WKWebView.title)) +// if #available(iOS 15.0, *) { +// removeObserver(self, forKeyPath: #keyPath(WKWebView.fullscreenState)) +// } scrollView.removeObserver(self, forKeyPath: #keyPath(UIScrollView.contentOffset)) scrollView.removeObserver(self, forKeyPath: #keyPath(UIScrollView.zoomScale)) resumeTimers() diff --git a/ios/Classes/InAppWebViewMethodHandler.swift b/ios/Classes/InAppWebViewMethodHandler.swift index 38f789f0..e504060b 100644 --- a/ios/Classes/InAppWebViewMethodHandler.swift +++ b/ios/Classes/InAppWebViewMethodHandler.swift @@ -592,6 +592,17 @@ public class InAppWebViewMethodHandler: FlutterMethodCallDelegate { result(nil) } break + case "isInFullscreen": +// if let webView = webView, #available(iOS 15.0, *) { +// result(webView.fullscreenState == .inFullscreen) +// } + if let webView = webView { + result(webView.inFullscreen) + } + else { + result(false) + } + break default: result(FlutterMethodNotImplemented) break diff --git a/lib/src/in_app_webview/in_app_webview_controller.dart b/lib/src/in_app_webview/in_app_webview_controller.dart index 3226c542..f5f83272 100644 --- a/lib/src/in_app_webview/in_app_webview_controller.dart +++ b/lib/src/in_app_webview/in_app_webview_controller.dart @@ -3192,6 +3192,16 @@ class InAppWebViewController { await _channel.invokeMethod('requestMediaPlaybackState', args)); } + ///Returns `true` if the [WebView] is in fullscreen mode, otherwise `false`. + /// + ///**Supported Platforms/Implementations**: + ///- Android native WebView + ///- iOS + Future isInFullscreen() async { + Map args = {}; + return await _channel.invokeMethod('isInFullscreen', args); + } + ///Returns the iframe `id` attribute used on the Web platform. /// ///**Supported Platforms/Implementations**: