H5和移动端通信

2022-10-21 17:31:24 浏览数 (2)

JS调用iOS方法

  1. url拦截
  2. 弹窗拦截(alert、confirm、prompt)
  3. JavaScriptCore(只适用于UIWebView)
  4. WKScriptMessageHandler(只适用于WKWebView,iOS8 )
  5. 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代码

代码语言:javascript复制
<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]
     }
}

以getAppInfo函数为例以getAppInfo函数为例

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");

以getAppInfo函数为例以getAppInfo函数为例

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);

0 人点赞