Commit bc47fd24 authored by pichillilorenzo's avatar pichillilorenzo

added the ability to create multiple instances of browsers

parent 5db9575a
This diff is collapsed.
## 0.1.0
## 0.2.0
- added support of Chrome CustomTabs for android
- added support of SFSafariViewController for iOS
- added the ability to create multiple instances of browsers
## 0.1.1
- updated/added new methods
- updated UI of android/iOS in-app browser
......
......@@ -30,6 +30,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
if (activity.options.useShouldOverrideUrlLoading) {
Map<String, Object> obj = new HashMap<>();
obj.put("uuid", activity.uuid);
obj.put("url", url);
InAppBrowserFlutterPlugin.channel.invokeMethod("shouldOverrideUrlLoading", obj);
return true;
......@@ -110,6 +111,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
}
Map<String, Object> obj = new HashMap<>();
obj.put("uuid", activity.uuid);
obj.put("url", url);
InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadStart", obj);
}
......@@ -133,6 +135,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
view.requestFocus();
Map<String, Object> obj = new HashMap<>();
obj.put("uuid", activity.uuid);
obj.put("url", url);
InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadStop", obj);
}
......@@ -143,6 +146,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
activity.isLoading = false;
Map<String, Object> obj = new HashMap<>();
obj.put("uuid", activity.uuid);
obj.put("url", failingUrl);
obj.put("code", errorCode);
obj.put("message", description);
......@@ -153,6 +157,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
super.onReceivedSslError(view, handler, error);
Map<String, Object> obj = new HashMap<>();
obj.put("uuid", activity.uuid);
obj.put("url", error.getUrl());
obj.put("code", error.getPrimaryError());
String message;
......
......@@ -7,7 +7,6 @@ import android.os.Build;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
......@@ -27,6 +26,7 @@ import io.flutter.plugin.common.MethodChannel;
public class WebViewActivity extends AppCompatActivity {
String uuid;
WebView webView;
ActionBar actionBar;
InAppBrowserWebViewClient inAppBrowserWebViewClient;
......@@ -47,6 +47,7 @@ public class WebViewActivity extends AppCompatActivity {
webView = findViewById(R.id.webView);
Bundle b = getIntent().getExtras();
uuid = b.getString("uuid");
String url = b.getString("url");
options = new InAppBrowserOptions();
......@@ -54,7 +55,7 @@ public class WebViewActivity extends AppCompatActivity {
headers = (HashMap<String, String>) b.getSerializable("headers");
InAppBrowserFlutterPlugin.webViewActivity = this;
InAppBrowserFlutterPlugin.webViewActivities.put(uuid, this);
actionBar = getSupportActionBar();
......@@ -243,7 +244,7 @@ public class WebViewActivity extends AppCompatActivity {
if (canGoBack())
goBack();
else if (options.closeOnCannotGoBack)
InAppBrowserFlutterPlugin.close();
InAppBrowserFlutterPlugin.close(uuid);
return true;
}
return super.onKeyDown(keyCode, event);
......@@ -340,7 +341,7 @@ public class WebViewActivity extends AppCompatActivity {
}
public void closeButtonClicked(MenuItem item) {
InAppBrowserFlutterPlugin.close();
InAppBrowserFlutterPlugin.close(uuid);
}
}
......@@ -6,6 +6,7 @@ import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.support.customtabs.CustomTabsIntent;
import android.util.Log;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserOptions;
......@@ -16,6 +17,9 @@ import java.util.Map;
public class ChromeCustomTabsActivity extends Activity {
protected static final String LOG_TAG = "CustomTabsActivity";
String uuid;
String uuidFallback;
CustomTabsIntent.Builder builder;
ChromeCustomTabsOptions options;
Map<String, String> headersFallback;
......@@ -30,6 +34,8 @@ public class ChromeCustomTabsActivity extends Activity {
setContentView(R.layout.chrome_custom_tabs_layout);
Bundle b = getIntent().getExtras();
uuid = b.getString("uuid");
uuidFallback = b.getString("uuidFallback");
String url = b.getString("url");
options = new ChromeCustomTabsOptions();
......@@ -40,8 +46,9 @@ public class ChromeCustomTabsActivity extends Activity {
optionsFallback = new InAppBrowserOptions();
optionsFallback.parse((HashMap<String, Object>) b.getSerializable("optionsFallback"));
customTabActivityHelper = new CustomTabActivityHelper();
InAppBrowserFlutterPlugin.chromeCustomTabsActivities.put(uuid, this);
customTabActivityHelper = new CustomTabActivityHelper();
builder = new CustomTabsIntent.Builder();
prepareCustomTabs();
......@@ -52,13 +59,20 @@ public class ChromeCustomTabsActivity extends Activity {
new CustomTabActivityHelper.CustomTabFallback() {
@Override
public void openUri(Activity activity, Uri uri) {
InAppBrowserFlutterPlugin.open(uri.toString(), optionsFallback, headersFallback, false, null);
if (!uuidFallback.isEmpty())
InAppBrowserFlutterPlugin.open(uuidFallback, null, uri.toString(), optionsFallback, headersFallback, false, null);
else {
Log.d(LOG_TAG, "No WebView fallback declared.");
activity.finish();
}
}
});
if (chromeCustomTabsOpened) {
InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserOpened", null);
InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserLoaded", null);
Map<String, Object> obj = new HashMap<>();
obj.put("uuid", uuid);
InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserOpened", obj);
InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserLoaded", obj);
}
}
......@@ -93,7 +107,9 @@ public class ChromeCustomTabsActivity extends Activity {
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CHROME_CUSTOM_TAB_REQUEST_CODE) {
finish();
InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserClosed", null);
Map<String, Object> obj = new HashMap<>();
obj.put("uuid", uuid);
InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserClosed", obj);
}
}
}
......@@ -6,13 +6,17 @@ class MyInAppBrowser extends InAppBrowser {
@override
Future onLoadStart(String url) async {
print("\n\nStarted $url\n\n");
print("\n\nStarted aaa $url\n\n");
inAppBrowserFallback2.open("https://www.google.com", options: {
"hidden": true
});
//print("\n\n ${await this.isHidden()} \n\n");
}
@override
Future onLoadStop(String url) async {
print("\n\nStopped $url\n\n");
print("\n\nStopped aaa $url\n\n");
inAppBrowserFallback2.show();
// print(await this.injectScriptCode("document.body.innerHTML"));
// print(await this.injectScriptCode("3"));
// print(await this.injectScriptCode("""
......@@ -61,7 +65,38 @@ class MyInAppBrowser extends InAppBrowser {
}
}
class MyInAppBrowser2 extends InAppBrowser {
@override
Future onLoadStart(String url) async {
print("\n\nStarted $url\n\n");
//print("\n\n ${await this.isHidden()} \n\n");
}
@override
Future onLoadStop(String url) async {
print("\n\nStopped $url\n\n");
}
@override
void onLoadError(String url, int code, String message) {
print("\n\nCan't load $url.. Error: $message\n\n");
}
@override
void onExit() {
print("\n\nBrowser closed!\n\n");
}
@override
void shouldOverrideUrlLoading(String url) {
print("\n\n override $url\n\n");
this.loadUrl(url);
}
}
MyInAppBrowser inAppBrowserFallback = new MyInAppBrowser();
MyInAppBrowser2 inAppBrowserFallback2 = new MyInAppBrowser2();
class MyChromeSafariBrowser extends ChromeSafariBrowser {
MyChromeSafariBrowser(browserFallback) : super(browserFallback);
......@@ -79,6 +114,7 @@ class MyChromeSafariBrowser extends ChromeSafariBrowser {
@override
void onClosed() {
print("ChromeSafari browser closed");
inAppBrowserFallback.open("https://flutter.io/");
}
}
......
......@@ -80,6 +80,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
var browserOptions: InAppBrowserOptions?
var initHeaders: [String: String]?
var isHidden = false
var uuid: String = ""
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
......@@ -323,7 +324,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
currentURL = nil
if (navigationDelegate != nil) {
navigationDelegate?.browserExit()
navigationDelegate?.browserExit(uuid: self.uuid)
}
weak var weakSelf = self
......@@ -419,7 +420,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
let url = navigationAction.request.url
if (url != nil && navigationAction.navigationType == .linkActivated && (browserOptions?.useShouldOverrideUrlLoading)!) {
navigationDelegate?.shouldOverrideUrlLoading(webView, url: url!)
navigationDelegate?.shouldOverrideUrlLoading(uuid: self.uuid, webView: webView, url: url!)
decisionHandler(.cancel)
return
}
......@@ -475,7 +476,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
spinner.startAnimating()
}
return (navigationDelegate?.onLoadStart(webView))!
return (navigationDelegate?.onLoadStart(uuid: self.uuid, webView: webView))!
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
......@@ -485,7 +486,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
backButton.isEnabled = webView.canGoBack
forwardButton.isEnabled = webView.canGoForward
spinner.stopAnimating()
navigationDelegate?.onLoadStop(webView)
navigationDelegate?.onLoadStop(uuid: self.uuid, webView: webView)
}
// func webView(_ webView: WKWebView,
......@@ -495,7 +496,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
// backButton.isEnabled = webView.canGoBack
// forwardButton.isEnabled = webView.canGoForward
// spinner.stopAnimating()
// navigationDelegate?.webView(webView, didFailLoadWithError: error)
// navigationDelegate?.webView(uuid: self.uuid, webView: webView, didFailLoadWithError: error)
// }
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
......@@ -503,6 +504,6 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
backButton.isEnabled = webView.canGoBack
forwardButton.isEnabled = webView.canGoForward
spinner.stopAnimating()
navigationDelegate?.onLoadError(webView, error: error)
navigationDelegate?.onLoadError(uuid: self.uuid, webView: webView, error: error)
}
}
......@@ -14,6 +14,7 @@ class SafariViewController: SFSafariViewController, SFSafariViewControllerDelega
weak var statusDelegate: SwiftFlutterPlugin?
var tmpWindow: UIWindow?
var safariOptions: SafariBrowserOptions?
var uuid: String = ""
override func viewWillAppear(_ animated: Bool) {
prepareSafariBrowser()
......@@ -37,7 +38,7 @@ class SafariViewController: SFSafariViewController, SFSafariViewControllerDelega
func close() {
if (statusDelegate != nil) {
statusDelegate?.safariExit()
statusDelegate?.safariExit(uuid: self.uuid)
}
dismiss(animated: true)
......@@ -55,7 +56,7 @@ class SafariViewController: SFSafariViewController, SFSafariViewControllerDelega
func safariViewController(_ controller: SFSafariViewController,
didCompleteInitialLoad didLoadSuccessfully: Bool) {
if didLoadSuccessfully {
statusDelegate?.onChromeSafariBrowserLoaded()
statusDelegate?.onChromeSafariBrowserLoaded(uuid: self.uuid)
}
else {
print("Cant load successfully the 'SafariViewController'.")
......
This diff is collapsed.
......@@ -20,25 +20,30 @@
*/
import 'dart:async';
import 'dart:collection';
import 'package:flutter/services.dart';
import 'package:uuid/uuid.dart';
typedef Future<dynamic> ListenerCallback(MethodCall call);
var uuidGenerator = new Uuid();
class _ChannelManager {
static const MethodChannel channel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser');
static final initialized = false;
static final listeners = <Function>[];
static final listeners = HashMap<String, ListenerCallback>();
static Future<dynamic> _handleMethod(MethodCall call) async {
for (var listener in listeners) {
listener(call);
}
String uuid = call.arguments["uuid"];
listeners[uuid](call);
return new Future.value("");
}
static void addListener (Function callback) {
static void addListener (String key, ListenerCallback callback) {
if (!initialized)
init();
listeners.add(callback);
listeners.putIfAbsent(key, () => callback);
}
static void init () {
......@@ -51,9 +56,12 @@ class _ChannelManager {
/// This class uses the native WebView of the platform.
class InAppBrowser {
String uuid;
///
InAppBrowser () {
_ChannelManager.addListener(_handleMethod);
uuid = uuidGenerator.v4();
_ChannelManager.addListener(uuid, _handleMethod);
}
Future<dynamic> _handleMethod(MethodCall call) async {
......@@ -144,6 +152,7 @@ class InAppBrowser {
/// - __spinner__: Set to `false` to hide the spinner when the WebView is loading a page. The default value is `true`.
Future<void> open(String url, {Map<String, String> headers = const {}, String target = "_self", Map<String, dynamic> options = const {}}) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => headers);
args.putIfAbsent('target', () => target);
......@@ -155,6 +164,7 @@ class InAppBrowser {
///Loads the given [url] with optional [headers] specified as a map from name to value.
Future<void> loadUrl(String url, {Map<String, String> headers = const {}}) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => headers);
return await _ChannelManager.channel.invokeMethod('loadUrl', args);
......@@ -162,52 +172,71 @@ class InAppBrowser {
///Displays an [InAppBrowser] window that was opened hidden. Calling this has no effect if the [InAppBrowser] was already visible.
Future<void> show() async {
return await _ChannelManager.channel.invokeMethod('show');
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
return await _ChannelManager.channel.invokeMethod('show', args);
}
///Hides the [InAppBrowser] window. Calling this has no effect if the [InAppBrowser] was already hidden.
Future<void> hide() async {
return await _ChannelManager.channel.invokeMethod('hide');
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
return await _ChannelManager.channel.invokeMethod('hide', args);
}
///Closes the [InAppBrowser] window.
Future<void> close() async {
return await _ChannelManager.channel.invokeMethod('close');
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
return await _ChannelManager.channel.invokeMethod('close', args);
}
///Reloads the [InAppBrowser] window.
Future<void> reload() async {
return await _ChannelManager.channel.invokeMethod('reload');
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
return await _ChannelManager.channel.invokeMethod('reload', args);
}
///Goes back in the history of the [InAppBrowser] window.
Future<void> goBack() async {
return await _ChannelManager.channel.invokeMethod('goBack');
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
return await _ChannelManager.channel.invokeMethod('goBack', args);
}
///Goes forward in the history of the [InAppBrowser] window.
Future<void> goForward() async {
return await _ChannelManager.channel.invokeMethod('goForward');
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
return await _ChannelManager.channel.invokeMethod('goForward', args);
}
///Check if the Web View of the [InAppBrowser] instance is in a loading state.
Future<bool> isLoading() async {
return await _ChannelManager.channel.invokeMethod('isLoading');
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
return await _ChannelManager.channel.invokeMethod('isLoading', args);
}
///Stops the Web View of the [InAppBrowser] instance from loading.
Future<void> stopLoading() async {
return await _ChannelManager.channel.invokeMethod('stopLoading');
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
return await _ChannelManager.channel.invokeMethod('stopLoading', args);
}
///Check if the Web View of the [InAppBrowser] instance is hidden.
Future<bool> isHidden() async {
return await _ChannelManager.channel.invokeMethod('isHidden');
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
return await _ChannelManager.channel.invokeMethod('isHidden', args);
}
///Injects JavaScript code into the [InAppBrowser] window and returns the result of the evaluation. (Only available when the target is set to `_blank` or to `_self`)
Future<String> injectScriptCode(String source) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('source', () => source);
return await _ChannelManager.channel.invokeMethod('injectScriptCode', args);
}
......@@ -215,6 +244,7 @@ class InAppBrowser {
///Injects a JavaScript file into the [InAppBrowser] window. (Only available when the target is set to `_blank` or to `_self`)
Future<void> injectScriptFile(String urlFile) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('urlFile', () => urlFile);
return await _ChannelManager.channel.invokeMethod('injectScriptFile', args);
}
......@@ -222,6 +252,7 @@ class InAppBrowser {
///Injects CSS into the [InAppBrowser] window. (Only available when the target is set to `_blank` or to `_self`)
Future<void> injectStyleCode(String source) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('source', () => source);
return await _ChannelManager.channel.invokeMethod('injectStyleCode', args);
}
......@@ -229,6 +260,7 @@ class InAppBrowser {
///Injects a CSS file into the [InAppBrowser] window. (Only available when the target is set to `_blank` or to `_self`)
Future<void> injectStyleFile(String urlFile) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('urlFile', () => urlFile);
return await _ChannelManager.channel.invokeMethod('injectStyleFile', args);
}
......@@ -268,12 +300,14 @@ class InAppBrowser {
///
///[browserFallback] represents the [InAppBrowser] instance fallback in case [Chrome Custom Tabs]/[SFSafariViewController] is not available.
class ChromeSafariBrowser {
String uuid;
InAppBrowser browserFallback;
///
ChromeSafariBrowser (browserFallback) {
this.browserFallback = browserFallback;
_ChannelManager.addListener(_handleMethod);
ChromeSafariBrowser (bf) {
uuid = uuidGenerator.v4();
browserFallback = bf;
_ChannelManager.addListener(uuid, _handleMethod);
}
Future<dynamic> _handleMethod(MethodCall call) async {
......@@ -294,6 +328,9 @@ class ChromeSafariBrowser {
///
Future<void> open(String url, {Map<String, dynamic> options = const {}, Map<String, String> headersFallback = const {}, Map<String, dynamic> optionsFallback = const {}}) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
print(browserFallback.uuid);
args.putIfAbsent('uuidFallback', () => (browserFallback != null) ? browserFallback.uuid : '');
args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => headersFallback);
args.putIfAbsent('target', () => "");
......
name: flutter_inappbrowser
description: A Flutter plugin that allows you to open an in-app browser window. (inspired by the popular cordova-plugin-inappbrowser).
version: 0.1.1
version: 0.2.0
author: Lorenzo Pichilli <pichillilorenzo@gmail.com>
homepage: https://github.com/pichillilorenzo/flutter_inappbrowser
......@@ -10,6 +10,7 @@ environment:
dependencies:
flutter:
sdk: flutter
uuid: ^1.0.3
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec
......
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