JS调用iOS方法
- url拦截
- 弹窗拦截(alert、confirm、prompt)
- JavaScriptCore(只适用于UIWebView)
- WKScriptMessageHandler(只适用于WKWebView,iOS8 )
- Bridge第三方框架(适用于UIWebView和WKWebView)
1. url拦截
url拦截是在H5请求一个地址后,客户端拦截住这个地址,对地址进行解析处理
H5中调用iOS方法代码:
代码语言:javascript复制<a href="news://login">弹出登录弹窗(拦截url)</a>
iOS中拦截到url代码:
代码语言:javascript复制- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
// 判断地址是否是需要拦截url
if ([request.URL.absoluteString hasPrefix:@"news://login"]) {
//弹出登录弹窗
[self login];
// 禁止打开页面
return NO;
}
return YES;
}
2. 弹窗拦截
弹窗包括:alert、confirm、prompt, 和url拦截类似都在回调方法中处理
以WKWebView的alert为例:
代码语言:javascript复制- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
NSLog(@"弹窗信息:%@",message);
}
3. JavaSciptCore(JSC)
JSC只适用于UIWebView,UIWebView基本被WKWebView替代
代码语言:javascript复制<body>
<input type="button" name="" value="登录" onclick="login()">
<script type="text/javascript">
// 登录
function login(){
// 调用app登录方法
app.login();
}
</script>
</body>
iOS代码:
iOS中封装AppJSObject, 用于注入方法
AppJSObject.h
代码语言:javascript复制#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>
@protocol AppJSObjectDelegate <JSExport>
-(void)login;
@end
@interface AppJSObject : NSObject<AppJSObjectDelegate>
@property(nonatomic,weak) id<AppJSObjectDelegate> delegate;
@end
AppJSObject.m
代码语言:javascript复制#import "AppJSObject.h"
@implementation AppJSObject
- (void)login{
[self.delegate login];
}
@end
代码语言:javascript复制// H5加载完成
- (void)webViewDidFinishLoad:(UIWebView *)webView{
// js运行上下文,交互接口
JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 承载方法的对象
AppJSObject *jsObject = [[AppJSObject alloc] init];
jsObject.delegate = self;
// 将方法注入接口
context[@"app"] = jsObject;
}
4. WKScriptMessageHandler
WKScriptMessageHandler是一个协议,iOS中按照协议实现回调方法,在回调方法中可以拿到js发送的消息
window.webkit.messageHandlers.(app方法名).postMessage()
H5代码
<body>
<input type="button" name="" value="登录" onclick="login()">
<script type="text/javascript">
// 登录
function login(){
// 调用app登录方法
window.webkit.messageHandlers.login.postMessage()
}
</script>
</body>
iOS代码
代码语言:javascript复制- (void)viewDidLoad {
WKWebViewConfiguration * config = [[WKWebViewConfiguration alloc] init];
config.userContentController = [[WKUserContentController alloc] init];
// 添加监听
[config.userContentController addScriptMessageHandler:self name:@"login"];
// 创建webview
WKWebView * webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:config];
webView.UIDelegate = self;
}
// H5 window.webkit.messageHandlers.(app方法名).postMessage() 方法调用监听回调
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
if ([message.name isEqualToString:@"login"]) {
// 调用登录功能
[self login]
}
}
5. JSBridge
JS桥接第三方框架
(1)第三方框架DSBridge
(2)第三方框架WebViewJavascript
iOS调用JS方法
1. UIWebView
2. WKWebView
1. UIWebView
stringByEvaluatingJavaScriptFromString
代码语言:javascript复制[self.webView stringByEvaluatingJavaScriptFromString:@"loginResult('success')"];
2. WKWebView
evaluateJavaScript:completionHandler:
代码语言:javascript复制 [self.wkWebView evaluateJavaScript:@"loginResult('success')" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"结果%@", result);
}];
JS调用Android
1. 拦截url 2. 拦截弹窗 3. JavaScriptInterface(JSI) 4. JSBridge
1. 拦截url
和iOS中使用类似
H5中调用iOS方法代码:
代码语言:javascript复制<a href="news://login">弹出登录弹窗(拦截url)</a>
Android中拦截到url代码:
代码语言:javascript复制webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (Uri.parse(url).getHost().equals("news://login")) {
// 调用登录函数
this.login();
return true;
}
return false
}
);
2. 拦截弹窗
- onJsAlert、onJsPrompt、onJsConfirm
以alert为例
代码语言:javascript复制@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
System.out.print(url);
return true;
}
3. JavaScriptInterface
H5端代码
代码语言:javascript复制<body>
<input type="button" name="" value="登录" onclick="login()">
<script type="text/javascript">
// 登录
function login(){
// 调用app登录方法
window.app.login();
}
</script>
</body>
Android代码
代码语言:javascript复制webView.addJavascriptInterface(this, "app");
Android调用JS
1. loadUrl() 2. evaluateJavascript() (Android4.4之后)
1. loadUrl
代码语言:javascript复制// 调用H5中的loginResult函数
webView.loadUrl("javascript:loginResult()");
2. evaluateJavascript
代码语言:javascript复制webView.evaluateJavascript("javascript:loginResult()", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
System.out.print(s);
}
});
JS Hippy中调用iOS、Android
callNative/callNativeWithPromise/callUIFunction
前端代码
代码语言:javascript复制call('login')
iOS、Android Hippy中调用JS
前端代码,监听调用
代码语言:javascript复制 hippyEventEmitter.addListener("loginResult", (e) => {
console.log(’登录‘,e) ;
});
iOS代码
代码语言:javascript复制[self sendEvent: @"loginResult" params: @{@"success"}];
- (void)sendEvent:(NSString *)eventName params:(NSDictionary *)params
{
HippyAssertParam(eventName);
[self.bridge.eventDispatcher dispatchEvent:@"EventDispatcher" methodName:@"receiveNativeEvent" args:@{@"eventName": eventName, @"extra": params ? : @{}}];
}
Android代码
代码语言:javascript复制HippyMap hippyMap = new HippyMap();
hippyMap.pushString("success");
mEngineManager.getCurrentEngineContext()
.getModuleManager()
.getJavaScriptModule(EventDispatcher.class)
.receiveNativeEvent("loginResult", hippyMap);