Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions packages/webview_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 0.3.15+3

* Re-land support for the v2 Android embedding. This correctly sets the minimum
SDK to the latest stable and avoid any compile errors. *WARNING:* the V2
embedding itself still requires the current Flutter master channel
(flutter/flutter@1d4d63a) for text input to work properly on all Android
versions.

## 0.3.15+2

* Remove AndroidX warnings.
Expand Down
25 changes: 25 additions & 0 deletions packages/webview_flutter/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,28 @@ android {
implementation 'androidx.webkit:webkit:1.0.0'
}
}

// TODO(mklim): Remove this hack once androidx.lifecycle is included on stable. https://github.com/flutter/flutter/issues/42348
afterEvaluate {
def containsEmbeddingDependencies = false
for (def configuration : configurations.all) {
for (def dependency : configuration.dependencies) {
if (dependency.group == 'io.flutter' &&
dependency.name.startsWith('flutter_embedding') &&
dependency.isTransitive())
{
containsEmbeddingDependencies = true
break
}
}
}
if (!containsEmbeddingDependencies) {
android {
dependencies {
def lifecycle_version = "1.1.1"
compileOnly "android.arch.lifecycle:common-java8:$lifecycle_version"
compileOnly "android.arch.lifecycle:runtime:$lifecycle_version"
}
}
}
}
1 change: 0 additions & 1 deletion packages/webview_flutter/android/gradle.properties

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,11 @@
import io.flutter.plugin.common.MethodChannel.Result;

class FlutterCookieManager implements MethodCallHandler {
private final MethodChannel methodChannel;

private FlutterCookieManager() {
// Do not instantiate.
// This class should only be used in context of a BinaryMessenger.
// Use FlutterCookieManager#registerWith instead.
}

static void registerWith(BinaryMessenger messenger) {
MethodChannel methodChannel = new MethodChannel(messenger, "plugins.flutter.io/cookie_manager");
FlutterCookieManager cookieManager = new FlutterCookieManager();
methodChannel.setMethodCallHandler(cookieManager);
FlutterCookieManager(BinaryMessenger messenger) {
methodChannel = new MethodChannel(messenger, "plugins.flutter.io/cookie_manager");
methodChannel.setMethodCallHandler(this);
}

@Override
Expand All @@ -39,6 +33,10 @@ public void onMethodCall(MethodCall methodCall, Result result) {
}
}

void dispose() {
methodChannel.setMethodCallHandler(null);
}

private static void clearCookies(final Result result) {
CookieManager cookieManager = CookieManager.getInstance();
final boolean hasCookies = cookieManager.hasCookies();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
BinaryMessenger messenger,
int id,
Map<String, Object> params,
final View containerView) {
View containerView) {

DisplayListenerProxy displayListenerProxy = new DisplayListenerProxy();
DisplayManager displayManager =
Expand Down Expand Up @@ -95,6 +95,26 @@ public void onInputConnectionLocked() {
webView.lockInputConnection();
}

// @Override
// This is overriding a method that hasn't rolled into stable Flutter yet. Including the
// annotation would cause compile time failures in versions of Flutter too old to include the new
// method. However leaving it raw like this means that the method will be ignored in old versions
// of Flutter but used as an override anyway wherever it's actually defined.
// TODO(mklim): Add the @Override annotation once stable passes v1.10.9.
public void onFlutterViewAttached(View flutterView) {
webView.setContainerView(flutterView);
}

// @Override
// This is overriding a method that hasn't rolled into stable Flutter yet. Including the
// annotation would cause compile time failures in versions of Flutter too old to include the new
// method. However leaving it raw like this means that the method will be ignored in old versions
// of Flutter but used as an override anyway wherever it's actually defined.
// TODO(mklim): Add the @Override annotation once stable passes v1.10.9.
public void onFlutterViewDetached() {
webView.setContainerView(null);
}

@Override
public void onMethodCall(MethodCall methodCall, Result result) {
switch (methodCall.method) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.annotation.NonNull;
import androidx.webkit.WebViewClientCompat;
import io.flutter.plugin.common.MethodChannel;
import java.util.HashMap;
Expand Down Expand Up @@ -124,8 +123,7 @@ public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
private WebViewClientCompat internalCreateWebViewClientCompat() {
return new WebViewClientCompat() {
@Override
public boolean shouldOverrideUrlLoading(
@NonNull WebView view, @NonNull WebResourceRequest request) {
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return FlutterWebViewClient.this.shouldOverrideUrlLoading(view, request);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static android.content.Context.INPUT_METHOD_SERVICE;

import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebView;
Expand All @@ -22,16 +23,29 @@
* <p>See also {@link ThreadedInputConnectionProxyAdapterView}.
*/
final class InputAwareWebView extends WebView {
private final View containerView;

private static final String TAG = "InputAwareWebView";
private View threadedInputConnectionProxyView;
private ThreadedInputConnectionProxyAdapterView proxyAdapterView;
private View containerView;

InputAwareWebView(Context context, View containerView) {
super(context);
this.containerView = containerView;
}

void setContainerView(View containerView) {
this.containerView = containerView;

if (proxyAdapterView == null) {
return;
}

Log.w(TAG, "The containerView has changed while the proxyAdapterView exists.");
if (containerView != null) {
setInputConnectionTarget(proxyAdapterView);
}
}

/**
* Set our proxy adapter view to use its cached input connection instead of creating new ones.
*
Expand Down Expand Up @@ -81,6 +95,12 @@ public boolean checkInputConnectionProxy(final View view) {
// This isn't a new ThreadedInputConnectionProxyView. Ignore it.
return super.checkInputConnectionProxy(view);
}
if (containerView == null) {
Log.e(
TAG,
"Can't create a proxy view because there's no container view. Text input may not work.");
return super.checkInputConnectionProxy(view);
}

// We've never seen this before, so we make the assumption that this is WebView's
// ThreadedInputConnectionProxyView. We are making the assumption that the only view that could
Expand Down Expand Up @@ -120,6 +140,10 @@ private void resetInputConnection() {
// No need to reset the InputConnection to the default thread if we've never changed it.
return;
}
if (containerView == null) {
Log.e(TAG, "Can't reset the input connection to the container view because there is none.");
return;
}
setInputConnectionTarget(/*targetView=*/ containerView);
}

Expand All @@ -132,6 +156,13 @@ private void resetInputConnection() {
* InputConnections should be created on.
*/
private void setInputConnectionTarget(final View targetView) {
if (containerView == null) {
Log.e(
TAG,
"Can't set the input connection target because there is no containerView to use as a handler.");
return;
}

targetView.requestFocus();
containerView.post(
new Runnable() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,71 @@

package io.flutter.plugins.webviewflutter;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry.Registrar;

/** WebViewFlutterPlugin */
public class WebViewFlutterPlugin {
/** Plugin registration. */
/**
* Java platform implementation of the webview_flutter plugin.
*
* <p>Register this in an add to app scenario to gracefully handle activity and context changes.
*
* <p>Call {@link #registerWith(Registrar)} to use the stable {@code io.flutter.plugin.common}
* package instead.
*/
public class WebViewFlutterPlugin implements FlutterPlugin {

private FlutterCookieManager flutterCookieManager;

/**
* Add an instance of this to {@link io.flutter.embedding.engine.plugins.PluginRegistry} to
* register it.
*
* <p>THIS PLUGIN CODE PATH DEPENDS ON A NEWER VERSION OF FLUTTER THAN THE ONE DEFINED IN THE
* PUBSPEC.YAML. Text input will fail on some Android devices unless this is used with at least
* flutter/flutter@1d4d63ace1f801a022ea9ec737bf8c15395588b9. Use the V1 embedding with {@link
* #registerWith(Registrar)} to use this plugin with older Flutter versions.
*
* <p>Registration should eventually be handled automatically by v2 of the
* GeneratedPluginRegistrant. https://github.com/flutter/flutter/issues/42694
*/
public WebViewFlutterPlugin() {}

/**
* Registers a plugin implementation that uses the stable {@code io.flutter.plugin.common}
* package.
*
* <p>Calling this automatically initializes the plugin. However plugins initialized this way
* won't react to changes in activity or context, unlike {@link CameraPlugin}.
*/
public static void registerWith(Registrar registrar) {
registrar
.platformViewRegistry()
.registerViewFactory(
"plugins.flutter.io/webview",
new WebViewFactory(registrar.messenger(), registrar.view()));
FlutterCookieManager.registerWith(registrar.messenger());
new FlutterCookieManager(registrar.messenger());
}

@Override
public void onAttachedToEngine(FlutterPluginBinding binding) {
BinaryMessenger messenger = binding.getFlutterEngine().getDartExecutor();
binding
.getFlutterEngine()
.getPlatformViewsController()
.getRegistry()
.registerViewFactory(
"plugins.flutter.io/webview", new WebViewFactory(messenger, /*containerView=*/ null));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: extra =?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a subjective style decision. I tend to manually write in parameter hints in the style of /*parameterName=*/ to make function calls easier to reason about even when the code is being read as plain text.

// Extreme hypothetical confusing example.
return new Fraction(/*numerator=*/2, /*denominator=*/3);

Most IDEs will automatically do this for you, but for reading Github or something like Vim I think it's helpful.

flutterCookieManager = new FlutterCookieManager(messenger);
}

@Override
public void onDetachedFromEngine(FlutterPluginBinding binding) {
if (flutterCookieManager == null) {
return;
}

flutterCookieManager.dispose();
flutterCookieManager = null;
}
}
5 changes: 3 additions & 2 deletions packages/webview_flutter/example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ flutter {

dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test:rules:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.flutter.plugins.webviewflutterexample;

import androidx.test.rule.ActivityTestRule;
import dev.flutter.plugins.e2e.FlutterRunner;
import org.junit.Rule;
import org.junit.runner.RunWith;

@RunWith(FlutterRunner.class)
public class EmbeddingV1ActivityTest {
@Rule
public ActivityTestRule<EmbeddingV1Activity> rule =
new ActivityTestRule<>(EmbeddingV1Activity.class);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.flutter.plugins.webviewflutterexample;

import androidx.test.rule.ActivityTestRule;
import dev.flutter.plugins.e2e.FlutterRunner;
import org.junit.Rule;
import org.junit.runner.RunWith;

@RunWith(FlutterRunner.class)
public class MainActivityTest {
@Rule public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class);
}
Loading