diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 22dc6f32..d235d503 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -15,30 +15,24 @@
-
-
-
-
+
-
-
+
-
+
-
-
+
-
@@ -56,39 +50,41 @@
-
+
-
+
+
+
-
-
+
+
-
-
+
+
-
+
-
+
@@ -109,7 +105,7 @@
-
+
@@ -119,10 +115,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
@@ -130,8 +141,8 @@
-
-
+
+
@@ -147,10 +158,6 @@
- initialData
- openData
- optionsType
- InAppWebView
fromInAppBrowser
InAppWebViewController
InAppBrowser
@@ -175,8 +182,12 @@
onExit
_handleMethod
javaScriptHandlersMap
- JavaScriptHandlerCallback
onConsoleM
+ return this
+ return await
+ onCallJsHandler
+ JavaScriptHandlerCallback
+ ListenerCallback
activity.getPreferences(0)
@@ -230,11 +241,11 @@
-
+
@@ -249,6 +260,7 @@
+
@@ -295,7 +307,6 @@
-
@@ -446,8 +457,8 @@
-
-
+
+
@@ -456,7 +467,7 @@
-
+
@@ -464,7 +475,7 @@
-
+
@@ -489,13 +500,6 @@
-
-
-
-
-
-
-
@@ -615,9 +619,7 @@
-
-
-
+
@@ -723,13 +725,6 @@
-
-
-
-
-
-
-
@@ -744,16 +739,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -761,17 +746,47 @@
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/build.gradle b/android/build.gradle
index 32b5cf75..f1b54ece 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -53,5 +53,4 @@ dependencies {
implementation 'androidx.browser:browser:1.0.0'
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'com.squareup.okhttp3:mockwebserver:3.11.0'
- implementation 'com.google.code.gson:gson:2.8.5'
}
diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java
index badf13b6..0ee20e27 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java
@@ -4,6 +4,7 @@ import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.View;
+import android.view.inputmethod.InputMethodManager;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
@@ -129,6 +130,7 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
if (webView != null) {
source = call.argument("source").toString();
webView.injectScriptCode(source, result);
+ // ((InputMethodManager) this.activity.getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
else {
result.success("");
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 57363bc9..2f0bd3df 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/JavaScriptBridgeInterface.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/JavaScriptBridgeInterface.java
@@ -4,7 +4,6 @@ import android.os.Build;
import android.util.Log;
import android.webkit.JavascriptInterface;
-import com.google.gson.Gson;
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebView;
import java.util.HashMap;
@@ -43,13 +42,12 @@ public class JavaScriptBridgeInterface {
getChannel().invokeMethod("onCallJsHandler", obj, new MethodChannel.Result() {
@Override
- public void success(Object o) {
- String json = new Gson().toJson(o);
+ public void success(Object json) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- flutterWebView.webView.evaluateJavascript("window." + name + "[" + _callHandlerID + "](" + json + ");", null);
+ flutterWebView.webView.evaluateJavascript("window." + name + "[" + _callHandlerID + "](" + json + "); delete window." + name + "[" + _callHandlerID + "];", null);
}
else {
- flutterWebView.webView.loadUrl("javascript:window." + name + "[" + _callHandlerID + "](" + json + ");");
+ flutterWebView.webView.loadUrl("javascript:window." + name + "[" + _callHandlerID + "](" + json + "); delete window." + name + "[" + _callHandlerID + "];");
}
}
diff --git a/example/assets/index.html b/example/assets/index.html
index 4e8e6833..c11b01b0 100644
--- a/example/assets/index.html
+++ b/example/assets/index.html
@@ -32,6 +32,7 @@
window.flutter_inappbrowser.callHandler('handlerTest', 1).then(function(result) {
console.log(result, typeof result);
+ console.log(JSON.stringify(result));
});
});
diff --git a/example/lib/inline_example.screen.dart b/example/lib/inline_example.screen.dart
index 966815ed..bb30a943 100644
--- a/example/lib/inline_example.screen.dart
+++ b/example/lib/inline_example.screen.dart
@@ -6,6 +6,20 @@ class InlineExampleScreen extends StatefulWidget {
_InlineExampleScreenState createState() => new _InlineExampleScreenState();
}
+class User {
+ String username;
+ String password;
+
+ User({this.username, this.password});
+
+ Map toJson() {
+ return {
+ 'username': this.username,
+ 'password': this.password
+ };
+ }
+}
+
class _InlineExampleScreenState extends State {
InAppWebViewController webView;
String url = "";
@@ -40,15 +54,18 @@ class _InlineExampleScreenState extends State {
decoration:
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: InAppWebView(
- initialUrl: "https://flutter.dev/",
- //initialFile: "assets/index.html",
+ //initialUrl: "https://mottie.github.io/Keyboard/",
+ initialFile: "assets/index.html",
initialHeaders: {},
initialOptions: {
- "useShouldOverrideUrlLoading": true,
- "useOnLoadResource": true
+ //"useShouldOverrideUrlLoading": true,
+ //"useOnLoadResource": true
},
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
+ controller.addJavaScriptHandler('handlerTest', (args) {
+ return new User(username: 'user', password: 'secret');
+ });
},
onLoadStart: (InAppWebViewController controller, String url) {
print("started $url");
diff --git a/ios/Classes/InAppWebView.swift b/ios/Classes/InAppWebView.swift
index d0b2e552..fe662b90 100644
--- a/ios/Classes/InAppWebView.swift
+++ b/ios/Classes/InAppWebView.swift
@@ -722,12 +722,9 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
else {
var json = "null"
if let r = result {
- json = JSONSerializer.toJson(r)
- if json == "{}" {
- json = "\(r)"
- }
+ json = r as! String
}
- self.evaluateJavaScript("window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)](\(json));", completionHandler: nil)
+ self.evaluateJavaScript("window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)](\(json)); delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)];", completionHandler: nil)
}
})
}
diff --git a/ios/Classes/JsonSerializer.swift b/ios/Classes/JsonSerializer.swift
deleted file mode 100644
index 7e483cf6..00000000
--- a/ios/Classes/JsonSerializer.swift
+++ /dev/null
@@ -1,284 +0,0 @@
-/*The MIT License (MIT)
- Copyright (c) 2015 Peter Helstrup Jensen
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.*/
-
-import Foundation
-
-/// Handles Convertion from instances of objects to JSON strings. Also helps with casting strings of JSON to Arrays or Dictionaries.
-open class JSONSerializer {
-
- /**
- Errors that indicates failures of JSONSerialization
- - JsonIsNotDictionary: -
- - JsonIsNotArray: -
- - JsonIsNotValid: -
- */
- public enum JSONSerializerError: Error {
- case jsonIsNotDictionary
- case jsonIsNotArray
- case jsonIsNotValid
- }
-
- //http://stackoverflow.com/questions/30480672/how-to-convert-a-json-string-to-a-dictionary
- /**
- Tries to convert a JSON string to a NSDictionary. NSDictionary can be easier to work with, and supports string bracket referencing. E.g. personDictionary["name"].
- - parameter jsonString: JSON string to be converted to a NSDictionary.
- - throws: Throws error of type JSONSerializerError. Either JsonIsNotValid or JsonIsNotDictionary. JsonIsNotDictionary will typically be thrown if you try to parse an array of JSON objects.
- - returns: A NSDictionary representation of the JSON string.
- */
- open static func toDictionary(_ jsonString: String) throws -> NSDictionary {
- if let dictionary = try jsonToAnyObject(jsonString) as? NSDictionary {
- return dictionary
- } else {
- throw JSONSerializerError.jsonIsNotDictionary
- }
- }
-
- /**
- Tries to convert a JSON string to a NSArray. NSArrays can be iterated and each item in the array can be converted to a NSDictionary.
- - parameter jsonString: The JSON string to be converted to an NSArray
- - throws: Throws error of type JSONSerializerError. Either JsonIsNotValid or JsonIsNotArray. JsonIsNotArray will typically be thrown if you try to parse a single JSON object.
- - returns: NSArray representation of the JSON objects.
- */
- open static func toArray(_ jsonString: String) throws -> NSArray {
- if let array = try jsonToAnyObject(jsonString) as? NSArray {
- return array
- } else {
- throw JSONSerializerError.jsonIsNotArray
- }
- }
-
- /**
- Tries to convert a JSON string to AnyObject. AnyObject can then be casted to either NSDictionary or NSArray.
- - parameter jsonString: JSON string to be converted to AnyObject
- - throws: Throws error of type JSONSerializerError.
- - returns: Returns the JSON string as AnyObject
- */
- fileprivate static func jsonToAnyObject(_ jsonString: String) throws -> Any? {
- var any: Any?
-
- if let data = jsonString.data(using: String.Encoding.utf8) {
- do {
- any = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
- }
- catch let error as NSError {
- let sError = String(describing: error)
- NSLog(sError)
- throw JSONSerializerError.jsonIsNotValid
- }
- }
- return any
- }
-
- /**
- Generates the JSON representation given any custom object of any custom class. Inherited properties will also be represented.
- - parameter object: The instantiation of any custom class to be represented as JSON.
- - returns: A string JSON representation of the object.
- */
- open static func toJson(_ object: Any, prettify: Bool = false) -> String {
- var json = ""
- if (!(object is Array)) {
- json += "{"
- }
- let mirror = Mirror(reflecting: object)
-
- var children = [(label: String?, value: Any)]()
-
- if let mirrorChildrenCollection = AnyRandomAccessCollection(mirror.children) {
- children += mirrorChildrenCollection
- }
- else {
- let mirrorIndexCollection = AnyCollection(mirror.children)
- children += mirrorIndexCollection
- }
-
- var currentMirror = mirror
- while let superclassChildren = currentMirror.superclassMirror?.children {
- let randomCollection = AnyRandomAccessCollection(superclassChildren)!
- children += randomCollection
- currentMirror = currentMirror.superclassMirror!
- }
-
- var filteredChildren = [(label: String?, value: Any)]()
-
- for (optionalPropertyName, value) in children {
-
- if let optionalPropertyName = optionalPropertyName {
-
- if !optionalPropertyName.contains("notMapped_") {
- filteredChildren.append((optionalPropertyName, value))
- }
-
- }
- else {
- filteredChildren.append((nil, value))
- }
- }
-
- var skip = false
- let size = filteredChildren.count
- var index = 0
-
- var first = true
-
- for (optionalPropertyName, value) in filteredChildren {
- skip = false
-
- let propertyName = optionalPropertyName
- let property = Mirror(reflecting: value)
-
- var handledValue = String()
-
- if propertyName != nil && propertyName == "some" && property.displayStyle == Mirror.DisplayStyle.struct {
- handledValue = toJson(value)
- skip = true
- }
- else if (value is Int ||
- value is Int32 ||
- value is Int64 ||
- value is Double ||
- value is Float ||
- value is Bool) && property.displayStyle != Mirror.DisplayStyle.optional {
- handledValue = String(describing: value)
- }
- else if let array = value as? [Int?] {
- handledValue += "["
- for (index, value) in array.enumerated() {
- handledValue += value != nil ? String(value!) : "null"
- handledValue += (index < array.count-1 ? ", " : "")
- }
- handledValue += "]"
- }
- else if let array = value as? [Double?] {
- handledValue += "["
- for (index, value) in array.enumerated() {
- handledValue += value != nil ? String(value!) : "null"
- handledValue += (index < array.count-1 ? ", " : "")
- }
- handledValue += "]"
- }
- else if let array = value as? [Float?] {
- handledValue += "["
- for (index, value) in array.enumerated() {
- handledValue += value != nil ? String(value!) : "null"
- handledValue += (index < array.count-1 ? ", " : "")
- }
- handledValue += "]"
- }
- else if let array = value as? [Bool?] {
- handledValue += "["
- for (index, value) in array.enumerated() {
- handledValue += value != nil ? String(value!) : "null"
- handledValue += (index < array.count-1 ? ", " : "")
- }
- handledValue += "]"
- }
- else if let array = value as? [String?] {
- handledValue += "["
- for (index, value) in array.enumerated() {
- handledValue += value != nil ? "\"\(value!)\"" : "null"
- handledValue += (index < array.count-1 ? ", " : "")
- }
- handledValue += "]"
- }
- else if let array = value as? [String] {
- handledValue += "["
- for (index, value) in array.enumerated() {
- handledValue += "\"\(value)\""
- handledValue += (index < array.count-1 ? ", " : "")
- }
- handledValue += "]"
- }
- else if let array = value as? NSArray {
- handledValue += "["
- for (index, value) in array.enumerated() {
- if !(value is Int) &&
- !(value is Int32) &&
- !(value is Int64) &&
- !(value is Double) && !(value is Float) && !(value is Bool) && !(value is String) {
- handledValue += toJson(value)
- }
- else {
- handledValue += "\(value)"
- }
- handledValue += (index < array.count-1 ? ", " : "")
- }
- handledValue += "]"
- }
- else if property.displayStyle == Mirror.DisplayStyle.class ||
- property.displayStyle == Mirror.DisplayStyle.struct ||
- String(describing: value).contains("#") {
- handledValue = toJson(value)
- }
- else if property.displayStyle == Mirror.DisplayStyle.optional {
- let str = String(describing: value)
- if str != "nil" {
- // Some optional values cannot be unpacked if type is "Any"
- // We remove the "Optional(" and last ")" from the value by string manipulation
- var d = String(str).dropFirst(9)
- d = d.dropLast(1)
- handledValue = String(d)
- } else {
- handledValue = "null"
- }
- }
- else {
- handledValue = String(describing: value) != "nil" ? "\"\(value)\"" : "null"
- }
-
- if !skip {
-
- // if optional propertyName is populated we'll use it
- if let propertyName = propertyName {
- json += "\"\(propertyName)\": \(handledValue)" + (index < size-1 ? ", " : "")
- }
- // if not then we have a member an array
- else {
- // if it's the first member we need to prepend ]
- if first {
- json += "["
- first = false
- }
- // if it's not the last we need a comma. if it is the last we need to close ]
- json += "\(handledValue)" + (index < size-1 ? ", " : "]")
- }
-
- } else {
- json = "\(handledValue)" + (index < size-1 ? ", " : "")
- }
-
- index += 1
- }
-
- if !skip {
- if (!(object is Array)) {
- json += "}"
- }
- }
-
- if prettify {
- let jsonData = json.data(using: String.Encoding.utf8)!
- let jsonObject = try! JSONSerialization.jsonObject(with: jsonData, options: [])
- let prettyJsonData = try! JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted)
- json = NSString(data: prettyJsonData, encoding: String.Encoding.utf8.rawValue)! as String
- }
-
- return json
- }
-
-
-}
diff --git a/lib/flutter_inappbrowser.dart b/lib/flutter_inappbrowser.dart
index 59b76eba..68e015a5 100644
--- a/lib/flutter_inappbrowser.dart
+++ b/lib/flutter_inappbrowser.dart
@@ -34,6 +34,17 @@ import 'package:uuid/uuid.dart';
import 'package:mime/mime.dart';
typedef Future ListenerCallback(MethodCall call);
+
+///This type represents a callback, added with [addJavaScriptHandler], that listens to post messages sent from JavaScript.
+///
+///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.
+///
+///Also, a [JavaScriptHandlerCallback] can return json data to the JavaScript side.
+///In this case, simply return data that you want to send and it will be automatically json encoded using [jsonEncode] from the `dart:convert` library.
typedef dynamic JavaScriptHandlerCallback(List arguments);
var _uuidGenerator = new Uuid();
@@ -849,7 +860,13 @@ class InAppWebViewController {
String handlerName = call.arguments["handlerName"];
List args = jsonDecode(call.arguments["args"]);
if (javaScriptHandlersMap.containsKey(handlerName)) {
- return await javaScriptHandlersMap[handlerName](args);
+ // convert result to json
+ try {
+ return jsonEncode(await javaScriptHandlersMap[handlerName](args));
+ } catch (error) {
+ print(error);
+ return null;
+ }
}
break;
default:
@@ -1145,6 +1162,9 @@ class InAppWebViewController {
///
///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.
+ ///
+ ///Also, a [JavaScriptHandlerCallback] can return json data to the JavaScript side.
+ ///In this case, simply return data that you want to send and it will be automatically json encoded using [jsonEncode] from the `dart:convert` library.
void addJavaScriptHandler(String handlerName, JavaScriptHandlerCallback callback) {
this.javaScriptHandlersMap[handlerName] = (callback);
}