) call.argument("options");
+ inAppBrowserOptions.parse(inAppBrowserOptionsMap);
+ setOptions(uuid, inAppBrowserOptions, inAppBrowserOptionsMap);
break;
default:
result.error(LOG_TAG, "Options " + optionsType + " not available.", null);
@@ -276,85 +256,10 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
}
- /**
- * Inject an object (script or style) into the InAppBrowserFlutterPlugin WebView.
- *
- * This is a helper method for the inject{Script|Style}{Code|File} API calls, which
- * provides a consistent method for injecting JavaScript code into the document.
- *
- * If a wrapper string is supplied, then the source string will be JSON-encoded (adding
- * quotes) and wrapped using string formatting. (The wrapper string should have a single
- * '%s' marker)
- *
- * @param uuid
- * @param source The source object (filename or script/style text) to inject into
- * the document.
- * @param jsWrapper A JavaScript string to wrap the source string in, so that the object
- * is properly injected, or null if the source string is JavaScript text
- * @param result
- */
private void injectDeferredObject(String uuid, String source, String jsWrapper, final Result result) {
- final WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null) {
- String scriptToInject;
- if (jsWrapper != null) {
- org.json.JSONArray jsonEsc = new org.json.JSONArray();
- jsonEsc.put(source);
- String jsonRepr = jsonEsc.toString();
- String jsonSourceString = jsonRepr.substring(1, jsonRepr.length() - 1);
- scriptToInject = String.format(jsWrapper, jsonSourceString);
- } else {
- scriptToInject = source;
- }
- final String finalScriptToInject = scriptToInject;
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- // This action will have the side-effect of blurring the currently focused element
- webViewActivity.webView.loadUrl("javascript:" + finalScriptToInject);
- } else {
- webViewActivity.webView.evaluateJavascript(finalScriptToInject, new ValueCallback() {
- @Override
- public void onReceiveValue(String s) {
- if (result == null)
- return;
-
- JsonReader reader = new JsonReader(new StringReader(s));
-
- // Must set lenient to parse single values
- reader.setLenient(true);
-
- try {
- String msg;
- if (reader.peek() == JsonToken.STRING) {
- msg = reader.nextString();
-
- JsonReader reader2 = new JsonReader(new StringReader(msg));
- reader2.setLenient(true);
-
- if (reader2.peek() == JsonToken.STRING)
- msg = reader2.nextString();
-
- result.success(msg);
- } else {
- result.success("");
- }
-
- } catch (IOException e) {
- Log.e(LOG_TAG, "IOException", e);
- } finally {
- try {
- reader.close();
- } catch (IOException e) {
- // NOOP
- }
- }
- }
- });
- }
- }
- });
+ final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null) {
+ inAppBrowserActivity.injectDeferredObject(source, jsWrapper, result);
} else {
Log.d(LOG_TAG, "Can't inject code into the system browser");
}
@@ -435,14 +340,14 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
}
}
- public void open(String uuid, String uuidFallback, String url, Options options, Map headers, boolean useChromeSafariBrowser, InAppBrowserOptions optionsFallback, Result result) {
+ public void open(String uuid, String uuidFallback, String url, HashMap options, Map headers, boolean useChromeSafariBrowser, HashMap optionsFallback, Result result) {
Intent intent = null;
Bundle extras = new Bundle();
extras.putString("url", url);
extras.putString("uuid", uuid);
- extras.putSerializable("options", options.getHashMap());
+ extras.putSerializable("options", options);
extras.putSerializable("headers", (Serializable) headers);
if (useChromeSafariBrowser && CustomTabActivityHelper.isAvailable(activity)) {
@@ -454,15 +359,15 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
// overwrite with extras fallback parameters
extras.putString("uuid", uuidFallback);
if (optionsFallback != null)
- extras.putSerializable("options", optionsFallback.getHashMap());
+ extras.putSerializable("options", optionsFallback);
else
extras.putSerializable("options", (new InAppBrowserOptions()).getHashMap());
extras.putSerializable("headers", (Serializable) headers);
- intent = new Intent(activity, WebViewActivity.class);
+ intent = new Intent(activity, InAppBrowserActivity.class);
}
// native webview
else if (!useChromeSafariBrowser) {
- intent = new Intent(activity, WebViewActivity.class);
+ intent = new Intent(activity, InAppBrowserActivity.class);
}
else {
Log.d(LOG_TAG, "No WebView fallback declared.");
@@ -479,93 +384,93 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
}
public void loadUrl(String uuid, String url, Map headers, Result result) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null) {
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null) {
if (headers != null)
- webViewActivity.loadUrl(url, headers, result);
+ inAppBrowserActivity.loadUrl(url, headers, result);
else
- webViewActivity.loadUrl(url, result);
+ inAppBrowserActivity.loadUrl(url, result);
}
}
public void loadFile(String uuid, String url, Map headers, Result result) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null) {
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null) {
if (headers != null)
- webViewActivity.loadFile(url, headers, result);
+ inAppBrowserActivity.loadFile(url, headers, result);
else
- webViewActivity.loadFile(url, result);
+ inAppBrowserActivity.loadFile(url, result);
}
}
public void show(String uuid) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- webViewActivity.show();
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ inAppBrowserActivity.show();
}
public void hide(String uuid) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- webViewActivity.hide();
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ inAppBrowserActivity.hide();
}
public void reload(String uuid) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- webViewActivity.reload();
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ inAppBrowserActivity.reload();
}
public boolean isLoading(String uuid) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- return webViewActivity.isLoading();
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ return inAppBrowserActivity.isLoading();
return false;
}
public boolean isHidden(String uuid) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- return webViewActivity.isHidden;
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ return inAppBrowserActivity.isHidden;
return false;
}
public void stopLoading(String uuid) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- webViewActivity.stopLoading();
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ inAppBrowserActivity.stopLoading();
}
public void goBack(String uuid) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- webViewActivity.goBack();
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ inAppBrowserActivity.goBack();
}
public boolean canGoBack(String uuid) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- return webViewActivity.canGoBack();
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ return inAppBrowserActivity.canGoBack();
return false;
}
public void goForward(String uuid) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- webViewActivity.goForward();
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ inAppBrowserActivity.goForward();
}
public boolean canGoForward(String uuid) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- return webViewActivity.canGoForward();
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ return inAppBrowserActivity.canGoForward();
return false;
}
public static void close(final String uuid, final Result result) {
- final WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null) {
+ final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null) {
registrar.activity().runOnUiThread(new Runnable() {
@Override
public void run() {
@@ -576,23 +481,23 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
// The JS protects against multiple calls, so this should happen only when
// close() is called by other native code.
- if (webViewActivity == null) {
+ if (inAppBrowserActivity == null) {
if (result != null) {
result.success(true);
}
return;
}
- webViewActivity.webView.setWebViewClient(new WebViewClient() {
+ inAppBrowserActivity.webView.setWebViewClient(new WebViewClient() {
// NB: wait for about:blank before dismissing
public void onPageFinished(WebView view, String url) {
- webViewActivity.close();
+ inAppBrowserActivity.close();
}
});
// NB: From SDK 19: "If you call methods on WebView from any thread
// other than your app's UI thread, it can cause unexpected results."
// http://developer.android.com/guide/webapps/migrating.html#Threads
- webViewActivity.webView.loadUrl("about:blank");
+ inAppBrowserActivity.webView.loadUrl("about:blank");
if (result != null) {
result.success(true);
}
@@ -605,22 +510,22 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
}
public byte[] takeScreenshot(String uuid) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- return webViewActivity.takeScreenshot();
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ return inAppBrowserActivity.takeScreenshot();
return null;
}
public void setOptions(String uuid, InAppBrowserOptions options, HashMap optionsMap) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- webViewActivity.setOptions(options, optionsMap);
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ inAppBrowserActivity.setOptions(options, optionsMap);
}
public HashMap getOptions(String uuid) {
- WebViewActivity webViewActivity = webViewActivities.get(uuid);
- if (webViewActivity != null)
- return webViewActivity.getOptions();
+ InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
+ if (inAppBrowserActivity != null)
+ return inAppBrowserActivity.getOptions();
return null;
}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java
index ec33f116..58f81d56 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java
@@ -4,29 +4,13 @@ public class InAppBrowserOptions extends Options {
static final String LOG_TAG = "InAppBrowserOptions";
- public boolean useShouldOverrideUrlLoading = false;
- public boolean useOnLoadResource = false;
- public boolean openWithSystemBrowser = false;
- public boolean clearCache = false;
- public String userAgent = "";
- public boolean javaScriptEnabled = true;
- public boolean javaScriptCanOpenWindowsAutomatically = false;
public boolean hidden = false;
public boolean toolbarTop = true;
public String toolbarTopBackgroundColor = "";
public String toolbarTopFixedTitle = "";
public boolean hideUrlBar = false;
- public boolean mediaPlaybackRequiresUserGesture = true;
- public boolean isLocalFile = false;
public boolean hideTitleBar = false;
public boolean closeOnCannotGoBack = true;
- public boolean clearSessionCache = false;
- public boolean builtInZoomControls = false;
- public boolean supportZoom = true;
- public boolean databaseEnabled = false;
- public boolean domStorageEnabled = false;
- public boolean useWideViewPort = true;
- public boolean safeBrowsingEnabled = true;
public boolean progressBar = true;
}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebChromeClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebChromeClient.java
similarity index 57%
rename from android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebChromeClient.java
rename to android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebChromeClient.java
index d940b64b..1324b0b9 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebChromeClient.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebChromeClient.java
@@ -1,65 +1,82 @@
-package com.pichillilorenzo.flutter_inappbrowser;
+package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
-import android.util.Log;
import android.view.View;
import android.webkit.ConsoleMessage;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
+import com.pichillilorenzo.flutter_inappbrowser.FlutterWebView;
+import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity;
+import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
+
import java.util.HashMap;
import java.util.Map;
-public class InAppBrowserWebChromeClient extends WebChromeClient {
+import io.flutter.plugin.common.MethodChannel;
+
+public class InAppWebChromeClient extends WebChromeClient {
protected static final String LOG_TAG = "IABWebChromeClient";
- private WebViewActivity activity;
+ private FlutterWebView flutterWebView;
+ private InAppBrowserActivity inAppBrowserActivity;
private ValueCallback mUploadMessageArray;
private ValueCallback mUploadMessage;
private final static int FILECHOOSER_RESULTCODE = 1;
- public InAppBrowserWebChromeClient(WebViewActivity activity) {
+ public InAppWebChromeClient(Object obj) {
super();
- this.activity = activity;
+ if (obj instanceof InAppBrowserActivity)
+ this.inAppBrowserActivity = (InAppBrowserActivity) obj;
+ else if (obj instanceof FlutterWebView)
+ this.flutterWebView = (FlutterWebView) obj;
}
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
Map obj = new HashMap<>();
- obj.put("uuid", activity.uuid);
+ if (inAppBrowserActivity != null)
+ obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("sourceURL", consoleMessage.sourceId());
obj.put("lineNumber", consoleMessage.lineNumber());
obj.put("message", consoleMessage.message());
obj.put("messageLevel", consoleMessage.messageLevel().toString());
- InAppBrowserFlutterPlugin.channel.invokeMethod("onConsoleMessage", obj);
+ getChannel().invokeMethod("onConsoleMessage", obj);
return true;
}
@Override
public void onProgressChanged(WebView view, int progress) {
- if (activity.progressBar != null) {
- activity.progressBar.setVisibility(View.VISIBLE);
+ if (inAppBrowserActivity != null && inAppBrowserActivity.progressBar != null) {
+ inAppBrowserActivity.progressBar.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- activity.progressBar.setProgress(progress, true);
+ inAppBrowserActivity.progressBar.setProgress(progress, true);
} else {
- activity.progressBar.setProgress(progress);
+ inAppBrowserActivity.progressBar.setProgress(progress);
}
if (progress == 100) {
- activity.progressBar.setVisibility(View.GONE);
+ inAppBrowserActivity.progressBar.setVisibility(View.GONE);
}
}
+
+ Map obj = new HashMap<>();
+ if (inAppBrowserActivity != null)
+ obj.put("uuid", inAppBrowserActivity.uuid);
+ obj.put("progress", progress);
+ getChannel().invokeMethod("onProgressChanged", obj);
+
super.onProgressChanged(view, progress);
}
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
- if (activity.actionBar != null && activity.options.toolbarTopFixedTitle.isEmpty())
- activity.actionBar.setTitle(title);
+ if (inAppBrowserActivity != null && inAppBrowserActivity.actionBar != null && inAppBrowserActivity.options.toolbarTopFixedTitle.isEmpty())
+ inAppBrowserActivity.actionBar.setTitle(title);
}
@Override
@@ -76,7 +93,7 @@ public class InAppBrowserWebChromeClient extends WebChromeClient {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
- activity.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
+ ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
}
@@ -86,7 +103,7 @@ public class InAppBrowserWebChromeClient extends WebChromeClient {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
- activity.startActivityForResult(
+ ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivityForResult(
Intent.createChooser(i, "File Browser"),
FILECHOOSER_RESULTCODE);
}
@@ -97,7 +114,7 @@ public class InAppBrowserWebChromeClient extends WebChromeClient {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
- activity.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
+ ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
}
@@ -120,7 +137,11 @@ public class InAppBrowserWebChromeClient extends WebChromeClient {
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
- activity.startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
+ ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
return true;
}
+
+ private MethodChannel getChannel() {
+ return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.channel : flutterWebView.channel;
+ }
}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java
new file mode 100644
index 00000000..79fc739d
--- /dev/null
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java
@@ -0,0 +1,374 @@
+package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Picture;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.util.JsonReader;
+import android.util.JsonToken;
+import android.util.Log;
+import android.webkit.CookieManager;
+import android.webkit.ValueCallback;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+
+import com.pichillilorenzo.flutter_inappbrowser.FlutterWebView;
+import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity;
+import com.pichillilorenzo.flutter_inappbrowser.JavaScriptBridgeInterface;
+import com.pichillilorenzo.flutter_inappbrowser.Util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+
+import io.flutter.plugin.common.MethodChannel;
+import okhttp3.Cache;
+import okhttp3.OkHttpClient;
+
+import static com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin.registrar;
+
+public class InAppWebView extends WebView {
+
+ static final String LOG_TAG = "InAppWebView";
+
+ public InAppBrowserActivity inAppBrowserActivity;
+ public FlutterWebView flutterWebView;
+ int id;
+ InAppWebViewClient inAppWebViewClient;
+ InAppWebChromeClient inAppWebChromeClient;
+ public InAppWebViewOptions options;
+ public boolean isLoading = false;
+ OkHttpClient httpClient;
+ int okHttpClientCacheSize = 10 * 1024 * 1024; // 10MB
+
+ static final String consoleLogJS = "(function() {" +
+ " var oldLogs = {" +
+ " 'log': console.log," +
+ " 'debug': console.debug," +
+ " 'error': console.error," +
+ " 'info': console.info," +
+ " 'warn': console.warn" +
+ " };" +
+ " for (var k in oldLogs) {" +
+ " (function(oldLog) {" +
+ " console[oldLog] = function() {" +
+ " var message = '';" +
+ " for (var i in arguments) {" +
+ " if (message == '') {" +
+ " message += arguments[i];" +
+ " }" +
+ " else {" +
+ " message += ' ' + arguments[i];" +
+ " }" +
+ " }" +
+ " oldLogs[oldLog].call(console, message);" +
+ " }" +
+ " })(k);" +
+ " }" +
+ "})();";
+
+ public InAppWebView(Context context) {
+ super(context);
+ }
+
+ public InAppWebView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public InAppWebView(Context context, AttributeSet attrs, int defaultStyle) {
+ super(context, attrs, defaultStyle);
+ }
+
+ public InAppWebView(Context context, Object obj, int id, InAppWebViewOptions options) {
+ super(context);
+ if (obj instanceof InAppBrowserActivity)
+ this.inAppBrowserActivity = (InAppBrowserActivity) obj;
+ else if (obj instanceof FlutterWebView)
+ this.flutterWebView = (FlutterWebView) obj;
+ this.id = id;
+ this.options = options;
+ }
+
+ public void prepare() {
+
+ boolean isFromInAppBrowserActivity = inAppBrowserActivity != null;
+
+ httpClient = new OkHttpClient().newBuilder().cache(new Cache(getContext().getCacheDir(), okHttpClientCacheSize)).build();
+
+ addJavascriptInterface(new JavaScriptBridgeInterface((isFromInAppBrowserActivity) ? inAppBrowserActivity : flutterWebView), JavaScriptBridgeInterface.name);
+
+ inAppWebChromeClient = new InAppWebChromeClient((isFromInAppBrowserActivity) ? inAppBrowserActivity : flutterWebView);
+ setWebChromeClient(inAppWebChromeClient);
+
+ inAppWebViewClient = new InAppWebViewClient((isFromInAppBrowserActivity) ? inAppBrowserActivity : flutterWebView);
+ setWebViewClient(inAppWebViewClient);
+
+// final Activity activity = this;
+//
+// webView.setDownloadListener(new DownloadListener() {
+// @Override
+// public void onDownloadStart(final String url, final String userAgent,
+// final String contentDisposition, final String mimetype,
+// final long contentLength) {
+//
+// RequestPermissionHandler.checkAndRun(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, RequestPermissionHandler.REQUEST_CODE_WRITE_EXTERNAL_STORAGE, new Runnable(){
+// @Override
+// public void run(){
+// DownloadManager.Request request = new DownloadManager.Request(
+// Uri.parse(url));
+//
+// final String filename = URLUtil.guessFileName(url, contentDisposition, mimetype);
+// request.allowScanningByMediaScanner();
+// request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed!
+// request.setVisibleInDownloadsUi(true);
+// request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
+// DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
+// if (dm != null) {
+// dm.enqueue(request);
+// Toast.makeText(getApplicationContext(), "Downloading File: " + filename, //To notify the Client that the file is being downloaded
+// Toast.LENGTH_LONG).show();
+// }
+// else {
+// Toast.makeText(getApplicationContext(), "Cannot Download File: " + filename, //To notify the Client that the file cannot be downloaded
+// Toast.LENGTH_LONG).show();
+// }
+// }
+// });
+// }
+// });
+
+ WebSettings settings = getSettings();
+
+ settings.setJavaScriptEnabled(options.javaScriptEnabled);
+ settings.setJavaScriptCanOpenWindowsAutomatically(options.javaScriptCanOpenWindowsAutomatically);
+ settings.setBuiltInZoomControls(options.builtInZoomControls);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ settings.setSafeBrowsingEnabled(options.safeBrowsingEnabled);
+
+ settings.setMediaPlaybackRequiresUserGesture(options.mediaPlaybackRequiresUserGesture);
+
+ settings.setDatabaseEnabled(options.databaseEnabled);
+ settings.setDomStorageEnabled(options.domStorageEnabled);
+
+ if (!options.userAgent.isEmpty())
+ settings.setUserAgentString(options.userAgent);
+
+ if (options.clearCache)
+ clearAllCache();
+ else if (options.clearSessionCache)
+ CookieManager.getInstance().removeSessionCookie();
+
+ // Enable Thirdparty Cookies on >=Android 5.0 device
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ CookieManager.getInstance().setAcceptThirdPartyCookies(this, true);
+
+ settings.setLoadWithOverviewMode(true);
+ settings.setUseWideViewPort(options.useWideViewPort);
+ settings.setSupportZoom(options.supportZoom);
+
+ // fix webview scaling
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
+ settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING);
+ else
+ settings.setTextZoom(100);
+
+ }
+
+ public void loadUrl(String url, MethodChannel.Result result) {
+ if (!url.isEmpty()) {
+ loadUrl(url);
+ } else {
+ result.error(LOG_TAG, "url is empty", null);
+ }
+ }
+
+ public void loadUrl(String url, Map headers, MethodChannel.Result result) {
+ if (!url.isEmpty()) {
+ loadUrl(url, headers);
+ } else {
+ result.error(LOG_TAG, "url is empty", null);
+ }
+ }
+
+ public void loadFile(String url, MethodChannel.Result result) {
+ try {
+ url = Util.getUrlAsset(registrar, url);
+ } catch (IOException e) {
+ result.error(LOG_TAG, url + " asset file cannot be found!", e);
+ return;
+ }
+
+ if (!url.isEmpty()) {
+ loadUrl(url);
+ } else {
+ result.error(LOG_TAG, "url is empty", null);
+ }
+ }
+
+ public void loadFile(String url, Map headers, MethodChannel.Result result) {
+ try {
+ url = Util.getUrlAsset(registrar, url);
+ } catch (IOException e) {
+ result.error(LOG_TAG, url + " asset file cannot be found!", e);
+ return;
+ }
+
+ if (!url.isEmpty()) {
+ loadUrl(url, headers);
+ } else {
+ result.error(LOG_TAG, "url is empty", null);
+ }
+ }
+
+ public boolean isLoading() {
+ return isLoading;
+ }
+
+ private void clearCookies() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ CookieManager.getInstance().removeAllCookies(new ValueCallback() {
+ @Override
+ public void onReceiveValue(Boolean aBoolean) {
+
+ }
+ });
+ } else {
+ CookieManager.getInstance().removeAllCookie();
+ }
+ }
+
+ public void clearAllCache() {
+ clearCache(true);
+ clearCookies();
+ clearFormData();
+ }
+
+ public byte[] takeScreenshot() {
+ Picture picture = capturePicture();
+ Bitmap b = Bitmap.createBitmap( getWidth(),
+ getHeight(), Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(b);
+
+ picture.draw(c);
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ b.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
+ try {
+ byteArrayOutputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return byteArrayOutputStream.toByteArray();
+ }
+
+ public void setOptions(InAppWebViewOptions newOptions, HashMap newOptionsMap) {
+
+ WebSettings settings = getSettings();
+
+ if (newOptionsMap.get("javaScriptEnabled") != null && options.javaScriptEnabled != newOptions.javaScriptEnabled)
+ settings.setJavaScriptEnabled(newOptions.javaScriptEnabled);
+
+ if (newOptionsMap.get("javaScriptCanOpenWindowsAutomatically") != null && options.javaScriptCanOpenWindowsAutomatically != newOptions.javaScriptCanOpenWindowsAutomatically)
+ settings.setJavaScriptCanOpenWindowsAutomatically(newOptions.javaScriptCanOpenWindowsAutomatically);
+
+ if (newOptionsMap.get("builtInZoomControls") != null && options.builtInZoomControls != newOptions.builtInZoomControls)
+ settings.setBuiltInZoomControls(newOptions.builtInZoomControls);
+
+ if (newOptionsMap.get("safeBrowsingEnabled") != null && options.safeBrowsingEnabled != newOptions.safeBrowsingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ settings.setSafeBrowsingEnabled(newOptions.safeBrowsingEnabled);
+
+ if (newOptionsMap.get("mediaPlaybackRequiresUserGesture") != null && options.mediaPlaybackRequiresUserGesture != newOptions.mediaPlaybackRequiresUserGesture)
+ settings.setMediaPlaybackRequiresUserGesture(newOptions.mediaPlaybackRequiresUserGesture);
+
+ if (newOptionsMap.get("databaseEnabled") != null && options.databaseEnabled != newOptions.databaseEnabled)
+ settings.setDatabaseEnabled(newOptions.databaseEnabled);
+
+ if (newOptionsMap.get("domStorageEnabled") != null && options.domStorageEnabled != newOptions.domStorageEnabled)
+ settings.setDomStorageEnabled(newOptions.domStorageEnabled);
+
+ if (newOptionsMap.get("userAgent") != null && options.userAgent != newOptions.userAgent && !newOptions.userAgent.isEmpty())
+ settings.setUserAgentString(newOptions.userAgent);
+
+ if (newOptionsMap.get("clearCache") != null && newOptions.clearCache)
+ clearAllCache();
+ else if (newOptionsMap.get("clearSessionCache") != null && newOptions.clearSessionCache)
+ CookieManager.getInstance().removeSessionCookie();
+
+ if (newOptionsMap.get("useWideViewPort") != null && options.useWideViewPort != newOptions.useWideViewPort)
+ settings.setUseWideViewPort(newOptions.useWideViewPort);
+
+ if (newOptionsMap.get("supportZoom") != null && options.supportZoom != newOptions.supportZoom)
+ settings.setSupportZoom(newOptions.supportZoom);
+
+ options = newOptions;
+ }
+
+ public HashMap getOptions() {
+ return (options != null) ? options.getHashMap() : null;
+ }
+
+ public void injectDeferredObject(String source, String jsWrapper, final MethodChannel.Result result) {
+ String scriptToInject;
+ if (jsWrapper != null) {
+ org.json.JSONArray jsonEsc = new org.json.JSONArray();
+ jsonEsc.put(source);
+ String jsonRepr = jsonEsc.toString();
+ String jsonSourceString = jsonRepr.substring(1, jsonRepr.length() - 1);
+ scriptToInject = String.format(jsWrapper, jsonSourceString);
+ } else {
+ scriptToInject = source;
+ }
+ final String finalScriptToInject = scriptToInject;
+ ( (inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity ).runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ // This action will have the side-effect of blurring the currently focused element
+ loadUrl("javascript:" + finalScriptToInject);
+ } else {
+ evaluateJavascript(finalScriptToInject, new ValueCallback() {
+ @Override
+ public void onReceiveValue(String s) {
+ if (result == null)
+ return;
+
+ JsonReader reader = new JsonReader(new StringReader(s));
+
+ // Must set lenient to parse single values
+ reader.setLenient(true);
+
+ try {
+ String msg;
+ if (reader.peek() == JsonToken.STRING) {
+ msg = reader.nextString();
+
+ JsonReader reader2 = new JsonReader(new StringReader(msg));
+ reader2.setLenient(true);
+
+ if (reader2.peek() == JsonToken.STRING)
+ msg = reader2.nextString();
+
+ result.success(msg);
+ } else {
+ result.success("");
+ }
+
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "IOException", e);
+ } finally {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ // NOOP
+ }
+ }
+ }
+ });
+ }
+ }
+ });
+ }
+}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java
similarity index 77%
rename from android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java
rename to android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java
index 6594b99c..35da3b6d 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java
@@ -1,4 +1,4 @@
-package com.pichillilorenzo.flutter_inappbrowser;
+package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
import android.content.Intent;
import android.graphics.Bitmap;
@@ -16,6 +16,11 @@ import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
+import com.pichillilorenzo.flutter_inappbrowser.FlutterWebView;
+import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity;
+import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
+import com.pichillilorenzo.flutter_inappbrowser.JavaScriptBridgeInterface;
+
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -27,16 +32,24 @@ import io.flutter.plugin.common.MethodChannel;
import okhttp3.Request;
import okhttp3.Response;
-public class InAppBrowserWebViewClient extends WebViewClient {
+public class InAppWebViewClient extends WebViewClient {
protected static final String LOG_TAG = "IABWebViewClient";
- private WebViewActivity activity;
+ private FlutterWebView flutterWebView;
+ private InAppBrowserActivity inAppBrowserActivity;
Map statusCodeMapping = new HashMap();
long startPageTime = 0;
- public InAppBrowserWebViewClient(WebViewActivity activity) {
+ public InAppWebViewClient(Object obj) {
super();
- this.activity = activity;
+ if (obj instanceof InAppBrowserActivity)
+ this.inAppBrowserActivity = (InAppBrowserActivity) obj;
+ else if (obj instanceof FlutterWebView)
+ this.flutterWebView = (FlutterWebView) obj;
+ prepareStatusCodeMapping();
+ }
+
+ private void prepareStatusCodeMapping () {
statusCodeMapping.put(100, "Continue");
statusCodeMapping.put(101, "Switching Protocols");
statusCodeMapping.put(200, "OK");
@@ -90,11 +103,12 @@ public class InAppBrowserWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
- if (activity.options.useShouldOverrideUrlLoading) {
+ if (((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).options.useShouldOverrideUrlLoading) {
Map obj = new HashMap<>();
- obj.put("uuid", activity.uuid);
+ if (inAppBrowserActivity != null)
+ obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url);
- InAppBrowserFlutterPlugin.channel.invokeMethod("shouldOverrideUrlLoading", obj);
+ getChannel().invokeMethod("shouldOverrideUrlLoading", obj);
return true;
}
@@ -102,7 +116,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
try {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse(url));
- activity.startActivity(intent);
+ ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivity(intent);
return true;
} catch (android.content.ActivityNotFoundException e) {
Log.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
@@ -111,7 +125,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
- activity.startActivity(intent);
+ ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivity(intent);
return true;
} catch (android.content.ActivityNotFoundException e) {
Log.e(LOG_TAG, "Error with " + url + ": " + e.toString());
@@ -142,7 +156,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
intent.setData(Uri.parse("sms:" + address));
intent.putExtra("address", address);
intent.setType("vnd.android-dir/mms-sms");
- activity.startActivity(intent);
+ ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivity(intent);
return true;
} catch (android.content.ActivityNotFoundException e) {
Log.e(LOG_TAG, "Error sending sms " + url + ":" + e.toString());
@@ -167,23 +181,24 @@ public class InAppBrowserWebViewClient extends WebViewClient {
startPageTime = System.currentTimeMillis();
- activity.isLoading = true;
+ ((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).isLoading = true;
- if (activity.searchView != null && !url.equals(activity.searchView.getQuery().toString())) {
- activity.searchView.setQuery(url, false);
+ if (inAppBrowserActivity != null && inAppBrowserActivity.searchView != null && !url.equals(inAppBrowserActivity.searchView.getQuery().toString())) {
+ inAppBrowserActivity.searchView.setQuery(url, false);
}
Map obj = new HashMap<>();
- obj.put("uuid", activity.uuid);
+ if (inAppBrowserActivity != null)
+ obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url);
- InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadStart", obj);
+ getChannel().invokeMethod("onLoadStart", obj);
}
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
- activity.isLoading = false;
+ ((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).isLoading = false;
// CB-10395 InAppBrowserFlutterPlugin's WebView not storing cookies reliable to local device storage
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@@ -197,38 +212,41 @@ public class InAppBrowserWebViewClient extends WebViewClient {
view.requestFocus();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- view.evaluateJavascript(WebViewActivity.consoleLogJS, null);
+ view.evaluateJavascript(InAppWebView.consoleLogJS, null);
view.evaluateJavascript(JavaScriptBridgeInterface.flutterInAppBroserJSClass, null);
}
else {
- view.loadUrl("javascript:"+WebViewActivity.consoleLogJS);
+ view.loadUrl("javascript:"+InAppWebView.consoleLogJS);
view.loadUrl("javascript:"+JavaScriptBridgeInterface.flutterInAppBroserJSClass);
}
Map obj = new HashMap<>();
- obj.put("uuid", activity.uuid);
+ if (inAppBrowserActivity != null)
+ obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url);
- InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadStop", obj);
+ getChannel().invokeMethod("onLoadStop", obj);
}
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
- activity.isLoading = false;
+ ((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).isLoading = false;
Map obj = new HashMap<>();
- obj.put("uuid", activity.uuid);
+ if (inAppBrowserActivity != null)
+ obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", failingUrl);
obj.put("code", errorCode);
obj.put("message", description);
- InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadError", obj);
+ getChannel().invokeMethod("onLoadError", obj);
}
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
super.onReceivedSslError(view, handler, error);
Map obj = new HashMap<>();
- obj.put("uuid", activity.uuid);
+ if (inAppBrowserActivity != null)
+ obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", error.getUrl());
obj.put("code", error.getPrimaryError());
String message;
@@ -254,7 +272,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
break;
}
obj.put("message", "SslError: " + message);
- InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadError", obj);
+ getChannel().invokeMethod("onLoadError", obj);
handler.cancel();
}
@@ -271,8 +289,8 @@ public class InAppBrowserWebViewClient extends WebViewClient {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
-
- if (!request.getMethod().toLowerCase().equals("get") || !activity.options.useOnLoadResource) {
+ if (!request.getMethod().toLowerCase().equals("get") ||
+ !(((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).options.useOnLoadResource)) {
return null;
}
@@ -282,7 +300,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
Request mRequest = new Request.Builder().url(url).build();
long startResourceTime = System.currentTimeMillis();
- Response response = activity.httpClient.newCall(mRequest).execute();
+ Response response = ((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).httpClient.newCall(mRequest).execute();
long startTime = startResourceTime - startPageTime;
startTime = (startTime < 0) ? 0 : startTime;
long duration = System.currentTimeMillis() - startResourceTime;
@@ -319,7 +337,8 @@ public class InAppBrowserWebViewClient extends WebViewClient {
Map res = new HashMap<>();
Map req = new HashMap<>();
- obj.put("uuid", activity.uuid);
+ if (inAppBrowserActivity != null)
+ obj.put("uuid", inAppBrowserActivity.uuid);
byte[] dataBytes = response.body().bytes();
InputStream dataStream = new ByteArrayInputStream(dataBytes);
@@ -338,7 +357,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
obj.put("response", res);
obj.put("request", req);
- InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadResource", obj);
+ getChannel().invokeMethod("onLoadResource", obj);
return new WebResourceResponse(
response.header("content-type", "text/plain").split(";")[0].trim(),
@@ -359,5 +378,8 @@ public class InAppBrowserWebViewClient extends WebViewClient {
return null;
}
+ private MethodChannel getChannel() {
+ return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.channel : flutterWebView.channel;
+ }
}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java
new file mode 100644
index 00000000..06ea38b0
--- /dev/null
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java
@@ -0,0 +1,24 @@
+package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
+
+import com.pichillilorenzo.flutter_inappbrowser.Options;
+
+public class InAppWebViewOptions extends Options {
+
+ static final String LOG_TAG = "InAppWebViewOptions";
+
+ public boolean useShouldOverrideUrlLoading = false;
+ public boolean useOnLoadResource = false;
+ public boolean clearCache = false;
+ public String userAgent = "";
+ public boolean javaScriptEnabled = true;
+ public boolean javaScriptCanOpenWindowsAutomatically = false;
+ public boolean mediaPlaybackRequiresUserGesture = true;
+
+ public boolean clearSessionCache = false;
+ public boolean builtInZoomControls = false;
+ public boolean supportZoom = true;
+ public boolean databaseEnabled = false;
+ public boolean domStorageEnabled = false;
+ public boolean useWideViewPort = true;
+ public boolean safeBrowsingEnabled = true;
+}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/JavaScriptBridgeInterface.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/JavaScriptBridgeInterface.java
index ab3aa4a5..c4d7aac7 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/JavaScriptBridgeInterface.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/JavaScriptBridgeInterface.java
@@ -5,25 +5,36 @@ import android.webkit.JavascriptInterface;
import java.util.HashMap;
import java.util.Map;
+import io.flutter.plugin.common.MethodChannel;
+
public class JavaScriptBridgeInterface {
private static final String LOG_TAG = "JSBridgeInterface";
- static final String name = "flutter_inappbrowser";
- WebViewActivity activity;
+ public static final String name = "flutter_inappbrowser";
+ private FlutterWebView flutterWebView;
+ private InAppBrowserActivity inAppBrowserActivity;
- static final String flutterInAppBroserJSClass = "window." + name + ".callHandler = function(handlerName, ...args) {" +
+ public static final String flutterInAppBroserJSClass = "window." + name + ".callHandler = function(handlerName, ...args) {" +
"window." + name + "._callHandler(handlerName, JSON.stringify(args));" +
"}";
- JavaScriptBridgeInterface(WebViewActivity a) {
- activity = a;
+ public JavaScriptBridgeInterface(Object obj) {
+ if (obj instanceof InAppBrowserActivity)
+ this.inAppBrowserActivity = (InAppBrowserActivity) obj;
+ else if (obj instanceof FlutterWebView)
+ this.flutterWebView = (FlutterWebView) obj;
}
@JavascriptInterface
public void _callHandler(String handlerName, String args) {
Map obj = new HashMap<>();
- obj.put("uuid", activity.uuid);
+ if (inAppBrowserActivity != null)
+ obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("handlerName", handlerName);
obj.put("args", args);
- InAppBrowserFlutterPlugin.channel.invokeMethod("onCallJsHandler", obj);
+ getChannel().invokeMethod("onCallJsHandler", obj);
+ }
+
+ private MethodChannel getChannel() {
+ return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.channel : flutterWebView.channel;
}
}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Options.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Options.java
index 1961f98c..ec492402 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Options.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Options.java
@@ -9,7 +9,7 @@ import java.util.HashMap;
public class Options {
- static String LOG_TAG = "";
+ static String LOG_TAG = "Options";
public Options parse(HashMap options) {
Iterator it = options.entrySet().iterator();
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Util.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Util.java
new file mode 100644
index 00000000..e5592261
--- /dev/null
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Util.java
@@ -0,0 +1,39 @@
+package com.pichillilorenzo.flutter_inappbrowser;
+
+import android.content.res.AssetManager;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import io.flutter.plugin.common.PluginRegistry;
+
+public class Util {
+
+ public static final String ANDROID_ASSET_URL = "file:///android_asset/";
+
+ public static String getUrlAsset (PluginRegistry.Registrar registrar, String assetFilePath) throws IOException {
+ String key = registrar.lookupKeyForAsset(assetFilePath);
+ AssetManager mg = registrar.activeContext().getResources().getAssets();
+ InputStream is = null;
+ IOException e = null;
+
+ try {
+ is = mg.open(key);
+ } catch (IOException ex) {
+ e = ex;
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException ex) {
+ e = ex;
+ }
+ }
+ }
+ if (e != null) {
+ throw e;
+ }
+
+ return ANDROID_ASSET_URL + key;
+ }
+}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java
deleted file mode 100644
index c596b550..00000000
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java
+++ /dev/null
@@ -1,517 +0,0 @@
-package com.pichillilorenzo.flutter_inappbrowser;
-
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Picture;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Build;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.CookieManager;
-import android.webkit.ValueCallback;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.widget.ProgressBar;
-import android.widget.SearchView;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import io.flutter.plugin.common.MethodChannel;
-import okhttp3.Cache;
-import okhttp3.OkHttpClient;
-
-public class WebViewActivity extends AppCompatActivity {
-
- String uuid;
- WebView webView;
- ActionBar actionBar;
- Menu menu;
- InAppBrowserWebViewClient inAppBrowserWebViewClient;
- InAppBrowserWebChromeClient inAppBrowserWebChromeClient;
- SearchView searchView;
- InAppBrowserOptions options;
- Map headers;
- ProgressBar progressBar;
- public boolean isLoading = false;
- public boolean isHidden = false;
- OkHttpClient httpClient;
-
- static final String consoleLogJS = "(function() {" +
- " var oldLogs = {" +
- " 'log': console.log," +
- " 'debug': console.debug," +
- " 'error': console.error," +
- " 'info': console.info," +
- " 'warn': console.warn" +
- " };" +
- " for (var k in oldLogs) {" +
- " (function(oldLog) {" +
- " console[oldLog] = function() {" +
- " var message = '';" +
- " for (var i in arguments) {" +
- " if (message == '') {" +
- " message += arguments[i];" +
- " }" +
- " else {" +
- " message += ' ' + arguments[i];" +
- " }" +
- " }" +
- " oldLogs[oldLog].call(console, message);" +
- " }" +
- " })(k);" +
- " }" +
- "})();";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.activity_web_view);
-
- webView = findViewById(R.id.webView);
-
- Bundle b = getIntent().getExtras();
- uuid = b.getString("uuid");
- String url = b.getString("url");
-
- options = new InAppBrowserOptions();
- options.parse((HashMap) b.getSerializable("options"));
-
- headers = (HashMap) b.getSerializable("headers");
-
- InAppBrowserFlutterPlugin.webViewActivities.put(uuid, this);
-
- actionBar = getSupportActionBar();
-
- prepareWebView();
-
- int cacheSize = 10 * 1024 * 1024; // 10MB
- httpClient = new OkHttpClient().newBuilder().cache(new Cache(getApplicationContext().getCacheDir(), cacheSize)).build();
-
- webView.loadUrl(url, headers);
- //webView.loadData(" Document ciao ", "text/assets", "utf8");
-
- }
-
- private void prepareWebView() {
-
- webView.addJavascriptInterface(new JavaScriptBridgeInterface(this), JavaScriptBridgeInterface.name);
-
- inAppBrowserWebChromeClient = new InAppBrowserWebChromeClient(this);
- webView.setWebChromeClient(inAppBrowserWebChromeClient);
-
- inAppBrowserWebViewClient = new InAppBrowserWebViewClient(this);
- webView.setWebViewClient(inAppBrowserWebViewClient);
-
-// final Activity activity = this;
-//
-// webView.setDownloadListener(new DownloadListener() {
-// @Override
-// public void onDownloadStart(final String url, final String userAgent,
-// final String contentDisposition, final String mimetype,
-// final long contentLength) {
-//
-// RequestPermissionHandler.checkAndRun(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, RequestPermissionHandler.REQUEST_CODE_WRITE_EXTERNAL_STORAGE, new Runnable(){
-// @Override
-// public void run(){
-// DownloadManager.Request request = new DownloadManager.Request(
-// Uri.parse(url));
-//
-// final String filename = URLUtil.guessFileName(url, contentDisposition, mimetype);
-// request.allowScanningByMediaScanner();
-// request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed!
-// request.setVisibleInDownloadsUi(true);
-// request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
-// DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
-// if (dm != null) {
-// dm.enqueue(request);
-// Toast.makeText(getApplicationContext(), "Downloading File: " + filename, //To notify the Client that the file is being downloaded
-// Toast.LENGTH_LONG).show();
-// }
-// else {
-// Toast.makeText(getApplicationContext(), "Cannot Download File: " + filename, //To notify the Client that the file cannot be downloaded
-// Toast.LENGTH_LONG).show();
-// }
-// }
-// });
-// }
-// });
-
- WebSettings settings = webView.getSettings();
-
- if (options.hidden)
- hide();
- else
- show();
-
- settings.setJavaScriptEnabled(options.javaScriptEnabled);
- settings.setJavaScriptCanOpenWindowsAutomatically(options.javaScriptCanOpenWindowsAutomatically);
- settings.setBuiltInZoomControls(options.builtInZoomControls);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
- settings.setSafeBrowsingEnabled(options.safeBrowsingEnabled);
-
- settings.setMediaPlaybackRequiresUserGesture(options.mediaPlaybackRequiresUserGesture);
-
- settings.setDatabaseEnabled(options.databaseEnabled);
- settings.setDomStorageEnabled(options.domStorageEnabled);
-
- if (!options.userAgent.isEmpty())
- settings.setUserAgentString(options.userAgent);
-
- if (options.clearCache)
- clearCache();
- else if (options.clearSessionCache)
- CookieManager.getInstance().removeSessionCookie();
-
- // Enable Thirdparty Cookies on >=Android 5.0 device
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
- CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);
-
- settings.setLoadWithOverviewMode(true);
- settings.setUseWideViewPort(options.useWideViewPort);
- settings.setSupportZoom(options.supportZoom);
-
- // fix webview scaling
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
- settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING);
- else
- settings.setTextZoom(100);
-
- progressBar = findViewById(R.id.progressBar);
-
- if (!options.progressBar)
- progressBar.setMax(0);
- else
- progressBar.setMax(100);
-
- actionBar.setDisplayShowTitleEnabled(!options.hideTitleBar);
-
- if (!options.toolbarTop)
- actionBar.hide();
-
- if (!options.toolbarTopBackgroundColor.isEmpty())
- actionBar.setBackgroundDrawable(new ColorDrawable(Color.parseColor(options.toolbarTopBackgroundColor)));
-
- if (!options.toolbarTopFixedTitle.isEmpty())
- actionBar.setTitle(options.toolbarTopFixedTitle);
-
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu m) {
- menu = m;
-
- MenuInflater inflater = getMenuInflater();
- // Inflate menu to add items to action bar if it is present.
- inflater.inflate(R.menu.menu_main, menu);
-
- searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
- searchView.setFocusable(true);
-
- if (options.hideUrlBar)
- menu.findItem(R.id.menu_search).setVisible(false);
-
- searchView.setQuery(webView.getUrl(), false);
-
- if (options.toolbarTopFixedTitle.isEmpty())
- actionBar.setTitle(webView.getTitle());
-
- searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String query) {
- if (!query.isEmpty()) {
- webView.loadUrl(query);
- searchView.setQuery("", false);
- searchView.setIconified(true);
- return true;
- }
- return false;
- }
-
- @Override
- public boolean onQueryTextChange(String newText) {
- return false;
- }
-
- });
-
- searchView.setOnCloseListener(new SearchView.OnCloseListener() {
- @Override
- public boolean onClose() {
- if (searchView.getQuery().toString().isEmpty())
- searchView.setQuery(webView.getUrl(), false);
- return false;
- }
- });
-
- searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View view, boolean b) {
- if (!b) {
- searchView.setQuery("", false);
- searchView.setIconified(true);
- }
- }
- });
-
- return true;
- }
-
- public void loadUrl(String url, MethodChannel.Result result) {
- if (webView != null && !url.isEmpty()) {
- webView.loadUrl(url);
- } else {
- result.error("Cannot load url", "", null);
- }
- }
-
- public void loadUrl(String url, Map headers, MethodChannel.Result result) {
- if (webView != null && !url.isEmpty()) {
- webView.loadUrl(url, headers);
- } else {
- result.error("Cannot load url", "", null);
- }
- }
-
- public void loadFile(String url, MethodChannel.Result result) {
- if (webView != null && !url.isEmpty()) {
- webView.loadUrl(url);
- } else {
- result.error("Cannot load url", "", null);
- }
- }
-
- public void loadFile(String url, Map headers, MethodChannel.Result result) {
- if (webView != null && !url.isEmpty()) {
- webView.loadUrl(url, headers);
- } else {
- result.error("Cannot load url", "", null);
- }
- }
-
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if ((keyCode == KeyEvent.KEYCODE_BACK)) {
- if (canGoBack())
- goBack();
- else if (options.closeOnCannotGoBack)
- InAppBrowserFlutterPlugin.close(uuid, null);
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- public void close() {
- hide();
- finish();
- }
-
- public void reload() {
- if (webView != null)
- webView.reload();
- }
-
- public void goBack() {
- if (webView != null && canGoBack())
- webView.goBack();
- }
-
- public void goForward() {
- if (webView != null && canGoForward())
- webView.goForward();
- }
-
- public boolean canGoBack() {
- return webView.canGoBack();
- }
-
- public boolean canGoForward() {
- return webView.canGoForward();
- }
-
- public void hide() {
- isHidden = true;
- Intent openActivity = new Intent(this, InAppBrowserFlutterPlugin.registrar.activity().getClass());
- openActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
- startActivityIfNeeded(openActivity, 0);
- }
-
- public void show() {
- isHidden = false;
- Intent openActivity = new Intent(InAppBrowserFlutterPlugin.registrar.activity(), WebViewActivity.class);
- openActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
- startActivityIfNeeded(openActivity, 0);
- }
-
- public void stopLoading() {
- if (webView != null)
- webView.stopLoading();
- }
-
- public boolean isLoading() {
- if (webView != null)
- return isLoading;
- return false;
- }
-
- private void clearCookies() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- CookieManager.getInstance().removeAllCookies(new ValueCallback() {
- @Override
- public void onReceiveValue(Boolean aBoolean) {
-
- }
- });
- } else {
- CookieManager.getInstance().removeAllCookie();
- }
- }
-
- private void clearCache() {
- if (webView != null) {
- webView.clearCache(true);
- clearCookies();
- webView.clearFormData();
- }
- }
-
- public void goBackButtonClicked(MenuItem item) {
- goBack();
- }
-
- public void goForwardButtonClicked(MenuItem item) {
- goForward();
- }
-
- public void shareButtonClicked(MenuItem item) {
- Intent share = new Intent(Intent.ACTION_SEND);
- share.setType("text/plain");
- share.putExtra(Intent.EXTRA_TEXT, webView.getUrl());
- startActivity(Intent.createChooser(share, "Share"));
- }
-
- public void reloadButtonClicked(MenuItem item) {
- reload();
- }
-
- public void closeButtonClicked(MenuItem item) {
- InAppBrowserFlutterPlugin.close(uuid, null);
- }
-
- public byte[] takeScreenshot() {
- if (webView != null) {
- Picture picture = webView.capturePicture();
- Bitmap b = Bitmap.createBitmap( webView.getWidth(),
- webView.getHeight(), Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(b);
-
- picture.draw(c);
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- b.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
- try {
- byteArrayOutputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return byteArrayOutputStream.toByteArray();
- }
- return null;
- }
-
- public void setOptions(InAppBrowserOptions newOptions, HashMap newOptionsMap) {
-
- WebSettings settings = webView.getSettings();
-
- if (newOptionsMap.get("hidden") != null && options.hidden != newOptions.hidden) {
- if (newOptions.hidden)
- hide();
- else
- show();
- }
-
- if (newOptionsMap.get("javaScriptEnabled") != null && options.javaScriptEnabled != newOptions.javaScriptEnabled)
- settings.setJavaScriptEnabled(newOptions.javaScriptEnabled);
-
- if (newOptionsMap.get("javaScriptCanOpenWindowsAutomatically") != null && options.javaScriptCanOpenWindowsAutomatically != newOptions.javaScriptCanOpenWindowsAutomatically)
- settings.setJavaScriptCanOpenWindowsAutomatically(newOptions.javaScriptCanOpenWindowsAutomatically);
-
- if (newOptionsMap.get("builtInZoomControls") != null && options.builtInZoomControls != newOptions.builtInZoomControls)
- settings.setBuiltInZoomControls(newOptions.builtInZoomControls);
-
- if (newOptionsMap.get("safeBrowsingEnabled") != null && options.safeBrowsingEnabled != newOptions.safeBrowsingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
- settings.setSafeBrowsingEnabled(newOptions.safeBrowsingEnabled);
-
- if (newOptionsMap.get("mediaPlaybackRequiresUserGesture") != null && options.mediaPlaybackRequiresUserGesture != newOptions.mediaPlaybackRequiresUserGesture)
- settings.setMediaPlaybackRequiresUserGesture(newOptions.mediaPlaybackRequiresUserGesture);
-
- if (newOptionsMap.get("databaseEnabled") != null && options.databaseEnabled != newOptions.databaseEnabled)
- settings.setDatabaseEnabled(newOptions.databaseEnabled);
-
- if (newOptionsMap.get("domStorageEnabled") != null && options.domStorageEnabled != newOptions.domStorageEnabled)
- settings.setDomStorageEnabled(newOptions.domStorageEnabled);
-
- if (newOptionsMap.get("userAgent") != null && options.userAgent != newOptions.userAgent && !newOptions.userAgent.isEmpty())
- settings.setUserAgentString(newOptions.userAgent);
-
- if (newOptionsMap.get("clearCache") != null && newOptions.clearCache)
- clearCache();
- else if (newOptionsMap.get("clearSessionCache") != null && newOptions.clearSessionCache)
- CookieManager.getInstance().removeSessionCookie();
-
- if (newOptionsMap.get("useWideViewPort") != null && options.useWideViewPort != newOptions.useWideViewPort)
- settings.setUseWideViewPort(newOptions.useWideViewPort);
-
- if (newOptionsMap.get("supportZoom") != null && options.supportZoom != newOptions.supportZoom)
- settings.setSupportZoom(newOptions.supportZoom);
-
- if (newOptionsMap.get("progressBar") != null && options.progressBar != newOptions.progressBar && progressBar != null) {
- if (newOptions.progressBar)
- progressBar.setMax(0);
- else
- progressBar.setMax(100);
- }
-
- if (newOptionsMap.get("hideTitleBar") != null && options.hideTitleBar != newOptions.hideTitleBar)
- actionBar.setDisplayShowTitleEnabled(!newOptions.hideTitleBar);
-
- if (newOptionsMap.get("toolbarTop") != null && options.toolbarTop != newOptions.toolbarTop) {
- if (!newOptions.toolbarTop)
- actionBar.hide();
- else
- actionBar.show();
- }
-
- if (newOptionsMap.get("toolbarTopBackgroundColor") != null && options.toolbarTopBackgroundColor != newOptions.toolbarTopBackgroundColor && !newOptions.toolbarTopBackgroundColor.isEmpty())
- actionBar.setBackgroundDrawable(new ColorDrawable(Color.parseColor(newOptions.toolbarTopBackgroundColor)));
-
- if (newOptionsMap.get("toolbarTopFixedTitle") != null && options.toolbarTopFixedTitle != newOptions.toolbarTopFixedTitle && !newOptions.toolbarTopFixedTitle.isEmpty())
- actionBar.setTitle(newOptions.toolbarTopFixedTitle);
-
- if (newOptionsMap.get("hideUrlBar") != null && options.hideUrlBar != newOptions.hideUrlBar) {
- if (newOptions.hideUrlBar)
- menu.findItem(R.id.menu_search).setVisible(false);
- else
- menu.findItem(R.id.menu_search).setVisible(true);
- }
-
- options = newOptions;
- }
-
- public HashMap getOptions() {
- return (options != null) ? options.getHashMap() : null;
- }
-
-}
diff --git a/android/src/main/res/layout/activity_web_view.xml b/android/src/main/res/layout/activity_web_view.xml
index 8b19f543..ba38f899 100644
--- a/android/src/main/res/layout/activity_web_view.xml
+++ b/android/src/main/res/layout/activity_web_view.xml
@@ -7,15 +7,13 @@
android:layout_height="match_parent"
android:clickable="true"
android:focusableInTouchMode="true"
- tools:context=".WebViewActivity"
+ tools:context=".InAppBrowserActivity"
android:focusable="true">
-
-
-
+ android:layout_height="match_parent" />
+ tools:context=".InAppBrowserActivity">
- {
@override
void initState() {
super.initState();
-// int indexTest = inAppBrowserFallback.addJavaScriptHandler("handlerTest",
+// int indexTest = inAppBrowserFallback.webViewController.addJavaScriptHandler("handlerTest",
// (arguments) async {
// print("handlerTest arguments");
// print(arguments);
// });
-// int indexTest2 = inAppBrowserFallback.addJavaScriptHandler("test2", (arguments) async {
+// int indexTest2 = inAppBrowserFallback.webViewController.addJavaScriptHandler("test2", (arguments) async {
// print("handlerTest2 arguments");
// print(arguments);
-// inAppBrowserFallback.removeJavaScriptHandler("test", indexTest);
+// inAppBrowserFallback.webViewController.removeJavaScriptHandler("test", indexTest);
// });
}
@@ -194,34 +206,32 @@ class _MyAppState extends State {
),
body: new Center(
child: new RaisedButton(
- onPressed: () async {
+ onPressed: () async {
// await chromeSafariBrowser.open("https://flutter.io/");
-
+//
// await InAppBrowser.openWithSystemBrowser("https://flutter.io/");
-
-// await inAppBrowserFallback.openOnLocalhost("assets/index.html", options: {
+//
+// await inAppBrowserFallback.open(url: "http://localhost:8080/assets/index.html", options: {
// "useOnLoadResource": true,
// //"hidden": true,
// //"toolbarTopFixedTitle": "Fixed title",
// //"useShouldOverrideUrlLoading": true
// //"hideUrlBar": true,
// //"toolbarTop": false,
-// //"toolbarBottom": false
+// "toolbarBottom": false
// });
-
-// await inAppBrowserFallback.open(url: "assets/index.html", options: {
-// "isLocalFile": true,
+//
+// await inAppBrowserFallback.openFile("assets/index.html", options: {
// "useOnLoadResource": true,
// //"hidden": true,
-// //"toolbarTopFixedTitle": "Fixed title",
// //"useShouldOverrideUrlLoading": true
// //"hideUrlBar": true,
// //"toolbarTop": false,
// //"toolbarBottom": false
// });
-
+//
await inAppBrowserFallback.open(url: "https://flutter.io/", options: {
- //"useOnLoadResource": true,
+ "useOnLoadResource": true,
//"hidden": true,
//"toolbarTopFixedTitle": "Fixed title",
//"useShouldOverrideUrlLoading": true
@@ -229,11 +239,143 @@ class _MyAppState extends State {
//"toolbarTop": false,
//"toolbarBottom": false
});
- //await inAppBrowserFallback.openOnLocalhost("assets/index.html");
- },
- child: Text("Open InAppBrowser")),
+ },
+ child: Text("Open InAppBrowser")
+ ),
),
),
);
}
}
+
+
+// Inline WebView Example
+//
+//import 'dart:async';
+//import 'package:flutter/material.dart';
+//import 'package:flutter_inappbrowser/flutter_inappbrowser.dart';
+//
+//Future main() async {
+// runApp(new MyApp());
+//}
+//
+//class MyApp extends StatefulWidget {
+// @override
+// _MyAppState createState() => new _MyAppState();
+//}
+//
+//class _MyAppState extends State {
+//
+// InAppWebViewController webView;
+// String url = "";
+// double progress = 0;
+//
+// @override
+// void initState() {
+// super.initState();
+// }
+//
+// @override
+// void dispose() {
+// super.dispose();
+// }
+//
+// @override
+// Widget build(BuildContext context) {
+// return MaterialApp(
+// home: Scaffold(
+// appBar: AppBar(
+// title: const Text('Inline WebView example app'),
+// ),
+// body: Container(
+// child: Column(
+// children: [
+// Container(
+// padding: EdgeInsets.all(20.0),
+// child: Text("CURRENT URL\n${ (url.length > 50) ? url.substring(0, 50) + "..." : url }"),
+// ),
+// (progress != 1.0) ? LinearProgressIndicator(value: progress) : null,
+// Expanded(
+// child: Container(
+// margin: const EdgeInsets.all(10.0),
+// decoration: BoxDecoration(
+// border: Border.all(color: Colors.blueAccent)
+// ),
+// child: InAppWebView(
+// initialUrl: "https://flutter.io/",
+// initialHeaders: {
+//
+// },
+// initialOptions: {
+//
+// },
+// onWebViewCreated: (InAppWebViewController controller) {
+// webView = controller;
+// },
+// onLoadStart: (InAppWebViewController controller, String url) {
+// print("started $url");
+// setState(() {
+// this.url = url;
+// });
+// },
+// onProgressChanged: (InAppWebViewController controller, int progress) {
+// setState(() {
+// this.progress = progress/100;
+// });
+// },
+// ),
+// ),
+// ),
+// ButtonBar(
+// alignment: MainAxisAlignment.center,
+// children: [
+// RaisedButton(
+// child: Icon(Icons.arrow_back),
+// onPressed: () {
+// if (webView != null) {
+// webView.goBack();
+// }
+// },
+// ),
+// RaisedButton(
+// child: Icon(Icons.arrow_forward),
+// onPressed: () {
+// if (webView != null) {
+// webView.goForward();
+// }
+// },
+// ),
+// RaisedButton(
+// child: Icon(Icons.refresh),
+// onPressed: () {
+// if (webView != null) {
+// webView.reload();
+// }
+// },
+// ),
+// ],
+// ),
+// ].where((Object o) => o != null).toList(),
+// ),
+// ),
+// bottomNavigationBar: BottomNavigationBar(
+// currentIndex: 0,
+// items: [
+// BottomNavigationBarItem(
+// icon: Icon(Icons.home),
+// title: Text('Home'),
+// ),
+// BottomNavigationBarItem(
+// icon: Icon(Icons.mail),
+// title: Text('Item 2'),
+// ),
+// BottomNavigationBarItem(
+// icon: Icon(Icons.person),
+// title: Text('Item 3')
+// )
+// ],
+// ),
+// ),
+// );
+// }
+//}
diff --git a/flutter_inappbrowser.iml b/flutter_inappbrowser.iml
index 4b6ef47a..175d8e0e 100644
--- a/flutter_inappbrowser.iml
+++ b/flutter_inappbrowser.iml
@@ -20,7 +20,6 @@
-
diff --git a/ios/Classes/InAppBrowserOptions.swift b/ios/Classes/InAppBrowserOptions.swift
index 6bac1ed0..6c6596cf 100644
--- a/ios/Classes/InAppBrowserOptions.swift
+++ b/ios/Classes/InAppBrowserOptions.swift
@@ -10,21 +10,12 @@ import Foundation
@objcMembers
public class InAppBrowserOptions: Options {
- var useShouldOverrideUrlLoading = false
- var useOnLoadResource = false
- var openWithSystemBrowser = false;
- var clearCache = false
- var userAgent = ""
- var javaScriptEnabled = true
- var javaScriptCanOpenWindowsAutomatically = false
var hidden = false
var toolbarTop = true
var toolbarTopBackgroundColor = ""
+ var toolbarTopFixedTitle = ""
var hideUrlBar = false
- var mediaPlaybackRequiresUserGesture = true
- var isLocalFile = false
- var disallowOverScroll = false
var toolbarBottom = true
var toolbarBottomBackgroundColor = ""
var toolbarBottomTranslucent = true
@@ -32,15 +23,6 @@ public class InAppBrowserOptions: Options {
var closeButtonColor = ""
var presentationStyle = 0 //fullscreen
var transitionStyle = 0 //crossDissolve
- var enableViewportScale = false
- //var keyboardDisplayRequiresUserAction = true
- var suppressesIncrementalRendering = false
- var allowsAirPlayForMediaPlayback = true
- var allowsBackForwardNavigationGestures = true
- var allowsLinkPreview = true
- var ignoresViewportScaleLimits = false
- var allowsInlineMediaPlayback = false
- var allowsPictureInPictureMediaPlayback = true
var spinner = true
override init(){
diff --git a/ios/Classes/InAppBrowserWebViewController.swift b/ios/Classes/InAppBrowserWebViewController.swift
index 7222697b..c2a5ce40 100644
--- a/ios/Classes/InAppBrowserWebViewController.swift
+++ b/ios/Classes/InAppBrowserWebViewController.swift
@@ -129,7 +129,7 @@ func convertToDictionary(text: String) -> [String: Any]? {
//
//}
-class WKWebView_IBWrapper: WKWebView {
+class InAppWebView_IBWrapper: InAppWebView {
required convenience init?(coder: NSCoder) {
let config = WKWebViewConfiguration()
self.init(frame: .zero, configuration: config)
@@ -139,7 +139,7 @@ class WKWebView_IBWrapper: WKWebView {
class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate, UITextFieldDelegate, WKScriptMessageHandler {
- @IBOutlet var webView: WKWebView_IBWrapper!
+ @IBOutlet var webView: InAppWebView_IBWrapper!
@IBOutlet var closeButton: UIButton!
@IBOutlet var reloadButton: UIBarButtonItem!
@IBOutlet var backButton: UIBarButtonItem!
@@ -159,6 +159,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
var currentURL: URL?
var tmpWindow: UIWindow?
var browserOptions: InAppBrowserOptions?
+ var webViewOptions: InAppWebViewOptions?
var initHeaders: [String: String]?
var isHidden = false
var uuid: String = ""
@@ -216,7 +217,8 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
// Prevent crashes on closing windows
deinit {
- webView?.uiDelegate = nil
+ webView.removeObserver(self, forKeyPath: "estimatedProgress")
+ webView.uiDelegate = nil
}
override func viewWillDisappear (_ animated: Bool) {
@@ -231,6 +233,11 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
func prepareWebView() {
//UIApplication.shared.statusBarStyle = preferredStatusBarStyle
+ self.webView.addObserver(self,
+ forKeyPath: #keyPath(WKWebView.estimatedProgress),
+ options: .new,
+ context: nil)
+
self.webView.configuration.userContentController = WKUserContentController()
self.webView.configuration.preferences = WKPreferences()
@@ -273,7 +280,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
self.modalTransitionStyle = UIModalTransitionStyle(rawValue: (browserOptions?.transitionStyle)!)!
// prevent webView from bouncing
- if (browserOptions?.disallowOverScroll)! {
+ if (webViewOptions?.disallowOverScroll)! {
if self.webView.responds(to: #selector(getter: self.webView.scrollView)) {
self.webView.scrollView.bounces = false
}
@@ -286,7 +293,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
}
}
- if (browserOptions?.enableViewportScale)! {
+ if (webViewOptions?.enableViewportScale)! {
let jscript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
let userScript = WKUserScript(source: jscript, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
self.webView.configuration.userContentController.addUserScript(userScript)
@@ -314,44 +321,44 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
self.webView.configuration.userContentController.add(self, name: "resourceLoaded")
if #available(iOS 10.0, *) {
- self.webView.configuration.mediaTypesRequiringUserActionForPlayback = ((browserOptions?.mediaPlaybackRequiresUserGesture)!) ? .all : []
+ self.webView.configuration.mediaTypesRequiringUserActionForPlayback = ((webViewOptions?.mediaPlaybackRequiresUserGesture)!) ? .all : []
} else {
// Fallback on earlier versions
- self.webView.configuration.mediaPlaybackRequiresUserAction = (browserOptions?.mediaPlaybackRequiresUserGesture)!
+ self.webView.configuration.mediaPlaybackRequiresUserAction = (webViewOptions?.mediaPlaybackRequiresUserGesture)!
}
- self.webView.configuration.allowsInlineMediaPlayback = (browserOptions?.allowsInlineMediaPlayback)!
+ self.webView.configuration.allowsInlineMediaPlayback = (webViewOptions?.allowsInlineMediaPlayback)!
//self.webView.keyboardDisplayRequiresUserAction = browserOptions?.keyboardDisplayRequiresUserAction
- self.webView.configuration.suppressesIncrementalRendering = (browserOptions?.suppressesIncrementalRendering)!
- self.webView.allowsBackForwardNavigationGestures = (browserOptions?.allowsBackForwardNavigationGestures)!
+ self.webView.configuration.suppressesIncrementalRendering = (webViewOptions?.suppressesIncrementalRendering)!
+ self.webView.allowsBackForwardNavigationGestures = (webViewOptions?.allowsBackForwardNavigationGestures)!
if #available(iOS 9.0, *) {
- self.webView.allowsLinkPreview = (browserOptions?.allowsLinkPreview)!
+ self.webView.allowsLinkPreview = (webViewOptions?.allowsLinkPreview)!
}
if #available(iOS 10.0, *) {
- self.webView.configuration.ignoresViewportScaleLimits = (browserOptions?.ignoresViewportScaleLimits)!
+ self.webView.configuration.ignoresViewportScaleLimits = (webViewOptions?.ignoresViewportScaleLimits)!
}
- self.webView.configuration.allowsInlineMediaPlayback = (browserOptions?.allowsInlineMediaPlayback)!
+ self.webView.configuration.allowsInlineMediaPlayback = (webViewOptions?.allowsInlineMediaPlayback)!
if #available(iOS 9.0, *) {
- self.webView.configuration.allowsPictureInPictureMediaPlayback = (browserOptions?.allowsPictureInPictureMediaPlayback)!
+ self.webView.configuration.allowsPictureInPictureMediaPlayback = (webViewOptions?.allowsPictureInPictureMediaPlayback)!
}
- self.webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = (browserOptions?.javaScriptCanOpenWindowsAutomatically)!
+ self.webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = (webViewOptions?.javaScriptCanOpenWindowsAutomatically)!
- self.webView.configuration.preferences.javaScriptEnabled = (browserOptions?.javaScriptEnabled)!
+ self.webView.configuration.preferences.javaScriptEnabled = (webViewOptions?.javaScriptEnabled)!
- if ((browserOptions?.userAgent)! != "") {
+ if ((webViewOptions?.userAgent)! != "") {
if #available(iOS 9.0, *) {
- self.webView.customUserAgent = (browserOptions?.userAgent)!
+ self.webView.customUserAgent = (webViewOptions?.userAgent)!
}
}
- if (browserOptions?.clearCache)! {
+ if (webViewOptions?.clearCache)! {
clearCache()
}
@@ -519,14 +526,14 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
if let url = navigationAction.request.url {
- if url.absoluteString != self.currentURL?.absoluteString && (browserOptions?.useOnLoadResource)! {
+ if url.absoluteString != self.currentURL?.absoluteString && (webViewOptions?.useOnLoadResource)! {
WKNavigationMap[url.absoluteString] = [
"startTime": currentTimeInMilliSeconds(),
"request": navigationAction.request
]
}
- if navigationAction.navigationType == .linkActivated && (browserOptions?.useShouldOverrideUrlLoading)! {
+ if navigationAction.navigationType == .linkActivated && (webViewOptions?.useShouldOverrideUrlLoading)! {
if navigationDelegate != nil {
navigationDelegate?.shouldOverrideUrlLoading(uuid: self.uuid, webView: webView, url: url)
}
@@ -548,7 +555,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
decidePolicyFor navigationResponse: WKNavigationResponse,
decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
- if (browserOptions?.useOnLoadResource)! {
+ if (webViewOptions?.useOnLoadResource)! {
if let url = navigationResponse.response.url {
if WKNavigationMap[url.absoluteString] != nil {
let startResourceTime = (WKNavigationMap[url.absoluteString]!["startTime"] as! Int)
@@ -678,7 +685,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
navigationDelegate?.onConsoleMessage(uuid: self.uuid, sourceURL: "", lineNumber: 1, message: message.body as! String, messageLevel: messageLevel)
}
}
- else if message.name == "resourceLoaded" && (browserOptions?.useOnLoadResource)! {
+ else if message.name == "resourceLoaded" && (webViewOptions?.useOnLoadResource)! {
if let resource = convertToDictionary(text: message.body as! String) {
let url = URL(string: resource["name"] as! String)!
if !UIApplication.shared.canOpenURL(url) {
@@ -730,6 +737,9 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
func setOptions(newOptions: InAppBrowserOptions, newOptionsMap: [String: Any]) {
+ let newInAppWebViewOptions = InAppWebViewOptions()
+ newInAppWebViewOptions.parse(options: newOptionsMap)
+
if newOptionsMap["hidden"] != nil && browserOptions?.hidden != newOptions.hidden {
if newOptions.hidden {
self.navigationDelegate?.hide(uuid: self.uuid)
@@ -784,93 +794,107 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
self.modalTransitionStyle = UIModalTransitionStyle(rawValue: newOptions.transitionStyle)!
}
- if newOptionsMap["disallowOverScroll"] != nil && browserOptions?.disallowOverScroll != newOptions.disallowOverScroll {
+ if newOptionsMap["disallowOverScroll"] != nil && webViewOptions?.disallowOverScroll != newInAppWebViewOptions.disallowOverScroll {
if self.webView.responds(to: #selector(getter: self.webView.scrollView)) {
- self.webView.scrollView.bounces = !newOptions.disallowOverScroll
+ self.webView.scrollView.bounces = !newInAppWebViewOptions.disallowOverScroll
}
else {
for subview: UIView in self.webView.subviews {
if subview is UIScrollView {
- (subview as! UIScrollView).bounces = !newOptions.disallowOverScroll
+ (subview as! UIScrollView).bounces = !newInAppWebViewOptions.disallowOverScroll
}
}
}
}
- if newOptionsMap["enableViewportScale"] != nil && browserOptions?.enableViewportScale != newOptions.enableViewportScale && newOptions.enableViewportScale {
+ if newOptionsMap["enableViewportScale"] != nil && webViewOptions?.enableViewportScale != newInAppWebViewOptions.enableViewportScale && newInAppWebViewOptions.enableViewportScale {
let jscript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
self.webView.evaluateJavaScript(jscript, completionHandler: nil)
}
- if newOptionsMap["mediaPlaybackRequiresUserGesture"] != nil && browserOptions?.mediaPlaybackRequiresUserGesture != newOptions.mediaPlaybackRequiresUserGesture {
+ if newOptionsMap["mediaPlaybackRequiresUserGesture"] != nil && webViewOptions?.mediaPlaybackRequiresUserGesture != newInAppWebViewOptions.mediaPlaybackRequiresUserGesture {
if #available(iOS 10.0, *) {
- self.webView.configuration.mediaTypesRequiringUserActionForPlayback = (newOptions.mediaPlaybackRequiresUserGesture) ? .all : []
+ self.webView.configuration.mediaTypesRequiringUserActionForPlayback = (newInAppWebViewOptions.mediaPlaybackRequiresUserGesture) ? .all : []
} else {
// Fallback on earlier versions
- self.webView.configuration.mediaPlaybackRequiresUserAction = newOptions.mediaPlaybackRequiresUserGesture
+ self.webView.configuration.mediaPlaybackRequiresUserAction = newInAppWebViewOptions.mediaPlaybackRequiresUserGesture
}
}
- if newOptionsMap["allowsInlineMediaPlayback"] != nil && browserOptions?.allowsInlineMediaPlayback != newOptions.allowsInlineMediaPlayback {
- self.webView.configuration.allowsInlineMediaPlayback = newOptions.allowsInlineMediaPlayback
+ if newOptionsMap["allowsInlineMediaPlayback"] != nil && webViewOptions?.allowsInlineMediaPlayback != newInAppWebViewOptions.allowsInlineMediaPlayback {
+ self.webView.configuration.allowsInlineMediaPlayback = newInAppWebViewOptions.allowsInlineMediaPlayback
}
// if newOptionsMap["keyboardDisplayRequiresUserAction"] != nil && browserOptions?.keyboardDisplayRequiresUserAction != newOptions.keyboardDisplayRequiresUserAction {
// self.webView.keyboardDisplayRequiresUserAction = newOptions.keyboardDisplayRequiresUserAction
// }
- if newOptionsMap["suppressesIncrementalRendering"] != nil && browserOptions?.suppressesIncrementalRendering != newOptions.suppressesIncrementalRendering {
- self.webView.configuration.suppressesIncrementalRendering = newOptions.suppressesIncrementalRendering
+ if newOptionsMap["suppressesIncrementalRendering"] != nil && webViewOptions?.suppressesIncrementalRendering != newInAppWebViewOptions.suppressesIncrementalRendering {
+ self.webView.configuration.suppressesIncrementalRendering = newInAppWebViewOptions.suppressesIncrementalRendering
}
- if newOptionsMap["allowsBackForwardNavigationGestures"] != nil && browserOptions?.allowsBackForwardNavigationGestures != newOptions.allowsBackForwardNavigationGestures {
- self.webView.allowsBackForwardNavigationGestures = newOptions.allowsBackForwardNavigationGestures
+ if newOptionsMap["allowsBackForwardNavigationGestures"] != nil && webViewOptions?.allowsBackForwardNavigationGestures != newInAppWebViewOptions.allowsBackForwardNavigationGestures {
+ self.webView.allowsBackForwardNavigationGestures = newInAppWebViewOptions.allowsBackForwardNavigationGestures
}
- if newOptionsMap["allowsLinkPreview"] != nil && browserOptions?.allowsLinkPreview != newOptions.allowsLinkPreview {
+ if newOptionsMap["allowsLinkPreview"] != nil && webViewOptions?.allowsLinkPreview != newInAppWebViewOptions.allowsLinkPreview {
if #available(iOS 9.0, *) {
- self.webView.allowsLinkPreview = newOptions.allowsLinkPreview
+ self.webView.allowsLinkPreview = newInAppWebViewOptions.allowsLinkPreview
}
}
- if newOptionsMap["ignoresViewportScaleLimits"] != nil && browserOptions?.ignoresViewportScaleLimits != newOptions.ignoresViewportScaleLimits {
+ if newOptionsMap["ignoresViewportScaleLimits"] != nil && webViewOptions?.ignoresViewportScaleLimits != newInAppWebViewOptions.ignoresViewportScaleLimits {
if #available(iOS 10.0, *) {
- self.webView.configuration.ignoresViewportScaleLimits = newOptions.ignoresViewportScaleLimits
+ self.webView.configuration.ignoresViewportScaleLimits = newInAppWebViewOptions.ignoresViewportScaleLimits
}
}
- if newOptionsMap["allowsInlineMediaPlayback"] != nil && browserOptions?.allowsInlineMediaPlayback != newOptions.allowsInlineMediaPlayback {
- self.webView.configuration.allowsInlineMediaPlayback = newOptions.allowsInlineMediaPlayback
+ if newOptionsMap["allowsInlineMediaPlayback"] != nil && webViewOptions?.allowsInlineMediaPlayback != newInAppWebViewOptions.allowsInlineMediaPlayback {
+ self.webView.configuration.allowsInlineMediaPlayback = newInAppWebViewOptions.allowsInlineMediaPlayback
}
- if newOptionsMap["allowsPictureInPictureMediaPlayback"] != nil && browserOptions?.allowsPictureInPictureMediaPlayback != newOptions.allowsPictureInPictureMediaPlayback {
+ if newOptionsMap["allowsPictureInPictureMediaPlayback"] != nil && webViewOptions?.allowsPictureInPictureMediaPlayback != newInAppWebViewOptions.allowsPictureInPictureMediaPlayback {
if #available(iOS 9.0, *) {
- self.webView.configuration.allowsPictureInPictureMediaPlayback = newOptions.allowsPictureInPictureMediaPlayback
+ self.webView.configuration.allowsPictureInPictureMediaPlayback = newInAppWebViewOptions.allowsPictureInPictureMediaPlayback
}
}
- if newOptionsMap["javaScriptCanOpenWindowsAutomatically"] != nil && browserOptions?.javaScriptCanOpenWindowsAutomatically != newOptions.javaScriptCanOpenWindowsAutomatically {
- self.webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = newOptions.javaScriptCanOpenWindowsAutomatically
+ if newOptionsMap["javaScriptCanOpenWindowsAutomatically"] != nil && webViewOptions?.javaScriptCanOpenWindowsAutomatically != newInAppWebViewOptions.javaScriptCanOpenWindowsAutomatically {
+ self.webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = newInAppWebViewOptions.javaScriptCanOpenWindowsAutomatically
}
- if newOptionsMap["javaScriptEnabled"] != nil && browserOptions?.javaScriptEnabled != newOptions.javaScriptEnabled {
- self.webView.configuration.preferences.javaScriptEnabled = newOptions.javaScriptEnabled
+ if newOptionsMap["javaScriptEnabled"] != nil && webViewOptions?.javaScriptEnabled != newInAppWebViewOptions.javaScriptEnabled {
+ self.webView.configuration.preferences.javaScriptEnabled = newInAppWebViewOptions.javaScriptEnabled
}
- if newOptionsMap["userAgent"] != nil && browserOptions?.userAgent != newOptions.userAgent && (newOptions.userAgent != "") {
+ if newOptionsMap["userAgent"] != nil && webViewOptions?.userAgent != newInAppWebViewOptions.userAgent && (newInAppWebViewOptions.userAgent != "") {
if #available(iOS 9.0, *) {
- self.webView.customUserAgent = newOptions.userAgent
+ self.webView.customUserAgent = newInAppWebViewOptions.userAgent
}
}
- if newOptionsMap["clearCache"] != nil && newOptions.clearCache {
+ if newOptionsMap["clearCache"] != nil && newInAppWebViewOptions.clearCache {
clearCache()
}
self.browserOptions = newOptions
+ self.webViewOptions = newInAppWebViewOptions
}
func getOptions() -> [String: Any]? {
- return (self.browserOptions != nil) ? self.browserOptions?.getHashMap() : nil
+ if (self.browserOptions == nil || self.webViewOptions == nil) {
+ return nil
+ }
+ var optionsMap = self.browserOptions!.getHashMap()
+ optionsMap.merge(self.webViewOptions!.getHashMap(), uniquingKeysWith: { (current, _) in current })
+ return optionsMap
+ }
+
+ override func observeValue(forKeyPath keyPath: String?, of object: Any?,
+ change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
+ if keyPath == "estimatedProgress" {
+ let progress = Int(webView.estimatedProgress * 100)
+ self.navigationDelegate?.onProgressChanged(uuid: self.uuid, webView: self.webView, progress: progress)
+ }
}
}
diff --git a/ios/Classes/InAppWebView.swift b/ios/Classes/InAppWebView.swift
new file mode 100644
index 00000000..4f533130
--- /dev/null
+++ b/ios/Classes/InAppWebView.swift
@@ -0,0 +1,13 @@
+//
+// InAppWebView.swift
+// flutter_inappbrowser
+//
+// Created by Lorenzo on 21/10/18.
+//
+
+import Foundation
+import WebKit
+
+public class InAppWebView: WKWebView {
+
+}
diff --git a/ios/Classes/InAppWebViewOptions.swift b/ios/Classes/InAppWebViewOptions.swift
new file mode 100644
index 00000000..e9b5e6f3
--- /dev/null
+++ b/ios/Classes/InAppWebViewOptions.swift
@@ -0,0 +1,38 @@
+//
+// InAppWebViewOptions.swift
+// flutter_inappbrowser
+//
+// Created by Lorenzo on 21/10/18.
+//
+
+import Foundation
+
+@objcMembers
+public class InAppWebViewOptions: Options {
+
+ var useShouldOverrideUrlLoading = false
+ var useOnLoadResource = false
+ var clearCache = false
+ var userAgent = ""
+ var javaScriptEnabled = true
+ var javaScriptCanOpenWindowsAutomatically = false
+ var mediaPlaybackRequiresUserGesture = true
+
+ var disallowOverScroll = false
+ var enableViewportScale = false
+ //var keyboardDisplayRequiresUserAction = true
+ var suppressesIncrementalRendering = false
+ var allowsAirPlayForMediaPlayback = true
+ var allowsBackForwardNavigationGestures = true
+ var allowsLinkPreview = true
+ var ignoresViewportScaleLimits = false
+ var allowsInlineMediaPlayback = false
+ var allowsPictureInPictureMediaPlayback = true
+
+ override init(){
+ super.init()
+ }
+
+}
+
+
diff --git a/ios/Classes/SwiftFlutterPlugin.swift b/ios/Classes/SwiftFlutterPlugin.swift
index b0b5d216..cce85a0d 100644
--- a/ios/Classes/SwiftFlutterPlugin.swift
+++ b/ios/Classes/SwiftFlutterPlugin.swift
@@ -68,6 +68,9 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
case "loadUrl":
self.loadUrl(uuid: uuid, arguments: arguments!, result: result)
break
+ case "loadFile":
+ self.loadFile(uuid: uuid, arguments: arguments!, result: result)
+ break
case "close":
self.close(uuid: uuid)
result(true)
@@ -205,29 +208,39 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
let url: String = (arguments["url"] as? String)!
let headers = (arguments["headers"] as? [String: String])!
- let absoluteUrl = URL(string: url)?.absoluteURL
+ var absoluteUrl = URL(string: url)?.absoluteURL
+
+ let useChromeSafariBrowser = (arguments["useChromeSafariBrowser"] as? Bool)!
- let useChromeSafariBrowser = (arguments["useChromeSafariBrowser"] as? Bool)
-
- if useChromeSafariBrowser! {
+ if useChromeSafariBrowser {
let uuidFallback = (arguments["uuidFallback"] as? String)!
- let safariOptions = SafariBrowserOptions()
- safariOptions.parse(options: (arguments["options"] as? [String: Any])!)
+ let safariOptions = (arguments["options"] as? [String: Any])!
- let optionsFallback = InAppBrowserOptions()
- optionsFallback.parse(options: (arguments["optionsFallback"] as? [String: Any])!)
+ let optionsFallback = (arguments["optionsFallback"] as? [String: Any])!
open(uuid: uuid, uuidFallback: uuidFallback, inAppBrowser: absoluteUrl!, headers: headers, withOptions: safariOptions, useChromeSafariBrowser: true, withOptionsFallback: optionsFallback, result: result);
}
else {
- let options = InAppBrowserOptions()
- options.parse(options: (arguments["options"] as? [String: Any])!)
+ let options = (arguments["options"] as? [String: Any])!
+
+ let isLocalFile = (arguments["isLocalFile"] as? Bool)!
+ var openWithSystemBrowser = (arguments["openWithSystemBrowser"] as? Bool)!
+
+ if isLocalFile {
+ let key = SwiftFlutterPlugin.registrar!.lookupKey(forAsset: url)
+ let assetURL = Bundle.main.url(forResource: key, withExtension: nil)
+ if assetURL == nil {
+ result(FlutterError(code: "InAppBrowserFlutterPlugin", message: url + " asset file cannot be found!", details: nil))
+ return
+ }
+ absoluteUrl = assetURL!
+ }
if isSystemUrl(absoluteUrl!) {
- options.openWithSystemBrowser = true
+ openWithSystemBrowser = true
}
- if (options.openWithSystemBrowser) {
+ if (openWithSystemBrowser) {
open(inSystem: absoluteUrl!, result: result)
}
else {
@@ -236,7 +249,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
}
}
- func open(uuid: String, uuidFallback: String?, inAppBrowser url: URL, headers: [String: String], withOptions options: Options, useChromeSafariBrowser: Bool, withOptionsFallback optionsFallback: Options?, result: @escaping FlutterResult) {
+ func open(uuid: String, uuidFallback: String?, inAppBrowser url: URL, headers: [String: String], withOptions options: [String: Any], useChromeSafariBrowser: Bool, withOptionsFallback optionsFallback: [String: Any]?, result: @escaping FlutterResult) {
var uuid = uuid
@@ -270,10 +283,12 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
self.tmpWindow?.makeKeyAndVisible()
let browserOptions: InAppBrowserOptions
+ let webViewOptions: InAppWebViewOptions
if useChromeSafariBrowser == true {
if #available(iOS 9.0, *) {
- let safariOptions = options as! SafariBrowserOptions
+ let safariOptions = SafariBrowserOptions()
+ safariOptions.parse(options: options)
let safari: SafariViewController
@@ -310,23 +325,19 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
return
}
uuid = uuidFallback!
- browserOptions = optionsFallback as! InAppBrowserOptions
+ browserOptions = InAppBrowserOptions()
+ browserOptions.parse(options: optionsFallback!)
+
+ webViewOptions = InAppWebViewOptions()
+ webViewOptions.parse(options: optionsFallback!)
}
}
else {
- browserOptions = options as! InAppBrowserOptions
- }
-
- var currentURL = url
-
- if browserOptions.isLocalFile {
- let key = SwiftFlutterPlugin.registrar!.lookupKey(forAsset: url.absoluteString)
- let assetURL = Bundle.main.url(forResource: key, withExtension: nil)
- if assetURL == nil {
- result(FlutterError(code: "InAppBrowserFlutterPlugin", message: url.absoluteString + " asset file cannot be found!", details: nil))
- return
- }
- currentURL = assetURL!
+ browserOptions = InAppBrowserOptions()
+ browserOptions.parse(options: options)
+
+ webViewOptions = InAppWebViewOptions()
+ webViewOptions.parse(options: options)
}
let storyboard = UIStoryboard(name: WEBVIEW_STORYBOARD, bundle: Bundle(for: InAppBrowserFlutterPlugin.self))
@@ -335,9 +346,10 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
let webViewController: InAppBrowserWebViewController = self.webViewControllers[uuid] as! InAppBrowserWebViewController
webViewController.uuid = uuid
webViewController.browserOptions = browserOptions
+ webViewController.webViewOptions = webViewOptions
webViewController.isHidden = browserOptions.hidden
webViewController.tmpWindow = tmpWindow
- webViewController.currentURL = currentURL
+ webViewController.currentURL = url
webViewController.initHeaders = headers
webViewController.navigationDelegate = self
@@ -365,11 +377,29 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
public func loadUrl(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
let webViewController: InAppBrowserWebViewController = self.webViewControllers[uuid] as! InAppBrowserWebViewController
- let url: String? = (arguments["url"] as? String)!
- let headers = (arguments["headers"] as? [String: String])!
-
- if url != nil {
- let absoluteUrl = URL(string: url!)!.absoluteURL
+ if let url = arguments["url"] as? String {
+ let headers = (arguments["headers"] as? [String: String])!
+ let absoluteUrl = URL(string: url)!.absoluteURL
+ webViewController.loadUrl(url: absoluteUrl, headers: headers)
+ }
+ else {
+ result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "url is empty", details: nil))
+ }
+ result(true)
+ }
+
+ public func loadFile(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
+ let webViewController: InAppBrowserWebViewController = self.webViewControllers[uuid] as! InAppBrowserWebViewController
+ if let url = arguments["url"] as? String {
+ let headers = (arguments["headers"] as? [String: String])!
+
+ let key = SwiftFlutterPlugin.registrar!.lookupKey(forAsset: url)
+ let assetURL = Bundle.main.url(forResource: key, withExtension: nil)
+ if assetURL == nil {
+ result(FlutterError(code: "InAppBrowserFlutterPlugin", message: url + " asset file cannot be found!", details: nil))
+ return
+ }
+ let absoluteUrl = URL(string: url)!.absoluteURL
webViewController.loadUrl(url: absoluteUrl, headers: headers)
}
else {
@@ -530,6 +560,12 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
}
}
+ func onProgressChanged(uuid: String, webView: WKWebView, progress: Int) {
+ if let webViewController = self.webViewControllers[uuid] {
+ channel.invokeMethod("onProgressChanged", arguments: ["uuid": uuid, "progress": progress])
+ }
+ }
+
func onLoadResource(uuid: String, webView: WKWebView, response: URLResponse, fromRequest request: URLRequest?, withData data: Data, startTime: Int, duration: Int) {
if self.webViewControllers[uuid] != nil {
var headersResponse = (response as! HTTPURLResponse).allHeaderFields as! [String: String]
diff --git a/ios/Storyboards/WebView.storyboard b/ios/Storyboards/WebView.storyboard
index bfc191a0..97a7ef2b 100644
--- a/ios/Storyboards/WebView.storyboard
+++ b/ios/Storyboards/WebView.storyboard
@@ -21,7 +21,7 @@
-
+
@@ -96,7 +96,7 @@
-
+
diff --git a/lib/flutter_inappbrowser.dart b/lib/flutter_inappbrowser.dart
index 2c51eb98..6256ed15 100644
--- a/lib/flutter_inappbrowser.dart
+++ b/lib/flutter_inappbrowser.dart
@@ -25,7 +25,11 @@ import 'dart:collection';
import 'dart:typed_data';
import 'dart:convert';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter/gestures.dart';
import 'package:uuid/uuid.dart';
import 'package:mime/mime.dart';
@@ -90,7 +94,7 @@ class _ChannelManager {
return await listeners[uuid](call);
}
- static void addListener (String key, ListenerCallback callback) {
+ static void addListener(String key, ListenerCallback callback) {
if (!initialized)
init();
listeners.putIfAbsent(key, () => callback);
@@ -101,102 +105,37 @@ class _ChannelManager {
}
}
-///InAppBrowser class.
+///InAppBrowser class. [webViewController] can be used to access the [InAppWebView] API.
///
///This class uses the native WebView of the platform.
class InAppBrowser {
String uuid;
Map> javaScriptHandlersMap = HashMap>();
- HttpServer _server;
bool _isOpened = false;
+ /// WebView Controller that can be used to access the [InAppWebView] API.
+ InAppWebViewController webViewController;
///
InAppBrowser () {
uuid = _uuidGenerator.v4();
_ChannelManager.addListener(uuid, _handleMethod);
_isOpened = false;
+ webViewController = new InAppWebViewController.fromInAppBrowser(uuid, _ChannelManager.channel, this);
}
Future _handleMethod(MethodCall call) async {
switch(call.method) {
- case "onLoadStart":
- String url = call.arguments["url"];
- onLoadStart(url);
- break;
- case "onLoadStop":
- String url = call.arguments["url"];
- onLoadStop(url);
- break;
- case "onLoadError":
- String url = call.arguments["url"];
- int code = call.arguments["code"];
- String message = call.arguments["message"];
- onLoadError(url, code, message);
- break;
case "onExit":
- this._closeServer();
this._isOpened = false;
onExit();
break;
- case "shouldOverrideUrlLoading":
- String url = call.arguments["url"];
- shouldOverrideUrlLoading(url);
- break;
- case "onLoadResource":
- Map rawResponse = call.arguments["response"];
- rawResponse = rawResponse.cast();
- Map rawRequest = call.arguments["request"];
- rawRequest = rawRequest.cast();
-
- String urlResponse = rawResponse["url"];
- Map headersResponse = rawResponse["headers"];
- headersResponse = headersResponse.cast();
- int statusCode = rawResponse["statusCode"];
- int startTime = rawResponse["startTime"];
- int duration = rawResponse["duration"];
- Uint8List data = rawResponse["data"];
-
- String urlRequest = rawRequest["url"];
- Map headersRequest = rawRequest["headers"];
- headersRequest = headersResponse.cast();
- String method = rawRequest["method"];
-
- var response = new WebResourceResponse(urlResponse, headersResponse, statusCode, startTime, duration, data);
- var request = new WebResourceRequest(urlRequest, headersRequest, method);
-
- onLoadResource(response, request);
- break;
- case "onConsoleMessage":
- String sourceURL = call.arguments["sourceURL"];
- int lineNumber = call.arguments["lineNumber"];
- String message = call.arguments["message"];
- ConsoleMessageLevel messageLevel;
- ConsoleMessageLevel.values.forEach((element) {
- if ("ConsoleMessageLevel." + call.arguments["messageLevel"] == element.toString()) {
- messageLevel = element;
- return;
- }
- });
- onConsoleMessage(ConsoleMessage(sourceURL, lineNumber, message, messageLevel));
- break;
- case "onCallJsHandler":
- String handlerName = call.arguments["handlerName"];
- List args = jsonDecode(call.arguments["args"]);
- if (javaScriptHandlersMap.containsKey(handlerName)) {
- for (var handler in javaScriptHandlersMap[handlerName]) {
- handler(args);
- }
- }
- break;
default:
- throw UnimplementedError("Unimplemented ${call.method} method");
+ return webViewController._handleMethod(call);
}
}
- ///Opens an [url] in a new [InAppBrowser] instance or in the system browser (`openWithSystemBrowser: true`).
- ///
- ///**NOTE**: If you open the given [url] with the system browser (`openWithSystemBrowser: true`), you wont be able to use the [InAppBrowser] methods!
+ ///Opens an [url] in a new [InAppBrowser] instance.
///
///- [url]: The [url] to load. Call [encodeUriComponent()] on this if the [url] contains Unicode characters. The default value is `about:blank`.
///
@@ -207,15 +146,13 @@ class InAppBrowser {
/// - All platforms support:
/// - __useShouldOverrideUrlLoading__: Set to `true` to be able to listen at the [shouldOverrideUrlLoading()] event. The default value is `false`.
/// - __useOnLoadResource__: Set to `true` to be able to listen at the [onLoadResource()] event. The default value is `false`.
- /// - __openWithSystemBrowser__: Set to `true` to open the given `url` with the system browser. The default value is `false`.
- /// - __isLocalFile__: Set to `true` if the [url] is pointing to a local file (the file must be addded in the `assets` section of your `pubspec.yaml`. See [loadFile()] explanation). The default value is `false`.
/// - __clearCache__: Set to `true` to have all the browser's cache cleared before the new window is opened. The default value is `false`.
/// - __userAgent___: Set the custom WebView's user-agent.
/// - __javaScriptEnabled__: Set to `true` to enable JavaScript. The default value is `true`.
/// - __javaScriptCanOpenWindowsAutomatically__: Set to `true` to allow JavaScript open windows without user interaction. The default value is `false`.
/// - __hidden__: Set to `true` to create the browser and load the page, but not show it. The `onLoadStop` event fires when loading is complete. Omit or set to `false` (default) to have the browser open and load normally.
/// - __toolbarTop__: Set to `false` to hide the toolbar at the top of the WebView. The default value is `true`.
- /// - __toolbarTopBackgroundColor__: Set the custom background color of the toolbat at the top.
+ /// - __toolbarTopBackgroundColor__: Set the custom background color of the toolbar at the top.
/// - __hideUrlBar__: Set to `true` to hide the url bar on the toolbar at the top. The default value is `false`.
/// - __mediaPlaybackRequiresUserGesture__: Set to `true` to prevent HTML5 audio or video from autoplaying. The default value is `true`.
///
@@ -236,7 +173,7 @@ class InAppBrowser {
///
/// - __disallowOverScroll__: Set to `true` to disable the bouncing of the WebView when the scrolling has reached an edge of the content. The default value is `false`.
/// - __toolbarBottom__: Set to `false` to hide the toolbar at the bottom of the WebView. The default value is `true`.
- /// - __toolbarBottomBackgroundColor__: Set the custom background color of the toolbat at the bottom.
+ /// - __toolbarBottomBackgroundColor__: Set the custom background color of the toolbar at the bottom.
/// - __toolbarBottomTranslucent__: Set to `true` to set the toolbar at the bottom translucent. The default value is `true`.
/// - __closeButtonCaption__: Set the custom text for the close button.
/// - __closeButtonColor__: Set the custom color for the close button.
@@ -252,120 +189,21 @@ class InAppBrowser {
/// - __allowsPictureInPictureMediaPlayback__: Set to `true` to allow HTML5 videos play picture-in-picture. The default value is `true`.
/// - __spinner__: Set to `false` to hide the spinner when the WebView is loading a page. The default value is `true`.
Future open({String url = "about:blank", Map headers = const {}, Map options = const {}}) async {
+ assert(url != null);
this._throwIsAlreadyOpened(message: 'Cannot open $url!');
Map args = {};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => headers);
args.putIfAbsent('options', () => options);
+ args.putIfAbsent('openWithSystemBrowser', () => false);
+ args.putIfAbsent('isLocalFile', () => false);
args.putIfAbsent('useChromeSafariBrowser', () => false);
await _ChannelManager.channel.invokeMethod('open', args);
this._isOpened = true;
}
- ///This is a static method that opens an [url] in the system browser.
- ///This has the same behaviour of an [InAppBrowser] instance calling the [open()] method with option `openWithSystemBrowser: true`.
- static Future openWithSystemBrowser(String url) async {
- Map args = {};
- args.putIfAbsent('uuid', () => "");
- args.putIfAbsent('url', () => url);
- args.putIfAbsent('headers', () => {});
- args.putIfAbsent('options', () => {"openWithSystemBrowser": true});
- args.putIfAbsent('useChromeSafariBrowser', () => false);
- return await _ChannelManager.channel.invokeMethod('open', args);
- }
-
- Future _startServer({int port = 8080}) async {
-
- this._closeServer();
- var completer = new Completer();
-
- runZoned(() {
- HttpServer.bind('127.0.0.1', port).then((server) {
- print('Server running at http://127.0.0.1:' + port.toString());
-
- this._server = server;
-
- server.listen((HttpRequest request) async {
- var body = List();
- var path = request.requestedUri.path;
- path = (path.startsWith('/')) ? path.substring(1) : path;
- path += (path.endsWith('/')) ? 'index.html' : '';
-
- try {
- body = (await rootBundle.load(path))
- .buffer.asUint8List();
- } catch (e) {
- print(e.toString());
- request.response.close();
- return;
- }
-
- var contentType = ['text', 'html'];
- if (!request.requestedUri.path.endsWith('/') && request.requestedUri.pathSegments.isNotEmpty) {
- var mimeType = lookupMimeType(request.requestedUri.path, headerBytes: body);
- if (mimeType != null) {
- contentType = mimeType.split('/');
- }
- }
-
- request.response.headers.contentType = new ContentType(contentType[0], contentType[1], charset: 'utf-8');
- request.response.add(body);
- request.response.close();
- });
-
- completer.complete();
- });
- }, onError: (e, stackTrace) => print('Error: $e $stackTrace'));
-
- return completer.future;
- }
-
- Future _closeServer() async {
- if (this._server != null) {
- final port = this._server.port;
- await this._server.close(force: true);
- print('Server running at http://127.0.0.1:$port closed');
- this._server = null;
- }
- }
-
- ///Serve the [assetFilePath] from Flutter assets on http://localhost:[port]/. It is similar to [InAppBrowser.open()] with option `isLocalFile: true`, but it starts a server.
- ///
- ///**NOTE for iOS**: For the iOS Platform, you need to add the `NSAllowsLocalNetworking` key with `true` in the `Info.plist` file (See [ATS Configuration Basics](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW35):
- ///```xml
- ///NSAppTransportSecurity
- ///
- /// NSAllowsLocalNetworking
- ///
- ///
- ///```
- ///The `NSAllowsLocalNetworking` key is available since **iOS 10**.
- Future openOnLocalhost(String assetFilePath, {int port = 8080, Map headers = const {}, Map options = const {}}) async {
- this._throwIsAlreadyOpened(message: 'Cannot open $assetFilePath!');
- await this._startServer(port: port);
- Map args = {};
- args.putIfAbsent('uuid', () => uuid);
- args.putIfAbsent('url', () => 'http://localhost:${this._server.port}/' + assetFilePath);
- args.putIfAbsent('headers', () => headers);
- options["isLocalFile"] = false;
- args.putIfAbsent('options', () => options);
- args.putIfAbsent('useChromeSafariBrowser', () => false);
- await _ChannelManager.channel.invokeMethod('open', args);
- this._isOpened = true;
- }
-
- ///Loads the given [url] with optional [headers] specified as a map from name to value.
- Future loadUrl(String url, {Map headers = const {}}) async {
- this._throwIsNotOpened(message: 'Cannot laod $url!');
- Map args = {};
- args.putIfAbsent('uuid', () => uuid);
- args.putIfAbsent('url', () => url);
- args.putIfAbsent('headers', () => headers);
- await _ChannelManager.channel.invokeMethod('loadUrl', args);
- }
-
- ///Loads the given [assetFilePath] with optional [headers] specified as a map from name to value.
+ ///Opens the giver [assetFilePath] file in a new [InAppBrowser] instance. The other arguments are the same of [InAppBrowser.open()].
///
///To be able to load your local files (assets, js, css, etc.), you need to add them in the `assets` section of the `pubspec.yaml` file, otherwise they cannot be found!
///
@@ -391,16 +229,35 @@ class InAppBrowser {
///Example of a `main.dart` file:
///```dart
///...
- ///inAppBrowser.loadFile("assets/index.html");
+ ///inAppBrowser.openFile("assets/index.html");
///...
///```
- Future loadFile(String assetFilePath, {Map headers = const {}}) async {
- this._throwIsNotOpened(message: 'Cannot laod $assetFilePath!');
+ Future openFile(String assetFilePath, {Map headers = const {}, Map options = const {}}) async {
+ assert(assetFilePath != null);
+ this._throwIsAlreadyOpened(message: 'Cannot open $assetFilePath!');
Map args = {};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('url', () => assetFilePath);
args.putIfAbsent('headers', () => headers);
- await _ChannelManager.channel.invokeMethod('loadFile', args);
+ args.putIfAbsent('options', () => options);
+ args.putIfAbsent('openWithSystemBrowser', () => false);
+ args.putIfAbsent('isLocalFile', () => true);
+ args.putIfAbsent('useChromeSafariBrowser', () => false);
+ await _ChannelManager.channel.invokeMethod('open', args);
+ this._isOpened = true;
+ }
+
+ ///This is a static method that opens an [url] in the system browser. You wont be able to use the [InAppBrowser] methods here!
+ static Future openWithSystemBrowser(String url) async {
+ assert(url != null);
+ Map args = {};
+ args.putIfAbsent('uuid', () => "");
+ args.putIfAbsent('url', () => url);
+ args.putIfAbsent('headers', () => {});
+ args.putIfAbsent('isLocalFile', () => false);
+ args.putIfAbsent('openWithSystemBrowser', () => true);
+ args.putIfAbsent('useChromeSafariBrowser', () => false);
+ return await _ChannelManager.channel.invokeMethod('open', args);
}
///Displays an [InAppBrowser] window that was opened hidden. Calling this has no effect if the [InAppBrowser] was already visible.
@@ -427,46 +284,6 @@ class InAppBrowser {
await _ChannelManager.channel.invokeMethod('close', args);
}
- ///Reloads the [InAppBrowser] window.
- Future reload() async {
- this._throwIsNotOpened();
- Map args = {};
- args.putIfAbsent('uuid', () => uuid);
- await _ChannelManager.channel.invokeMethod('reload', args);
- }
-
- ///Goes back in the history of the [InAppBrowser] window.
- Future goBack() async {
- this._throwIsNotOpened();
- Map args = {};
- args.putIfAbsent('uuid', () => uuid);
- await _ChannelManager.channel.invokeMethod('goBack', args);
- }
-
- ///Goes forward in the history of the [InAppBrowser] window.
- Future goForward() async {
- this._throwIsNotOpened();
- Map args = {};
- args.putIfAbsent('uuid', () => uuid);
- await _ChannelManager.channel.invokeMethod('goForward', args);
- }
-
- ///Check if the Web View of the [InAppBrowser] instance is in a loading state.
- Future isLoading() async {
- this._throwIsNotOpened();
- Map args = {};
- args.putIfAbsent('uuid', () => uuid);
- return await _ChannelManager.channel.invokeMethod('isLoading', args);
- }
-
- ///Stops the Web View of the [InAppBrowser] instance from loading.
- Future stopLoading() async {
- this._throwIsNotOpened();
- Map args = {};
- args.putIfAbsent('uuid', () => uuid);
- await _ChannelManager.channel.invokeMethod('stopLoading', args);
- }
-
///Check if the Web View of the [InAppBrowser] instance is hidden.
Future isHidden() async {
this._throwIsNotOpened();
@@ -475,120 +292,6 @@ class InAppBrowser {
return await _ChannelManager.channel.invokeMethod('isHidden', args);
}
- ///Injects JavaScript code into the [InAppBrowser] window and returns the result of the evaluation.
- Future injectScriptCode(String source) async {
- this._throwIsNotOpened();
- Map args = {};
- args.putIfAbsent('uuid', () => uuid);
- args.putIfAbsent('source', () => source);
- return await _ChannelManager.channel.invokeMethod('injectScriptCode', args);
- }
-
- ///Injects a JavaScript file into the [InAppBrowser] window.
- Future injectScriptFile(String urlFile) async {
- this._throwIsNotOpened();
- Map args = {};
- args.putIfAbsent('uuid', () => uuid);
- args.putIfAbsent('urlFile', () => urlFile);
- await _ChannelManager.channel.invokeMethod('injectScriptFile', args);
- }
-
- ///Injects CSS into the [InAppBrowser] window.
- Future injectStyleCode(String source) async {
- this._throwIsNotOpened();
- Map args = {};
- args.putIfAbsent('uuid', () => uuid);
- args.putIfAbsent('source', () => source);
- await _ChannelManager.channel.invokeMethod('injectStyleCode', args);
- }
-
- ///Injects a CSS file into the [InAppBrowser] window.
- Future injectStyleFile(String urlFile) async {
- this._throwIsNotOpened();
- Map args = {};
- args.putIfAbsent('uuid', () => uuid);
- args.putIfAbsent('urlFile', () => urlFile);
- await _ChannelManager.channel.invokeMethod('injectStyleFile', args);
- }
-
- ///Adds/Appends a JavaScript message handler [callback] ([JavaScriptHandlerCallback]) that listen to post messages sent from JavaScript by the handler with name [handlerName].
- ///Returns the position `index` of the handler that can be used to remove it with the [removeJavaScriptHandler()] method.
- ///
- ///The Android implementation uses [addJavascriptInterface](https://developer.android.com/reference/android/webkit/WebView#addJavascriptInterface(java.lang.Object,%20java.lang.String)).
- ///The iOS implementation uses [addScriptMessageHandler](https://developer.apple.com/documentation/webkit/wkusercontentcontroller/1537172-addscriptmessagehandler?language=objc)
- ///
- ///The JavaScript function that can be used to call the handler is `window.flutter_inappbrowser.callHandler(handlerName , ...args);`, where `args` are [rest parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters).
- ///The `args` will be stringified automatically using `JSON.stringify(args)` method and then they will be decoded on the Dart side.
- int addJavaScriptHandler(String handlerName, JavaScriptHandlerCallback callback) {
- this.javaScriptHandlersMap.putIfAbsent(handlerName, () => List());
- this.javaScriptHandlersMap[handlerName].add(callback);
- return this.javaScriptHandlersMap[handlerName].indexOf(callback);
- }
-
- ///Removes a JavaScript message handler previously added with the [addJavaScriptHandler()] method in the [handlerName] list by its position [index].
- ///Returns `true` if the callback is removed, otherwise `false`.
- bool removeJavaScriptHandler(String handlerName, int index) {
- try {
- this.javaScriptHandlersMap[handlerName].removeAt(index);
- return true;
- }
- on RangeError catch(e) {
- print(e);
- }
- return false;
- }
-
- ///Event fires when the [InAppBrowser] starts to load an [url].
- void onLoadStart(String url) {
-
- }
-
- ///Event fires when the [InAppBrowser] finishes loading an [url].
- void onLoadStop(String url) {
-
- }
-
- ///Event fires when the [InAppBrowser] encounters an error loading an [url].
- void onLoadError(String url, int code, String message) {
-
- }
-
- ///Event fires when the [InAppBrowser] window is closed.
- void onExit() {
-
- }
-
- ///Give the host application a chance to take control when a URL is about to be loaded in the current WebView.
- ///
- ///**NOTE**: In order to be able to listen this event, you need to set `useShouldOverrideUrlLoading` option to `true`.
- void shouldOverrideUrlLoading(String url) {
-
- }
-
- ///Event fires when the [InAppBrowser] webview loads a resource.
- ///
- ///**NOTE**: In order to be able to listen this event, you need to set `useOnLoadResource` option to `true`.
- ///
- ///**NOTE only for iOS**: In some cases, the [response.data] of a [response] with `text/assets` encoding could be empty.
- void onLoadResource(WebResourceResponse response, WebResourceRequest request) {
-
- }
-
- ///Event fires when the [InAppBrowser] webview receives a [ConsoleMessage].
- void onConsoleMessage(ConsoleMessage consoleMessage) {
-
- }
-
- ///Takes a screenshot (in PNG format) of the WebView's visible viewport and returns a `Uint8List`. Returns `null` if it wasn't be able to take it.
- ///
- ///**NOTE for iOS**: available from iOS 11.0+.
- Future takeScreenshot() async {
- this._throwIsNotOpened();
- Map args = {};
- args.putIfAbsent('uuid', () => uuid);
- return await _ChannelManager.channel.invokeMethod('takeScreenshot', args);
- }
-
///Sets the [InAppBrowser] options with the new [options] and evaluates them.
Future setOptions(Map options) async {
this._throwIsNotOpened();
@@ -615,6 +318,52 @@ class InAppBrowser {
return this._isOpened;
}
+ ///Event fires when the [InAppBrowser] starts to load an [url].
+ void onLoadStart(String url) {
+
+ }
+
+ ///Event fires when the [InAppBrowser] finishes loading an [url].
+ void onLoadStop(String url) {
+
+ }
+
+ ///Event fires when the [InAppBrowser] encounters an error loading an [url].
+ void onLoadError(String url, int code, String message) {
+
+ }
+
+ ///Event fires when the current [progress] (range 0-100) of loading a page is changed.
+ void onProgressChanged(int progress) {
+
+ }
+
+ ///Event fires when the [InAppBrowser] window is closed.
+ void onExit() {
+
+ }
+
+ ///Event fires when the [InAppBrowser] webview receives a [ConsoleMessage].
+ void onConsoleMessage(ConsoleMessage consoleMessage) {
+
+ }
+
+ ///Give the host application a chance to take control when a URL is about to be loaded in the current WebView.
+ ///
+ ///**NOTE**: In order to be able to listen this event, you need to set `useShouldOverrideUrlLoading` option to `true`.
+ void shouldOverrideUrlLoading(String url) {
+
+ }
+
+ ///Event fires when the [InAppBrowser] webview loads a resource.
+ ///
+ ///**NOTE**: In order to be able to listen this event, you need to set `useOnLoadResource` option to `true`.
+ ///
+ ///**NOTE only for iOS**: In some cases, the [response.data] of a [response] with `text/assets` encoding could be empty.
+ void onLoadResource(WebResourceResponse response, WebResourceRequest request) {
+
+ }
+
void _throwIsAlreadyOpened({String message = ''}) {
if (this.isOpened()) {
throw Exception(['Error: ${ (message.isEmpty) ? '' : message + ' '}The browser is already opened.']);
@@ -639,7 +388,7 @@ class ChromeSafariBrowser {
InAppBrowser browserFallback;
bool _isOpened = false;
- ///Initialize the [ChromeSafariBrowser] instance with a [InAppBrowser] fallback instance or `null`.
+ ///Initialize the [ChromeSafariBrowser] instance with an [InAppBrowser] fallback instance or `null`.
ChromeSafariBrowser (bf) {
uuid = _uuidGenerator.v4();
browserFallback = bf;
@@ -664,7 +413,7 @@ class ChromeSafariBrowser {
}
}
- ///Opens an [url] in a new [ChromeSafariBrowser] instance or the system browser.
+ ///Opens an [url] in a new [ChromeSafariBrowser] instance.
///
///- [url]: The [url] to load. Call [encodeUriComponent()] on this if the [url] contains Unicode characters.
///
@@ -692,6 +441,7 @@ class ChromeSafariBrowser {
///- __presentationStyle__: Set the custom modal presentation style when presenting the WebView. The default value is `0 //fullscreen`. See [UIModalPresentationStyle](https://developer.apple.com/documentation/uikit/uimodalpresentationstyle) for all the available styles.
///- __transitionStyle__: Set to the custom transition style when presenting the WebView. The default value is `0 //crossDissolve`. See [UIModalTransitionStyle](https://developer.apple.com/documentation/uikit/uimodaltransitionStyle) for all the available styles.
Future open(String url, {Map options = const {}, Map headersFallback = const {}, Map optionsFallback = const {}}) async {
+ assert(url != null);
this._throwIsAlreadyOpened(message: 'Cannot open $url!');
Map args = {};
args.putIfAbsent('uuid', () => uuid);
@@ -735,4 +485,606 @@ class ChromeSafariBrowser {
throw Exception(['Error: ${ (message.isEmpty) ? '' : message + ' '}The browser is not opened.']);
}
}
+}
+
+typedef void onWebViewCreatedCallback(InAppWebViewController controller);
+typedef void onWebViewLoadStartCallback(InAppWebViewController controller, String url);
+typedef void onWebViewLoadStopCallback(InAppWebViewController controller, String url);
+typedef void onWebViewLoadErrorCallback(InAppWebViewController controller, String url, int code, String message);
+typedef void onWebViewProgressChangedCallback(InAppWebViewController controller, int progress);
+typedef void onWebViewConsoleMessageCallback(InAppWebViewController controller, ConsoleMessage consoleMessage);
+typedef void shouldOverrideUrlLoadingCallback(InAppWebViewController controller, String url);
+typedef void onWebViewLoadResourceCallback(InAppWebViewController controller, WebResourceResponse response, WebResourceRequest request);
+
+///InAppWebView Widget class.
+///
+///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree.
+///
+///All platforms support these options:
+/// - __useShouldOverrideUrlLoading__: Set to `true` to be able to listen at the [InAppWebView.shouldOverrideUrlLoading()] event. The default value is `false`.
+/// - __useOnLoadResource__: Set to `true` to be able to listen at the [InAppWebView.onLoadResource()] event. The default value is `false`.
+/// - __clearCache__: Set to `true` to have all the browser's cache cleared before the new window is opened. The default value is `false`.
+/// - __userAgent___: Set the custom WebView's user-agent.
+/// - __javaScriptEnabled__: Set to `true` to enable JavaScript. The default value is `true`.
+/// - __javaScriptCanOpenWindowsAutomatically__: Set to `true` to allow JavaScript open windows without user interaction. The default value is `false`.
+/// - __mediaPlaybackRequiresUserGesture__: Set to `true` to prevent HTML5 audio or video from autoplaying. The default value is `true`.
+///
+/// **Android** supports these additional options:
+///
+/// - __clearSessionCache__: Set to `true` to have the session cookie cache cleared before the new window is opened.
+/// - __builtInZoomControls__: Set to `true` if the WebView should use its built-in zoom mechanisms. The default value is `false`.
+/// - __supportZoom__: Set to `false` if the WebView should not support zooming using its on-screen zoom controls and gestures. The default value is `true`.
+/// - __databaseEnabled__: Set to `true` if you want the database storage API is enabled. The default value is `false`.
+/// - __domStorageEnabled__: Set to `true` if you want the DOM storage API is enabled. The default value is `false`.
+/// - __useWideViewPort__: Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport. When the value of the setting is false, the layout width is always set to the width of the WebView control in device-independent (CSS) pixels. When the value is true and the page contains the viewport meta tag, the value of the width specified in the tag is used. If the page does not contain the tag or does not provide a width, then a wide viewport will be used. The default value is `true`.
+/// - __safeBrowsingEnabled__: Set to `true` if you want the Safe Browsing is enabled. Safe Browsing allows WebView to protect against malware and phishing attacks by verifying the links. The default value is `true`.
+///
+/// **iOS** supports these additional options:
+///
+/// - __disallowOverScroll__: Set to `true` to disable the bouncing of the WebView when the scrolling has reached an edge of the content. The default value is `false`.
+/// - __enableViewportScale__: Set to `true` to allow a viewport meta tag to either disable or restrict the range of user scaling. The default value is `false`.
+/// - __suppressesIncrementalRendering__: Set to `true` if you want the WebView suppresses content rendering until it is fully loaded into memory.. The default value is `false`.
+/// - __allowsAirPlayForMediaPlayback__: Set to `true` to allow AirPlay. The default value is `true`.
+/// - __allowsBackForwardNavigationGestures__: Set to `true` to allow the horizontal swipe gestures trigger back-forward list navigations. The default value is `true`.
+/// - __allowsLinkPreview__: Set to `true` to allow that pressing on a link displays a preview of the destination for the link. The default value is `true`.
+/// - __ignoresViewportScaleLimits__: Set to `true` if you want that the WebView should always allow scaling of the webpage, regardless of the author's intent. The ignoresViewportScaleLimits property overrides the `user-scalable` HTML property in a webpage. The default value is `false`.
+/// - __allowsInlineMediaPlayback__: Set to `true` to allow HTML5 media playback to appear inline within the screen layout, using browser-supplied controls rather than native controls. For this to work, add the `webkit-playsinline` attribute to any `