v0.2.1, fixed InAppBrowser.injectScriptCode() method when there is not a return value, added InAppBrowser.onConsoleMessage() method to manage console messages #5
This commit is contained in:
parent
db65f7a042
commit
f032b7f635
|
@ -1,5 +1,5 @@
|
||||||
<component name="libraryTable">
|
<component name="libraryTable">
|
||||||
<library name="Flutter Plugins" type="FlutterPluginsLibraryType">
|
<library name="Flutter Plugins">
|
||||||
<CLASSES>
|
<CLASSES>
|
||||||
<root url="file://$PROJECT_DIR$" />
|
<root url="file://$PROJECT_DIR$" />
|
||||||
</CLASSES>
|
</CLASSES>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,8 @@
|
||||||
|
## 0.2.1
|
||||||
|
|
||||||
|
- added InAppBrowser.onConsoleMessage() method to manage console messages
|
||||||
|
- fixed InAppBrowser.injectScriptCode() method when there is not a return value
|
||||||
|
|
||||||
## 0.2.0
|
## 0.2.0
|
||||||
|
|
||||||
- added support of Chrome CustomTabs for Android
|
- added support of Chrome CustomTabs for Android
|
||||||
|
|
24
README.md
24
README.md
|
@ -41,6 +41,11 @@ class MyInAppBrowser extends InAppBrowser {
|
||||||
print("\n\nStopped $url\n\n");
|
print("\n\nStopped $url\n\n");
|
||||||
// print body html
|
// print body html
|
||||||
print(await this.injectScriptCode("document.body.innerHTML"));
|
print(await this.injectScriptCode("document.body.innerHTML"));
|
||||||
|
|
||||||
|
// console messages
|
||||||
|
await this.injectScriptCode("console.log({'testObject': 5});"); // the message will be: [object Object]
|
||||||
|
await this.injectScriptCode("console.log('testObjectStringify', JSON.stringify({'testObject': 5}));"); // the message will be: testObjectStringify {"testObject": 5}
|
||||||
|
await this.injectScriptCode("console.error('testError', false);"); // the message will be: testError false
|
||||||
|
|
||||||
// add jquery library and custom javascript
|
// add jquery library and custom javascript
|
||||||
await this.injectScriptFile("https://code.jquery.com/jquery-3.3.1.min.js");
|
await this.injectScriptFile("https://code.jquery.com/jquery-3.3.1.min.js");
|
||||||
|
@ -73,6 +78,17 @@ class MyInAppBrowser extends InAppBrowser {
|
||||||
this.loadUrl(url);
|
this.loadUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onConsoleMessage(ConsoleMessage consoleMessage) {
|
||||||
|
print("""
|
||||||
|
console output:
|
||||||
|
sourceURL: ${consoleMessage.sourceURL}
|
||||||
|
lineNumber: ${consoleMessage.lineNumber}
|
||||||
|
message: ${consoleMessage.message}
|
||||||
|
messageLevel: ${consoleMessage.messageLevel}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MyInAppBrowser inAppBrowser = new MyInAppBrowser();
|
MyInAppBrowser inAppBrowser = new MyInAppBrowser();
|
||||||
|
@ -228,6 +244,14 @@ Event fires when the `InAppBrowser` window is closed.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Event fires when the `InAppBrowser` webview receives a `ConsoleMessage`.
|
||||||
|
```dart
|
||||||
|
@override
|
||||||
|
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.
|
Give the host application a chance to take control when a URL is about to be loaded in the current WebView.
|
||||||
In order to be able to listen this event, you need to set `useShouldOverrideUrlLoading` option to `true`.
|
In order to be able to listen this event, you need to set `useShouldOverrideUrlLoading` option to `true`.
|
||||||
```dart
|
```dart
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
flutter_inappbrowser
|
Binary file not shown.
|
@ -0,0 +1,29 @@
|
||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<Objective-C-extensions>
|
||||||
|
<file>
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||||
|
</file>
|
||||||
|
<class>
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||||
|
</class>
|
||||||
|
<extensions>
|
||||||
|
<pair source="cpp" header="h" fileNamingConvention="NONE" />
|
||||||
|
<pair source="c" header="h" fileNamingConvention="NONE" />
|
||||||
|
</extensions>
|
||||||
|
</Objective-C-extensions>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="GradleSettings">
|
||||||
|
<option name="linkedExternalProjectsSettings">
|
||||||
|
<GradleProjectSettings>
|
||||||
|
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="modules">
|
||||||
|
<set>
|
||||||
|
<option value="$PROJECT_DIR$" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
|
</GradleProjectSettings>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="NullableNotNullManager">
|
||||||
|
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||||
|
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||||
|
<option name="myNullables">
|
||||||
|
<value>
|
||||||
|
<list size="7">
|
||||||
|
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||||
|
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||||
|
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||||
|
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||||
|
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||||
|
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
|
||||||
|
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="myNotNulls">
|
||||||
|
<value>
|
||||||
|
<list size="6">
|
||||||
|
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||||
|
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||||
|
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||||
|
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||||
|
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
|
||||||
|
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectType">
|
||||||
|
<option name="id" value="Android" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/flutter_inappbrowser.iml" filepath="$PROJECT_DIR$/flutter_inappbrowser.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RunConfigurationProducerService">
|
||||||
|
<option name="ignoredProducers">
|
||||||
|
<set>
|
||||||
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||||
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||||
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
Binary file not shown.
|
@ -0,0 +1,5 @@
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
|
@ -285,15 +285,20 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String msg;
|
String msg;
|
||||||
msg = reader.nextString();
|
if (reader.peek() == JsonToken.STRING) {
|
||||||
|
msg = reader.nextString();
|
||||||
|
|
||||||
JsonReader reader2 = new JsonReader(new StringReader(msg));
|
JsonReader reader2 = new JsonReader(new StringReader(msg));
|
||||||
reader2.setLenient(true);
|
reader2.setLenient(true);
|
||||||
|
|
||||||
if (reader2.peek() == JsonToken.STRING)
|
if (reader2.peek() == JsonToken.STRING)
|
||||||
msg = reader2.nextString();
|
msg = reader2.nextString();
|
||||||
|
|
||||||
result.success(msg);
|
result.success(msg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.success("");
|
||||||
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(LOG_TAG, "IOException", e);
|
Log.e(LOG_TAG, "IOException", e);
|
||||||
|
|
|
@ -4,11 +4,16 @@ import android.content.Intent;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.webkit.ConsoleMessage;
|
||||||
import android.webkit.ValueCallback;
|
import android.webkit.ValueCallback;
|
||||||
import android.webkit.WebChromeClient;
|
import android.webkit.WebChromeClient;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class InAppBrowserWebChromeClient extends WebChromeClient {
|
public class InAppBrowserWebChromeClient extends WebChromeClient {
|
||||||
|
|
||||||
protected static final String LOG_TAG = "IABWebChromeClient";
|
protected static final String LOG_TAG = "IABWebChromeClient";
|
||||||
|
@ -22,6 +27,18 @@ public class InAppBrowserWebChromeClient extends WebChromeClient {
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
|
||||||
|
Map<String, Object> obj = new HashMap<>();
|
||||||
|
obj.put("uuid", activity.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);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(WebView view, int progress) {
|
public void onProgressChanged(WebView view, int progress) {
|
||||||
if (activity.progressBar != null) {
|
if (activity.progressBar != null) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Intent;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.net.http.SslError;
|
import android.net.http.SslError;
|
||||||
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.webkit.CookieManager;
|
import android.webkit.CookieManager;
|
||||||
import android.webkit.CookieSyncManager;
|
import android.webkit.CookieSyncManager;
|
||||||
|
@ -124,7 +125,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
|
||||||
activity.isLoading = false;
|
activity.isLoading = false;
|
||||||
|
|
||||||
// CB-10395 InAppBrowserFlutterPlugin's WebView not storing cookies reliable to local device storage
|
// CB-10395 InAppBrowserFlutterPlugin's WebView not storing cookies reliable to local device storage
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
CookieManager.getInstance().flush();
|
CookieManager.getInstance().flush();
|
||||||
} else {
|
} else {
|
||||||
CookieSyncManager.getInstance().sync();
|
CookieSyncManager.getInstance().sync();
|
||||||
|
@ -134,6 +135,10 @@ public class InAppBrowserWebViewClient extends WebViewClient {
|
||||||
view.clearFocus();
|
view.clearFocus();
|
||||||
view.requestFocus();
|
view.requestFocus();
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
|
view.evaluateJavascript(activity.jsConsoleLogScript, null);
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, Object> obj = new HashMap<>();
|
Map<String, Object> obj = new HashMap<>();
|
||||||
obj.put("uuid", activity.uuid);
|
obj.put("uuid", activity.uuid);
|
||||||
obj.put("url", url);
|
obj.put("url", url);
|
||||||
|
|
|
@ -38,6 +38,32 @@ public class WebViewActivity extends AppCompatActivity {
|
||||||
public boolean isLoading = false;
|
public boolean isLoading = false;
|
||||||
public boolean isHidden = false;
|
public boolean isHidden = false;
|
||||||
|
|
||||||
|
static final String jsConsoleLogScript = "(function() {\n"+
|
||||||
|
" var oldLogs = {\n"+
|
||||||
|
" 'log': console.log,\n"+
|
||||||
|
" 'debug': console.debug,\n"+
|
||||||
|
" 'error': console.error,\n"+
|
||||||
|
" 'info': console.info,\n"+
|
||||||
|
" 'warn': console.warn\n"+
|
||||||
|
" };\n"+
|
||||||
|
" for (var k in oldLogs) {\n"+
|
||||||
|
" (function(oldLog) {\n"+
|
||||||
|
" console[oldLog] = function() {\n"+
|
||||||
|
" var message = ''\n"+
|
||||||
|
" for (var i in arguments) {\n"+
|
||||||
|
" if (message == '') {\n"+
|
||||||
|
" message += arguments[i];\n"+
|
||||||
|
" }\n"+
|
||||||
|
" else {\n"+
|
||||||
|
" message += ' ' + arguments[i];\n"+
|
||||||
|
" }\n"+
|
||||||
|
" }\n"+
|
||||||
|
" oldLogs[oldLog].call(console, message);\n"+
|
||||||
|
" }\n"+
|
||||||
|
" })(k);\n"+
|
||||||
|
" }\n"+
|
||||||
|
"})();";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
|
@ -5,7 +5,7 @@ buildscript {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.1.4'
|
classpath 'com.android.tools.build:gradle:3.2.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#Fri Jun 23 08:50:38 CEST 2017
|
#Fri Oct 05 14:08:48 CEST 2018
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||||
|
|
|
@ -12,7 +12,19 @@ class MyInAppBrowser extends InAppBrowser {
|
||||||
@override
|
@override
|
||||||
Future onLoadStop(String url) async {
|
Future onLoadStop(String url) async {
|
||||||
print("\n\nStopped $url\n\n");
|
print("\n\nStopped $url\n\n");
|
||||||
|
|
||||||
|
// // javascript error
|
||||||
|
// await this.injectScriptCode("console.log({'testJavaScriptError': 5}));");
|
||||||
|
//
|
||||||
|
// await this.injectScriptCode("console.log({'testObject': 5});");
|
||||||
|
// await this.injectScriptCode("console.warn('testWarn',null);");
|
||||||
|
// await this.injectScriptCode("console.log('testObjectStringify', JSON.stringify({'asd': 5}));");
|
||||||
|
// await this.injectScriptCode("console.info('testInfo', 6);");
|
||||||
|
// await this.injectScriptCode("console.error('testError', false);");
|
||||||
|
// await this.injectScriptCode("console.debug('testDebug', true);");
|
||||||
// print(await this.injectScriptCode("document.body.innerHTML"));
|
// print(await this.injectScriptCode("document.body.innerHTML"));
|
||||||
|
// print(await this.injectScriptCode("null"));
|
||||||
|
// print(await this.injectScriptCode("undefined"));
|
||||||
// print(await this.injectScriptCode("3"));
|
// print(await this.injectScriptCode("3"));
|
||||||
// print(await this.injectScriptCode("""
|
// print(await this.injectScriptCode("""
|
||||||
// function asd (a,b) {
|
// function asd (a,b) {
|
||||||
|
@ -58,6 +70,17 @@ class MyInAppBrowser extends InAppBrowser {
|
||||||
print("\n\n override $url\n\n");
|
print("\n\n override $url\n\n");
|
||||||
this.loadUrl(url);
|
this.loadUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onConsoleMessage(ConsoleMessage consoleMessage) {
|
||||||
|
print("""
|
||||||
|
console output:
|
||||||
|
sourceURL: ${consoleMessage.sourceURL}
|
||||||
|
lineNumber: ${consoleMessage.lineNumber}
|
||||||
|
message: ${consoleMessage.message}
|
||||||
|
messageLevel: ${consoleMessage.messageLevel}
|
||||||
|
""");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MyInAppBrowser inAppBrowserFallback = new MyInAppBrowser();
|
MyInAppBrowser inAppBrowserFallback = new MyInAppBrowser();
|
||||||
|
@ -107,15 +130,15 @@ class _MyAppState extends State<MyApp> {
|
||||||
),
|
),
|
||||||
body: new Center(
|
body: new Center(
|
||||||
child: new RaisedButton(onPressed: () {
|
child: new RaisedButton(onPressed: () {
|
||||||
chromeSafariBrowser.open("https://flutter.io/");
|
//chromeSafariBrowser.open("https://flutter.io/");
|
||||||
// inAppBrowserFallback.open("https://flutter.io/", options: {
|
inAppBrowserFallback.open("https://flutter.io/", options: {
|
||||||
// //"hidden": true,
|
//"hidden": true,
|
||||||
// //"toolbarTopFixedTitle": "Fixed title",
|
//"toolbarTopFixedTitle": "Fixed title",
|
||||||
// //"useShouldOverrideUrlLoading": true
|
//"useShouldOverrideUrlLoading": true
|
||||||
// //"hideUrlBar": true,
|
//"hideUrlBar": true,
|
||||||
// //"toolbarTop": false,
|
//"toolbarTop": false,
|
||||||
// //"toolbarBottom": false
|
//"toolbarBottom": false
|
||||||
// });
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
child: Text("Open InAppBrowser")
|
child: Text("Open InAppBrowser")
|
||||||
|
|
|
@ -14,6 +14,36 @@ import AVFoundation
|
||||||
typealias OlderClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Any?) -> Void
|
typealias OlderClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Any?) -> Void
|
||||||
typealias NewerClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void
|
typealias NewerClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void
|
||||||
|
|
||||||
|
// the message needs to be concatenated with '' in order to have the same behavior like on Android
|
||||||
|
let jsConsoleLog = """
|
||||||
|
(function() {
|
||||||
|
var oldLogs = {
|
||||||
|
'consoleLog': console.log,
|
||||||
|
'consoleDebug': console.debug,
|
||||||
|
'consoleError': console.error,
|
||||||
|
'consoleInfo': console.info,
|
||||||
|
'consoleWarn': console.warn
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var k in oldLogs) {
|
||||||
|
(function(oldLog) {
|
||||||
|
console[oldLog.replace('console', '').toLowerCase()] = function() {
|
||||||
|
var message = '';
|
||||||
|
for (var i in arguments) {
|
||||||
|
if (message == '') {
|
||||||
|
message += arguments[i];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
message += ' ' + arguments[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.webkit.messageHandlers[oldLog].postMessage(message);
|
||||||
|
}
|
||||||
|
})(k);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
"""
|
||||||
|
|
||||||
extension WKWebView{
|
extension WKWebView{
|
||||||
|
|
||||||
var keyboardDisplayRequiresUserAction: Bool? {
|
var keyboardDisplayRequiresUserAction: Bool? {
|
||||||
|
@ -62,7 +92,7 @@ extension WKWebView{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate, UITextFieldDelegate {
|
class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate, UITextFieldDelegate, WKScriptMessageHandler {
|
||||||
@IBOutlet var webView: WKWebView!
|
@IBOutlet var webView: WKWebView!
|
||||||
@IBOutlet var closeButton: UIButton!
|
@IBOutlet var closeButton: UIButton!
|
||||||
@IBOutlet var reloadButton: UIBarButtonItem!
|
@IBOutlet var reloadButton: UIBarButtonItem!
|
||||||
|
@ -132,7 +162,6 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareWebView() {
|
func prepareWebView() {
|
||||||
|
|
||||||
//UIApplication.shared.statusBarStyle = preferredStatusBarStyle
|
//UIApplication.shared.statusBarStyle = preferredStatusBarStyle
|
||||||
|
|
||||||
self.webView.configuration.userContentController = WKUserContentController()
|
self.webView.configuration.userContentController = WKUserContentController()
|
||||||
|
@ -208,6 +237,13 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
|
||||||
let jscriptWebkitTouchCallout = WKUserScript(source: "document.body.style.webkitTouchCallout='none';", injectionTime: .atDocumentEnd, forMainFrameOnly: true)
|
let jscriptWebkitTouchCallout = WKUserScript(source: "document.body.style.webkitTouchCallout='none';", injectionTime: .atDocumentEnd, forMainFrameOnly: true)
|
||||||
self.webView.configuration.userContentController.addUserScript(jscriptWebkitTouchCallout)
|
self.webView.configuration.userContentController.addUserScript(jscriptWebkitTouchCallout)
|
||||||
|
|
||||||
|
let jsConsoleLogScript = WKUserScript(source: jsConsoleLog, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
|
||||||
|
self.webView.configuration.userContentController.addUserScript(jsConsoleLogScript)
|
||||||
|
self.webView.configuration.userContentController.add(self, name: "consoleLog")
|
||||||
|
self.webView.configuration.userContentController.add(self, name: "consoleDebug")
|
||||||
|
self.webView.configuration.userContentController.add(self, name: "consoleError")
|
||||||
|
self.webView.configuration.userContentController.add(self, name: "consoleInfo")
|
||||||
|
self.webView.configuration.userContentController.add(self, name: "consoleWarn")
|
||||||
|
|
||||||
if #available(iOS 10.0, *) {
|
if #available(iOS 10.0, *) {
|
||||||
if (browserOptions?.mediaPlaybackRequiresUserGesture)! {
|
if (browserOptions?.mediaPlaybackRequiresUserGesture)! {
|
||||||
|
@ -481,6 +517,10 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
|
||||||
|
|
||||||
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||||
// update url, stop spinner, update back/forward
|
// update url, stop spinner, update back/forward
|
||||||
|
|
||||||
|
// evaluate the console log script
|
||||||
|
webView.evaluateJavaScript(jsConsoleLog)
|
||||||
|
|
||||||
currentURL = webView.url
|
currentURL = webView.url
|
||||||
updateUrlTextField(url: (currentURL?.absoluteString)!)
|
updateUrlTextField(url: (currentURL?.absoluteString)!)
|
||||||
backButton.isEnabled = webView.canGoBack
|
backButton.isEnabled = webView.canGoBack
|
||||||
|
@ -506,4 +546,34 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
|
||||||
spinner.stopAnimating()
|
spinner.stopAnimating()
|
||||||
navigationDelegate?.onLoadError(uuid: self.uuid, webView: webView, error: error)
|
navigationDelegate?.onLoadError(uuid: self.uuid, webView: webView, error: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
|
||||||
|
print(message.name)
|
||||||
|
if message.name.starts(with: "console") {
|
||||||
|
var messageLevel = "LOG"
|
||||||
|
switch (message.name) {
|
||||||
|
case "consoleLog":
|
||||||
|
messageLevel = "LOG"
|
||||||
|
break;
|
||||||
|
case "consoleDebug":
|
||||||
|
// on Android, console.debug is TIP
|
||||||
|
messageLevel = "TIP"
|
||||||
|
break;
|
||||||
|
case "consoleError":
|
||||||
|
messageLevel = "ERROR"
|
||||||
|
break;
|
||||||
|
case "consoleInfo":
|
||||||
|
// on Android, console.info is LOG
|
||||||
|
messageLevel = "LOG"
|
||||||
|
break;
|
||||||
|
case "consoleWarn":
|
||||||
|
messageLevel = "WARNING"
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
messageLevel = "LOG"
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
navigationDelegate?.onConsoleMessage(uuid: self.uuid, sourceURL: "", lineNumber: 1, message: message.body as! String, messageLevel: messageLevel)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,98 +48,98 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
||||||
let uuid: String = (arguments!["uuid"] as? String)!
|
let uuid: String = (arguments!["uuid"] as? String)!
|
||||||
|
|
||||||
switch call.method {
|
switch call.method {
|
||||||
case "open":
|
case "open":
|
||||||
self.open(uuid: uuid, arguments: arguments!, result: result)
|
self.open(uuid: uuid, arguments: arguments!, result: result)
|
||||||
break
|
break
|
||||||
case "loadUrl":
|
case "loadUrl":
|
||||||
self.loadUrl(uuid: uuid, arguments: arguments!, result: result)
|
self.loadUrl(uuid: uuid, arguments: arguments!, result: result)
|
||||||
break
|
break
|
||||||
case "close":
|
case "close":
|
||||||
self.close(uuid: uuid)
|
self.close(uuid: uuid)
|
||||||
result(true)
|
result(true)
|
||||||
break
|
break
|
||||||
case "show":
|
case "show":
|
||||||
self.show(uuid: uuid)
|
self.show(uuid: uuid)
|
||||||
result(true)
|
result(true)
|
||||||
break
|
break
|
||||||
case "hide":
|
case "hide":
|
||||||
self.hide(uuid: uuid)
|
self.hide(uuid: uuid)
|
||||||
result(true)
|
result(true)
|
||||||
break
|
break
|
||||||
case "reload":
|
case "reload":
|
||||||
if let webViewController = self.webViewControllers[uuid] {
|
if let webViewController = self.webViewControllers[uuid] {
|
||||||
webViewController?.reload()
|
webViewController?.reload()
|
||||||
}
|
}
|
||||||
result(true)
|
result(true)
|
||||||
break
|
break
|
||||||
case "goBack":
|
case "goBack":
|
||||||
if let webViewController = self.webViewControllers[uuid] {
|
if let webViewController = self.webViewControllers[uuid] {
|
||||||
webViewController?.goBack()
|
webViewController?.goBack()
|
||||||
}
|
}
|
||||||
result(true)
|
result(true)
|
||||||
break
|
break
|
||||||
case "canGoBack":
|
case "canGoBack":
|
||||||
if let webViewController = self.webViewControllers[uuid] {
|
if let webViewController = self.webViewControllers[uuid] {
|
||||||
result(webViewController?.canGoBack() ?? false)
|
result(webViewController?.canGoBack() ?? false)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result(false)
|
result(false)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "goForward":
|
case "goForward":
|
||||||
if let webViewController = self.webViewControllers[uuid] {
|
if let webViewController = self.webViewControllers[uuid] {
|
||||||
webViewController?.goForward()
|
webViewController?.goForward()
|
||||||
}
|
}
|
||||||
result(true)
|
result(true)
|
||||||
break
|
break
|
||||||
case "canGoForward":
|
case "canGoForward":
|
||||||
if let webViewController = self.webViewControllers[uuid] {
|
if let webViewController = self.webViewControllers[uuid] {
|
||||||
result(webViewController?.canGoForward() ?? false)
|
result(webViewController?.canGoForward() ?? false)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result(false)
|
result(false)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "isLoading":
|
case "isLoading":
|
||||||
if let webViewController = self.webViewControllers[uuid] {
|
if let webViewController = self.webViewControllers[uuid] {
|
||||||
result((webViewController?.webView.isLoading ?? false) == true)
|
result((webViewController?.webView.isLoading ?? false) == true)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result(false)
|
result(false)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "stopLoading":
|
case "stopLoading":
|
||||||
if let webViewController = self.webViewControllers[uuid] {
|
if let webViewController = self.webViewControllers[uuid] {
|
||||||
webViewController?.webView.stopLoading()
|
webViewController?.webView.stopLoading()
|
||||||
}
|
}
|
||||||
result(true)
|
result(true)
|
||||||
break
|
break
|
||||||
case "isHidden":
|
case "isHidden":
|
||||||
if let webViewController = self.webViewControllers[uuid] {
|
if let webViewController = self.webViewControllers[uuid] {
|
||||||
result((webViewController?.isHidden ?? false) == true)
|
result((webViewController?.isHidden ?? false) == true)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result(false)
|
result(false)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "injectScriptCode":
|
case "injectScriptCode":
|
||||||
self.injectScriptCode(uuid: uuid, arguments: arguments!, result: result)
|
self.injectScriptCode(uuid: uuid, arguments: arguments!, result: result)
|
||||||
break
|
break
|
||||||
case "injectScriptFile":
|
case "injectScriptFile":
|
||||||
self.injectScriptFile(uuid: uuid, arguments: arguments!, result: nil)
|
self.injectScriptFile(uuid: uuid, arguments: arguments!, result: nil)
|
||||||
result(true)
|
result(true)
|
||||||
break
|
break
|
||||||
case "injectStyleCode":
|
case "injectStyleCode":
|
||||||
self.injectStyleCode(uuid: uuid, arguments: arguments!, result: nil)
|
self.injectStyleCode(uuid: uuid, arguments: arguments!, result: nil)
|
||||||
result(true)
|
result(true)
|
||||||
break
|
break
|
||||||
case "injectStyleFile":
|
case "injectStyleFile":
|
||||||
self.injectStyleFile(uuid: uuid, arguments: arguments!, result: nil)
|
self.injectStyleFile(uuid: uuid, arguments: arguments!, result: nil)
|
||||||
result(true)
|
result(true)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
result(FlutterMethodNotImplemented)
|
result(FlutterMethodNotImplemented)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,6 +410,16 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if error != nil {
|
||||||
|
let userInfo = (error! as NSError).userInfo
|
||||||
|
self.onConsoleMessage(uuid: uuid, sourceURL: (userInfo["WKJavaScriptExceptionSourceURL"] as! URL).absoluteString, lineNumber: userInfo["WKJavaScriptExceptionLineNumber"] as! Int, message: userInfo["WKJavaScriptExceptionMessage"] as! String, messageLevel: "ERROR")
|
||||||
|
}
|
||||||
|
|
||||||
|
if value == nil {
|
||||||
|
result!("")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let data: Data = ("[" + String(describing: value!) + "]").data(using: String.Encoding.utf8, allowLossyConversion: false)!
|
let data: Data = ("[" + String(describing: value!) + "]").data(using: String.Encoding.utf8, allowLossyConversion: false)!
|
||||||
let json: Array<Any> = try JSONSerialization.jsonObject(with: data, options: []) as! Array<Any>
|
let json: Array<Any> = try JSONSerialization.jsonObject(with: data, options: []) as! Array<Any>
|
||||||
|
@ -476,19 +486,25 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldOverrideUrlLoading(uuid: String, webView: WKWebView, url: URL) {
|
func shouldOverrideUrlLoading(uuid: String, webView: WKWebView, url: URL) {
|
||||||
if let webViewController = self.webViewControllers[uuid] {
|
if self.webViewControllers[uuid] != nil {
|
||||||
channel.invokeMethod("shouldOverrideUrlLoading", arguments: ["uuid": uuid, "url": url.absoluteString])
|
channel.invokeMethod("shouldOverrideUrlLoading", arguments: ["uuid": uuid, "url": url.absoluteString])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func onConsoleMessage(uuid: String, sourceURL: String, lineNumber: Int, message: String, messageLevel: String) {
|
||||||
|
if self.webViewControllers[uuid] != nil {
|
||||||
|
channel.invokeMethod("onConsoleMessage", arguments: ["uuid": uuid, "sourceURL": sourceURL, "lineNumber": lineNumber, "message": message, "messageLevel": messageLevel])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func onChromeSafariBrowserOpened(uuid: String) {
|
func onChromeSafariBrowserOpened(uuid: String) {
|
||||||
if let safariViewController = self.safariViewControllers[uuid] {
|
if self.safariViewControllers[uuid] != nil {
|
||||||
channel.invokeMethod("onChromeSafariBrowserOpened", arguments: ["uuid": uuid])
|
channel.invokeMethod("onChromeSafariBrowserOpened", arguments: ["uuid": uuid])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func onChromeSafariBrowserLoaded(uuid: String) {
|
func onChromeSafariBrowserLoaded(uuid: String) {
|
||||||
if let safariViewController = self.safariViewControllers[uuid] {
|
if self.safariViewControllers[uuid] != nil {
|
||||||
channel.invokeMethod("onChromeSafariBrowserLoaded", arguments: ["uuid": uuid])
|
channel.invokeMethod("onChromeSafariBrowserLoaded", arguments: ["uuid": uuid])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,26 @@ import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
typedef Future<dynamic> ListenerCallback(MethodCall call);
|
typedef Future<dynamic> ListenerCallback(MethodCall call);
|
||||||
|
|
||||||
var uuidGenerator = new Uuid();
|
var _uuidGenerator = new Uuid();
|
||||||
|
|
||||||
|
///
|
||||||
|
enum ConsoleMessageLevel {
|
||||||
|
DEBUG, ERROR, LOG, TIP, WARNING
|
||||||
|
}
|
||||||
|
|
||||||
|
///Public class representing a JavaScript console message from WebCore.
|
||||||
|
///This could be a issued by a call to one of the console logging functions (e.g. console.log('...')) or a JavaScript error on the page.
|
||||||
|
///
|
||||||
|
///To receive notifications of these messages, override the [InAppBrowser.onConsoleMessage()] function.
|
||||||
|
class ConsoleMessage {
|
||||||
|
|
||||||
|
String sourceURL = "";
|
||||||
|
int lineNumber = 1;
|
||||||
|
String message = "";
|
||||||
|
ConsoleMessageLevel messageLevel = ConsoleMessageLevel.LOG;
|
||||||
|
|
||||||
|
ConsoleMessage(this.sourceURL, this.lineNumber, this.message, this.messageLevel);
|
||||||
|
}
|
||||||
|
|
||||||
class _ChannelManager {
|
class _ChannelManager {
|
||||||
static const MethodChannel channel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser');
|
static const MethodChannel channel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser');
|
||||||
|
@ -53,14 +72,14 @@ class _ChannelManager {
|
||||||
|
|
||||||
///InAppBrowser class.
|
///InAppBrowser class.
|
||||||
///
|
///
|
||||||
/// This class uses the native WebView of the platform.
|
///This class uses the native WebView of the platform.
|
||||||
class InAppBrowser {
|
class InAppBrowser {
|
||||||
|
|
||||||
String uuid;
|
String uuid;
|
||||||
|
|
||||||
///
|
///
|
||||||
InAppBrowser () {
|
InAppBrowser () {
|
||||||
uuid = uuidGenerator.v4();
|
uuid = _uuidGenerator.v4();
|
||||||
_ChannelManager.addListener(uuid, _handleMethod);
|
_ChannelManager.addListener(uuid, _handleMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +106,19 @@ class InAppBrowser {
|
||||||
String url = call.arguments["url"];
|
String url = call.arguments["url"];
|
||||||
shouldOverrideUrlLoading(url);
|
shouldOverrideUrlLoading(url);
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
return new Future.value("");
|
return new Future.value("");
|
||||||
}
|
}
|
||||||
|
@ -291,6 +323,11 @@ class InAppBrowser {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Event fires when the [InAppBrowser] webview receives a [ConsoleMessage].
|
||||||
|
void onConsoleMessage(ConsoleMessage consoleMessage) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///ChromeSafariBrowser class.
|
///ChromeSafariBrowser class.
|
||||||
|
@ -305,7 +342,7 @@ class ChromeSafariBrowser {
|
||||||
|
|
||||||
///Initialize the [ChromeSafariBrowser] instance with a [InAppBrowser] fallback instance or `null`.
|
///Initialize the [ChromeSafariBrowser] instance with a [InAppBrowser] fallback instance or `null`.
|
||||||
ChromeSafariBrowser (bf) {
|
ChromeSafariBrowser (bf) {
|
||||||
uuid = uuidGenerator.v4();
|
uuid = _uuidGenerator.v4();
|
||||||
browserFallback = bf;
|
browserFallback = bf;
|
||||||
_ChannelManager.addListener(uuid, _handleMethod);
|
_ChannelManager.addListener(uuid, _handleMethod);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: flutter_inappbrowser
|
name: flutter_inappbrowser
|
||||||
description: A Flutter plugin that allows you to open an in-app browser window. (inspired by the popular cordova-plugin-inappbrowser).
|
description: A Flutter plugin that allows you to open an in-app browser window. (inspired by the popular cordova-plugin-inappbrowser).
|
||||||
version: 0.2.0
|
version: 0.2.1
|
||||||
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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue