Commit da99de05 authored by pichillilorenzo's avatar pichillilorenzo

fix #98, fix #93, fix #80

parent 76ffe41d
This diff is collapsed.
## 1.2.0
- Merge "Adds a transparentBackground option for iOS and Android" [#86](https://github.com/pichillilorenzo/flutter_inappbrowser/pull/86) (thanks to [matthewlloyd](https://github.com/matthewlloyd))
- Merge "The 'open' method requires an options dictionary" [#87](https://github.com/pichillilorenzo/flutter_inappbrowser/pull/87) (thanks to [matthewlloyd](https://github.com/matthewlloyd))
- Merge "iOS: Call setNeedsLayout() in scrollViewDidScroll()" [#88](https://github.com/pichillilorenzo/flutter_inappbrowser/pull/88) (thanks to [matthewlloyd](https://github.com/matthewlloyd))
- Fixed "java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread." [#98](https://github.com/pichillilorenzo/flutter_inappbrowser/issues/98) (thanks to [DreamBuddy](https://github.com/DreamBuddy))
- Fixed "app force close/crash when enabling zoom and repeatedly changing orientation and zoomin zoomout" [#93](https://github.com/pichillilorenzo/flutter_inappbrowser/issues/93)
- Added `displayZoomControls` webview option for Android
- Fixed "Compatibility with other plugins" [#80](https://github.com/pichillilorenzo/flutter_inappbrowser/issues/80)
## 1.1.3 ## 1.1.3
- Merge "Add null checks around calls to InAppWebView callbacks" [#85](https://github.com/pichillilorenzo/flutter_inappbrowser/pull/85) (thanks to [matthewlloyd](https://github.com/matthewlloyd)) - Merge "Add null checks around calls to InAppWebView callbacks" [#85](https://github.com/pichillilorenzo/flutter_inappbrowser/pull/85) (thanks to [matthewlloyd](https://github.com/matthewlloyd))
......
...@@ -246,6 +246,7 @@ All platforms support: ...@@ -246,6 +246,7 @@ All platforms support:
- __clearSessionCache__: Set to `true` to have the session cookie cache cleared before the new window is opened. - __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`. - __builtInZoomControls__: Set to `true` if the WebView should use its built-in zoom mechanisms. The default value is `false`.
- __displayZoomControls__: Set to `true` if the WebView should display on-screen zoom controls when using the 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`. - __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`. - __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`. - __domStorageEnabled__: Set to `true` if you want the DOM storage API is enabled. The default value is `false`.
...@@ -819,6 +820,7 @@ Opens an `url` in a new `InAppBrowser` instance. ...@@ -819,6 +820,7 @@ Opens an `url` in a new `InAppBrowser` instance.
- __closeOnCannotGoBack__: Set to `false` to not close the InAppBrowser when the user click on the back button and the WebView cannot go back to the history. The default value is `true`. - __closeOnCannotGoBack__: Set to `false` to not close the InAppBrowser when the user click on the back button and the WebView cannot go back to the history. The default value is `true`.
- __clearSessionCache__: Set to `true` to have the session cookie cache cleared before the new window is opened. - __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`. - __builtInZoomControls__: Set to `true` if the WebView should use its built-in zoom mechanisms. The default value is `false`.
- __displayZoomControls__: Set to `true` if the WebView should display on-screen zoom controls when using the 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`. - __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`. - __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`. - __domStorageEnabled__: Set to `true` if you want the DOM storage API is enabled. The default value is `false`.
......
...@@ -30,13 +30,11 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { ...@@ -30,13 +30,11 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
public InAppWebView webView; public InAppWebView webView;
public MethodChannel channel; public MethodChannel channel;
public final Registrar registrar; public final Registrar registrar;
public final Context context;
public FlutterWebView(Registrar registrar, int id, HashMap<String, Object> params) { public FlutterWebView(Registrar registrar, int id, HashMap<String, Object> params) {
this.registrar = registrar; this.registrar = registrar;
this.activity = registrar.activity(); this.activity = registrar.activity();
this.context = registrar.context();
String initialUrl = (String) params.get("initialUrl"); String initialUrl = (String) params.get("initialUrl");
String initialFile = (String) params.get("initialFile"); String initialFile = (String) params.get("initialFile");
...@@ -47,7 +45,7 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { ...@@ -47,7 +45,7 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
InAppWebViewOptions options = new InAppWebViewOptions(); InAppWebViewOptions options = new InAppWebViewOptions();
options.parse(initialOptions); options.parse(initialOptions);
webView = new InAppWebView(context, this, id, options); webView = new InAppWebView(registrar, this, id, options);
webView.prepare(); webView.prepare();
channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappwebview_" + id); channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappwebview_" + id);
......
package com.pichillilorenzo.flutter_inappbrowser; package com.pichillilorenzo.flutter_inappbrowser;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import java.util.HashMap; import java.util.HashMap;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry.Registrar; import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.plugin.common.StandardMessageCodec; import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.platform.PlatformView; import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory; import io.flutter.plugin.platform.PlatformViewFactory;
public class FlutterWebViewFactory extends PlatformViewFactory { public class FlutterWebViewFactory extends PlatformViewFactory {
private final BinaryMessenger messenger;
private final Registrar registrar; private final Registrar registrar;
private final Activity activity;
public FlutterWebViewFactory(Registrar registrar, Activity activity) { public FlutterWebViewFactory(Registrar registrar) {
super(StandardMessageCodec.INSTANCE); super(StandardMessageCodec.INSTANCE);
this.registrar = registrar; this.registrar = registrar;
this.messenger = registrar.messenger();
this.activity = activity;
} }
@Override @Override
......
package com.pichillilorenzo.flutter_inappbrowser; package com.pichillilorenzo.flutter_inappbrowser;
import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
...@@ -9,6 +10,7 @@ import android.graphics.drawable.ColorDrawable; ...@@ -9,6 +10,7 @@ import android.graphics.drawable.ColorDrawable;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
...@@ -25,6 +27,8 @@ import java.io.IOException; ...@@ -25,6 +27,8 @@ import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import io.flutter.app.FlutterActivity;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
public class InAppBrowserActivity extends AppCompatActivity { public class InAppBrowserActivity extends AppCompatActivity {
...@@ -39,6 +43,7 @@ public class InAppBrowserActivity extends AppCompatActivity { ...@@ -39,6 +43,7 @@ public class InAppBrowserActivity extends AppCompatActivity {
public Map<String, String> headers; public Map<String, String> headers;
public ProgressBar progressBar; public ProgressBar progressBar;
public boolean isHidden = false; public boolean isHidden = false;
public String fromActivity;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
...@@ -51,6 +56,7 @@ public class InAppBrowserActivity extends AppCompatActivity { ...@@ -51,6 +56,7 @@ public class InAppBrowserActivity extends AppCompatActivity {
Bundle b = getIntent().getExtras(); Bundle b = getIntent().getExtras();
uuid = b.getString("uuid"); uuid = b.getString("uuid");
fromActivity = b.getString("fromActivity");
HashMap<String, Object> optionsMap = (HashMap<String, Object>) b.getSerializable("options"); HashMap<String, Object> optionsMap = (HashMap<String, Object>) b.getSerializable("options");
...@@ -247,7 +253,7 @@ public class InAppBrowserActivity extends AppCompatActivity { ...@@ -247,7 +253,7 @@ public class InAppBrowserActivity extends AppCompatActivity {
if (canGoBack()) if (canGoBack())
goBack(); goBack();
else if (options.closeOnCannotGoBack) else if (options.closeOnCannotGoBack)
InAppBrowserFlutterPlugin.close(uuid, null); InAppBrowserFlutterPlugin.close(this, uuid, null);
return true; return true;
} }
return super.onKeyDown(keyCode, event); return super.onKeyDown(keyCode, event);
...@@ -297,15 +303,20 @@ public class InAppBrowserActivity extends AppCompatActivity { ...@@ -297,15 +303,20 @@ public class InAppBrowserActivity extends AppCompatActivity {
} }
public void hide() { public void hide() {
isHidden = true; try {
Intent openActivity = new Intent(this, InAppBrowserFlutterPlugin.registrar.activity().getClass()); isHidden = true;
openActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); Intent openActivity = new Intent(this, Class.forName(fromActivity));
startActivityIfNeeded(openActivity, 0); openActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivityIfNeeded(openActivity, 0);
} catch (ClassNotFoundException e) {
e.printStackTrace();
Log.d(LOG_TAG, e.getMessage());
}
} }
public void show() { public void show() {
isHidden = false; isHidden = false;
Intent openActivity = new Intent(InAppBrowserFlutterPlugin.registrar.activity(), InAppBrowserActivity.class); Intent openActivity = new Intent(this, InAppBrowserActivity.class);
openActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); openActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivityIfNeeded(openActivity, 0); startActivityIfNeeded(openActivity, 0);
} }
...@@ -341,7 +352,7 @@ public class InAppBrowserActivity extends AppCompatActivity { ...@@ -341,7 +352,7 @@ public class InAppBrowserActivity extends AppCompatActivity {
} }
public void closeButtonClicked(MenuItem item) { public void closeButtonClicked(MenuItem item) {
InAppBrowserFlutterPlugin.close(uuid, null); InAppBrowserFlutterPlugin.close(this, uuid, null);
} }
public byte[] takeScreenshot() { public byte[] takeScreenshot() {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
package com.pichillilorenzo.flutter_inappbrowser; package com.pichillilorenzo.flutter_inappbrowser;
import android.app.Activity; import android.app.Activity;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
...@@ -39,13 +40,12 @@ import com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs.CustomTabActivi ...@@ -39,13 +40,12 @@ import com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs.CustomTabActivi
import java.io.IOException; import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
...@@ -57,17 +57,15 @@ import io.flutter.plugin.common.PluginRegistry.Registrar; ...@@ -57,17 +57,15 @@ import io.flutter.plugin.common.PluginRegistry.Registrar;
*/ */
public class InAppBrowserFlutterPlugin implements MethodCallHandler { public class InAppBrowserFlutterPlugin implements MethodCallHandler {
public static Registrar registrar; public Registrar registrar;
public Activity activity;
public static MethodChannel channel; public static MethodChannel channel;
public static Map<String, InAppBrowserActivity> webViewActivities = new HashMap<>(); public static Map<String, InAppBrowserActivity> webViewActivities = new HashMap<>();
public static Map<String, ChromeCustomTabsActivity> chromeCustomTabsActivities = new HashMap<>(); public static Map<String, ChromeCustomTabsActivity> chromeCustomTabsActivities = new HashMap<>();
protected static final String LOG_TAG = "IABFlutterPlugin"; protected static final String LOG_TAG = "IABFlutterPlugin";
public InAppBrowserFlutterPlugin(Registrar r, Activity activity) { public InAppBrowserFlutterPlugin(Registrar r) {
registrar = r; registrar = r;
this.activity = activity;
channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser"); channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser");
} }
...@@ -76,23 +74,26 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -76,23 +74,26 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
*/ */
public static void registerWith(Registrar registrar) { public static void registerWith(Registrar registrar) {
Activity activity = registrar.activity(); Activity activity = registrar.activity();
// registrar.activity() may return null because of Flutter's background execution feature
final MethodChannel channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser"); // described here: https://medium.com/flutter-io/executing-dart-in-the-background-with-flutter-plugins-and-geofencing-2b3e40a1a124
channel.setMethodCallHandler(new InAppBrowserFlutterPlugin(registrar, activity)); if (activity != null) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser");
new MyCookieManager(registrar); channel.setMethodCallHandler(new InAppBrowserFlutterPlugin(registrar));
registrar new MyCookieManager(registrar);
.platformViewRegistry()
.registerViewFactory( registrar
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(registrar, activity)); .platformViewRegistry()
.registerViewFactory(
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(registrar));
}
} }
@Override @Override
public void onMethodCall(final MethodCall call, final Result result) { public void onMethodCall(final MethodCall call, final Result result) {
String source; String source;
String jsWrapper;
String urlFile; String urlFile;
final Activity activity = registrar.activity();
final String uuid = (String) call.argument("uuid"); final String uuid = (String) call.argument("uuid");
switch (call.method) { switch (call.method) {
...@@ -107,7 +108,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -107,7 +108,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
Log.d(LOG_TAG, "use Chrome Custom Tabs = " + useChromeSafariBrowser); Log.d(LOG_TAG, "use Chrome Custom Tabs = " + useChromeSafariBrowser);
this.activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
...@@ -119,7 +120,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -119,7 +120,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
final HashMap<String, Object> optionsFallback = (HashMap<String, Object>) call.argument("optionsFallback"); final HashMap<String, Object> optionsFallback = (HashMap<String, Object>) call.argument("optionsFallback");
open(uuid, uuidFallback, url_final, options, headers, true, optionsFallback, result); open(activity, uuid, uuidFallback, url_final, options, headers, true, optionsFallback, result);
} else { } else {
String url = url_final; String url = url_final;
...@@ -142,7 +143,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -142,7 +143,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
// SYSTEM // SYSTEM
if (openWithSystemBrowser) { if (openWithSystemBrowser) {
Log.d(LOG_TAG, "in system"); Log.d(LOG_TAG, "in system");
openExternal(url, result); openExternal(activity, url, result);
} else { } else {
//Load the dialer //Load the dialer
if (url.startsWith(WebView.SCHEME_TEL)) { if (url.startsWith(WebView.SCHEME_TEL)) {
...@@ -158,7 +159,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -158,7 +159,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
// load in InAppBrowserFlutterPlugin // load in InAppBrowserFlutterPlugin
else { else {
Log.d(LOG_TAG, "loading in InAppBrowserFlutterPlugin"); Log.d(LOG_TAG, "loading in InAppBrowserFlutterPlugin");
open(uuid, null, url, options, headers, false, null, result); open(activity, uuid, null, url, options, headers, false, null, result);
} }
} }
} }
...@@ -166,7 +167,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -166,7 +167,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
}); });
} }
else { else {
this.activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options"); HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
...@@ -174,7 +175,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -174,7 +175,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
String mimeType = call.argument("mimeType").toString(); String mimeType = call.argument("mimeType").toString();
String encoding = call.argument("encoding").toString(); String encoding = call.argument("encoding").toString();
String baseUrl = call.argument("baseUrl").toString(); String baseUrl = call.argument("baseUrl").toString();
openData(uuid, options, data, mimeType, encoding, baseUrl); openData(activity, uuid, options, data, mimeType, encoding, baseUrl);
result.success(true); result.success(true);
} }
}); });
...@@ -208,7 +209,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -208,7 +209,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
loadFile(uuid, call.argument("url").toString(), (Map<String, String>) call.argument("headers"), result); loadFile(uuid, call.argument("url").toString(), (Map<String, String>) call.argument("headers"), result);
break; break;
case "close": case "close":
close(uuid, result); close(activity, uuid, result);
break; break;
case "injectScriptCode": case "injectScriptCode":
source = call.argument("source").toString(); source = call.argument("source").toString();
...@@ -349,7 +350,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -349,7 +350,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
* @param result * @param result
* @return "" if ok, or error message. * @return "" if ok, or error message.
*/ */
public void openExternal(String url, Result result) { public void openExternal(Activity activity, String url, Result result) {
try { try {
Intent intent; Intent intent;
intent = new Intent(Intent.ACTION_VIEW); intent = new Intent(Intent.ACTION_VIEW);
...@@ -363,7 +364,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -363,7 +364,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
} }
intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName()); intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName());
// CB-10795: Avoid circular loops by preventing it from opening in the current app // CB-10795: Avoid circular loops by preventing it from opening in the current app
this.openExternalExcludeCurrentApp(intent); this.openExternalExcludeCurrentApp(activity, intent);
result.success(true); result.success(true);
// not catching FileUriExposedException explicitly because buildtools<24 doesn't know about it // not catching FileUriExposedException explicitly because buildtools<24 doesn't know about it
} catch (java.lang.RuntimeException e) { } catch (java.lang.RuntimeException e) {
...@@ -376,7 +377,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -376,7 +377,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
* Opens the intent, providing a chooser that excludes the current app to avoid * Opens the intent, providing a chooser that excludes the current app to avoid
* circular loops. * circular loops.
*/ */
private void openExternalExcludeCurrentApp(Intent intent) { private void openExternalExcludeCurrentApp(Activity activity, Intent intent) {
String currentPackage = activity.getPackageName(); String currentPackage = activity.getPackageName();
boolean hasCurrentPackage = false; boolean hasCurrentPackage = false;
PackageManager pm = activity.getPackageManager(); PackageManager pm = activity.getPackageManager();
...@@ -408,10 +409,11 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -408,10 +409,11 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
} }
} }
public void open(String uuid, String uuidFallback, String url, HashMap<String, Object> options, Map<String, String> headers, boolean useChromeSafariBrowser, HashMap<String, Object> optionsFallback, Result result) { public void open(Activity activity, String uuid, String uuidFallback, String url, HashMap<String, Object> options, Map<String, String> headers, boolean useChromeSafariBrowser, HashMap<String, Object> optionsFallback, Result result) {
Intent intent = null; Intent intent = null;
Bundle extras = new Bundle(); Bundle extras = new Bundle();
extras.putString("fromActivity", activity.getClass().getName());
extras.putString("url", url); extras.putString("url", url);
extras.putBoolean("isData", false); extras.putBoolean("isData", false);
extras.putString("uuid", uuid); extras.putString("uuid", uuid);
...@@ -451,7 +453,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -451,7 +453,7 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
result.error(LOG_TAG, "No WebView fallback declared.", null); result.error(LOG_TAG, "No WebView fallback declared.", null);
} }
public void openData(String uuid, HashMap<String, Object> options, String data, String mimeType, String encoding, String baseUrl) { public void openData(Activity activity, String uuid, HashMap<String, Object> options, String data, String mimeType, String encoding, String baseUrl) {
Intent intent = new Intent(activity, InAppBrowserActivity.class); Intent intent = new Intent(activity, InAppBrowserActivity.class);
Bundle extras = new Bundle(); Bundle extras = new Bundle();
...@@ -597,10 +599,10 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler { ...@@ -597,10 +599,10 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
return false; return false;
} }
public static void close(final String uuid, final Result result) { public static void close(Activity activity, final String uuid, final Result result) {
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid); final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null) { if (inAppBrowserActivity != null) {
registrar.activity().runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
......
...@@ -32,15 +32,15 @@ import java.util.List; ...@@ -32,15 +32,15 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry;
import okhttp3.Cache; import okhttp3.Cache;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import static com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin.registrar;
public class InAppWebView extends WebView { public class InAppWebView extends WebView {
static final String LOG_TAG = "InAppWebView"; static final String LOG_TAG = "InAppWebView";
public PluginRegistry.Registrar registrar;
public InAppBrowserActivity inAppBrowserActivity; public InAppBrowserActivity inAppBrowserActivity;
public FlutterWebView flutterWebView; public FlutterWebView flutterWebView;
int id; int id;
...@@ -91,8 +91,9 @@ public class InAppWebView extends WebView { ...@@ -91,8 +91,9 @@ public class InAppWebView extends WebView {
super(context, attrs, defaultStyle); super(context, attrs, defaultStyle);
} }
public InAppWebView(Context context, Object obj, int id, InAppWebViewOptions options) { public InAppWebView(PluginRegistry.Registrar registrar, Object obj, int id, InAppWebViewOptions options) {
super(context); super(registrar.activeContext());
this.registrar = registrar;
if (obj instanceof InAppBrowserActivity) if (obj instanceof InAppBrowserActivity)
this.inAppBrowserActivity = (InAppBrowserActivity) obj; this.inAppBrowserActivity = (InAppBrowserActivity) obj;
else if (obj instanceof FlutterWebView) else if (obj instanceof FlutterWebView)
...@@ -160,6 +161,8 @@ public class InAppWebView extends WebView { ...@@ -160,6 +161,8 @@ public class InAppWebView extends WebView {
settings.setJavaScriptEnabled(options.javaScriptEnabled); settings.setJavaScriptEnabled(options.javaScriptEnabled);
settings.setJavaScriptCanOpenWindowsAutomatically(options.javaScriptCanOpenWindowsAutomatically); settings.setJavaScriptCanOpenWindowsAutomatically(options.javaScriptCanOpenWindowsAutomatically);
settings.setBuiltInZoomControls(options.builtInZoomControls); settings.setBuiltInZoomControls(options.builtInZoomControls);
settings.setDisplayZoomControls(options.displayZoomControls);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
settings.setSafeBrowsingEnabled(options.safeBrowsingEnabled); settings.setSafeBrowsingEnabled(options.safeBrowsingEnabled);
...@@ -312,6 +315,9 @@ public class InAppWebView extends WebView { ...@@ -312,6 +315,9 @@ public class InAppWebView extends WebView {
if (newOptionsMap.get("builtInZoomControls") != null && options.builtInZoomControls != newOptions.builtInZoomControls) if (newOptionsMap.get("builtInZoomControls") != null && options.builtInZoomControls != newOptions.builtInZoomControls)
settings.setBuiltInZoomControls(newOptions.builtInZoomControls); settings.setBuiltInZoomControls(newOptions.builtInZoomControls);
if (newOptionsMap.get("displayZoomControls") != null && options.displayZoomControls != newOptions.displayZoomControls)
settings.setDisplayZoomControls(newOptions.displayZoomControls);
if (newOptionsMap.get("safeBrowsingEnabled") != null && options.safeBrowsingEnabled != newOptions.safeBrowsingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) if (newOptionsMap.get("safeBrowsingEnabled") != null && options.safeBrowsingEnabled != newOptions.safeBrowsingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
settings.setSafeBrowsingEnabled(newOptions.safeBrowsingEnabled); settings.setSafeBrowsingEnabled(newOptions.safeBrowsingEnabled);
...@@ -341,6 +347,14 @@ public class InAppWebView extends WebView { ...@@ -341,6 +347,14 @@ public class InAppWebView extends WebView {
if (newOptionsMap.get("textZoom") != null && options.textZoom != newOptions.textZoom) if (newOptionsMap.get("textZoom") != null && options.textZoom != newOptions.textZoom)
settings.setTextZoom(newOptions.textZoom); settings.setTextZoom(newOptions.textZoom);
if (newOptionsMap.get("transparentBackground") != null && options.transparentBackground != newOptions.transparentBackground) {
if (newOptions.transparentBackground) {
setBackgroundColor(Color.TRANSPARENT);
} else {
setBackgroundColor(Color.parseColor("#FFFFFF"));
}
}
options = newOptions; options = newOptions;
} }
......
...@@ -6,6 +6,9 @@ import android.net.Uri; ...@@ -6,6 +6,9 @@ import android.net.Uri;
import android.net.http.SslError; import android.net.http.SslError;
import android.os.Build; import android.os.Build;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import android.os.Handler;
import android.os.Looper;
import android.util.Log; import android.util.Log;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import android.webkit.CookieSyncManager; import android.webkit.CookieSyncManager;
...@@ -341,7 +344,7 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -341,7 +344,7 @@ public class InAppWebViewClient extends WebViewClient {
headersRequest.put(entry.getKey().toLowerCase(), value.toString()); headersRequest.put(entry.getKey().toLowerCase(), value.toString());
} }
Map<String, Object> obj = new HashMap<>(); final Map<String, Object> obj = new HashMap<>();
Map<String, Object> res = new HashMap<>(); Map<String, Object> res = new HashMap<>();
Map<String, Object> req = new HashMap<>(); Map<String, Object> req = new HashMap<>();
...@@ -365,7 +368,15 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -365,7 +368,15 @@ public class InAppWebViewClient extends WebViewClient {
obj.put("response", res); obj.put("response", res);
obj.put("request", req); obj.put("request", req);
getChannel().invokeMethod("onLoadResource", obj); // java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread.
// https://github.com/pichillilorenzo/flutter_inappbrowser/issues/98
final Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
getChannel().invokeMethod("onLoadResource", obj);
}
});
// this return is not working (it blocks some resources), so return null // this return is not working (it blocks some resources), so return null
// return new WebResourceResponse( // return new WebResourceResponse(
......
...@@ -17,6 +17,7 @@ public class InAppWebViewOptions extends Options { ...@@ -17,6 +17,7 @@ public class InAppWebViewOptions extends Options {
public boolean clearSessionCache = false; public boolean clearSessionCache = false;
public boolean builtInZoomControls = false; public boolean builtInZoomControls = false;
public boolean displayZoomControls = false;
public boolean supportZoom = true; public boolean supportZoom = true;
public boolean databaseEnabled = false; public boolean databaseEnabled = false;
public boolean domStorageEnabled = false; public boolean domStorageEnabled = false;
......
package com.pichillilorenzo.flutter_inappbrowser; package com.pichillilorenzo.flutter_inappbrowser;
import android.os.Build; import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log; import android.util.Log;
import android.webkit.JavascriptInterface; import android.webkit.JavascriptInterface;
...@@ -34,33 +36,42 @@ public class JavaScriptBridgeInterface { ...@@ -34,33 +36,42 @@ public class JavaScriptBridgeInterface {
@JavascriptInterface @JavascriptInterface
public void _callHandler(String handlerName, final String _callHandlerID, String args) { public void _callHandler(String handlerName, final String _callHandlerID, String args) {
Map<String, Object> obj = new HashMap<>(); final Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null) if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid); obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("handlerName", handlerName); obj.put("handlerName", handlerName);
obj.put("args", args); obj.put("args", args);
getChannel().invokeMethod("onCallJsHandler", obj, new MethodChannel.Result() { // java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread.
// https://github.com/pichillilorenzo/flutter_inappbrowser/issues/98
final Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override @Override
public void success(Object json) { public void run() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { getChannel().invokeMethod("onCallJsHandler", obj, new MethodChannel.Result() {
flutterWebView.webView.evaluateJavascript("window." + name + "[" + _callHandlerID + "](" + json + "); delete window." + name + "[" + _callHandlerID + "];", null); @Override
} public void success(Object json) {
else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
flutterWebView.webView.loadUrl("javascript:window." + name + "[" + _callHandlerID + "](" + json + "); delete window." + name + "[" + _callHandlerID + "];"); flutterWebView.webView.evaluateJavascript("window." + name + "[" + _callHandlerID + "](" + json + "); delete window." + name + "[" + _callHandlerID + "];", null);
} }
} else {
flutterWebView.webView.loadUrl("javascript:window." + name + "[" + _callHandlerID + "](" + json + "); delete window." + name + "[" + _callHandlerID + "];");
}
}
@Override @Override
public void error(String s, String s1, Object o) { public void error(String s, String s1, Object o) {
Log.d(LOG_TAG, "ERROR: " + s + " " + s1); Log.d(LOG_TAG, "ERROR: " + s + " " + s1);
} }
@Override @Override
public void notImplemented() { public void notImplemented() {
}
});
} }
}); });
} }
private MethodChannel getChannel() { private MethodChannel getChannel() {
......
...@@ -112,7 +112,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi ...@@ -112,7 +112,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
configuration.userContentController = WKUserContentController() configuration.userContentController = WKUserContentController()
configuration.preferences = WKPreferences() configuration.preferences = WKPreferences()
if (options?.transparentBackground)! { if (options?.transparentBackground)! {
isOpaque = false isOpaque = false
backgroundColor = UIColor.clear backgroundColor = UIColor.clear
...@@ -299,6 +299,18 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi ...@@ -299,6 +299,18 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
func setOptions(newOptions: InAppWebViewOptions, newOptionsMap: [String: Any]) { func setOptions(newOptions: InAppWebViewOptions, newOptionsMap: [String: Any]) {
if newOptionsMap["transparentBackground"] != nil && options?.transparentBackground != newOptions.transparentBackground {
if newOptions.transparentBackground {
isOpaque = false
backgroundColor = UIColor.clear
scrollView.backgroundColor = UIColor.clear
} else {
isOpaque = true
backgroundColor = nil
scrollView.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 1)
}
}
if newOptionsMap["disallowOverScroll"] != nil && options?.disallowOverScroll != newOptions.disallowOverScroll { if newOptionsMap["disallowOverScroll"] != nil && options?.disallowOverScroll != newOptions.disallowOverScroll {
if responds(to: #selector(getter: scrollView)) { if responds(to: #selector(getter: scrollView)) {
scrollView.bounces = !newOptions.disallowOverScroll scrollView.bounces = !newOptions.disallowOverScroll
......
...@@ -179,6 +179,7 @@ class InAppBrowser { ...@@ -179,6 +179,7 @@ class InAppBrowser {
/// - __closeOnCannotGoBack__: Set to `false` to not close the InAppBrowser when the user click on the back button and the WebView cannot go back to the history. The default value is `true`. /// - __closeOnCannotGoBack__: Set to `false` to not close the InAppBrowser when the user click on the back button and the WebView cannot go back to the history. The default value is `true`.
/// - __clearSessionCache__: Set to `true` to have the session cookie cache cleared before the new window is opened. /// - __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`. /// - __builtInZoomControls__: Set to `true` if the WebView should use its built-in zoom mechanisms. The default value is `false`.
/// - __displayZoomControls__: Set to `true` if the WebView should display on-screen zoom controls when using the 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`. /// - __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`. /// - __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`. /// - __domStorageEnabled__: Set to `true` if you want the DOM storage API is enabled. The default value is `false`.
...@@ -582,11 +583,13 @@ class InAppWebViewInitialData { ...@@ -582,11 +583,13 @@ class InAppWebViewInitialData {
/// - __javaScriptEnabled__: Set to `true` to enable JavaScript. The default value is `true`. /// - __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`. /// - __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`. /// - __mediaPlaybackRequiresUserGesture__: Set to `true` to prevent HTML5 audio or video from autoplaying. The default value is `true`.
/// - __transparentBackground__: Set to `true` to make the background of the WebView transparent. If your app has a dark theme, this can prevent a white flash on initialization. The default value is `false`.
/// ///
/// **Android** supports these additional options: /// **Android** supports these additional options:
/// ///
/// - __clearSessionCache__: Set to `true` to have the session cookie cache cleared before the new window is opened. /// - __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`. /// - __builtInZoomControls__: Set to `true` if the WebView should use its built-in zoom mechanisms. The default value is `false`.
/// - __displayZoomControls__: Set to `true` if the WebView should display on-screen zoom controls when using the 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`. /// - __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`. /// - __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`. /// - __domStorageEnabled__: Set to `true` if you want the DOM storage API is enabled. The default value is `false`.
...@@ -652,6 +655,13 @@ class InAppWebView extends StatefulWidget { ...@@ -652,6 +655,13 @@ class InAppWebView extends StatefulWidget {
final Map<String, String> initialHeaders; final Map<String, String> initialHeaders;
///Initial options that will be used. ///Initial options that will be used.
final Map<String, dynamic> initialOptions; final Map<String, dynamic> initialOptions;
/// `gestureRecognizers` specifies which gestures should be consumed by the web view.
/// It is possible for other gesture recognizers to be competing with the web view on pointer
/// events, e.g if the web view is inside a [ListView] the [ListView] will want to handle
/// vertical drags. The web view will claim gestures that are recognized by any of the
/// recognizers on this list.
/// When `gestureRecognizers` is empty or null, the web view will only handle pointer events for gestures that
/// were not claimed by any other gesture recognizer.
final Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers; final Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers;
const InAppWebView({ const InAppWebView({
...@@ -695,6 +705,7 @@ class _InAppWebViewState extends State<InAppWebView> { ...@@ -695,6 +705,7 @@ class _InAppWebViewState extends State<InAppWebView> {
if (defaultTargetPlatform == TargetPlatform.android) { if (defaultTargetPlatform == TargetPlatform.android) {
return GestureDetector( return GestureDetector(
onLongPress: () {}, onLongPress: () {},
excludeFromSemantics: true,
child: AndroidView( child: AndroidView(
viewType: 'com.pichillilorenzo/flutter_inappwebview', viewType: 'com.pichillilorenzo/flutter_inappwebview',
onPlatformViewCreated: _onPlatformViewCreated, onPlatformViewCreated: _onPlatformViewCreated,
......
name: flutter_inappbrowser name: flutter_inappbrowser
description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window (inspired by the popular cordova-plugin-inappbrowser). description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window (inspired by the popular cordova-plugin-inappbrowser).
version: 1.1.3 version: 1.2.0
author: Lorenzo Pichilli <pichillilorenzo@gmail.com> author: Lorenzo Pichilli <pichillilorenzo@gmail.com>
homepage: https://github.com/pichillilorenzo/flutter_inappbrowser homepage: https://github.com/pichillilorenzo/flutter_inappbrowser
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment