url拦截是在H5请求一个地址后,客户端拦截住这个地址,对地址进行解析处理
H5中调用iOS方法代码:
<a href="news://login">弹出登录弹窗(拦截url)</a>
iOS中拦截到url代码:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
// 判断地址是否是需要拦截url
if ([request.URL.absoluteString hasPrefix:@"news://login"]) {
//弹出登录弹窗
[self login];
// 禁止打开页面
return NO;
}
return YES;
}
弹窗包括:alert、confirm、prompt, 和url拦截类似都在回调方法中处理
以WKWebView的alert为例:
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
NSLog(@"弹窗信息:%@",message);
}
JSC只适用于UIWebView,UIWebView基本被WKWebView替代
<body>
<input type="button" name="" value="登录" onclick="login()">
<script type="text/javascript">
// 登录
function login(){
// 调用app登录方法
app.login();
}
</script>
</body>
iOS代码:
iOS中封装AppJSObject, 用于注入方法
AppJSObject.h
#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
#import "AppJSObject.h"
@implementation AppJSObject
- (void)login{
[self.delegate login];
}
@end
// 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;
}
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代码
- (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]
}
}
JS桥接第三方框架
(1)第三方框架DSBridge
(2)第三方框架WebViewJavascript
1. UIWebView
2. WKWebView
stringByEvaluatingJavaScriptFromString
[self.webView stringByEvaluatingJavaScriptFromString:@"loginResult('success')"];
evaluateJavaScript:completionHandler:
[self.wkWebView evaluateJavaScript:@"loginResult('success')" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"结果%@", result);
}];
1. 拦截url 2. 拦截弹窗 3. JavaScriptInterface(JSI) 4. JSBridge
和iOS中使用类似
H5中调用iOS方法代码:
<a href="news://login">弹出登录弹窗(拦截url)</a>
Android中拦截到url代码:
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
}
);
以alert为例
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
System.out.print(url);
return true;
}
H5端代码
<body>
<input type="button" name="" value="登录" onclick="login()">
<script type="text/javascript">
// 登录
function login(){
// 调用app登录方法
window.app.login();
}
</script>
</body>
Android代码
webView.addJavascriptInterface(this, "app");
1. loadUrl() 2. evaluateJavascript() (Android4.4之后)
// 调用H5中的loginResult函数
webView.loadUrl("javascript:loginResult()");
webView.evaluateJavascript("javascript:loginResult()", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
System.out.print(s);
}
});
callNative/callNativeWithPromise/callUIFunction
前端代码
call('login')
前端代码,监听调用
hippyEventEmitter.addListener("loginResult", (e) => {
console.log(’登录‘,e) ;
});
iOS代码
[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代码
HippyMap hippyMap = new HippyMap();
hippyMap.pushString("success");
mEngineManager.getCurrentEngineContext()
.getModuleManager()
.getJavaScriptModule(EventDispatcher.class)
.receiveNativeEvent("loginResult", hippyMap);
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。