前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >H5和移动端通信

H5和移动端通信

原创
作者头像
无忧366
发布2022-10-21 17:31:24
1.3K0
发布2022-10-21 17:31:24
举报
文章被收录于专栏:Hello worldHello world

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JS调用iOS方法
    • 1. url拦截
      • 2. 弹窗拦截
        • 3.  JavaSciptCore(JSC)
          • 4. WKScriptMessageHandler
            • 5. JSBridge
            • iOS调用JS方法
              • 1. UIWebView
                • 2.  WKWebView
                • JS调用Android
                  • 1. 拦截url
                    • 2. 拦截弹窗
                      • 3. JavaScriptInterface
                      • Android调用JS
                        • 1. loadUrl
                          •  2.  evaluateJavascript
                          • JS Hippy中调用iOS、Android
                          • iOS、Android Hippy中调用JS
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档