Skip to content

Commit

Permalink
Add support for sending data from webview to native in iOS and Android
Browse files Browse the repository at this point in the history
  • Loading branch information
OPY-bbt committed Jun 26, 2019
1 parent 90f1e5a commit 8473e75
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.webkit.CookieManager;
import android.webkit.JavascriptInterface;
import android.webkit.GeolocationPermissions;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
Expand Down Expand Up @@ -244,6 +245,8 @@ public void onProgressChanged(WebView view, int progress) {
FlutterWebviewPlugin.channel.invokeMethod("onProgressChanged", args);
}
});

webView.addJavascriptInterface(new WebAppInterface(), "Android");
}

private Uri getOutputFilename(String intentType) {
Expand Down Expand Up @@ -495,4 +498,13 @@ void stopLoading(MethodCall call, MethodChannel.Result result){
webView.stopLoading();
}
}

public class WebAppInterface {
@JavascriptInterface
public void postMessage(String value){
Map<String, String> postMessageMap = new HashMap<>();
postMessageMap.put("postMessage", value);
FlutterWebviewPlugin.channel.invokeMethod("onPostMessage", postMessageMap);
}
}
}
30 changes: 30 additions & 0 deletions example/html/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button id="button" style="background-color:#158461;height:30px;">send to flutter</button>

<script>
function sendData(data) {
if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)){
window.webkit.messageHandlers.Native.postMessage(data);
}else{
if (window.Android && window.Android.postMessage) {
Android.postMessage(data);
}
}
}

window.onload = function () {
document.getElementById('button').onclick = function () {
sendData(JSON.stringify({ action: 'log', data: '1234' }));
}
}
</script>
</body>
</html>
14 changes: 7 additions & 7 deletions example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
objects = {

/* Begin PBXBuildFile section */
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
Expand Down Expand Up @@ -40,7 +39,8 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
0FF8E441CB3BD619650FCC75 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
2BCC7A531667984C22F241E2 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
Expand Down Expand Up @@ -77,6 +77,8 @@
840012C8B5EDBCF56B0E4AC1 /* Pods */ = {
isa = PBXGroup;
children = (
2BCC7A531667984C22F241E2 /* Pods-Runner.debug.xcconfig */,
0FF8E441CB3BD619650FCC75 /* Pods-Runner.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
Expand All @@ -86,7 +88,6 @@
children = (
3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
Expand Down Expand Up @@ -211,7 +212,6 @@
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
Expand Down Expand Up @@ -241,8 +241,8 @@
files = (
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../../../../../flutter/bin/cache/artifacts/engine/ios/Flutter.framework",
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../../../../../../Documents/flutter/bin/cache/artifacts/engine/ios/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/flutter_webview_plugin/flutter_webview_plugin.framework",
);
name = "[CP] Embed Pods Frameworks";
Expand All @@ -252,7 +252,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Original</string>
</dict>
</plist>
25 changes: 24 additions & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const kAndroidUserAgent =
'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Mobile Safari/537.36';

String selectedUrl = 'https://flutter.io';
String messageUrl = 'your_server/index.html';

void main() => runApp(MyApp());

Expand Down Expand Up @@ -99,6 +100,8 @@ class _MyHomePageState extends State<MyHomePage> {

StreamSubscription<double> _onScrollXChanged;

StreamSubscription<String> _onMessage;

final _urlCtrl = TextEditingController(text: selectedUrl);

final _codeCtrl = TextEditingController(text: 'window.navigator.userAgent');
Expand Down Expand Up @@ -173,6 +176,14 @@ class _MyHomePageState extends State<MyHomePage> {
});
}
});

_onMessage = flutterWebViewPlugin.onPostMessage.listen((msg) {
if (mounted) {
setState(() {
_history.add('message: $msg');
});
}
});
}

@override
Expand All @@ -185,6 +196,7 @@ class _MyHomePageState extends State<MyHomePage> {
_onProgressChanged.cancel();
_onScrollXChanged.cancel();
_onScrollYChanged.cancel();
_onMessage.cancel();

flutterWebViewPlugin.dispose();

Expand All @@ -211,12 +223,23 @@ class _MyHomePageState extends State<MyHomePage> {
flutterWebViewPlugin.launch(
selectedUrl,
rect: Rect.fromLTWH(0.0, 0.0, MediaQuery.of(context).size.width, 300.0),
userAgent: kAndroidUserAgent,
// userAgent: kAndroidUserAgent,
invalidUrlRegex: r'^(https).+(twitter)', // prevent redirecting to twitter when user click on its icon in flutter website
);
},
child: const Text('Open Webview (rect)'),
),
RaisedButton(
onPressed: () {
flutterWebViewPlugin.launch(
messageUrl,
rect: Rect.fromLTWH(0.0, 0.0, MediaQuery.of(context).size.width, 300.0),
// userAgent: kAndroidUserAgent,
invalidUrlRegex: r'^(https).+(twitter)', // prevent redirecting to twitter when user click on its icon in flutter website
);
},
child: const Text('Open Webview (message demo)'),
),
RaisedButton(
onPressed: () {
flutterWebViewPlugin.launch(selectedUrl, hidden: true);
Expand Down
13 changes: 12 additions & 1 deletion ios/Classes/FlutterWebviewPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,13 @@ - (void)initWebview:(FlutterMethodCall*)call {
rc = self.viewController.view.bounds;
}

self.webview = [[WKWebView alloc] initWithFrame:rc];
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.userContentController = [[WKUserContentController alloc] init];
// 注入JS对象Native,
// 声明WKScriptMessageHandler 协议
[config.userContentController addScriptMessageHandler:self name:@"Native"];

self.webview = [[WKWebView alloc] initWithFrame:rc configuration:config];
self.webview.UIDelegate = self;
self.webview.navigationDelegate = self;
self.webview.scrollView.delegate = self;
Expand Down Expand Up @@ -338,6 +344,11 @@ - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNaviga
decisionHandler(WKNavigationResponsePolicyAllow);
}

#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
[channel invokeMethod:@"onPostMessage" arguments: @{@"postMessage": message.body}];
}

#pragma mark -- UIScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
if (scrollView.pinchGestureRecognizer.isEnabled != _enableZoom) {
Expand Down
8 changes: 8 additions & 0 deletions lib/src/base.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'dart:ui';

import 'package:flutter/material.dart';
Expand Down Expand Up @@ -31,6 +32,7 @@ class FlutterWebviewPlugin {
final _onScrollYChanged = StreamController<double>.broadcast();
final _onProgressChanged = new StreamController<double>.broadcast();
final _onHttpError = StreamController<WebViewHttpError>.broadcast();
final _onPostMessage = StreamController<String>.broadcast();

Future<Null> _handleMessages(MethodCall call) async {
switch (call.method) {
Expand Down Expand Up @@ -62,6 +64,9 @@ class FlutterWebviewPlugin {
case 'onHttpError':
_onHttpError.add(WebViewHttpError(call.arguments['code'], call.arguments['url']));
break;
case 'onPostMessage':
_onPostMessage.add(call.arguments['postMessage']);
break;
}
}

Expand Down Expand Up @@ -90,6 +95,8 @@ class FlutterWebviewPlugin {

Stream<WebViewHttpError> get onHttpError => _onHttpError.stream;

Stream<String> get onPostMessage => _onPostMessage.stream;

/// Start the Webview with [url]
/// - [headers] specify additional HTTP headers
/// - [withJavascript] enable Javascript or not for the Webview
Expand Down Expand Up @@ -212,6 +219,7 @@ class FlutterWebviewPlugin {
_onScrollXChanged.close();
_onScrollYChanged.close();
_onHttpError.close();
_onPostMessage.close();
_instance = null;
}

Expand Down

0 comments on commit 8473e75

Please sign in to comment.