Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[webview_flutter_android] Added the functionality to fullscreen html5 video #3879

Merged
merged 64 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
1bbd61f
Added fullscreen capabilities to the android webview
paulppn May 2, 2023
279a678
Fixed the formatting
paulppn May 2, 2023
6649aa8
Fixed some more formatting + added a nonnull
paulppn May 2, 2023
fbc3f57
Removed empty line
paulppn May 2, 2023
06935c9
Adjusted another nonnull
paulppn May 2, 2023
ff9137f
Fixed two lint warnings
paulppn May 2, 2023
bef6c2a
customviewcallback dart impl
bparrishMines May 30, 2023
0cd62d0
view dart impl
bparrishMines May 30, 2023
6ca452a
Merge branch 'main' of github.com:flutter/packages into feature/add_f…
bparrishMines May 30, 2023
ba03b6b
formatting
bparrishMines May 30, 2023
9f0dbe1
dart side of webchromeclient wrap
bparrishMines May 30, 2023
e9295b2
implement java side
bparrishMines May 30, 2023
d547039
fix java side
bparrishMines May 31, 2023
59a0da4
formatting
bparrishMines May 31, 2023
f3693b8
fix pubspec
bparrishMines May 31, 2023
47c7d98
Merge branch 'main' of github.com:flutter/packages into feature/add_f…
bparrishMines May 31, 2023
8151750
remove unneeded lines
bparrishMines May 31, 2023
759f19b
remove unneeded mocks
bparrishMines May 31, 2023
bdb0806
fix lint
bparrishMines May 31, 2023
47e3108
Merge remote-tracking branch 'origin/main' into feature/add_fullscree…
mvanbeusekom Jul 5, 2023
5ea042d
Adds Dart implementation fullscreen video
mvanbeusekom Jul 5, 2023
216757e
Adds Android fullscreen functionality
mvanbeusekom Jul 6, 2023
4ff9e75
Merge branch 'main' into feature/add_fullscreen_video
mvanbeusekom Jul 6, 2023
76c02cc
Merge remote-tracking branch 'origin/main' into feature/add_fullscree…
mvanbeusekom Jul 7, 2023
b899cb0
Merge branch 'feature/add_fullscreen_video' of github.com:paulppn/flu…
mvanbeusekom Jul 7, 2023
24bc43e
Merge remote-tracking branch 'origin/main' into feature/add_fullscree…
mvanbeusekom Jul 11, 2023
afe0b8f
Apply review feedback
mvanbeusekom Jul 11, 2023
e9d418a
Merge branch 'main' into feature/add_fullscreen_video
mvanbeusekom Jul 11, 2023
e347a49
Merge branch 'main' into feature/add_fullscreen_video
mvanbeusekom Jul 12, 2023
ab876f2
Applied PR feedback
mvanbeusekom Jul 12, 2023
9323791
Merge branch 'feature/add_fullscreen_video' of github.com:paulppn/flu…
mvanbeusekom Jul 12, 2023
4cb8746
Merge branch 'main' into feature/add_fullscreen_video
mvanbeusekom Jul 12, 2023
8baca49
Merge branch 'main' into feature/add_fullscreen_video
mvanbeusekom Jul 12, 2023
f385bcc
Merge branch 'main' into feature/add_fullscreen_video
mvanbeusekom Jul 13, 2023
178c5e7
Merge branch 'main' into feature/add_fullscreen_video
mvanbeusekom Jul 19, 2023
37edbf1
Merge remote-tracking branch 'upstream/main' into feature/add_fullscr…
mvanbeusekom Aug 2, 2023
7219770
Merge branch 'feature/add_fullscreen_video' of github.com:paulppn/flu…
mvanbeusekom Aug 2, 2023
c612ef5
Adds integration test to validate fullscreen
mvanbeusekom Aug 3, 2023
9d06cae
Merge branch 'main' into feature/add_fullscreen_video
mvanbeusekom Aug 3, 2023
041441d
Ensure the CustomViewHostApi is setup correctly
mvanbeusekom Aug 3, 2023
d4359d5
Merge branch 'feature/add_fullscreen_video' of github.com:paulppn/flu…
mvanbeusekom Aug 3, 2023
5169000
Merge branch 'main' into feature/add_fullscreen_video
mvanbeusekom Aug 3, 2023
87443f5
Merge remote-tracking branch 'upstream/main' into feature/add_fullscr…
mvanbeusekom Aug 10, 2023
1f1ee82
Merge branch 'main' of https://github.com/flutter/packages into featu…
mvanbeusekom Aug 11, 2023
5ef97bc
Remove obsolete file
mvanbeusekom Aug 11, 2023
ba39519
Merge branch 'main' into feature/add_fullscreen_video
mvanbeusekom Aug 11, 2023
269ad02
Merge branch 'feature/add_fullscreen_video' of github.com:paulppn/flu…
mvanbeusekom Aug 11, 2023
6347f98
Fixed analysis warning
mvanbeusekom Aug 11, 2023
b319604
Formatted JAVA files
mvanbeusekom Aug 14, 2023
aa35251
Merge remote-tracking branch 'upstream/main' into feature/add_fullscr…
mvanbeusekom Aug 15, 2023
d9f9812
Merge branch 'main' of https://github.com/flutter/packages into featu…
mvanbeusekom Aug 17, 2023
3e39dd2
Explain the tapAt statement in integration test
mvanbeusekom Aug 17, 2023
3e74540
Update packages/webview_flutter/webview_flutter_android/example/integ…
bparrishMines Aug 18, 2023
289cccd
update dartdocs and changelog
bparrishMines Aug 18, 2023
1e63109
Merge branch 'main' of github.com:flutter/packages into feature/add_f…
bparrishMines Aug 18, 2023
5d45ea0
provide example for fullscreen
bparrishMines Aug 18, 2023
6ca8d15
require callbacks
bparrishMines Aug 18, 2023
0b7361a
formatting
bparrishMines Aug 21, 2023
cdcff55
Merge branch 'main' of github.com:flutter/packages into feature/add_f…
bparrishMines Aug 21, 2023
45720e4
add a default handler
bparrishMines Aug 25, 2023
67d660d
Merge branch 'main' of github.com:flutter/packages into feature/add_f…
bparrishMines Aug 25, 2023
acfd11d
add integration test
bparrishMines Aug 25, 2023
7744529
switch to unit test
bparrishMines Sep 7, 2023
1a65e0f
Merge branch 'main' of github.com:flutter/packages into feature/add_f…
bparrishMines Sep 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.7.0

* Adds support for fullscreen video.

## 3.6.3

* Updates gradle, AGP and fixes some lint errors.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,24 @@

package io.flutter.plugins.webviewflutter;

import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Message;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.webkit.PermissionRequest;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
Expand All @@ -29,28 +38,96 @@ public class WebChromeClientHostApiImpl implements WebChromeClientHostApi {
private final InstanceManager instanceManager;
private final WebChromeClientCreator webChromeClientCreator;
private final WebChromeClientFlutterApiImpl flutterApi;
private Context context;

/**
* Implementation of {@link WebChromeClient} that passes arguments of callback methods to Dart.
*/
public static class WebChromeClientImpl extends SecureWebChromeClient {
private final WebChromeClientFlutterApiImpl flutterApi;
private boolean returnValueForOnShowFileChooser = false;
private View mFullscreenView;
private Context context;

/**
* Creates a {@link WebChromeClient} that passes arguments of callbacks methods to Dart.
*
* @param flutterApi handles sending messages to Dart
* @param context the Activity or application context
*/
public WebChromeClientImpl(@NonNull WebChromeClientFlutterApiImpl flutterApi) {
public WebChromeClientImpl(
@NonNull WebChromeClientFlutterApiImpl flutterApi, @NonNull Context context) {
this.flutterApi = flutterApi;
this.context = context;
}

@Override
public void onProgressChanged(@NonNull WebView view, int progress) {
flutterApi.onProgressChanged(this, view, (long) progress, reply -> {});
}

@Override
public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
mvanbeusekom marked this conversation as resolved.
Show resolved Hide resolved
if (mFullscreenView != null) {
((ViewGroup) mFullscreenView.getParent()).removeView(mFullscreenView);
}
if (context instanceof Activity) {
Window window = ((Activity) context).getWindow();
mFullscreenView = view;
setFullscreenStatus(true, window);
window.addContentView(
mFullscreenView,
new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
Gravity.CENTER));
}
}

@Override
public void onHideCustomView() {
if (mFullscreenView == null) {
return;
}
if (context instanceof Activity) {
setFullscreenStatus(false, ((Activity) context).getWindow());
((ViewGroup) mFullscreenView.getParent()).removeView(mFullscreenView);
mFullscreenView = null;
}
}

@SuppressWarnings("deprecation")
void activateFullscreenDeprecated(Boolean fullscreen, Window window) {
View decorView = window.getDecorView();
if (fullscreen) {
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);

window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
decorView.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);

window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}

@RequiresApi(api = Build.VERSION_CODES.R) // >= 30
void setFullScreenCurrent(Boolean fullscreen, Window window) {
View decorView = window.getDecorView();
if (fullscreen) {
decorView.getWindowInsetsController().hide(WindowInsets.Type.statusBars());
} else {
decorView.getWindowInsetsController().show(WindowInsets.Type.statusBars());
}
}

void setFullscreenStatus(Boolean fullscreen, Window window) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
activateFullscreenDeprecated(fullscreen, window);
} else {
setFullScreenCurrent(fullscreen, window);
}
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@SuppressWarnings("LambdaLast")
@Override
Expand Down Expand Up @@ -87,6 +164,17 @@ public void onPermissionRequest(@NonNull PermissionRequest request) {
public void setReturnValueForOnShowFileChooser(boolean value) {
returnValueForOnShowFileChooser = value;
}

/**
* Returns the fullscreen view
*
* @return View
*/
@Nullable
@VisibleForTesting
public View getmFullscreenView() {
return this.mFullscreenView;
}
}

/**
Expand Down Expand Up @@ -183,12 +271,13 @@ public static class WebChromeClientCreator {
* Creates a {@link WebChromeClientHostApiImpl.WebChromeClientImpl}.
*
* @param flutterApi handles sending messages to Dart
* @param context the Activity or application context
* @return the created {@link WebChromeClientHostApiImpl.WebChromeClientImpl}
*/
@NonNull
public WebChromeClientImpl createWebChromeClient(
@NonNull WebChromeClientFlutterApiImpl flutterApi) {
return new WebChromeClientImpl(flutterApi);
@NonNull WebChromeClientFlutterApiImpl flutterApi, @NonNull Context context) {
return new WebChromeClientImpl(flutterApi, context);
}
}

Expand All @@ -202,16 +291,27 @@ public WebChromeClientImpl createWebChromeClient(
public WebChromeClientHostApiImpl(
@NonNull InstanceManager instanceManager,
@NonNull WebChromeClientCreator webChromeClientCreator,
@NonNull WebChromeClientFlutterApiImpl flutterApi) {
@NonNull WebChromeClientFlutterApiImpl flutterApi,
@NonNull Context context) {
this.instanceManager = instanceManager;
this.webChromeClientCreator = webChromeClientCreator;
this.flutterApi = flutterApi;
this.context = context;
}

/**
* Sets the context to construct {@link WebChromeClientImpl}s.
*
* @param context the new context
*/
public void setContext(@NonNull Context context) {
this.context = context;
}

@Override
public void create(@NonNull Long instanceId) {
final WebChromeClient webChromeClient =
webChromeClientCreator.createWebChromeClient(flutterApi);
webChromeClientCreator.createWebChromeClient(flutterApi, context);
instanceManager.addDartCreatedInstance(webChromeClient, instanceId);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class WebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
private FlutterPluginBinding pluginBinding;
private WebViewHostApiImpl webViewHostApi;
private JavaScriptChannelHostApiImpl javaScriptChannelHostApi;
private WebChromeClientHostApiImpl webChromeClientHostApi;

/**
* Add an instance of this to {@link io.flutter.embedding.engine.plugins.PluginRegistry} to
Expand Down Expand Up @@ -100,6 +101,13 @@ private void setUp(
new JavaScriptChannelFlutterApiImpl(binaryMessenger, instanceManager),
new Handler(context.getMainLooper()));

webChromeClientHostApi =
new WebChromeClientHostApiImpl(
instanceManager,
new WebChromeClientHostApiImpl.WebChromeClientCreator(),
new WebChromeClientFlutterApiImpl(binaryMessenger, instanceManager),
context);

JavaObjectHostApi.setup(binaryMessenger, new JavaObjectHostApiImpl(instanceManager));
WebViewHostApi.setup(binaryMessenger, webViewHostApi);
JavaScriptChannelHostApi.setup(binaryMessenger, javaScriptChannelHostApi);
Expand All @@ -109,12 +117,7 @@ private void setUp(
instanceManager,
new WebViewClientHostApiImpl.WebViewClientCreator(),
new WebViewClientFlutterApiImpl(binaryMessenger, instanceManager)));
WebChromeClientHostApi.setup(
binaryMessenger,
new WebChromeClientHostApiImpl(
instanceManager,
new WebChromeClientHostApiImpl.WebChromeClientCreator(),
new WebChromeClientFlutterApiImpl(binaryMessenger, instanceManager)));
WebChromeClientHostApi.setup(binaryMessenger, webChromeClientHostApi);
DownloadListenerHostApi.setup(
binaryMessenger,
new DownloadListenerHostApiImpl(
Expand Down Expand Up @@ -181,6 +184,7 @@ public void onDetachedFromActivity() {
private void updateContext(Context context) {
webViewHostApi.setContext(context);
javaScriptChannelHostApi.setPlatformThreadHandler(new Handler(context.getMainLooper()));
webChromeClientHostApi.setContext(context);
}

/** Maintains instances used to communicate with the corresponding objects in Dart. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package io.flutter.plugins.webviewflutter;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
Expand All @@ -13,8 +14,11 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.Message;
import android.view.Window;
import android.webkit.PermissionRequest;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
Expand All @@ -41,6 +45,12 @@ public class WebChromeClientTest {

@Mock public WebViewClient mockWebViewClient;

@Mock public Context mockContext;

@Mock public Activity mockActivity;

@Mock public Window mockWindow;

InstanceManager instanceManager;
WebChromeClientHostApiImpl hostApiImpl;
WebChromeClientImpl webChromeClient;
Expand All @@ -54,15 +64,21 @@ public void setUp() {
@Override
@NonNull
public WebChromeClientImpl createWebChromeClient(
@NonNull WebChromeClientFlutterApiImpl flutterApi) {
webChromeClient = super.createWebChromeClient(flutterApi);
@NonNull WebChromeClientFlutterApiImpl flutterApi, @NonNull Context context) {
webChromeClient = super.createWebChromeClient(flutterApi, context);
return webChromeClient;
}
};

hostApiImpl =
new WebChromeClientHostApiImpl(instanceManager, webChromeClientCreator, mockFlutterApi);
new WebChromeClientHostApiImpl(
instanceManager, webChromeClientCreator, mockFlutterApi, mockContext);
hostApiImpl.setContext(mockActivity);
hostApiImpl.create(2L);

when(mockActivity.getWindow()).thenReturn(mockWindow);
when(mockWebView.getParent()).thenReturn(mockWebView);
when(mockWindow.getDecorView()).thenReturn(mockWebView);
}

@After
Expand Down Expand Up @@ -125,4 +141,17 @@ public void onPermissionRequest() {

verify(mockFlutterApi).onPermissionRequest(eq(webChromeClient), eq(mockRequest), any());
}

@Test
public void onShowCustomView() {
webChromeClient.onShowCustomView(mockWebView, null);
assertNotNull(webChromeClient.getmFullscreenView());
}

@Test
public void onHideCustomView() {
webChromeClient.onShowCustomView(mockWebView, null);
webChromeClient.onHideCustomView();
assertNull(webChromeClient.getmFullscreenView());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: webview_flutter_android
description: A Flutter plugin that provides a WebView widget on Android.
repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
version: 3.6.3
version: 3.7.0

environment:
sdk: ">=2.18.0 <4.0.0"
Expand Down