Commit 57557407 authored by Lorenzo Pichilli's avatar Lorenzo Pichilli Committed by GitHub

Merge branch 'master' into feature/android-11

parents c9a440c5 f968d8e5
## 5.0.0 ## 5.0.0-nullsafety.0
- Added support for Dart null-safety feature
- Added Android Hybrid Composition support "Use PlatformViewLink widget for Android WebView" [#462](https://github.com/pichillilorenzo/flutter_inappwebview/pull/462) (thanks to [plateaukao](https://github.com/plateaukao) and [tneotia](https://github.com/tneotia)) - Added Android Hybrid Composition support "Use PlatformViewLink widget for Android WebView" [#462](https://github.com/pichillilorenzo/flutter_inappwebview/pull/462) (thanks to [plateaukao](https://github.com/plateaukao) and [tneotia](https://github.com/tneotia))
- Added `allowUniversalAccessFromFileURLs` and `allowFileAccessFromFileURLs` WebView options also for iOS (also thanks to [liranhao](https://github.com/liranhao))
- Updated integration tests
- Merge "Upgraded appcompat to 1.2.0-rc-02" [#465](https://github.com/pichillilorenzo/flutter_inappwebview/pull/465) (thanks to [andreidiaconu](https://github.com/andreidiaconu)) - Merge "Upgraded appcompat to 1.2.0-rc-02" [#465](https://github.com/pichillilorenzo/flutter_inappwebview/pull/465) (thanks to [andreidiaconu](https://github.com/andreidiaconu))
- Merge "Added missing field 'headers' which returned by WebResourceResponse.toMap()" [#490](https://github.com/pichillilorenzo/flutter_inappwebview/pull/490) (thanks to [Doflatango](https://github.com/Doflatango)) - Merge "Added missing field 'headers' which returned by WebResourceResponse.toMap()" [#490](https://github.com/pichillilorenzo/flutter_inappwebview/pull/490) (thanks to [Doflatango](https://github.com/Doflatango))
- Merge "Fix: added iOS fallback module import" [#466](https://github.com/pichillilorenzo/flutter_inappwebview/pull/466) (thanks to [Eddayy](https://github.com/Eddayy)) - Merge "Fix: added iOS fallback module import" [#466](https://github.com/pichillilorenzo/flutter_inappwebview/pull/466) (thanks to [Eddayy](https://github.com/Eddayy))
- Merge "Fix NullPointerException after taking a photo by a camera app on Android" [#492](https://github.com/pichillilorenzo/flutter_inappwebview/pull/492) (thanks to [AAkira](https://github.com/AAkira)) - Merge "Fix NullPointerException after taking a photo by a camera app on Android" [#492](https://github.com/pichillilorenzo/flutter_inappwebview/pull/492) (thanks to [AAkira](https://github.com/AAkira))
- Merge "iOS CookieManager.getCookies - Check that URL has suffix of cookie do…" [#658](https://github.com/pichillilorenzo/flutter_inappwebview/pull/658) (thanks to [arneke](https://github.com/arneke))
- Merge "Add NTLM Auth" [#634](https://github.com/pichillilorenzo/flutter_inappwebview/pull/634) (thanks to [albatrosify](https://github.com/albatrosify))
- Merge "iOS ChromeSafariBrowserManager - Fixing unnecessary casting of rootViewController to FlutterViewController" [#567](https://github.com/pichillilorenzo/flutter_inappwebview/pull/567) (thanks to [gunantosteven](https://github.com/gunantosteven))
- Merge "Fix _channel.invokeMethod name for injectCSSFileFromUrl method" [#645](https://github.com/pichillilorenzo/flutter_inappwebview/pull/645) (thanks to [omralcrt](https://github.com/omralcrt))
- Merge "Add android media intents on wildcard input accept" [#620](https://github.com/pichillilorenzo/flutter_inappwebview/pull/620) (thanks to [cbodin](https://github.com/cbodin))
- Fixed missing properties initialization when using InAppWebViewController.fromInAppBrowser
- Fixed "Issue in Flutter web: 'Unsupported operation: Platform._operatingSystem'" [#507](https://github.com/pichillilorenzo/flutter_inappwebview/issues/507) - Fixed "Issue in Flutter web: 'Unsupported operation: Platform._operatingSystem'" [#507](https://github.com/pichillilorenzo/flutter_inappwebview/issues/507)
- Fixed "window.flutter_inappwebview.callHandler is not a function" [#218](https://github.com/pichillilorenzo/flutter_inappwebview/issues/218) - Fixed "window.flutter_inappwebview.callHandler is not a function" [#218](https://github.com/pichillilorenzo/flutter_inappwebview/issues/218)
- Fixed "Android ContentBlocker - java.lang.NullPointerException ContentBlockerTrigger resource type" [#506](https://github.com/pichillilorenzo/flutter_inappwebview/issues/506) - Fixed "Android ContentBlocker - java.lang.NullPointerException ContentBlockerTrigger resource type" [#506](https://github.com/pichillilorenzo/flutter_inappwebview/issues/506)
- Fixed "Android CookieManager throws error caused by websites that are sending back illegal/invalid cookies." [#476](https://github.com/pichillilorenzo/flutter_inappwebview/issues/476) - Fixed "Android CookieManager throws error caused by websites that are sending back illegal/invalid cookies." [#476](https://github.com/pichillilorenzo/flutter_inappwebview/issues/476)
- Fixed missing `clearHistory` webview method implementation on Android - Fixed missing `clearHistory` webview method implementation on Android
- Fixed iOS crash when using CookieManager getCookies for an URL and the host URL is `null` - Fixed iOS crash when using CookieManager getCookies for an URL and the host URL is `null`
- Fixed "IOS does not support allowUniversalAccessFromFileURLs" [#654](https://github.com/pichillilorenzo/flutter_inappwebview/issues/654)
### BREAKING CHANGES
- Minimum Flutter version required is `1.22.0` and Dart SDK `>=2.12.0-0 <3.0.0`
- Removed `debuggingEnabled` WebView option; on Android you should use now the `AndroidInAppWebViewController.setWebContentsDebuggingEnabled(bool debuggingEnabled)` static method; on iOS, debugging is always enabled
- `allowUniversalAccessFromFileURLs` and `allowFileAccessFromFileURLs` WebView options moved from Android-specific options to cross-platform options.
## 4.0.0+4 ## 4.0.0+4
......
This diff is collapsed.
...@@ -109,31 +109,33 @@ public class ContentBlockerHandler { ...@@ -109,31 +109,33 @@ public class ContentBlockerHandler {
latch.await(); latch.await();
} }
if (!trigger.loadType.isEmpty()) { if (webViewUrl[0] != null) {
URI cUrl = new URI(webViewUrl[0]); if (!trigger.loadType.isEmpty()) {
String cHost = cUrl.getHost(); URI cUrl = new URI(webViewUrl[0]);
int cPort = cUrl.getPort(); String cHost = cUrl.getHost();
String cScheme = cUrl.getScheme(); int cPort = cUrl.getPort();
String cScheme = cUrl.getScheme();
if ( (trigger.loadType.contains("first-party") && cHost != null && !(cScheme.equals(scheme) && cHost.equals(host) && cPort == port)) ||
(trigger.loadType.contains("third-party") && cHost != null && cHost.equals(host)) ) if ( (trigger.loadType.contains("first-party") && cHost != null && !(cScheme.equals(scheme) && cHost.equals(host) && cPort == port)) ||
return null; (trigger.loadType.contains("third-party") && cHost != null && cHost.equals(host)) )
} return null;
if (!trigger.ifTopUrl.isEmpty()) {
boolean matchFound = false;
for (String topUrl : trigger.ifTopUrl) {
if (webViewUrl[0].startsWith(topUrl)) {
matchFound = true;
break;
}
} }
if (!matchFound) if (!trigger.ifTopUrl.isEmpty()) {
return null; boolean matchFound = false;
} for (String topUrl : trigger.ifTopUrl) {
if (!trigger.unlessTopUrl.isEmpty()) { if (webViewUrl[0].startsWith(topUrl)) {
for (String topUrl : trigger.unlessTopUrl) matchFound = true;
if (webViewUrl[0].startsWith(topUrl)) break;
}
}
if (!matchFound)
return null; return null;
}
if (!trigger.unlessTopUrl.isEmpty()) {
for (String topUrl : trigger.unlessTopUrl)
if (webViewUrl[0].startsWith(topUrl))
return null;
}
} }
switch (action.type) { switch (action.type) {
......
...@@ -67,28 +67,9 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { ...@@ -67,28 +67,9 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
"- See the official wiki here: https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects\n\n\n"); "- See the official wiki here: https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects\n\n\n");
} }
// MutableContextWrapper mMutableContext = new MutableContextWrapper(Shared.activity); webView = new InAppWebView(context, this, id, windowId, options, contextMenu, containerView);
// webView = new InAppWebView(mMutableContext, this, id, options, contextMenu, containerView);
// displayListenerProxy.onPostWebViewInitialization(displayManager);
// mMutableContext.setBaseContext(context);
webView = new InAppWebView(Shared.activity, this, id, windowId, options, contextMenu, containerView);
displayListenerProxy.onPostWebViewInitialization(displayManager); displayListenerProxy.onPostWebViewInitialization(displayManager);
// fix https://github.com/pichillilorenzo/flutter_inappwebview/issues/182
try {
Class superClass = webView.getClass().getSuperclass();
while(!superClass.getName().equals("android.view.View")) {
superClass = superClass.getSuperclass();
}
Field mContext = superClass.getDeclaredField("mContext");
mContext.setAccessible(true);
mContext.set(webView, context);
} catch (Exception e) {
e.printStackTrace();
Log.e(LOG_TAG, "Cannot find mContext for this WebView");
}
webView.prepare(); webView.prepare();
if (windowId != null) { if (windowId != null) {
......
...@@ -677,9 +677,6 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -677,9 +677,6 @@ final public class InAppWebView extends InputAwareWebView {
WebSettings settings = getSettings(); WebSettings settings = getSettings();
settings.setJavaScriptEnabled(options.javaScriptEnabled); settings.setJavaScriptEnabled(options.javaScriptEnabled);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
setWebContentsDebuggingEnabled(options.debuggingEnabled);
}
settings.setJavaScriptCanOpenWindowsAutomatically(options.javaScriptCanOpenWindowsAutomatically); settings.setJavaScriptCanOpenWindowsAutomatically(options.javaScriptCanOpenWindowsAutomatically);
settings.setBuiltInZoomControls(options.builtInZoomControls); settings.setBuiltInZoomControls(options.builtInZoomControls);
settings.setDisplayZoomControls(options.displayZoomControls); settings.setDisplayZoomControls(options.displayZoomControls);
...@@ -853,7 +850,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -853,7 +850,7 @@ final public class InAppWebView extends InputAwareWebView {
} }
}; };
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && !options.useHybridComposition) {
checkContextMenuShouldBeClosedTask = new Runnable() { checkContextMenuShouldBeClosedTask = new Runnable() {
@Override @Override
public void run() { public void run() {
...@@ -1133,9 +1130,6 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1133,9 +1130,6 @@ final public class InAppWebView extends InputAwareWebView {
if (newOptionsMap.get("javaScriptEnabled") != null && options.javaScriptEnabled != newOptions.javaScriptEnabled) if (newOptionsMap.get("javaScriptEnabled") != null && options.javaScriptEnabled != newOptions.javaScriptEnabled)
settings.setJavaScriptEnabled(newOptions.javaScriptEnabled); settings.setJavaScriptEnabled(newOptions.javaScriptEnabled);
if (newOptionsMap.get("debuggingEnabled") != null && options.debuggingEnabled != newOptions.debuggingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
setWebContentsDebuggingEnabled(newOptions.debuggingEnabled);
if (newOptionsMap.get("useShouldInterceptAjaxRequest") != null && options.useShouldInterceptAjaxRequest != newOptions.useShouldInterceptAjaxRequest) { if (newOptionsMap.get("useShouldInterceptAjaxRequest") != null && options.useShouldInterceptAjaxRequest != newOptions.useShouldInterceptAjaxRequest) {
String placeholderValue = newOptions.useShouldInterceptAjaxRequest ? "true" : "false"; String placeholderValue = newOptions.useShouldInterceptAjaxRequest ? "true" : "false";
String sourceJs = InAppWebView.enableVariableForShouldInterceptAjaxRequestJS.replace("$PLACEHOLDER_VALUE", placeholderValue); String sourceJs = InAppWebView.enableVariableForShouldInterceptAjaxRequestJS.replace("$PLACEHOLDER_VALUE", placeholderValue);
...@@ -1505,14 +1499,11 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1505,14 +1499,11 @@ final public class InAppWebView extends InputAwareWebView {
} }
@Override @Override
protected void onScrollChanged (int l, protected void onScrollChanged (int x,
int t, int y,
int oldl, int oldX,
int oldt) { int oldY) {
super.onScrollChanged(l, t, oldl, oldt); super.onScrollChanged(x, y, oldX, oldY);
int x = (int) (l/scale);
int y = (int) (t/scale);
if (floatingContextMenu != null) { if (floatingContextMenu != null) {
floatingContextMenu.setAlpha(0f); floatingContextMenu.setAlpha(0f);
...@@ -1662,12 +1653,18 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1662,12 +1653,18 @@ final public class InAppWebView extends InputAwareWebView {
@Override @Override
public ActionMode startActionMode(ActionMode.Callback callback) { public ActionMode startActionMode(ActionMode.Callback callback) {
if (options.useHybridComposition && !options.disableContextMenu && (contextMenu == null || contextMenu.keySet().size() == 0)) {
return super.startActionMode(callback);
}
return rebuildActionMode(super.startActionMode(callback), callback); return rebuildActionMode(super.startActionMode(callback), callback);
} }
@RequiresApi(api = Build.VERSION_CODES.M) @RequiresApi(api = Build.VERSION_CODES.M)
@Override @Override
public ActionMode startActionMode(ActionMode.Callback callback, int type) { public ActionMode startActionMode(ActionMode.Callback callback, int type) {
if (options.useHybridComposition && !options.disableContextMenu && (contextMenu == null || contextMenu.keySet().size() == 0)) {
return super.startActionMode(callback, type);
}
return rebuildActionMode(super.startActionMode(callback, type), callback); return rebuildActionMode(super.startActionMode(callback, type), callback);
} }
...@@ -1711,6 +1708,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1711,6 +1708,7 @@ final public class InAppWebView extends InputAwareWebView {
final MenuItem menuItem = actionMenu.getItem(i); final MenuItem menuItem = actionMenu.getItem(i);
final int itemId = menuItem.getItemId(); final int itemId = menuItem.getItemId();
final String itemTitle = menuItem.getTitle().toString(); final String itemTitle = menuItem.getTitle().toString();
TextView text = (TextView) LayoutInflater.from(this.getContext()) TextView text = (TextView) LayoutInflater.from(this.getContext())
.inflate(R.layout.floating_action_mode_item, this, false); .inflate(R.layout.floating_action_mode_item, this, false);
text.setText(itemTitle); text.setText(itemTitle);
...@@ -1855,7 +1853,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1855,7 +1853,7 @@ final public class InAppWebView extends InputAwareWebView {
" var clientRect = range.getClientRects();" + " var clientRect = range.getClientRects();" +
" if (clientRect.length > 0) {" + " if (clientRect.length > 0) {" +
" rangeY = clientRect[0].y;" + " rangeY = clientRect[0].y;" +
" } else if (document.activeElement) {" + " } else if (document.activeElement != null && document.activeElement.tagName.toLowerCase() !== 'iframe') {" +
" var boundingClientRect = document.activeElement.getBoundingClientRect();" + " var boundingClientRect = document.activeElement.getBoundingClientRect();" +
" rangeY = boundingClientRect.y;" + " rangeY = boundingClientRect.y;" +
" }" + " }" +
...@@ -1865,7 +1863,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1865,7 +1863,7 @@ final public class InAppWebView extends InputAwareWebView {
@Override @Override
public void onReceiveValue(String value) { public void onReceiveValue(String value) {
if (floatingContextMenu != null) { if (floatingContextMenu != null) {
if (value != null) { if (value != null && !value.equals("null")) {
int x = contextMenuPoint.x; int x = contextMenuPoint.x;
int y = (int) ((Float.parseFloat(value) * scale) + (floatingContextMenu.getHeight() / 3.5)); int y = (int) ((Float.parseFloat(value) * scale) + (floatingContextMenu.getHeight() / 3.5));
contextMenuPoint.y = y; contextMenuPoint.y = y;
...@@ -1873,6 +1871,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1873,6 +1871,7 @@ final public class InAppWebView extends InputAwareWebView {
} else { } else {
floatingContextMenu.setVisibility(View.VISIBLE); floatingContextMenu.setVisibility(View.VISIBLE);
floatingContextMenu.animate().alpha(1f).setDuration(100).setListener(null); floatingContextMenu.animate().alpha(1f).setDuration(100).setListener(null);
onFloatingActionGlobalLayout(contextMenuPoint.x, contextMenuPoint.y);
} }
} }
} }
......
...@@ -3,9 +3,11 @@ package com.pichillilorenzo.flutter_inappwebview.InAppWebView; ...@@ -3,9 +3,11 @@ package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
import android.Manifest; import android.Manifest;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.Activity; import android.app.Activity;
import android.content.ContentResolver;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Color; import android.graphics.Color;
...@@ -46,6 +48,7 @@ import com.pichillilorenzo.flutter_inappwebview.Shared; ...@@ -46,6 +48,7 @@ import com.pichillilorenzo.flutter_inappwebview.Shared;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
...@@ -72,7 +75,8 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -72,7 +75,8 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
private static final int PICKER = 1; private static final int PICKER = 1;
private static final int PICKER_LEGACY = 3; private static final int PICKER_LEGACY = 3;
final String DEFAULT_MIME_TYPES = "*/*"; final String DEFAULT_MIME_TYPES = "*/*";
private static Uri outputFileUri; private static Uri videoOutputFileUri;
private static Uri imageOutputFileUri;
protected static final FrameLayout.LayoutParams FULLSCREEN_LAYOUT_PARAMS = new FrameLayout.LayoutParams( protected static final FrameLayout.LayoutParams FULLSCREEN_LAYOUT_PARAMS = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER); ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER);
...@@ -810,39 +814,37 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -810,39 +814,37 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
// this filename instead // this filename instead
switch (requestCode) { switch (requestCode) {
case PICKER: case PICKER:
if (resultCode != RESULT_OK) { Uri[] results = null;
if (InAppWebViewFlutterPlugin.filePathCallback != null) { if (resultCode == RESULT_OK) {
InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(null); results = getSelectedFiles(data, resultCode);
} }
} else {
Uri result[] = this.getSelectedFiles(data, resultCode); if (InAppWebViewFlutterPlugin.filePathCallback != null) {
if (result != null) { InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(results);
InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(result);
} else {
InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(new Uri[]{outputFileUri});
}
} }
break; break;
case PICKER_LEGACY: case PICKER_LEGACY:
Uri result = resultCode != Activity.RESULT_OK ? null : data == null ? outputFileUri : data.getData(); Uri result = null;
if (resultCode == RESULT_OK) {
result = data != null ? data.getData() : getCapturedMediaFile();
}
InAppWebViewFlutterPlugin.filePathCallbackLegacy.onReceiveValue(result); InAppWebViewFlutterPlugin.filePathCallbackLegacy.onReceiveValue(result);
break; break;
} }
InAppWebViewFlutterPlugin.filePathCallback = null; InAppWebViewFlutterPlugin.filePathCallback = null;
InAppWebViewFlutterPlugin.filePathCallbackLegacy = null; InAppWebViewFlutterPlugin.filePathCallbackLegacy = null;
outputFileUri = null; imageOutputFileUri = null;
videoOutputFileUri = null;
return true; return true;
} }
private Uri[] getSelectedFiles(Intent data, int resultCode) { private Uri[] getSelectedFiles(Intent data, int resultCode) {
if (data == null) {
return null;
}
// we have one file selected // we have one file selected
if (data.getData() != null) { if (data != null && data.getData() != null) {
if (resultCode == RESULT_OK && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (resultCode == RESULT_OK && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return WebChromeClient.FileChooserParams.parseResult(resultCode, data); return WebChromeClient.FileChooserParams.parseResult(resultCode, data);
} else { } else {
...@@ -851,7 +853,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -851,7 +853,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
// we have multiple files selected // we have multiple files selected
if (data.getClipData() != null) { if (data != null && data.getClipData() != null) {
final int numSelectedFiles = data.getClipData().getItemCount(); final int numSelectedFiles = data.getClipData().getItemCount();
Uri[] result = new Uri[numSelectedFiles]; Uri[] result = new Uri[numSelectedFiles];
for (int i = 0; i < numSelectedFiles; i++) { for (int i = 0; i < numSelectedFiles; i++) {
...@@ -859,6 +861,40 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -859,6 +861,40 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
return result; return result;
} }
// we have a captured image or video file
Uri mediaUri = getCapturedMediaFile();
if (mediaUri != null) {
return new Uri[]{mediaUri};
}
return null;
}
private boolean isFileNotEmpty(Uri uri) {
Activity activity = inAppBrowserActivity != null ? inAppBrowserActivity : Shared.activity;
long length;
try {
AssetFileDescriptor descriptor = activity.getContentResolver().openAssetFileDescriptor(uri, "r");
length = descriptor.getLength();
descriptor.close();
} catch (IOException e) {
return false;
}
return length > 0;
}
private Uri getCapturedMediaFile() {
if (imageOutputFileUri != null && isFileNotEmpty(imageOutputFileUri)) {
return imageOutputFileUri;
}
if (videoOutputFileUri != null && isFileNotEmpty(videoOutputFileUri)) {
return videoOutputFileUri;
}
return null; return null;
} }
...@@ -935,15 +971,15 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -935,15 +971,15 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
private Intent getPhotoIntent() { private Intent getPhotoIntent() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
outputFileUri = getOutputUri(MediaStore.ACTION_IMAGE_CAPTURE); imageOutputFileUri = getOutputUri(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageOutputFileUri);
return intent; return intent;
} }
private Intent getVideoIntent() { private Intent getVideoIntent() {
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
outputFileUri = getOutputUri(MediaStore.ACTION_VIDEO_CAPTURE); videoOutputFileUri = getOutputUri(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri); intent.putExtra(MediaStore.EXTRA_OUTPUT, videoOutputFileUri);
return intent; return intent;
} }
...@@ -971,6 +1007,20 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -971,6 +1007,20 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
return intent; return intent;
} }
private Boolean acceptsAny(String[] types) {
if (isArrayEmpty(types)) {
return true;
}
for (String type : types) {
if (type.equals("*/*")) {
return true;
}
}
return false;
}
private Boolean acceptsImages(String types) { private Boolean acceptsImages(String types) {
String mimeType = types; String mimeType = types;
if (types.matches("\\.\\w+")) { if (types.matches("\\.\\w+")) {
...@@ -981,7 +1031,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -981,7 +1031,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
private Boolean acceptsImages(String[] types) { private Boolean acceptsImages(String[] types) {
String[] mimeTypes = getAcceptedMimeType(types); String[] mimeTypes = getAcceptedMimeType(types);
return isArrayEmpty(mimeTypes) || arrayContainsString(mimeTypes, "image"); return acceptsAny(types) || arrayContainsString(mimeTypes, "image");
} }
private Boolean acceptsVideo(String types) { private Boolean acceptsVideo(String types) {
...@@ -994,7 +1044,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -994,7 +1044,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
private Boolean acceptsVideo(String[] types) { private Boolean acceptsVideo(String[] types) {
String[] mimeTypes = getAcceptedMimeType(types); String[] mimeTypes = getAcceptedMimeType(types);
return isArrayEmpty(mimeTypes) || arrayContainsString(mimeTypes, "video"); return acceptsAny(types) || arrayContainsString(mimeTypes, "video");
} }
private Boolean arrayContainsString(String[] array, String pattern) { private Boolean arrayContainsString(String[] array, String pattern) {
...@@ -1056,31 +1106,29 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -1056,31 +1106,29 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
String prefix = ""; String prefix = "";
String suffix = ""; String suffix = "";
String dir = ""; String dir = "";
String filename = "";
if (intentType.equals(MediaStore.ACTION_IMAGE_CAPTURE)) { if (intentType.equals(MediaStore.ACTION_IMAGE_CAPTURE)) {
prefix = "image-"; prefix = "image";
suffix = ".jpg"; suffix = ".jpg";
dir = Environment.DIRECTORY_PICTURES; dir = Environment.DIRECTORY_PICTURES;
} else if (intentType.equals(MediaStore.ACTION_VIDEO_CAPTURE)) { } else if (intentType.equals(MediaStore.ACTION_VIDEO_CAPTURE)) {
prefix = "video-"; prefix = "video";
suffix = ".mp4"; suffix = ".mp4";
dir = Environment.DIRECTORY_MOVIES; dir = Environment.DIRECTORY_MOVIES;
} }
filename = prefix + String.valueOf(System.currentTimeMillis()) + suffix;
// for versions below 6.0 (23) we use the old File creation & permissions model // for versions below 6.0 (23) we use the old File creation & permissions model
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// only this Directory works on all tested Android versions // only this Directory works on all tested Android versions
// ctx.getExternalFilesDir(dir) was failing on Android 5.0 (sdk 21) // ctx.getExternalFilesDir(dir) was failing on Android 5.0 (sdk 21)
File storageDir = Environment.getExternalStoragePublicDirectory(dir); File storageDir = Environment.getExternalStoragePublicDirectory(dir);
String filename = String.format("%s-%d%s", prefix, System.currentTimeMillis(), suffix);
return new File(storageDir, filename); return new File(storageDir, filename);
} }
Activity activity = inAppBrowserActivity != null ? inAppBrowserActivity : Shared.activity; Activity activity = inAppBrowserActivity != null ? inAppBrowserActivity : Shared.activity;
File storageDir = activity.getApplicationContext().getExternalFilesDir(null); File storageDir = activity.getApplicationContext().getExternalFilesDir(null);
return File.createTempFile(filename, suffix, storageDir); return File.createTempFile(prefix, suffix, storageDir);
} }
private Boolean isArrayEmpty(String[] arr) { private Boolean isArrayEmpty(String[] arr) {
......
...@@ -176,7 +176,9 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -176,7 +176,9 @@ public class InAppWebViewClient extends WebViewClient {
if (webView.options.useOnLoadResource) { if (webView.options.useOnLoadResource) {
js += InAppWebView.resourceObserverJS.replaceAll("[\r\n]+", ""); js += InAppWebView.resourceObserverJS.replaceAll("[\r\n]+", "");
} }
js += InAppWebView.checkGlobalKeyDownEventToHideContextMenuJS.replaceAll("[\r\n]+", ""); if (!webView.options.useHybridComposition) {
js += InAppWebView.checkGlobalKeyDownEventToHideContextMenuJS.replaceAll("[\r\n]+", "");
}
js += InAppWebView.onWindowFocusEventJS.replaceAll("[\r\n]+", ""); js += InAppWebView.onWindowFocusEventJS.replaceAll("[\r\n]+", "");
js += InAppWebView.onWindowBlurEventJS.replaceAll("[\r\n]+", ""); js += InAppWebView.onWindowBlurEventJS.replaceAll("[\r\n]+", "");
js += InAppWebView.printJS.replaceAll("[\r\n]+", ""); js += InAppWebView.printJS.replaceAll("[\r\n]+", "");
......
...@@ -26,7 +26,6 @@ public class InAppWebViewOptions implements Options<InAppWebView> { ...@@ -26,7 +26,6 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
public String userAgent = ""; public String userAgent = "";
public String applicationNameForUserAgent = ""; public String applicationNameForUserAgent = "";
public Boolean javaScriptEnabled = true; public Boolean javaScriptEnabled = true;
public Boolean debuggingEnabled = false;
public Boolean javaScriptCanOpenWindowsAutomatically = false; public Boolean javaScriptCanOpenWindowsAutomatically = false;
public Boolean mediaPlaybackRequiresUserGesture = true; public Boolean mediaPlaybackRequiresUserGesture = true;
public Integer minimumFontSize = 8; public Integer minimumFontSize = 8;
...@@ -44,6 +43,8 @@ public class InAppWebViewOptions implements Options<InAppWebView> { ...@@ -44,6 +43,8 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
public Boolean disableHorizontalScroll = false; public Boolean disableHorizontalScroll = false;
public Boolean disableContextMenu = false; public Boolean disableContextMenu = false;
public Boolean supportZoom = true; public Boolean supportZoom = true;
public Boolean allowFileAccessFromFileURLs = false;
public Boolean allowUniversalAccessFromFileURLs = false;
public Integer textZoom = 100; public Integer textZoom = 100;
public Boolean clearSessionCache = false; public Boolean clearSessionCache = false;
...@@ -56,8 +57,6 @@ public class InAppWebViewOptions implements Options<InAppWebView> { ...@@ -56,8 +57,6 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
public Integer mixedContentMode; public Integer mixedContentMode;
public Boolean allowContentAccess = true; public Boolean allowContentAccess = true;
public Boolean allowFileAccess = true; public Boolean allowFileAccess = true;
public Boolean allowFileAccessFromFileURLs = true;
public Boolean allowUniversalAccessFromFileURLs = true;
public String appCachePath; public String appCachePath;
public Boolean blockNetworkImage = false; public Boolean blockNetworkImage = false;
public Boolean blockNetworkLoads = false; public Boolean blockNetworkLoads = false;
...@@ -97,6 +96,7 @@ public class InAppWebViewOptions implements Options<InAppWebView> { ...@@ -97,6 +96,7 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
public Boolean useShouldInterceptRequest = false; public Boolean useShouldInterceptRequest = false;
public Boolean useOnRenderProcessGone = false; public Boolean useOnRenderProcessGone = false;
public Boolean disableDefaultErrorPage = false; public Boolean disableDefaultErrorPage = false;
public Boolean useHybridComposition = false;
@Override @Override
public InAppWebViewOptions parse(Map<String, Object> options) { public InAppWebViewOptions parse(Map<String, Object> options) {
...@@ -129,9 +129,6 @@ public class InAppWebViewOptions implements Options<InAppWebView> { ...@@ -129,9 +129,6 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
case "javaScriptEnabled": case "javaScriptEnabled":
javaScriptEnabled = (Boolean) value; javaScriptEnabled = (Boolean) value;
break; break;
case "debuggingEnabled":
debuggingEnabled = (Boolean) value;
break;
case "javaScriptCanOpenWindowsAutomatically": case "javaScriptCanOpenWindowsAutomatically":
javaScriptCanOpenWindowsAutomatically = (Boolean) value; javaScriptCanOpenWindowsAutomatically = (Boolean) value;
break; break;
...@@ -339,6 +336,9 @@ public class InAppWebViewOptions implements Options<InAppWebView> { ...@@ -339,6 +336,9 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
case "disableDefaultErrorPage": case "disableDefaultErrorPage":
disableDefaultErrorPage = (Boolean) value; disableDefaultErrorPage = (Boolean) value;
break; break;
case "useHybridComposition":
useHybridComposition = (Boolean) value;
break;
} }
} }
...@@ -355,7 +355,6 @@ public class InAppWebViewOptions implements Options<InAppWebView> { ...@@ -355,7 +355,6 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
options.put("userAgent", userAgent); options.put("userAgent", userAgent);
options.put("applicationNameForUserAgent", applicationNameForUserAgent); options.put("applicationNameForUserAgent", applicationNameForUserAgent);
options.put("javaScriptEnabled", javaScriptEnabled); options.put("javaScriptEnabled", javaScriptEnabled);
options.put("debuggingEnabled", debuggingEnabled);
options.put("javaScriptCanOpenWindowsAutomatically", javaScriptCanOpenWindowsAutomatically); options.put("javaScriptCanOpenWindowsAutomatically", javaScriptCanOpenWindowsAutomatically);
options.put("mediaPlaybackRequiresUserGesture", mediaPlaybackRequiresUserGesture); options.put("mediaPlaybackRequiresUserGesture", mediaPlaybackRequiresUserGesture);
options.put("minimumFontSize", minimumFontSize); options.put("minimumFontSize", minimumFontSize);
...@@ -425,6 +424,7 @@ public class InAppWebViewOptions implements Options<InAppWebView> { ...@@ -425,6 +424,7 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
options.put("useShouldInterceptRequest", useShouldInterceptRequest); options.put("useShouldInterceptRequest", useShouldInterceptRequest);
options.put("useOnRenderProcessGone", useOnRenderProcessGone); options.put("useOnRenderProcessGone", useOnRenderProcessGone);
options.put("disableDefaultErrorPage", disableDefaultErrorPage); options.put("disableDefaultErrorPage", disableDefaultErrorPage);
options.put("useHybridComposition", useHybridComposition);
return options; return options;
} }
......
...@@ -16,6 +16,8 @@ import android.widget.ListPopupWindow; ...@@ -16,6 +16,8 @@ import android.widget.ListPopupWindow;
* A WebView subclass that mirrors the same implementation hacks that the system WebView does in * A WebView subclass that mirrors the same implementation hacks that the system WebView does in
* order to correctly create an InputConnection. * order to correctly create an InputConnection.
* *
* These hacks are only needed in Android versions below N and exist to create an InputConnection
* on the WebView's dedicated input, or IME, thread. The majority of this proxying logic is in
* https://github.com/flutter/plugins/blob/master/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java * https://github.com/flutter/plugins/blob/master/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java
*/ */
public class InputAwareWebView extends WebView { public class InputAwareWebView extends WebView {
...@@ -234,9 +236,9 @@ public class InputAwareWebView extends WebView { ...@@ -234,9 +236,9 @@ public class InputAwareWebView extends WebView {
private boolean isCalledFromListPopupWindowShow() { private boolean isCalledFromListPopupWindowShow() {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
for (int i = 0; i < stackTraceElements.length; i++) { for (StackTraceElement stackTraceElement : stackTraceElements) {
if (stackTraceElements[i].getClassName().equals(ListPopupWindow.class.getCanonicalName()) if (stackTraceElement.getClassName().equals(ListPopupWindow.class.getCanonicalName())
&& stackTraceElements[i].getMethodName().equals("show")) { && stackTraceElement.getMethodName().equals("show")) {
return true; return true;
} }
} }
......
...@@ -72,6 +72,13 @@ public class InAppWebViewStatic implements MethodChannel.MethodCallHandler { ...@@ -72,6 +72,13 @@ public class InAppWebViewStatic implements MethodChannel.MethodCallHandler {
result.success(null); result.success(null);
} }
break; break;
case "setWebContentsDebuggingEnabled":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
boolean debuggingEnabled = (boolean) call.argument("debuggingEnabled");
WebView.setWebContentsDebuggingEnabled(debuggingEnabled);
}
result.success(true);
break;
default: default:
result.notImplemented(); result.notImplemented();
} }
......
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.11/","dependencies":[]}],"android":[{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.11/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+7/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+1/","dependencies":[]}],"windows":[],"web":[{"name":"url_launcher_web","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-0.1.2/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_inappwebview","dependencies":[]},{"name":"e2e","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_web","url_launcher_macos"]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]}],"date_created":"2020-09-07 18:06:16.830498","version":"1.20.3"} {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"android":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-01-29 00:53:56.206541","version":"1.26.0-13.0.pre.194"}
\ No newline at end of file \ No newline at end of file
package com.pichillilorenzo.flutterwebviewexample; package com.pichillilorenzo.flutterwebviewexample;
import android.os.Bundle; import android.os.Bundle;
import dev.flutter.plugins.e2e.E2EPlugin; import dev.flutter.plugins.integration_test.IntegrationTestPlugin;
import io.flutter.app.FlutterActivity;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin; import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
public class EmbedderV1Activity extends FlutterActivity { @SuppressWarnings("deprecation")
public class EmbedderV1Activity extends io.flutter.app.FlutterActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
E2EPlugin.registerWith(registrarFor("dev.flutter.plugins.e2e.E2EPlugin")); IntegrationTestPlugin.registerWith(
registrarFor("dev.flutter.plugins.integration_test.IntegrationTestPlugin"));
InAppWebViewFlutterPlugin.registerWith( InAppWebViewFlutterPlugin.registerWith(
registrarFor("com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin")); registrarFor("com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin"));
} }
......
final environment = {"NODE_SERVER_IP":"192.168.1.129"};
\ No newline at end of file
This diff is collapsed.
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig" #include "Generated.xcconfig"
FLUTTER_BUILD_MODE=debug FLUTTER_BUILD_MODE=debug
\ No newline at end of file
#
# NOTE: This podspec is NOT to be published. It is only used as a local source!
#
Pod::Spec.new do |s|
s.name = 'Flutter'
s.version = '1.0.0'
s.summary = 'High-performance, high-fidelity mobile apps.'
s.description = <<-DESC
Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
DESC
s.homepage = 'https://flutter.io'
s.license = { :type => 'MIT' }
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.vendored_frameworks = 'Flutter.framework'
end
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig" #include "Generated.xcconfig"
...@@ -2,14 +2,12 @@ ...@@ -2,14 +2,12 @@
# This is a generated file; do not edit or check into version control. # This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter" export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example" export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example"
export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart" export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build/ios" export "SYMROOT=${SOURCE_ROOT}/../build/ios"
export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios"
export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1" export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false" export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true" export "TRACK_WIDGET_CREATION=false"
export "TREE_SHAKE_ICONS=false" export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.packages" export "PACKAGE_CONFIG=.packages"
...@@ -254,19 +254,17 @@ ...@@ -254,19 +254,17 @@
); );
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../Flutter/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/e2e/e2e.framework",
"${BUILT_PRODUCTS_DIR}/flutter_downloader/flutter_downloader.framework", "${BUILT_PRODUCTS_DIR}/flutter_downloader/flutter_downloader.framework",
"${BUILT_PRODUCTS_DIR}/flutter_inappwebview/flutter_inappwebview.framework", "${BUILT_PRODUCTS_DIR}/flutter_inappwebview/flutter_inappwebview.framework",
"${BUILT_PRODUCTS_DIR}/integration_test/integration_test.framework",
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
"${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework",
); );
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/e2e.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_downloader.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_downloader.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappwebview.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappwebview.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/integration_test.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",
); );
...@@ -451,7 +449,7 @@ ...@@ -451,7 +449,7 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Flutter", "$(PROJECT_DIR)/Flutter",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.pichillilorenzo.flutter_inappwebviewExample; PRODUCT_BUNDLE_IDENTIFIER = "flutter-inappwebviewExample";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
......
...@@ -2,6 +2,6 @@ ...@@ -2,6 +2,6 @@
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "group:Runner.xcodeproj"> location = "self:">
</FileRef> </FileRef>
</Workspace> </Workspace>
...@@ -2,54 +2,52 @@ ...@@ -2,54 +2,52 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>NSLocationAlwaysUsageDescription</key> <key>CFBundleDevelopmentRegion</key>
<string>Need location</string> <string>en</string>
<key>NSLocationWhenInUseUsageDescription</key> <key>CFBundleExecutable</key>
<string>Need location</string> <string>$(EXECUTABLE_NAME)</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Need location</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleName</key>
<string>flutter_inappwebview_example</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key>
<string>flutter_inappwebview_example</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string> <string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Need location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Need location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Need location</string>
<key>UIBackgroundModes</key> <key>UIBackgroundModes</key>
<array> <array>
<string>fetch</string> <string>fetch</string>
<string>remote-notification</string> <string>remote-notification</string>
</array> </array>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIMainStoryboardFile</key> <key>UIMainStoryboardFile</key>
<string>Main</string> <string>Main</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
<key>UISupportedInterfaceOrientations</key> <key>UISupportedInterfaceOrientations</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>UISupportedInterfaceOrientations~ipad</key> <key>UISupportedInterfaceOrientations~ipad</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>
...@@ -57,7 +55,13 @@ ...@@ -57,7 +55,13 @@
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>CFBundleShortVersionString</key> <key>NSBonjourServices</key>
<string>$(FLUTTER_BUILD_NAME)</string> <array>
<string></string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSLocalNetworkUsageDescription</key>
<string>Allow Flutter tools on your computer to connect and debug your application.</string>
</dict> </dict>
</plist> </plist>
...@@ -11,7 +11,7 @@ class HeadlessInAppWebViewExampleScreen extends StatefulWidget { ...@@ -11,7 +11,7 @@ class HeadlessInAppWebViewExampleScreen extends StatefulWidget {
} }
class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebViewExampleScreen> { class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebViewExampleScreen> {
HeadlessInAppWebView headlessWebView; HeadlessInAppWebView? headlessWebView;
String url = ""; String url = "";
@override @override
...@@ -22,7 +22,7 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView ...@@ -22,7 +22,7 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView
initialUrl: "https://flutter.dev/", initialUrl: "https://flutter.dev/",
initialOptions: InAppWebViewGroupOptions( initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions( crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
), ),
), ),
onWebViewCreated: (controller) { onWebViewCreated: (controller) {
...@@ -34,19 +34,19 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView ...@@ -34,19 +34,19 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView
onLoadStart: (controller, url) async { onLoadStart: (controller, url) async {
print("onLoadStart $url"); print("onLoadStart $url");
setState(() { setState(() {
this.url = url; this.url = url ?? '';
}); });
}, },
onLoadStop: (controller, url) async { onLoadStop: (controller, url) async {
print("onLoadStop $url"); print("onLoadStop $url");
setState(() { setState(() {
this.url = url; this.url = url ?? '';
}); });
}, },
onUpdateVisitedHistory: (InAppWebViewController controller, String url, bool androidIsReload) { onUpdateVisitedHistory: (controller, url, androidIsReload) {
print("onUpdateVisitedHistory $url"); print("onUpdateVisitedHistory $url");
setState(() { setState(() {
this.url = url; this.url = url ?? '';
}); });
}, },
); );
...@@ -55,7 +55,7 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView ...@@ -55,7 +55,7 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
headlessWebView.dispose(); headlessWebView?.dispose();
} }
@override @override
...@@ -76,8 +76,8 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView ...@@ -76,8 +76,8 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView
Center( Center(
child: RaisedButton( child: RaisedButton(
onPressed: () async { onPressed: () async {
await headlessWebView.dispose(); await headlessWebView?.dispose();
await headlessWebView.run(); await headlessWebView?.run();
}, },
child: Text("Run HeadlessInAppWebView")), child: Text("Run HeadlessInAppWebView")),
), ),
...@@ -85,7 +85,7 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView ...@@ -85,7 +85,7 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView
child: RaisedButton( child: RaisedButton(
onPressed: () async { onPressed: () async {
try { try {
await headlessWebView.webViewController.evaluateJavascript(source: """console.log('Here is the message!');"""); await headlessWebView?.webViewController.evaluateJavascript(source: """console.log('Here is the message!');""");
} on MissingPluginException catch(e) { } on MissingPluginException catch(e) {
print("HeadlessInAppWebView is not running. Click on \"Run HeadlessInAppWebView\"!"); print("HeadlessInAppWebView is not running. Click on \"Run HeadlessInAppWebView\"!");
} }
...@@ -95,7 +95,7 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView ...@@ -95,7 +95,7 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView
Center( Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
headlessWebView.dispose(); headlessWebView?.dispose();
}, },
child: Text("Dispose HeadlessInAppWebView")), child: Text("Dispose HeadlessInAppWebView")),
) )
......
...@@ -12,22 +12,22 @@ class MyInAppBrowser extends InAppBrowser { ...@@ -12,22 +12,22 @@ class MyInAppBrowser extends InAppBrowser {
} }
@override @override
Future onLoadStart(String url) async { Future onLoadStart(url) async {
print("\n\nStarted $url\n\n"); print("\n\nStarted $url\n\n");
} }
@override @override
Future onLoadStop(String url) async { Future onLoadStop(url) async {
print("\n\nStopped $url\n\n"); print("\n\nStopped $url\n\n");
} }
@override @override
void onLoadError(String url, int code, String message) { void onLoadError(url, code, message) {
print("Can't load $url.. Error: $message"); print("Can't load $url.. Error: $message");
} }
@override @override
void onProgressChanged(int progress) { void onProgressChanged(progress) {
print("Progress: $progress"); print("Progress: $progress");
} }
...@@ -38,27 +38,27 @@ class MyInAppBrowser extends InAppBrowser { ...@@ -38,27 +38,27 @@ class MyInAppBrowser extends InAppBrowser {
@override @override
Future<ShouldOverrideUrlLoadingAction> shouldOverrideUrlLoading( Future<ShouldOverrideUrlLoadingAction> shouldOverrideUrlLoading(
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest) async { shouldOverrideUrlLoadingRequest) async {
print("\n\nOverride ${shouldOverrideUrlLoadingRequest.url}\n\n"); print("\n\nOverride ${shouldOverrideUrlLoadingRequest.url}\n\n");
return ShouldOverrideUrlLoadingAction.ALLOW; return ShouldOverrideUrlLoadingAction.ALLOW;
} }
@override @override
void onLoadResource(LoadedResource response) { void onLoadResource(response) {
print("Started at: " + print("Started at: " +
response.startTime.toString() + response.startTime.toString() +
"ms ---> duration: " + "ms ---> duration: " +
response.duration.toString() + response.duration.toString() +
"ms " + "ms " +
response.url); response.url!);
} }
@override @override
void onConsoleMessage(ConsoleMessage consoleMessage) { void onConsoleMessage(consoleMessage) {
print(""" print("""
console output: console output:
message: ${consoleMessage.message} message: ${consoleMessage.message}
messageLevel: ${consoleMessage.messageLevel.toValue()} messageLevel: ${consoleMessage.messageLevel!.toValue()}
"""); """);
} }
} }
...@@ -96,7 +96,6 @@ class _InAppBrowserExampleScreenState extends State<InAppBrowserExampleScreen> { ...@@ -96,7 +96,6 @@ class _InAppBrowserExampleScreenState extends State<InAppBrowserExampleScreen> {
options: InAppBrowserClassOptions( options: InAppBrowserClassOptions(
inAppWebViewGroupOptions: InAppWebViewGroupOptions( inAppWebViewGroupOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions( crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
useShouldOverrideUrlLoading: true, useShouldOverrideUrlLoading: true,
useOnLoadResource: true, useOnLoadResource: true,
)))); ))));
......
import 'dart:developer';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
...@@ -14,8 +13,8 @@ class InAppWebViewExampleScreen extends StatefulWidget { ...@@ -14,8 +13,8 @@ class InAppWebViewExampleScreen extends StatefulWidget {
} }
class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
InAppWebViewController webView; InAppWebViewController? webView;
ContextMenu contextMenu; late ContextMenu contextMenu;
String url = ""; String url = "";
double progress = 0; double progress = 0;
CookieManager _cookieManager = CookieManager.instance(); CookieManager _cookieManager = CookieManager.instance();
...@@ -28,8 +27,8 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -28,8 +27,8 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
menuItems: [ menuItems: [
ContextMenuItem(androidId: 1, iosId: "1", title: "Special", action: () async { ContextMenuItem(androidId: 1, iosId: "1", title: "Special", action: () async {
print("Menu item Special clicked!"); print("Menu item Special clicked!");
print(await webView.getSelectedText()); print(await webView?.getSelectedText());
await webView.clearFocus(); await webView?.clearFocus();
}) })
], ],
options: ContextMenuOptions( options: ContextMenuOptions(
...@@ -38,7 +37,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -38,7 +37,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
onCreateContextMenu: (hitTestResult) async { onCreateContextMenu: (hitTestResult) async {
print("onCreateContextMenu"); print("onCreateContextMenu");
print(hitTestResult.extra); print(hitTestResult.extra);
print(await webView.getSelectedText()); print(await webView?.getSelectedText());
}, },
onHideContextMenu: () { onHideContextMenu: () {
print("onHideContextMenu"); print("onHideContextMenu");
...@@ -81,26 +80,25 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -81,26 +80,25 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
BoxDecoration(border: Border.all(color: Colors.blueAccent)), BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: InAppWebView( child: InAppWebView(
// contextMenu: contextMenu, // contextMenu: contextMenu,
initialUrl: "https://github.com/flutter", initialUrl: "https://flutter.dev/",
// initialFile: "assets/index.html", // initialFile: "assets/index.html",
initialHeaders: {}, initialHeaders: {},
initialOptions: InAppWebViewGroupOptions( initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions( crossPlatform: InAppWebViewOptions(
debuggingEnabled: true, useShouldOverrideUrlLoading: false,
useShouldOverrideUrlLoading: true,
), ),
android: AndroidInAppWebViewOptions( android: AndroidInAppWebViewOptions(
useHybridComposition: true useHybridComposition: true
) )
), ),
onWebViewCreated: (InAppWebViewController controller) { onWebViewCreated: (controller) {
webView = controller; webView = controller;
print("onWebViewCreated"); print("onWebViewCreated");
}, },
onLoadStart: (InAppWebViewController controller, String url) { onLoadStart: (controller, url) {
print("onLoadStart $url"); print("onLoadStart $url");
setState(() { setState(() {
this.url = url; this.url = url ?? '';
}); });
}, },
shouldOverrideUrlLoading: (controller, shouldOverrideUrlLoadingRequest) async { shouldOverrideUrlLoading: (controller, shouldOverrideUrlLoadingRequest) async {
...@@ -122,21 +120,21 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -122,21 +120,21 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
return ShouldOverrideUrlLoadingAction.ALLOW; return ShouldOverrideUrlLoadingAction.ALLOW;
}, },
onLoadStop: (InAppWebViewController controller, String url) async { onLoadStop: (controller, url) async {
print("onLoadStop $url"); print("onLoadStop $url");
setState(() { setState(() {
this.url = url; this.url = url ?? '';
}); });
}, },
onProgressChanged: (InAppWebViewController controller, int progress) { onProgressChanged: (controller, progress) {
setState(() { setState(() {
this.progress = progress / 100; this.progress = progress / 100;
}); });
}, },
onUpdateVisitedHistory: (InAppWebViewController controller, String url, bool androidIsReload) { onUpdateVisitedHistory: (controller, url, androidIsReload) {
print("onUpdateVisitedHistory $url"); print("onUpdateVisitedHistory $url");
setState(() { setState(() {
this.url = url; this.url = url ?? '';
}); });
}, },
onConsoleMessage: (controller, consoleMessage) { onConsoleMessage: (controller, consoleMessage) {
...@@ -151,25 +149,19 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -151,25 +149,19 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
RaisedButton( RaisedButton(
child: Icon(Icons.arrow_back), child: Icon(Icons.arrow_back),
onPressed: () { onPressed: () {
if (webView != null) { webView?.goBack();
webView.goBack();
}
}, },
), ),
RaisedButton( RaisedButton(
child: Icon(Icons.arrow_forward), child: Icon(Icons.arrow_forward),
onPressed: () { onPressed: () {
if (webView != null) { webView?.goForward();
webView.goForward();
}
}, },
), ),
RaisedButton( RaisedButton(
child: Icon(Icons.refresh), child: Icon(Icons.refresh),
onPressed: () { onPressed: () {
if (webView != null) { webView?.reload();
webView.reload();
}
}, },
), ),
], ],
......
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_inappwebview_example/chrome_safari_browser_example.screen.dart'; import 'package:flutter_inappwebview_example/chrome_safari_browser_example.screen.dart';
import 'package:flutter_inappwebview_example/headless_in_app_webview.screen.dart'; import 'package:flutter_inappwebview_example/headless_in_app_webview.screen.dart';
...@@ -15,10 +17,13 @@ Future main() async { ...@@ -15,10 +17,13 @@ Future main() async {
// await Permission.camera.request(); // await Permission.camera.request();
// await Permission.storage.request(); // await Permission.storage.request();
// await localhostServer.start(); // await localhostServer.start();
if (Platform.isAndroid) {
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
}
runApp(MyApp()); runApp(MyApp());
} }
Drawer myDrawer({@required BuildContext context}) { Drawer myDrawer({required BuildContext context}) {
return Drawer( return Drawer(
child: ListView( child: ListView(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
......
...@@ -10,8 +10,8 @@ description: Demonstrates how to use the flutter_inappwebview plugin. ...@@ -10,8 +10,8 @@ description: Demonstrates how to use the flutter_inappwebview plugin.
version: 1.0.0+1 version: 1.0.0+1
environment: environment:
sdk: ">=2.0.0-dev.68.0 <3.0.0" sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.10.0 <2.0.0" flutter: ">=1.22.0"
dependencies: dependencies:
flutter: flutter:
...@@ -19,20 +19,26 @@ dependencies: ...@@ -19,20 +19,26 @@ dependencies:
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2 cupertino_icons: ^1.0.2
flutter_downloader: ^1.4.4 flutter_downloader: ^1.5.2
path_provider: ^1.6.9 path_provider: ^1.6.27
permission_handler: ^5.0.0+hotfix.6 permission_handler: ^5.0.1+1
url_launcher: ^5.4.11 url_launcher: ^6.0.0-nullsafety.4
# connectivity: ^0.4.5+6 # connectivity: ^0.4.5+6
flutter_inappwebview: flutter_inappwebview:
path: ../ path: ../
dev_dependencies: dev_dependencies:
e2e: "^0.2.0" flutter_test:
sdk: flutter
flutter_driver: flutter_driver:
sdk: flutter sdk: flutter
test: any # integration_test: ^1.0.2+1
integration_test:
git:
url: https://github.com/flutter/plugins.git
path: packages/integration_test
pedantic: ^1.8.0
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec # following page: https://www.dartlang.org/tools/pub/pubspec
...@@ -53,6 +59,8 @@ flutter: ...@@ -53,6 +59,8 @@ flutter:
- assets/css/ - assets/css/
- assets/images/ - assets/images/
- assets/favicon.ico - assets/favicon.ico
- assets/sample_audio.ogg
- assets/sample_video.mp4
- test_assets/certificate.pfx - test_assets/certificate.pfx
- test_assets/in_app_webview_initial_file_test.html - test_assets/in_app_webview_initial_file_test.html
- test_assets/in_app_webview_on_load_resource_test.html - test_assets/in_app_webview_on_load_resource_test.html
...@@ -64,6 +72,8 @@ flutter: ...@@ -64,6 +72,8 @@ flutter:
- test_assets/css/ - test_assets/css/
- test_assets/images/ - test_assets/images/
- test_assets/favicon.ico - test_assets/favicon.ico
- test_assets/sample_audio.ogg
- test_assets/sample_video.mp4
# To add assets to your application, add an assets section, like this: # To add assets to your application, add an assets section, like this:
# assets: # assets:
......
final environment = {"NODE_SERVER_IP":"192.168.1.122"};
\ No newline at end of file
import 'package:flutter_driver/driver_extension.dart';
import 'main_test.dart' as app;
void main() {
// This line enables the extension.
enableFlutterDriverExtension();
// Call the `main()` function of the app, or call `runApp` with
// any widget you are interested in testing.
app.main();
}
\ No newline at end of file
This diff is collapsed.
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
class WidgetTest extends StatefulWidget {
final WidgetTestState state = WidgetTestState();
WidgetTest({Key key}): super(key: key);
@override
WidgetTestState createState() {
return state;
}
}
class WidgetTestState extends State<WidgetTest> {
final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
InAppWebViewController webView;
String appBarTitle;
@override
Widget build(BuildContext context) {
return null;
}
}
\ No newline at end of file
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'main_test.dart';
import 'custom_widget_test.dart';
import '.env.dart';
class InAppWebViewAjaxTest extends WidgetTest {
final InAppWebViewAjaxTestState state = InAppWebViewAjaxTestState();
@override
InAppWebViewAjaxTestState createState() => state;
}
class InAppWebViewAjaxTestState extends WidgetTestState {
String appBarTitle = "InAppWebViewAjaxTest";
int totTests = 2;
int testsDone = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
key: this.scaffoldKey,
appBar: myAppBar(state: this, title: appBarTitle),
drawer: myDrawer(context: context),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialData: InAppWebViewInitialData(data: """
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>InAppWebViewAjaxTest</title>
</head>
<body>
<h1>InAppWebViewAjaxTest</h1>
<script>
window.addEventListener('flutterInAppWebViewPlatformReady', function(event) {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "http://${environment["NODE_SERVER_IP"]}:8082/test-ajax-post");
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("firstname=Foo&lastname=Bar");
var xhttp2 = new XMLHttpRequest();
xhttp2.open("GET", "http://${environment["NODE_SERVER_IP"]}:8082/test-download-file");
xhttp2.send();
});
</script>
</body>
</html>
"""),
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true,
useShouldInterceptAjaxRequest: true,
)
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) {
},
shouldInterceptAjaxRequest: (InAppWebViewController controller, AjaxRequest ajaxRequest) async {
if (ajaxRequest.url.endsWith("/test-ajax-post")) {
ajaxRequest.responseType = 'json';
ajaxRequest.data = "firstname=Lorenzo&lastname=Pichilli";
}
return ajaxRequest;
},
onAjaxReadyStateChange: (InAppWebViewController controller, AjaxRequest ajaxRequest) async {
if (ajaxRequest.readyState == AjaxRequestReadyState.DONE && ajaxRequest.status == 200 && ajaxRequest.url.endsWith("/test-ajax-post")) {
Map<String, Object> res = ajaxRequest.response;
appBarTitle = (appBarTitle == "InAppWebViewAjaxTest") ? res['fullname'] : appBarTitle + " " + res['fullname'];
updateCountTest(context: context);
}
return AjaxRequestAction.PROCEED;
},
onAjaxProgress: (InAppWebViewController controller, AjaxRequest ajaxRequest) async {
if (ajaxRequest.event.type == AjaxRequestEventType.LOAD && ajaxRequest.url.endsWith("/test-ajax-post")) {
Map<String, Object> res = ajaxRequest.response;
appBarTitle = (appBarTitle == "InAppWebViewAjaxTest") ? res['fullname'] : appBarTitle + " " + res['fullname'];
updateCountTest(context: context);
}
return AjaxRequestAction.PROCEED;
},
),
),
),
])
)
);
}
void updateCountTest({@required BuildContext context}) {
testsDone++;
if (testsDone == totTests) {
setState(() { });
}
}
}
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'custom_widget_test.dart';
import 'main_test.dart';
class InAppWebViewContentBlockerTest extends WidgetTest {
final InAppWebViewContentBlockerTestState state = InAppWebViewContentBlockerTestState();
@override
InAppWebViewContentBlockerTestState createState() => state;
}
class InAppWebViewContentBlockerTestState extends WidgetTestState {
String appBarTitle = "InAppWebViewContentBlockerTest";
@override
Widget build(BuildContext context) {
return Scaffold(
key: this.scaffoldKey,
appBar: myAppBar(state: this, title: appBarTitle),
drawer: myDrawer(context: context),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialUrl: "https://flutter.dev/",
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true,
contentBlockers: [
ContentBlocker(
trigger: ContentBlockerTrigger(
urlFilter: ".*",
resourceType: [
ContentBlockerTriggerResourceType.IMAGE,
ContentBlockerTriggerResourceType.STYLE_SHEET
],
ifTopUrl: [
"https://flutter.dev/"
]),
action: ContentBlockerAction(
type: ContentBlockerActionType.BLOCK))
]
)
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) {
setState(() {
appBarTitle = "true";
});
},
),
),
),
])
)
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'custom_widget_test.dart';
import 'main_test.dart';
class InAppWebViewCookieManagerTest extends WidgetTest {
final InAppWebViewCookieManagerTestState state = InAppWebViewCookieManagerTestState();
@override
InAppWebViewCookieManagerTestState createState() => state;
}
class InAppWebViewCookieManagerTestState extends WidgetTestState {
String appBarTitle = "InAppWebViewCookieManagerTest";
CookieManager cookieManager = CookieManager.instance();
@override
Widget build(BuildContext context) {
return Scaffold(
key: this.scaffoldKey,
appBar: myAppBar(state: this, title: appBarTitle),
drawer: myDrawer(context: context),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialUrl: "https://flutter.dev/",
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) async {
var title = "";
await cookieManager.getCookies(url: url);
await cookieManager.setCookie(url: url, name: "myCookie", value: "myValue");
Cookie cookie = await cookieManager.getCookie(url: url, name: "myCookie");
title = cookie.value.toString();
await cookieManager.deleteCookie(url: url, name: "myCookie");
cookie = await cookieManager.getCookie(url: url, name: "myCookie");
title += " " + ((cookie == null) ? "true" : "false");
await cookieManager.deleteCookies(url: url);
List<Cookie> cookies = await cookieManager.getCookies(url: url);
title += " " + ((cookies.length == 0) ? "true" : "false");
setState(() {
appBarTitle = title;
});
},
),
),
),
])
)
);
}
}
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'main_test.dart';
import 'custom_widget_test.dart';
import '.env.dart';
class InAppWebViewFetchTest extends WidgetTest {
final InAppWebViewFetchTestState state = InAppWebViewFetchTestState();
@override
InAppWebViewFetchTestState createState() => state;
}
class InAppWebViewFetchTestState extends WidgetTestState {
String appBarTitle = "InAppWebViewFetchTest";
int totTests = 2;
int testsDone = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
key: this.scaffoldKey,
appBar: myAppBar(state: this, title: appBarTitle),
drawer: myDrawer(context: context),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialData: InAppWebViewInitialData(data: """
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>InAppWebViewFetchTest</title>
</head>
<body>
<h1>InAppWebViewFetchTest</h1>
<script>
window.addEventListener('flutterInAppWebViewPlatformReady', function(event) {
fetch(new Request("http://${environment["NODE_SERVER_IP"]}:8082/test-download-file")).then(function(response) {
window.flutter_inappwebview.callHandler('fetchGet', response.status);
}).catch(function(error) {
window.flutter_inappwebview.callHandler('fetchGet', "ERROR: " + error);
});
fetch("http://${environment["NODE_SERVER_IP"]}:8082/test-ajax-post", {
method: 'POST',
body: JSON.stringify({
firstname: 'Foo',
lastname: 'Bar'
}),
headers: {
'Content-Type': 'application/json'
}
}).then(function(response) {
response.json().then(function(value) {
window.flutter_inappwebview.callHandler('fetchPost', value);
}).catch(function(error) {
window.flutter_inappwebview.callHandler('fetchPost', "ERROR: " + error);
});
}).catch(function(error) {
window.flutter_inappwebview.callHandler('fetchPost', "ERROR: " + error);
});
});
</script>
</body>
</html>
"""),
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true,
useShouldInterceptFetchRequest: true,
)
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
webView.addJavaScriptHandler(handlerName: "fetchGet", callback: (args) {
appBarTitle = (appBarTitle == "InAppWebViewFetchTest") ? args[0].toString() : appBarTitle + " " + args[0].toString();
updateCountTest(context: context);
});
webView.addJavaScriptHandler(handlerName: "fetchPost", callback: (args) {
appBarTitle = (appBarTitle == "InAppWebViewFetchTest") ? args[0]["fullname"] : appBarTitle + " " + args[0]["fullname"];
updateCountTest(context: context);
});
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) {
},
shouldInterceptFetchRequest: (InAppWebViewController controller, FetchRequest fetchRequest) async {
if (fetchRequest.url.endsWith("/test-ajax-post")) {
fetchRequest.body = utf8.encode("""{
"firstname": "Lorenzo",
"lastname": "Pichilli"
}
""");
}
return fetchRequest;
},
),
),
),
])
)
);
}
void updateCountTest({@required BuildContext context}) {
testsDone++;
if (testsDone == totTests) {
setState(() { });
}
}
}
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'custom_widget_test.dart';
import 'main_test.dart';
import '.env.dart';
class InAppWebViewHttpAuthCredentialDatabaseTest extends WidgetTest {
final InAppWebViewHttpAuthCredentialDatabaseTestState state = InAppWebViewHttpAuthCredentialDatabaseTestState();
@override
InAppWebViewHttpAuthCredentialDatabaseTestState createState() => state;
}
class InAppWebViewHttpAuthCredentialDatabaseTestState extends WidgetTestState {
String appBarTitle = "InAppWebViewHttpAuthCredentialDatabaseTest";
HttpAuthCredentialDatabase httpAuthCredentialDatabase = HttpAuthCredentialDatabase.instance();
@override
Widget build(BuildContext context) {
httpAuthCredentialDatabase.setHttpAuthCredential(
protectionSpace: ProtectionSpace(host: environment["NODE_SERVER_IP"], protocol: "http", realm: "Node", port: 8081),
credential: HttpAuthCredential(username: "USERNAME", password: "PASSWORD")
);
return Scaffold(
key: this.scaffoldKey,
appBar: myAppBar(state: this, title: appBarTitle),
drawer: myDrawer(context: context),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialUrl: "http://${environment["NODE_SERVER_IP"]}:8081/",
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) async {
var title = "";
String h1Content = await controller.evaluateJavascript(source: "document.body.querySelector('h1').textContent");
title = h1Content;
var credentials = await httpAuthCredentialDatabase.getHttpAuthCredentials(protectionSpace:
ProtectionSpace(host: environment["NODE_SERVER_IP"], protocol: "http", realm: "Node", port: 8081)
);
title += " " + ((credentials.length == 1) ? "true" : "false");
await httpAuthCredentialDatabase.clearAllAuthCredentials();
credentials = await httpAuthCredentialDatabase.getHttpAuthCredentials(protectionSpace:
ProtectionSpace(host: environment["NODE_SERVER_IP"], protocol: "http", realm: "Node", port: 8081)
);
title += " " + ((credentials.length == 0) ? "true" : "false");
setState(() {
appBarTitle = title;
});
},
onReceivedHttpAuthRequest: (InAppWebViewController controller, HttpAuthChallenge challenge) async {
return new HttpAuthResponse(action: HttpAuthResponseAction.USE_SAVED_HTTP_AUTH_CREDENTIALS);
},
),
),
),
])
)
);
}
}
// @dart = 2.9
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter_driver/flutter_driver.dart';
Future<void> main() async {
final FlutterDriver driver = await FlutterDriver.connect();
final String data =
await driver.requestData(null, timeout: const Duration(minutes: 1));
await driver.close();
final Map<String, dynamic> result = jsonDecode(data);
exit(result['result'] == 'true' ? 0 : 1);
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
...@@ -65,7 +65,9 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin { ...@@ -65,7 +65,9 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
if let flutterViewController = UIApplication.shared.delegate?.window.unsafelyUnwrapped?.rootViewController as? FlutterViewController { if let flutterViewController = UIApplication.shared.delegate?.window.unsafelyUnwrapped?.rootViewController {
// flutterViewController could be casted to FlutterViewController if needed
let safariOptions = SafariBrowserOptions() let safariOptions = SafariBrowserOptions()
let _ = safariOptions.parse(options: options) let _ = safariOptions.parse(options: options)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment