added new Android webview events and options, other bug fixes
This commit is contained in:
parent
3731ef5f52
commit
682c6e2243
|
@ -5,10 +5,19 @@
|
|||
- Added Android keyboard workaround to hide the keyboard when clicking other HTML elements, losing the focus on the previous input
|
||||
- Added `onEnterFullscreen`, `onExitFullscreen` webview events [#275](https://github.com/pichillilorenzo/flutter_inappwebview/issues/275)
|
||||
- Added Android support to use camera on HTML inputs that requires it, such as `<input type="file" accept="image/*" capture>` [#353](https://github.com/pichillilorenzo/flutter_inappwebview/issues/353)
|
||||
- Added `overScrollMode`, `networkAvailable`, `scrollBarStyle`, `verticalScrollbarPosition`, `scrollBarDefaultDelayBeforeFade`, `scrollbarFadingEnabled`, `scrollBarFadeDuration`, `rendererPriorityPolicy` webview options on Android
|
||||
- Added `pageDown`, `pageUp`, `saveWebArchive`, `zoomIn`, `zoomOut` webview methods on Android
|
||||
- Added `getCurrentWebViewPackage` static webview method on Android
|
||||
- Added `shouldInterceptRequest`, `onRenderProcessUnresponsive`, `onRenderProcessResponsive`, `onRenderProcessGone`, `onFormResubmission`, `onPageCommitVisible`, `onScaleChanged` Android events
|
||||
- Fixed `Print preview is not working? java.lang.IllegalStateException: Can print only from an activity` [#128](https://github.com/pichillilorenzo/flutter_inappwebview/issues/128)
|
||||
- Fixed `onJsAlert`, `onJsConfirm`, `onJsPrompt` for `InAppBrowser` on Android
|
||||
- Fixed `onActivityResult` for `InAppBrowser` on Android
|
||||
- Fixed `InAppBrowser.openWithSystemBrowser crash on iOS` [#358](https://github.com/pichillilorenzo/flutter_inappwebview/issues/358)
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
- Android `clearClientCertPreferences`, `getSafeBrowsingPrivacyPolicyUrl`, `setSafeBrowsingWhitelist` webview methods are static now
|
||||
|
||||
## 3.2.0
|
||||
|
||||
- Added `ContextMenu` and `ContextMenuItem` classes [#235](https://github.com/pichillilorenzo/flutter_inappwebview/issues/235)
|
||||
|
|
|
@ -142,7 +142,7 @@ On **Android**, you need to add some additional configurations.
|
|||
Add the following codes inside the `<application>` tag of your `android/app/src/main/AndroidManifest.xml`:
|
||||
```xml
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:name="com.pichillilorenzo.flutter_inappwebview.InAppWebViewFileProvider"
|
||||
android:authorities="${applicationId}.flutter_inappwebview.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
|
|
|
@ -45,8 +45,8 @@ android {
|
|||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation 'androidx.webkit:webkit:1.0.0'
|
||||
implementation 'androidx.browser:browser:1.0.0'
|
||||
implementation 'androidx.webkit:webkit:1.2.0'
|
||||
implementation 'androidx.browser:browser:1.2.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.0.0'
|
||||
implementation 'com.squareup.okhttp3:mockwebserver:3.11.0'
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import android.view.Menu;
|
|||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
@ -23,6 +24,8 @@ import android.widget.SearchView;
|
|||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.webkit.WebViewCompat;
|
||||
import androidx.webkit.WebViewFeature;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebViewOptions;
|
||||
|
@ -31,6 +34,7 @@ import com.pichillilorenzo.flutter_inappwebview.Shared;
|
|||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -52,6 +56,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
public ProgressBar progressBar;
|
||||
public boolean isHidden = false;
|
||||
public String fromActivity;
|
||||
public List<ActivityResultListener> activityResultListeners = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -256,9 +261,6 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
case "startSafeBrowsing":
|
||||
startSafeBrowsing(result);
|
||||
break;
|
||||
case "setSafeBrowsingWhitelist":
|
||||
setSafeBrowsingWhitelist((List<String>) call.argument("hosts"), result);
|
||||
break;
|
||||
case "clearCache":
|
||||
clearCache();
|
||||
result.success(true);
|
||||
|
@ -267,9 +269,6 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
clearSslPreferences();
|
||||
result.success(true);
|
||||
break;
|
||||
case "clearClientCertPreferences":
|
||||
clearClientCertPreferences(result);
|
||||
break;
|
||||
case "findAllAsync":
|
||||
String find = (String) call.argument("find");
|
||||
findAllAsync(find);
|
||||
|
@ -726,18 +725,19 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
return null;
|
||||
}
|
||||
|
||||
public void startSafeBrowsing(MethodChannel.Result result) {
|
||||
if (webView != null)
|
||||
webView.startSafeBrowsing(result);
|
||||
else
|
||||
result.success(false);
|
||||
}
|
||||
|
||||
public void setSafeBrowsingWhitelist(List<String> hosts, MethodChannel.Result result) {
|
||||
if (webView != null)
|
||||
webView.setSafeBrowsingWhitelist(hosts, result);
|
||||
else
|
||||
public void startSafeBrowsing(final MethodChannel.Result result) {
|
||||
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 &&
|
||||
WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING)) {
|
||||
WebViewCompat.startSafeBrowsing(webView.getContext(), new ValueCallback<Boolean>() {
|
||||
@Override
|
||||
public void onReceiveValue(Boolean success) {
|
||||
result.success(success);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
result.success(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
|
@ -750,19 +750,6 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
webView.clearSslPreferences();
|
||||
}
|
||||
|
||||
public void clearClientCertPreferences(final MethodChannel.Result result) {
|
||||
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
webView.clearClientCertPreferences(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
result.success(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
result.success(false);
|
||||
}
|
||||
|
||||
public void findAllAsync(String find) {
|
||||
if (webView != null)
|
||||
webView.findAllAsync(find);
|
||||
|
@ -867,7 +854,11 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
|
||||
public void dispose() {
|
||||
channel.setMethodCallHandler(null);
|
||||
activityResultListeners.clear();
|
||||
if (webView != null) {
|
||||
if (Shared.activityPluginBinding != null) {
|
||||
Shared.activityPluginBinding.removeActivityResultListener(webView.inAppWebViewChromeClient);
|
||||
}
|
||||
webView.setWebChromeClient(new WebChromeClient());
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
|
@ -880,9 +871,26 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult (int requestCode,
|
||||
int resultCode,
|
||||
Intent data) {
|
||||
for (ActivityResultListener listener : activityResultListeners) {
|
||||
if (listener.onActivityResult(requestCode, resultCode, data)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
dispose();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
public interface ActivityResultListener {
|
||||
/** @return true if the result has been handled. */
|
||||
boolean onActivityResult(int requestCode, int resultCode, Intent data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,15 @@ import android.os.Handler;
|
|||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import androidx.webkit.WebViewCompat;
|
||||
import androidx.webkit.WebViewFeature;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
|
||||
|
@ -31,7 +35,7 @@ import static io.flutter.plugin.common.MethodChannel.Result;
|
|||
|
||||
public class FlutterWebView implements PlatformView, MethodCallHandler {
|
||||
|
||||
static final String LOG_TAG = "FlutterWebView";
|
||||
static final String LOG_TAG = "IAWFlutterWebView";
|
||||
|
||||
public InAppWebView webView;
|
||||
public final MethodChannel channel;
|
||||
|
@ -253,24 +257,18 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
result.success((webView != null) ? webView.getCopyBackForwardList() : null);
|
||||
break;
|
||||
case "startSafeBrowsing":
|
||||
if (webView != null)
|
||||
webView.startSafeBrowsing(result);
|
||||
else
|
||||
result.success(false);
|
||||
break;
|
||||
case "setSafeBrowsingWhitelist":
|
||||
if (webView != null) {
|
||||
List<String> hosts = (List<String>) call.argument("hosts");
|
||||
webView.setSafeBrowsingWhitelist(hosts, result);
|
||||
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 &&
|
||||
WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING)) {
|
||||
WebViewCompat.startSafeBrowsing(webView.getContext(), new ValueCallback<Boolean>() {
|
||||
@Override
|
||||
public void onReceiveValue(Boolean success) {
|
||||
result.success(success);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
else {
|
||||
result.success(false);
|
||||
break;
|
||||
case "getSafeBrowsingPrivacyPolicyUrl":
|
||||
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||
result.success(webView.getSafeBrowsingPrivacyPolicyUrl().toString());
|
||||
} else
|
||||
result.success(null);
|
||||
}
|
||||
break;
|
||||
case "clearCache":
|
||||
if (webView != null)
|
||||
|
@ -282,18 +280,6 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
webView.clearSslPreferences();
|
||||
result.success(true);
|
||||
break;
|
||||
case "clearClientCertPreferences":
|
||||
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
webView.clearClientCertPreferences(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
result.success(true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "findAllAsync":
|
||||
if (webView != null) {
|
||||
String find = (String) call.argument("find");
|
||||
|
@ -379,7 +365,7 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
break;
|
||||
case "zoomBy":
|
||||
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Float zoomFactor = (Float) call.argument("zoomFactor");
|
||||
float zoomFactor = (float) call.argument("zoomFactor");
|
||||
webView.zoomBy(zoomFactor);
|
||||
result.success(true);
|
||||
} else {
|
||||
|
@ -410,6 +396,53 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
result.success(null);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case "pageDown":
|
||||
if (webView != null) {
|
||||
boolean bottom = (boolean) call.argument("bottom");
|
||||
result.success(webView.pageDown(bottom));
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "pageUp":
|
||||
if (webView != null) {
|
||||
boolean top = (boolean) call.argument("top");
|
||||
result.success(webView.pageUp(top));
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "saveWebArchive":
|
||||
if (webView != null) {
|
||||
String basename = (String) call.argument("basename");
|
||||
boolean autoname = (boolean) call.argument("autoname");
|
||||
webView.saveWebArchive(basename, autoname, new ValueCallback<String>() {
|
||||
@Override
|
||||
public void onReceiveValue(String value) {
|
||||
result.success(value);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result.success(null);
|
||||
}
|
||||
break;
|
||||
case "zoomIn":
|
||||
if (webView != null) {
|
||||
result.success(webView.zoomIn());
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "zoomOut":
|
||||
if (webView != null) {
|
||||
result.success(webView.zoomOut());
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result.notImplemented();
|
||||
}
|
||||
|
@ -419,6 +452,9 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
public void dispose() {
|
||||
channel.setMethodCallHandler(null);
|
||||
if (webView != null) {
|
||||
if (Shared.activityPluginBinding != null) {
|
||||
Shared.activityPluginBinding.removeActivityResultListener(webView.inAppWebViewChromeClient);
|
||||
}
|
||||
webView.setWebChromeClient(new WebChromeClient());
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
|
@ -35,6 +36,8 @@ import android.widget.LinearLayout;
|
|||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.webkit.WebViewCompat;
|
||||
import androidx.webkit.WebViewFeature;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlocker;
|
||||
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlockerAction;
|
||||
|
@ -69,6 +72,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
public Object id;
|
||||
public InAppWebViewClient inAppWebViewClient;
|
||||
public InAppWebViewChromeClient inAppWebViewChromeClient;
|
||||
public InAppWebViewRenderProcessClient inAppWebViewRenderProcessClient;
|
||||
public InAppWebViewOptions options;
|
||||
public boolean isLoading = false;
|
||||
public OkHttpClient httpClient;
|
||||
|
@ -636,6 +640,11 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
inAppWebViewClient = new InAppWebViewClient((isFromInAppBrowserActivity) ? inAppBrowserActivity : flutterWebView);
|
||||
setWebViewClient(inAppWebViewClient);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && WebViewFeature.isFeatureSupported(WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE)) {
|
||||
inAppWebViewRenderProcessClient = new InAppWebViewRenderProcessClient((isFromInAppBrowserActivity) ? inAppBrowserActivity : flutterWebView);
|
||||
WebViewCompat.setWebViewRenderProcessClient(this, inAppWebViewRenderProcessClient);
|
||||
}
|
||||
|
||||
if (options.useOnDownloadStart)
|
||||
setDownloadListener(new DownloadStartListener());
|
||||
|
||||
|
@ -745,6 +754,33 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
if (options.regexToCancelSubFramesLoading != null) {
|
||||
regexToCancelSubFramesLoadingCompiled = Pattern.compile(options.regexToCancelSubFramesLoading);
|
||||
}
|
||||
setScrollBarStyle(options.scrollBarStyle);
|
||||
if (options.scrollBarDefaultDelayBeforeFade != null) {
|
||||
setScrollBarDefaultDelayBeforeFade(options.scrollBarDefaultDelayBeforeFade);
|
||||
} else {
|
||||
options.scrollBarDefaultDelayBeforeFade = getScrollBarDefaultDelayBeforeFade();
|
||||
}
|
||||
setScrollbarFadingEnabled(options.scrollbarFadingEnabled);
|
||||
if (options.scrollBarFadeDuration != null) {
|
||||
setScrollBarFadeDuration(options.scrollBarFadeDuration);
|
||||
} else {
|
||||
options.scrollBarFadeDuration = getScrollBarFadeDuration();
|
||||
}
|
||||
setVerticalScrollbarPosition(options.verticalScrollbarPosition);
|
||||
setVerticalScrollBarEnabled(!options.disableVerticalScroll);
|
||||
setHorizontalScrollBarEnabled(!options.disableHorizontalScroll);
|
||||
setOverScrollMode(options.overScrollMode);
|
||||
if (options.networkAvailable != null) {
|
||||
setNetworkAvailable(options.networkAvailable);
|
||||
}
|
||||
if (options.rendererPriorityPolicy != null && !options.rendererPriorityPolicy.isEmpty() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
setRendererPriorityPolicy(
|
||||
(int) options.rendererPriorityPolicy.get("rendererRequestedPriority"),
|
||||
(boolean) options.rendererPriorityPolicy.get("waivedWhenNotVisible"));
|
||||
} else if (options.rendererPriorityPolicy == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
options.rendererPriorityPolicy.put("rendererRequestedPriority", getRendererRequestedPriority());
|
||||
options.rendererPriorityPolicy.put("waivedWhenNotVisible", getRendererPriorityWaivedWhenNotVisible());
|
||||
}
|
||||
|
||||
contentBlockerHandler.getRuleList().clear();
|
||||
for (Map<String, Map<String, Object>> contentBlocker : options.contentBlockers) {
|
||||
|
@ -767,9 +803,6 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
}
|
||||
});
|
||||
|
||||
setVerticalScrollBarEnabled(!options.disableVerticalScroll);
|
||||
setHorizontalScrollBarEnabled(!options.disableHorizontalScroll);
|
||||
|
||||
gestureDetector = new GestureDetector(this.getContext(), new GestureDetector.SimpleOnGestureListener() {
|
||||
@Override
|
||||
public boolean onSingleTapUp(MotionEvent ev) {
|
||||
|
@ -1300,12 +1333,42 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
}
|
||||
}
|
||||
|
||||
if (newOptionsMap.get("scrollBarStyle") != null && !options.scrollBarStyle.equals(newOptions.scrollBarStyle))
|
||||
setScrollBarStyle(newOptions.scrollBarStyle);
|
||||
|
||||
if (newOptionsMap.get("scrollBarDefaultDelayBeforeFade") != null && !options.scrollBarDefaultDelayBeforeFade.equals(newOptions.scrollBarDefaultDelayBeforeFade))
|
||||
setScrollBarDefaultDelayBeforeFade(newOptions.scrollBarDefaultDelayBeforeFade);
|
||||
|
||||
if (newOptionsMap.get("scrollbarFadingEnabled") != null && !options.scrollbarFadingEnabled.equals(newOptions.scrollbarFadingEnabled))
|
||||
setScrollbarFadingEnabled(newOptions.scrollbarFadingEnabled);
|
||||
|
||||
if (newOptionsMap.get("scrollBarFadeDuration") != null && !options.scrollBarFadeDuration.equals(newOptions.scrollBarFadeDuration))
|
||||
setScrollBarFadeDuration(newOptions.scrollBarFadeDuration);
|
||||
|
||||
if (newOptionsMap.get("verticalScrollbarPosition") != null && !options.verticalScrollbarPosition.equals(newOptions.verticalScrollbarPosition))
|
||||
setVerticalScrollbarPosition(newOptions.verticalScrollbarPosition);
|
||||
|
||||
if (newOptionsMap.get("disableVerticalScroll") != null && options.disableVerticalScroll != newOptions.disableVerticalScroll)
|
||||
setVerticalScrollBarEnabled(!newOptions.disableVerticalScroll);
|
||||
|
||||
if (newOptionsMap.get("disableHorizontalScroll") != null && options.disableHorizontalScroll != newOptions.disableHorizontalScroll)
|
||||
setHorizontalScrollBarEnabled(!newOptions.disableHorizontalScroll);
|
||||
|
||||
if (newOptionsMap.get("overScrollMode") != null && !options.overScrollMode.equals(newOptions.overScrollMode))
|
||||
setOverScrollMode(newOptions.overScrollMode);
|
||||
|
||||
if (newOptionsMap.get("networkAvailable") != null && options.networkAvailable != newOptions.networkAvailable)
|
||||
setNetworkAvailable(newOptions.networkAvailable);
|
||||
|
||||
if (newOptionsMap.get("rendererPriorityPolicy") != null &&
|
||||
(options.rendererPriorityPolicy.get("rendererRequestedPriority") != newOptions.rendererPriorityPolicy.get("rendererRequestedPriority") ||
|
||||
options.rendererPriorityPolicy.get("waivedWhenNotVisible") != newOptions.rendererPriorityPolicy.get("waivedWhenNotVisible")) &&
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
setRendererPriorityPolicy(
|
||||
(int) newOptions.rendererPriorityPolicy.get("rendererRequestedPriority"),
|
||||
(boolean) newOptions.rendererPriorityPolicy.get("waivedWhenNotVisible"));
|
||||
}
|
||||
|
||||
options = newOptions;
|
||||
}
|
||||
|
||||
|
@ -1412,32 +1475,6 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
channel.invokeMethod("onScrollChanged", obj);
|
||||
}
|
||||
|
||||
public void startSafeBrowsing(final MethodChannel.Result result) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||
startSafeBrowsing(getContext(), new ValueCallback<Boolean>() {
|
||||
@Override
|
||||
public void onReceiveValue(Boolean value) {
|
||||
result.success(value);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSafeBrowsingWhitelist(List<String> hosts, final MethodChannel.Result result) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||
setSafeBrowsingWhitelist(hosts, new ValueCallback<Boolean>() {
|
||||
@Override
|
||||
public void onReceiveValue(Boolean value) {
|
||||
result.success(value);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
}
|
||||
|
||||
class DownloadStartListener implements DownloadListener {
|
||||
@Override
|
||||
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
|
||||
|
|
|
@ -58,7 +58,7 @@ import io.flutter.plugin.common.PluginRegistry;
|
|||
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
|
||||
public class InAppWebViewChromeClient extends WebChromeClient implements PluginRegistry.ActivityResultListener {
|
||||
public class InAppWebViewChromeClient extends WebChromeClient implements PluginRegistry.ActivityResultListener, InAppBrowserActivity.ActivityResultListener {
|
||||
|
||||
protected static final String LOG_TAG = "IABWebChromeClient";
|
||||
private FlutterWebView flutterWebView;
|
||||
|
@ -96,10 +96,13 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
private int mOriginalSystemUiVisibility;
|
||||
|
||||
public InAppWebViewChromeClient(Object obj) {
|
||||
if (obj instanceof InAppBrowserActivity)
|
||||
if (obj instanceof InAppBrowserActivity) {
|
||||
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
|
||||
else if (obj instanceof FlutterWebView)
|
||||
this.inAppBrowserActivity.activityResultListeners.add(this);
|
||||
}
|
||||
else if (obj instanceof FlutterWebView) {
|
||||
this.flutterWebView = (FlutterWebView) obj;
|
||||
}
|
||||
this.channel = (this.inAppBrowserActivity != null) ? this.inAppBrowserActivity.channel : this.flutterWebView.channel;
|
||||
|
||||
if (Shared.registrar != null)
|
||||
|
|
|
@ -6,12 +6,14 @@ import android.net.http.SslCertificate;
|
|||
import android.net.http.SslError;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.webkit.ClientCertRequest;
|
||||
import android.webkit.CookieManager;
|
||||
import android.webkit.CookieSyncManager;
|
||||
import android.webkit.HttpAuthHandler;
|
||||
import android.webkit.RenderProcessGoneDetail;
|
||||
import android.webkit.SafeBrowsingResponse;
|
||||
import android.webkit.SslErrorHandler;
|
||||
import android.webkit.ValueCallback;
|
||||
|
@ -20,15 +22,20 @@ import android.webkit.WebResourceResponse;
|
|||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.webkit.WebViewFeature;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.CredentialDatabase.Credential;
|
||||
import com.pichillilorenzo.flutter_inappwebview.CredentialDatabase.CredentialDatabase;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.JavaScriptBridgeInterface;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
@ -47,7 +54,7 @@ import io.flutter.plugin.common.MethodChannel;
|
|||
|
||||
public class InAppWebViewClient extends WebViewClient {
|
||||
|
||||
protected static final String LOG_TAG = "IABWebViewClient";
|
||||
protected static final String LOG_TAG = "IAWebViewClient";
|
||||
private FlutterWebView flutterWebView;
|
||||
private InAppBrowserActivity inAppBrowserActivity;
|
||||
public MethodChannel channel;
|
||||
|
@ -358,7 +365,7 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
}
|
||||
}
|
||||
|
||||
handler.cancel();
|
||||
InAppWebViewClient.super.onReceivedHttpAuthRequest(view, handler, host, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -368,7 +375,7 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
|
||||
@Override
|
||||
public void notImplemented() {
|
||||
handler.cancel();
|
||||
InAppWebViewClient.super.onReceivedHttpAuthRequest(view, handler, host, realm);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -483,7 +490,7 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
}
|
||||
}
|
||||
|
||||
handler.cancel();
|
||||
InAppWebViewClient.super.onReceivedSslError(view, handler, error);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -493,7 +500,7 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
|
||||
@Override
|
||||
public void notImplemented() {
|
||||
handler.cancel();
|
||||
InAppWebViewClient.super.onReceivedSslError(view, handler, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -552,7 +559,7 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
}
|
||||
}
|
||||
|
||||
request.cancel();
|
||||
InAppWebViewClient.super.onReceivedClientCertRequest(view, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -562,20 +569,28 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
|
||||
@Override
|
||||
public void notImplemented() {
|
||||
request.cancel();
|
||||
InAppWebViewClient.super.onReceivedClientCertRequest(view, request);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleChanged(WebView view, float oldScale, float newScale) {
|
||||
super.onScaleChanged(view, oldScale, newScale);
|
||||
final InAppWebView webView = (InAppWebView) view;
|
||||
webView.scale = newScale;
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("oldScale", oldScale);
|
||||
obj.put("newScale", newScale);
|
||||
channel.invokeMethod("onScaleChanged", obj);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O_MR1)
|
||||
@Override
|
||||
public void onSafeBrowsingHit(final WebView view, WebResourceRequest request, int threatType, final SafeBrowsingResponse callback) {
|
||||
public void onSafeBrowsingHit(final WebView view, final WebResourceRequest request, final int threatType, final SafeBrowsingResponse callback) {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
|
@ -608,7 +623,7 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
}
|
||||
}
|
||||
|
||||
callback.showInterstitial(true);
|
||||
InAppWebViewClient.super.onSafeBrowsingHit(view, request, threatType, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -618,7 +633,7 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
|
||||
@Override
|
||||
public void notImplemented() {
|
||||
callback.showInterstitial(true);
|
||||
InAppWebViewClient.super.onSafeBrowsingHit(view, request, threatType, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -628,6 +643,13 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
|
||||
final InAppWebView webView = (InAppWebView) view;
|
||||
|
||||
if (webView.options.useShouldInterceptRequest) {
|
||||
WebResourceResponse onShouldInterceptResponse = onShouldInterceptRequest(url);
|
||||
if (onShouldInterceptResponse != null) {
|
||||
return onShouldInterceptResponse;
|
||||
}
|
||||
}
|
||||
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(url);
|
||||
|
@ -696,10 +718,137 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
final InAppWebView webView = (InAppWebView) view;
|
||||
|
||||
String url = request.getUrl().toString();
|
||||
|
||||
if (webView.options.useShouldInterceptRequest) {
|
||||
WebResourceResponse onShouldInterceptResponse = onShouldInterceptRequest(request);
|
||||
if (onShouldInterceptResponse != null) {
|
||||
return onShouldInterceptResponse;
|
||||
}
|
||||
}
|
||||
|
||||
return shouldInterceptRequest(view, url);
|
||||
}
|
||||
|
||||
public WebResourceResponse onShouldInterceptRequest(Object request) {
|
||||
String url = request instanceof String ? (String) request : null;
|
||||
String method = "GET";
|
||||
Map<String, String> headers = null;
|
||||
Boolean hasGesture = false;
|
||||
Boolean isForMainFrame = true;
|
||||
Boolean isRedirect = false;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && request instanceof WebResourceRequest) {
|
||||
WebResourceRequest webResourceRequest = (WebResourceRequest) request;
|
||||
url = webResourceRequest.getUrl().toString();
|
||||
headers = webResourceRequest.getRequestHeaders();
|
||||
hasGesture = webResourceRequest.hasGesture();
|
||||
isForMainFrame = webResourceRequest.isForMainFrame();
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
||||
isRedirect = webResourceRequest.isRedirect();
|
||||
}
|
||||
}
|
||||
|
||||
final Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("url", url);
|
||||
obj.put("method", method);
|
||||
obj.put("headers", headers);
|
||||
obj.put("isForMainFrame", isForMainFrame);
|
||||
obj.put("hasGesture", hasGesture);
|
||||
obj.put("isRedirect", isRedirect);
|
||||
|
||||
Util.WaitFlutterResult flutterResult;
|
||||
try {
|
||||
flutterResult = Util.invokeMethodAndWait(channel, "shouldInterceptRequest", obj);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(LOG_TAG, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
if (flutterResult.error != null) {
|
||||
Log.e(LOG_TAG, flutterResult.error);
|
||||
}
|
||||
else if (flutterResult.result != null) {
|
||||
Map<String, Object> res = (Map<String, Object>) flutterResult.result;
|
||||
byte[] data = (byte[]) res.get("data");
|
||||
return new WebResourceResponse(res.get("content-type").toString(), res.get("content-encoding").toString(), new ByteArrayInputStream(data));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFormResubmission (final WebView view, final Message dontResend, final Message resend) {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("url", view.getUrl());
|
||||
|
||||
channel.invokeMethod("onFormResubmission", obj, new MethodChannel.Result() {
|
||||
|
||||
@Override
|
||||
public void success(@Nullable Object response) {
|
||||
Map<String, Object> responseMap = (Map<String, Object>) response;
|
||||
Integer action = (Integer) responseMap.get("action");
|
||||
if (action != null) {
|
||||
switch (action) {
|
||||
case 1:
|
||||
resend.sendToTarget();
|
||||
return;
|
||||
case 0:
|
||||
default:
|
||||
dontResend.sendToTarget();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
InAppWebViewClient.super.onFormResubmission(view, dontResend, resend);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) {
|
||||
Log.d(LOG_TAG, "ERROR: " + errorCode + " " + errorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notImplemented() {
|
||||
InAppWebViewClient.super.onFormResubmission(view, dontResend, resend);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageCommitVisible(WebView view, String url) {
|
||||
super.onPageCommitVisible(view, url);
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("url", url);
|
||||
channel.invokeMethod("onPageCommitVisible", obj);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
@Override
|
||||
public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
|
||||
Boolean didCrash = detail.didCrash();
|
||||
Integer rendererPriorityAtExit = detail.rendererPriorityAtExit();
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("didCrash", didCrash);
|
||||
obj.put("rendererPriorityAtExit", rendererPriorityAtExit);
|
||||
|
||||
channel.invokeMethod("onRenderProcessGone", obj);
|
||||
|
||||
return super.onRenderProcessGone(view, detail);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
|
|||
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.webkit.WebSettings;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ChromeCustomTabsOptions;
|
||||
|
@ -87,6 +88,16 @@ public class InAppWebViewOptions implements Options {
|
|||
public Boolean supportMultipleWindows = false;
|
||||
public String regexToCancelSubFramesLoading;
|
||||
|
||||
public Integer overScrollMode = View.OVER_SCROLL_IF_CONTENT_SCROLLS;
|
||||
public Boolean networkAvailable = null;
|
||||
public Integer scrollBarStyle = View.SCROLLBARS_INSIDE_OVERLAY;
|
||||
public Integer verticalScrollbarPosition = View.SCROLLBAR_POSITION_DEFAULT;
|
||||
public Integer scrollBarDefaultDelayBeforeFade = null;
|
||||
public Boolean scrollbarFadingEnabled = true;
|
||||
public Integer scrollBarFadeDuration = null;
|
||||
public Map<String, Object> rendererPriorityPolicy = new HashMap<>();
|
||||
public Boolean useShouldInterceptRequest = false;
|
||||
|
||||
@Override
|
||||
public InAppWebViewOptions parse(HashMap<String, Object> options) {
|
||||
for (Map.Entry<String, Object> pair : options.entrySet()) {
|
||||
|
@ -295,6 +306,33 @@ public class InAppWebViewOptions implements Options {
|
|||
case "regexToCancelSubFramesLoading":
|
||||
regexToCancelSubFramesLoading = (String) value;
|
||||
break;
|
||||
case "overScrollMode":
|
||||
overScrollMode = (Integer) value;
|
||||
break;
|
||||
case "networkAvailable":
|
||||
networkAvailable = (Boolean) value;
|
||||
break;
|
||||
case "scrollBarStyle":
|
||||
scrollBarStyle = (Integer) value;
|
||||
break;
|
||||
case "verticalScrollbarPosition":
|
||||
verticalScrollbarPosition = (Integer) value;
|
||||
break;
|
||||
case "scrollBarDefaultDelayBeforeFade":
|
||||
scrollBarDefaultDelayBeforeFade = (Integer) value;
|
||||
break;
|
||||
case "scrollbarFadingEnabled":
|
||||
scrollbarFadingEnabled = (Boolean) value;
|
||||
break;
|
||||
case "scrollBarFadeDuration":
|
||||
scrollBarFadeDuration = (Integer) value;
|
||||
break;
|
||||
case "rendererPriorityPolicy":
|
||||
rendererPriorityPolicy = (Map<String, Object>) value;
|
||||
break;
|
||||
case "useShouldInterceptRequest":
|
||||
useShouldInterceptRequest = (Boolean) value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,6 +408,15 @@ public class InAppWebViewOptions implements Options {
|
|||
options.put("hardwareAcceleration", hardwareAcceleration);
|
||||
options.put("supportMultipleWindows", supportMultipleWindows);
|
||||
options.put("regexToCancelSubFramesLoading", regexToCancelSubFramesLoading);
|
||||
options.put("overScrollMode", overScrollMode);
|
||||
options.put("networkAvailable", networkAvailable);
|
||||
options.put("scrollBarStyle", scrollBarStyle);
|
||||
options.put("verticalScrollbarPosition", verticalScrollbarPosition);
|
||||
options.put("scrollBarDefaultDelayBeforeFade", scrollBarDefaultDelayBeforeFade);
|
||||
options.put("scrollbarFadingEnabled", scrollbarFadingEnabled);
|
||||
options.put("scrollBarFadeDuration", scrollBarFadeDuration);
|
||||
options.put("rendererPriorityPolicy", rendererPriorityPolicy);
|
||||
options.put("useShouldInterceptRequest", useShouldInterceptRequest);
|
||||
return options;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
|
||||
|
||||
import android.util.Log;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.webkit.WebViewFeature;
|
||||
import androidx.webkit.WebViewRenderProcess;
|
||||
import androidx.webkit.WebViewRenderProcessClient;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserActivity;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
public class InAppWebViewRenderProcessClient extends WebViewRenderProcessClient {
|
||||
|
||||
protected static final String LOG_TAG = "IAWRenderProcessClient";
|
||||
private FlutterWebView flutterWebView;
|
||||
private InAppBrowserActivity inAppBrowserActivity;
|
||||
public MethodChannel channel;
|
||||
|
||||
public InAppWebViewRenderProcessClient(Object obj) {
|
||||
super();
|
||||
if (obj instanceof InAppBrowserActivity)
|
||||
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
|
||||
else if (obj instanceof FlutterWebView)
|
||||
this.flutterWebView = (FlutterWebView) obj;
|
||||
this.channel = (this.inAppBrowserActivity != null) ? this.inAppBrowserActivity.channel : this.flutterWebView.channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRenderProcessUnresponsive(@NonNull WebView view, @Nullable final WebViewRenderProcess renderer) {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
channel.invokeMethod("onRenderProcessUnresponsive", obj, new MethodChannel.Result() {
|
||||
|
||||
@Override
|
||||
public void success(@Nullable Object response) {
|
||||
Map<String, Object> responseMap = (Map<String, Object>) response;
|
||||
Integer action = (Integer) responseMap.get("action");
|
||||
if (action != null && renderer != null) {
|
||||
switch (action) {
|
||||
case 1:
|
||||
if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_VIEW_RENDERER_TERMINATE))
|
||||
renderer.terminate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) {
|
||||
Log.d(LOG_TAG, "ERROR: " + errorCode + " " + errorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notImplemented() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRenderProcessResponsive(@NonNull WebView view, @Nullable final WebViewRenderProcess renderer) {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
channel.invokeMethod("onRenderProcessResponsive", obj, new MethodChannel.Result() {
|
||||
|
||||
@Override
|
||||
public void success(@Nullable Object response) {
|
||||
Map<String, Object> responseMap = (Map<String, Object>) response;
|
||||
Integer action = (Integer) responseMap.get("action");
|
||||
if (action != null && renderer != null) {
|
||||
switch (action) {
|
||||
case 1:
|
||||
if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_VIEW_RENDERER_TERMINATE))
|
||||
renderer.terminate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) {
|
||||
Log.d(LOG_TAG, "ERROR: " + errorCode + " " + errorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notImplemented() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview;
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
public class InAppWebViewFileProvider extends FileProvider {
|
||||
|
||||
// This class intentionally left blank.
|
||||
|
||||
}
|
|
@ -1,6 +1,17 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview;
|
||||
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.os.Build;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import androidx.webkit.WebViewCompat;
|
||||
import androidx.webkit.WebViewFeature;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
|
@ -17,16 +28,72 @@ public class InAppWebViewStatic implements MethodChannel.MethodCallHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
|
||||
public void onMethodCall(MethodCall call, final MethodChannel.Result result) {
|
||||
switch (call.method) {
|
||||
case "getDefaultUserAgent":
|
||||
result.success(WebSettings.getDefaultUserAgent(Shared.applicationContext));
|
||||
break;
|
||||
|
||||
|
||||
case "clearClientCertPreferences":
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
WebView.clearClientCertPreferences(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
result.success(true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "getSafeBrowsingPrivacyPolicyUrl":
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 && WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL)) {
|
||||
result.success(WebViewCompat.getSafeBrowsingPrivacyPolicyUrl().toString());
|
||||
} else
|
||||
result.success(null);
|
||||
break;
|
||||
case "setSafeBrowsingWhitelist":
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 && WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_WHITELIST)) {
|
||||
List<String> hosts = (List<String>) call.argument("hosts");
|
||||
WebViewCompat.setSafeBrowsingWhitelist(hosts, new ValueCallback<Boolean>() {
|
||||
@Override
|
||||
public void onReceiveValue(Boolean value) {
|
||||
result.success(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
result.success(false);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case "getCurrentWebViewPackage":
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
result.success(
|
||||
convertWebViewPackageToMap(WebViewCompat.getCurrentWebViewPackage(Shared.activity)));
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result.notImplemented();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> convertWebViewPackageToMap(PackageInfo webViewPackageInfo) {
|
||||
if (webViewPackageInfo == null) {
|
||||
return null;
|
||||
}
|
||||
HashMap<String, Object> webViewPackageInfoMap = new HashMap<>();
|
||||
|
||||
webViewPackageInfoMap.put("versionName", webViewPackageInfo.versionName);
|
||||
webViewPackageInfoMap.put("packageName", webViewPackageInfo.packageName);
|
||||
|
||||
return webViewPackageInfoMap;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
channel.setMethodCallHandler(null);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
|
@ -115,7 +119,7 @@ public class Util {
|
|||
}
|
||||
}
|
||||
|
||||
public static PrivateKeyAndCertificates loadPrivateKeyAndCertificate( String certificatePath, String certificatePassword, String keyStoreType) {
|
||||
public static PrivateKeyAndCertificates loadPrivateKeyAndCertificate(String certificatePath, String certificatePassword, String keyStoreType) {
|
||||
|
||||
PrivateKeyAndCertificates privateKeyAndCertificates = null;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.0+hotfix.6/","dependencies":[]}],"android":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.0+hotfix.6/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"e2e","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-05-23 18:32:59.790460","version":"1.17.1"}
|
||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.0+hotfix.6/","dependencies":[]}],"android":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.0+hotfix.6/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"e2e","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-05-26 00:10:53.444505","version":"1.17.1"}
|
|
@ -101,7 +101,7 @@ class _InAppBrowserExampleScreenState extends State<InAppBrowserExampleScreen> {
|
|||
useOnLoadResource: true,
|
||||
))));
|
||||
},
|
||||
child: Text("Open Webview Browser")),
|
||||
child: Text("Open In-App Browser")),
|
||||
Container(height: 40),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
|
|
|
@ -76,13 +76,12 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
|
||||
child: InAppWebView(
|
||||
contextMenu: contextMenu,
|
||||
initialUrl: "https://www.youtube.com/watch?v=oD5RtLhhubg",
|
||||
initialUrl: "https://github.com/flutter",
|
||||
// initialFile: "assets/index.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
disableContextMenu: true,
|
||||
debuggingEnabled: true
|
||||
),
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
|
|
|
@ -12,7 +12,8 @@ import 'package:permission_handler/permission_handler.dart';
|
|||
|
||||
Future main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
// await Permission.camera.request();
|
||||
// await Permission.camera.request();
|
||||
// await Permission.storage.request();
|
||||
// await localhostServer.start();
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
|
|
@ -1343,56 +1343,12 @@ class AndroidInAppWebViewController {
|
|||
return await _controller._channel.invokeMethod('startSafeBrowsing', args);
|
||||
}
|
||||
|
||||
///Sets the list of hosts (domain names/IP addresses) that are exempt from SafeBrowsing checks. The list is global for all the WebViews.
|
||||
///
|
||||
/// Each rule should take one of these:
|
||||
///| Rule | Example | Matches Subdomain |
|
||||
///| -- | -- | -- |
|
||||
///| HOSTNAME | example.com | Yes |
|
||||
///| .HOSTNAME | .example.com | No |
|
||||
///| IPV4_LITERAL | 192.168.1.1 | No |
|
||||
///| IPV6_LITERAL_WITH_BRACKETS | [10:20:30:40:50:60:70:80] | No |
|
||||
///
|
||||
///All other rules, including wildcards, are invalid. The correct syntax for hosts is defined by [RFC 3986](https://tools.ietf.org/html/rfc3986#section-3.2.2).
|
||||
///
|
||||
///[hosts] represents the list of hosts. This value must never be null.
|
||||
///
|
||||
///**NOTE**: available only on Android 27+.
|
||||
Future<bool> setSafeBrowsingWhitelist({@required List<String> hosts}) async {
|
||||
assert(hosts != null);
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('hosts', () => hosts);
|
||||
return await _controller._channel
|
||||
.invokeMethod('setSafeBrowsingWhitelist', args);
|
||||
}
|
||||
|
||||
///Returns a URL pointing to the privacy policy for Safe Browsing reporting. This value will never be `null`.
|
||||
///
|
||||
///**NOTE**: available only on Android 27+.
|
||||
Future<String> getSafeBrowsingPrivacyPolicyUrl() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _controller._channel
|
||||
.invokeMethod('getSafeBrowsingPrivacyPolicyUrl', args);
|
||||
}
|
||||
|
||||
///Clears the SSL preferences table stored in response to proceeding with SSL certificate errors.
|
||||
Future<void> clearSslPreferences() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _controller._channel.invokeMethod('clearSslPreferences', args);
|
||||
}
|
||||
|
||||
///Clears the client certificate preferences stored in response to proceeding/cancelling client cert requests.
|
||||
///Note that WebView automatically clears these preferences when the system keychain is updated.
|
||||
///The preferences are shared by all the WebViews that are created by the embedder application.
|
||||
///
|
||||
///**NOTE**: On iOS certificate-based credentials are never stored permanently.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
Future<void> clearClientCertPreferences() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _controller._channel.invokeMethod('clearClientCertPreferences', args);
|
||||
}
|
||||
|
||||
///Does a best-effort attempt to pause any processing that can be paused safely, such as animations and geolocation. Note that this call does not pause JavaScript.
|
||||
///To pause JavaScript globally, use [pauseTimers()]. To resume WebView, call [resume()].
|
||||
Future<void> pause() async {
|
||||
|
@ -1413,6 +1369,50 @@ class AndroidInAppWebViewController {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _controller._channel.invokeMethod('getOriginalUrl', args);
|
||||
}
|
||||
|
||||
///Clears the client certificate preferences stored in response to proceeding/cancelling client cert requests.
|
||||
///Note that WebView automatically clears these preferences when the system keychain is updated.
|
||||
///The preferences are shared by all the WebViews that are created by the embedder application.
|
||||
///
|
||||
///**NOTE**: On iOS certificate-based credentials are never stored permanently.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
static Future<void> clearClientCertPreferences() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await InAppWebViewController._staticChannel.invokeMethod('clearClientCertPreferences', args);
|
||||
}
|
||||
|
||||
///Returns a URL pointing to the privacy policy for Safe Browsing reporting. This value will never be `null`.
|
||||
///
|
||||
///**NOTE**: available only on Android 27+.
|
||||
static Future<String> getSafeBrowsingPrivacyPolicyUrl() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await InAppWebViewController._staticChannel
|
||||
.invokeMethod('getSafeBrowsingPrivacyPolicyUrl', args);
|
||||
}
|
||||
|
||||
///Sets the list of hosts (domain names/IP addresses) that are exempt from SafeBrowsing checks. The list is global for all the WebViews.
|
||||
///
|
||||
/// Each rule should take one of these:
|
||||
///| Rule | Example | Matches Subdomain |
|
||||
///| -- | -- | -- |
|
||||
///| HOSTNAME | example.com | Yes |
|
||||
///| .HOSTNAME | .example.com | No |
|
||||
///| IPV4_LITERAL | 192.168.1.1 | No |
|
||||
///| IPV6_LITERAL_WITH_BRACKETS | [10:20:30:40:50:60:70:80] | No |
|
||||
///
|
||||
///All other rules, including wildcards, are invalid. The correct syntax for hosts is defined by [RFC 3986](https://tools.ietf.org/html/rfc3986#section-3.2.2).
|
||||
///
|
||||
///[hosts] represents the list of hosts. This value must never be null.
|
||||
///
|
||||
///**NOTE**: available only on Android 27+.
|
||||
static Future<bool> setSafeBrowsingWhitelist({@required List<String> hosts}) async {
|
||||
assert(hosts != null);
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('hosts', () => hosts);
|
||||
return await InAppWebViewController._staticChannel
|
||||
.invokeMethod('setSafeBrowsingWhitelist', args);
|
||||
}
|
||||
}
|
||||
|
||||
///InAppWebViewControllerIOS class represents the iOS controller that contains only ios-specific methods for the WebView.
|
||||
|
|
Loading…
Reference in New Issue