H5&&Android交互

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了H5&&Android交互相关的知识,希望对你有一定的参考价值。

参考技术A JS调用android原生方法,参数须是Java的内置类型:int、String等,若是javascript对象,需字符串化,否则Android无法正确接收;

JS调用Android原生方法,返回值是内置类型:int、String等,JS能够正确接收。若是Java自定义类型,则JS接收不到正确数据;

JS可以通过Android原生方法的返回值获取内置类型的参数,如String

若需要互传复杂类型的对象,双方须以String对媒介,以各自语言的Json工具类进行相互转化;

Vue框架下 JS与native的交互(iOS&Android)

需求: 在原生App里打开webview, 嵌入H5. 在H5中点击某个元素, 触发与native app交互, 又跳回到app中. 同理, 在app中完成某项操作后, 获得某个参数, 根据这个状态刷新页面.

框架: Vue. JavaScript原生的写法已经调通了, 并且与native端的已经联调通过. 所以这里是把它们迁移到Vue框架的写法.

这里要区分iOS系统和Android系统.

iOS系统

  1. 在这里与iOS开发的同事协商后, 决定使用 WebViewJavascriptBridge来开发. 前端不需要放入任何js插件. 只需要准备一下这段内容.

bridge.js

function setupWebViewJavascriptBridge(callback) {
  if (window.WebViewJavascriptBridge) {
    return callback(window.WebViewJavascriptBridge)
  }
  if (window.WVJBCallbacks) {
    returnwindow.WVJBCallbacks.push(callback)
  }
  window.WVJBCallbacks = [callback]
  let WVJBIframe = document.createElement(‘iframe‘)
  WVJBIframe.style.display = ‘none‘
  WVJBIframe.src = ‘https://__bridge_loaded__‘
  document.documentElement.appendChild(WVJBIframe)
  setTimeout(() => {
    document.documentElement.removeChild(WVJBIframe)
  }, 0)
}

export default {
  callhandlerIOS(name, data, callback) {
      setupWebViewJavascriptBridge(function (bridge) {
        bridge.callHandler(name, data, callback)
      })
    },
  registerhandlerIOS(name, callback) {
      setupWebViewJavascriptBridge(function (bridge) {
        bridge.registerHandler(name, function (data, responseCallback) {
          callback(data, responseCallback)
        })
      })
    }
}
  1. 在main.js里注入
import Bridge from "./js/bridge.js";

Vue.prototype.$bridge = Bridge  //在这里注入后, 页面里所有需要用到调用native的地方, 都可以直接调用this.$bridge.xxx

new Vue({
  el: "#app",
  router,
  store,
 // Bridge,  
  components: { App },
  template: "<App/>",
})
  1. 在要使用的.vue文件里使用

这里举一个例子.

H5调用iOS

callNative方法里使用this.$bridge.callhandler(‘ObjC Echo‘, params, function(response){//todo})

其中ObjC Echo是和客户端约定好的方法. 即在客户端注册好的方法, 写上这个方法名, 在使用的时候客户端就能接收到, 从而拿到params里的参数, 而后面跟的function(response){}就是处理response里的数据. 进行一些操作.

this.$bridge.callhandlerIOS(
    "HY_H5_CALL_NATIVE",
    { action: "pick me" },
    data => {
        // 处理返回数据
    }
)
iOS调用H5

使用this.$bridge.registerhandler(‘JS Echo‘, (data, responseCallback)=>{//todo}

JS Echo即是和客户端约定好的方法名, 在客户端使用这个方法名时, 会自动调起H5执行某些操作. 客户端传来的信息放在data里, responseCallback即执行回调.

this.$bridge.registerhandlerIOS("JS Echo", (data, responseCallback) => {
    alert("JS Echo called with:", data);
    // this.responseCallback(data)
});

Android系统

由于Android系统同样也使用webviewJavaScriptBridge, 所以我自然而然想到了是否也能像iOS一样export出两个处理的handler.

  1. 在bridge.js中添加声明代码
//Android 交互声明
function connectWebViewJavascriptBridgeANDROID(callback) {
  if (window.WebViewJavascriptBridge) {
    callback(WebViewJavascriptBridge);
  } else {
    document.addEventListener(
      "WebViewJavascriptBridgeReady",
      function () {
        callback(WebViewJavascriptBridge);
      },
      false
    );
  }
}

  1. 在bridge.js的export中添加导出

这里我在handler后面添加了Android作为和iOS的handler做区分.


  callhandlerAndroid(name, data, callback){  //Android方法
    connectWebViewJavascriptBridgeANDROID(function(bridge){
      bridge.callHandler(name, data, callback)
    })
  },
  registerhandlerAndroid(name, callback){  //Android方法
    connectWebViewJavascriptBridgeANDROID(function(bridge){
      bridge.init(function(message, responseCallback) {
        if (responseCallback) {
          // responseCallback(data);
        }
      });
      bridge.registerHandler(name, function(data, responseCallback){
        callback(data, responseCallback)
      })
    })
  }
  1. .vue文件中使用. 使用方法同iOS
JS调用Android
this.$bridge.callhandlerAndroid(
    ‘action‘, 
    {message: ‘111‘},
    function(response){}
)
Android调用JS
this.$bridge.registerhandlerAndroid(
    "registerAction",
    (message, responseCallback) => {
        alert("JS Echo called with:" + message);
        // this.responseCallback(data)
    }
);

至此, js和Android, iOS端就算调通了.

感觉Android这一块还有很多可以优化的地方, 但是我的js还掌握的不是很牢靠...所以就先这样吧. 等以后我又新的感悟了, 再来更新.

附上所有代码

  1. bridge.js代码
//iOS 交互声明
function connectWebViewJavascriptBridgeIOS(callback) {
  if (window.WebViewJavascriptBridge) {
    return callback(window.WebViewJavascriptBridge)
  }
  if (window.WVJBCallbacks) {
    returnwindow.WVJBCallbacks.push(callback)
  }
  window.WVJBCallbacks = [callback]
  let WVJBIframe = document.createElement(‘iframe‘)
  WVJBIframe.style.display = ‘none‘
  WVJBIframe.src = ‘https://__bridge_loaded__‘
  document.documentElement.appendChild(WVJBIframe)
  setTimeout(() => {
    document.documentElement.removeChild(WVJBIframe)
  }, 0)
}


//Android 交互声明
function connectWebViewJavascriptBridgeANDROID(callback) {
  if (window.WebViewJavascriptBridge) {
    callback(WebViewJavascriptBridge);
  } else {
    document.addEventListener(
      "WebViewJavascriptBridgeReady",
      function () {
        callback(WebViewJavascriptBridge);
      },
      false
    );
  }
}

export default {
  callhandlerIOS(name, data, callback) { //iOS的方法
    connectWebViewJavascriptBridgeIOS(function (bridge) {
      bridge.callHandler(name, data, callback)
    })
  },
  registerhandlerIOS(name, callback) { //iOS的方法
    connectWebViewJavascriptBridgeIOS(function (bridge) {
      bridge.registerHandler(name, function (data, responseCallback) {
        callback(data, responseCallback)
      })
    })
  },
  callhandlerAndroid(name, data, callback){  //Android方法
    connectWebViewJavascriptBridgeANDROID(function(bridge){
      bridge.callHandler(name, data, callback)
    })
  },
  registerhandlerAndroid(name, callback){  //Android方法
    connectWebViewJavascriptBridgeANDROID(function(bridge){
      bridge.init(function(message, responseCallback) {
        if (responseCallback) {
          // responseCallback(data);
        }
      });
      bridge.registerHandler(name, function(data, responseCallback){
        callback(data, responseCallback)
      })
    })
  }
}
  1. main.js代码
import Bridge from "./js/bridge.js";

Vue.prototype.$bridge = Bridge


/* eslint-disable no-new */
new Vue({
  el: "#app",
  router,
  store,
  components: { App },
  template: "<App/>",
});

  1. .vue文件
<template>
    <div>
        <h1>hi, this is a test</h1>
        <h2 v-if="isShow">234</h2>      
        <button @click="callNative">点击点击</button>
        <h3>234</h3>
    </div>
</template>

<script>
export default {
    data() {
        return {
            isShow: false
        };
    },
    created() {
        this.$bridge.registerhandlerIOS("JS Echo", (data, responseCallback) => {
            alert("JS Echo called with:", data);
            // this.responseCallback(data)
        });
        this.$bridge.registerhandlerAndroid(
            "registerAction",
            (message, responseCallback) => {
                alert("JS Echo called with:" + message);
                // this.responseCallback(data)
            }
        );
    },
    methods: {
        callNative() {
            this.isShow = !this.isShow;
            if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
                this.$bridge.callhandlerIOS(
                    "HY_H5_CALL_NATIVE",
                    { action: "pick me" },
                    data => {
                        // 处理返回数据
                    }
                )
            }else if (/(Android)/i.test(navigator.userAgent)){
                this.$bridge.callhandlerAndroid(
                    ‘action‘, 
                    {message: ‘111‘},
                    function(response){}
                )
            }
        },

    }
};
</script>

<style>
button {
    margin: 30px auto;
    display: block;
    padding: 10px;
    border: 1px solid #ccc;
    background-color:dodgerblue
}
</style>

以上是关于H5&&Android交互的主要内容,如果未能解决你的问题,请参考以下文章

android项目嵌套uniapp页面及交互

PC&H5适配

PC&H5视频

PC&H5适配

Android WebView与H5交互

Android-WebView加载网络图片&网页