微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

HTML5和原生app如何进行交互?

本篇文章给大家带来的内容是关于HTML5和原生app如何进行交互?有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

h5与原生 app 交互的原理

现在移动端 web 应用,很多时候都需要与原生 app 进行交互、沟通(运行在 webview 中),比如微信的 jssdk,通过 window.wx 对象调用一些原生 app 的功能。所以,这次就来捋一捋 h5 与原生 app 交互的原理。

h5 与原生 app 的交互,本质上说,就是两种调用

  1. app 调用 h5 的代码

  2. h5 调用 app 的代码

1. app 调用 h5 的代码

因为 app 是宿主,可以直接访问 h5,所以这种调用比较简单,就是在 h5 中曝露一些全局对象(包括方法),然后在原生 app 中调用这些对象。

251094793-5bcd47918084f_articlex.png

javascript

window.sdk = {
  double = value => value * 2,
  triple = value => value * 3,
};

android

webview.evaluateJavascript('window.sdk.double(10)', new ValueCallback<String>() {
  @Override
  public void onReceiveValue(String s) {
    // 20
  }
});

ios

Nsstring *func = @window.sdk.double(10);
Nsstring *str = [webview stringByEvaluatingJavaScriptFromString:func]; // 20

2. h5 调用 app 的代码

因为 h5 不能直接访问宿主 app,所以这种调用就相对复杂一点。

这种调用常用有两种方式:

  1. 由app向h5注入一个全局js对象,然后在h5直接访问这个对象

  2. 由h5发起一个自定义协议请求,app拦截这个请求后,再由app调用 h5 中的回调函数

2.1 由 app 向 h5 注入一个全局 js 对象

这种方式沟通机制简单,比较好理解,并且对于 h5 来说,没有新的东西,所以是比较推荐的一种方式。但这种方式可能存在安全隐患,详细查看 你不知道的 Android WebView 使用漏洞。

668561095-5bcd479f406f3_articlex.png

android

webview.addJavascriptInterface(new Object() {
  @JavascriptInterface
  public int double(value) {
    return value * 2;
  }
  
  @JavascriptInterface
  public int triple(value) {
    return value * 3;
  }
}, appSdk);

ios

Nsstring *scripts = @window.appSdk = {double: value => value * 2, triple: value => value * 3};
[webview stringByEvaluatingJavaScriptFromString:scripts];

javascript

window.appSdk.double(10); // 20

2.2 由 h5 发起一个自定义协议请求

这种方式要稍复杂一点,因为需要自定义协议,这对很多前端开发者来说是比较新的东西。所以一般不推荐这种方式,可以作为第一种方式的补充。

大致需要以下几个步骤:

  1. 由 app自定义协议,比如 sdk://action?params

  2. 在 h5 定义好回调函数,比如 window.bridge = {getDouble: value => {}, getTriple: value => {}}

  3. 由 h5 发起一个自定义协议请求,比如 location.href = 'sdk://double?value=10'

  4. app 拦截这个请求后,进行相应的操作,获取返回值

  5. 由 app 调用 h5 中的回调函数,比如 window.bridge.getDouble(20);

568479427-5bcd47ade3aa8_articlex.png

javascript

window.bridge = {
  getDouble: value => {
    // 20
  }, 
  getTriple: value => {
    // more  
  }
};

location.href = 'sdk://double?value=10';

android

webview.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // 判断如果 url 是 sdk:// 打头的就拦截掉
        // 然后从 url sdk://action?params 中取出 action 与params 
        
        Uri uri = Uri.parse(url);                                 
        if ( uri.getScheme().equals(sdk)) {

            // 比如 action = double, params = value=10
            webview.evaluateJavascript('window.bridge.getDouble(20)');

            return true;
        }
        return super.shouldOverrideUrlLoading(view, url);
    }
});

ios

- (BOOL)webview:(UIWebView *)webview shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
  // 判断如果 url 是 sdk:// 打头的就拦截掉
  // 然后从 url sdk://action?params 中取出 action 与params

  Nsstring *urlStr = request.URL.absoluteString;
  
  if ([urlStr hasPrefix:@sdk://]) {
    
    // 比如 action = double, params = value=10
    Nsstring *func = @window.bridge.getDouble(20);
    [webview stringByEvaluatingJavaScriptFromString:func];

    return NO;
  }

  return YES;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。