App与 JS 交互,桥连接代码以及原理

App与 JS 交互桥连接代码以及原理

概述: 1 使用demo   2 文档 3 源码解析

  1. 举个例子

1,js调用app

 

2,app 调用js

 

2,文档

(1)js 调用app

// 调用时传递的参数均为字符串,未方便书写,写成了对象形式,下同。

/**

 * 向app发起请求

 * actionName {String} 调用app的方法名

 * @param args.__token {String} token为唯一标识,用来区别,同一方法的多次调用。

 * @param args 其他的所有字段均为请求时需要的数据

 */

// js调用app,iOS

window.webkit.messageHandlers['actionName'].postMessage({

    __token: 'token',

    ...args

});

// js调用app,Android

window.AndroidInterface['actionName']({

    __token: 'token',

    ...args

});

 

// app处理完毕后回调js

/**

 * app处理完毕后回调js

 * @param args.__name {String} js调用app时使用的方法名

 * @param args.__token {String} js调用时传递的token

 * @param args.__status {Number} 是否处理成功,Number类型 0为成功,其他值为失败

 * @param args.__message {String} 可选,如果处理失败,则必须在这个字段中添加失败描述

 * @param args 其他的所有字段均为处理后的返回结果

 */

window['myApp2jsBridge.callback']({

    __name: 'actionName',

    __token: 'token',

    __status: 0,

    __message: '',

    ...args

});

 

  1. app 调用js

/**

 * 向js发起请求

 * @param args.__name {String} js处理完毕后回调app的方法名

 * @param args.__token {String} token为唯一标识,用来区别,同一方法的多次调用。

 * @param args 其他的所有字段均为请求时需要的数据

 */

window['myApp2jsBridge.trigger']({

    __name: 'actionName',

    __token: 'token',

    ...args

});

 

/**

 * js处理完毕后回调app

 * actionName {String} app发起调用时传递的方法名

 * @param args.__token {String} app调用时传递的token

 * @param args.__status {Number} 是否处理成功,Number类型 0为成功,其他值为失败

 * @param args.__message {String} 可选,如果处理失败,则必须在这个字段中添加失败描述

 * @param args 其他的所有字段均为处理后的返回结果

 */

// js回调app,iOS

window.webkit.messageHandlers['actionName'].postMessage({

    __token: 'token',

    __status: 0,

    __message: '',

    ..args

});

// js回调app,Android

window.AndroidInterface['actionName']({

    __token: 'token',

    __status: 0,

    __message: '',

    ...args

})

 

  1. 源码
  2. /* eslint-disable */

    /* 前端调用app后。告诉app 调用的方法,与此同时注册(同名)回调函数

    * 在app执行完毕后,调用(同名)回调函数达到 get 参数的目的;

    * 原理: 利用windows 为载体,发布订阅,结合 promise

    *

    *

    */

     

    let CALLBACK_NAME = 'myApp2jsBridge.callback';

    let TRIGGER_NAME = 'myApp2jsBridge.trigger';

    const ua = navigator.userAgent.toLowerCase();

    let isIOS = /iphone|ipad|ipod/.test(ua);

    let isAndroid = /android/.test(ua);

     

    let send = function(name, params) {

    let data = JSON.stringify(params);

    switch (true) {

    case isIOS:

    sendIOS(name, data);

    break;

    case isAndroid:

    sendAndroid(name, data);

    break;

    default:

    console.log('不是移动端', name, params);

    }

    };

     

    let getToken = (function() {

    let num = 0;

    return function() {

    num++;

    return `${num}`;

    };

    })();

     

    function clone(base, obj) {

    if (arguments.length === 1) {

    obj = base;

    base = {};

    }

    for (let key in obj) {

    if (obj.hasOwnProperty(key)) {

    base[key] = obj[key];

    }

    }

    return base;

    }

     

    window[CALLBACK_NAME] = function(args) {

    let name = args.__name;

    let token = args.__token;

    if (!name || !token) return;

    if (window[CALLBACK_NAME][name] && window[CALLBACK_NAME][name][token]) {

    window[CALLBACK_NAME][name][token](args);

    delete window[CALLBACK_NAME][name][token];

    }

    };

     

    // app主动触发js,把方法放到数组中

    window[TRIGGER_NAME] = function(args) {

    let name = args.__name;

    let token = args.__token;

    if (!name || !token) return;

    if (window[TRIGGER_NAME][name]) {

    window[TRIGGER_NAME][name].forEach((fn) => {

    fn && fn(args);

    });

    }

    };

     

    function sendIOS(name, params) {

    try {

    window.webkit.messageHandlers[name].postMessage(params);

    } catch (e) {

    console.log('ios消息发送失败', e.message);

    }

    }

     

    function sendAndroid(name, params) {

    try {

    params ? window.AndroidInterface[name](params) : window.AndroidInterface[name]();

    } catch (e) {

    console.log('android消息发送失败', e.message);

    }

    }

     

    /**

    * js向app发送详细

    * @name<String>: 接口名

    * @params<Object>:参数对象,不需要传空对象

    * @needCallback<Boolean>: 是否需要Promise回调

    * */

    export function js2app(name, params, needCallback) {

    if (!!needCallback === false) {

    return send(name, params);

    }

    let token = getToken();

    return new Promise((resolve, reject) => {

    window[CALLBACK_NAME][name] = window[CALLBACK_NAME][name] || {};

    window[CALLBACK_NAME][name][token] = function(args) {

    args = args || {};

    if (args.__status === 0) {

    delete args.__name;

    delete args.__token;

    delete args.__status;

    delete args.__message;

    resolve(args);

    } else {

    reject(args.__message);

    console.error(name + '\n' + args.__message)

    }

    };

    send(name, clone({ __token: token }, params));

    });

    }

     

    /**

    * app调用js中的方法

    * @name<String>: js中的方法名给app标识用

    * @callback<Function>: js使用的回调方法,如果回调方法返回一个Primose,会自动通知app端

    * */

    export function app2js(name, callback) {

    window[TRIGGER_NAME][name] = window[TRIGGER_NAME][name] || [];

    window[TRIGGER_NAME][name].push((args) => {

    let token = args.__token;

    // var data = clone({}, args);

    let promise;

    delete args.__name;

    delete args.__token;

    promise = callback(clone({}, args));

    promise && promise.then && promise.then(

    (data) => {

    let result = clone({

    __token: token,

    __status: 0,

    }, data);

    send(name, result);

    },

    (message) => {

    let sendData = {};

    let status = 1;

    let result;

    if (typeof message === 'object') {

    sendData = message;

    status = sendData.status || status;

    message = sendData.message;

    sendData = sendData.data || {};

    }

    result = clone({

    __token: token,

    __status: status,

    __message: message,

    }, sendData);

    send(name, result);

    },

    );

    });

    }

     

/* eslint-disable */

/* 前端调用app后。告诉app 调用的方法,与此同时注册(同名)回调函数

* 在app执行完毕后,调用(同名)回调函数达到 get 参数的目的;

* 原理: 利用windows 为载体,发布订阅,结合 promise

*

*

*/

 

let CALLBACK_NAME = 'myApp2jsBridge.callback';

let TRIGGER_NAME = 'myApp2jsBridge.trigger';

const ua = navigator.userAgent.toLowerCase();

let isIOS = /iphone|ipad|ipod/.test(ua);

let isAndroid = /android/.test(ua);

 

let send = function(name, params) {

let data = JSON.stringify(params);

switch (true) {

case isIOS:

sendIOS(name, data);

break;

case isAndroid:

sendAndroid(name, data);

break;

default:

console.log('不是移动端', name, params);

}

};

 

let getToken = (function() {

let num = 0;

return function() {

num++;

return `${num}`;

};

})();

 

function clone(base, obj) {

if (arguments.length === 1) {

obj = base;

base = {};

}

for (let key in obj) {

if (obj.hasOwnProperty(key)) {

base[key] = obj[key];

}

}

return base;

}

 

window[CALLBACK_NAME] = function(args) {

let name = args.__name;

let token = args.__token;

if (!name || !token) return;

if (window[CALLBACK_NAME][name] && window[CALLBACK_NAME][name][token]) {

window[CALLBACK_NAME][name][token](args);

delete window[CALLBACK_NAME][name][token];

}

};

 

// app主动触发js,把方法放到数组中

window[TRIGGER_NAME] = function(args) {

let name = args.__name;

let token = args.__token;

if (!name || !token) return;

if (window[TRIGGER_NAME][name]) {

window[TRIGGER_NAME][name].forEach((fn) => {

fn && fn(args);

});

}

};

 

function sendIOS(name, params) {

try {

window.webkit.messageHandlers[name].postMessage(params);

} catch (e) {

console.log('ios消息发送失败', e.message);

}

}

 

function sendAndroid(name, params) {

try {

params ? window.AndroidInterface[name](params) : window.AndroidInterface[name]();

} catch (e) {

console.log('android消息发送失败', e.message);

}

}

 

/**

* js向app发送详细

* @name<String>: 接口名

* @params<Object>:参数对象,不需要传空对象

* @needCallback<Boolean>: 是否需要Promise回调

* */

export function js2app(name, params, needCallback) {

if (!!needCallback === false) {

return send(name, params);

}

let token = getToken();

return new Promise((resolve, reject) => {

window[CALLBACK_NAME][name] = window[CALLBACK_NAME][name] || {};

window[CALLBACK_NAME][name][token] = function(args) {

args = args || {};

if (args.__status === 0) {

delete args.__name;

delete args.__token;

delete args.__status;

delete args.__message;

resolve(args);

} else {

reject(args.__message);

console.error(name + '\n' + args.__message)

}

};

send(name, clone({ __token: token }, params));

});

}

 

/**

* app调用js中的方法

* @name<String>: js中的方法名给app标识用

* @callback<Function>: js使用的回调方法,如果回调方法返回一个Primose,会自动通知app端

* */

export function app2js(name, callback) {

window[TRIGGER_NAME][name] = window[TRIGGER_NAME][name] || [];

window[TRIGGER_NAME][name].push((args) => {

let token = args.__token;

// var data = clone({}, args);

let promise;

delete args.__name;

delete args.__token;

promise = callback(clone({}, args));

promise && promise.then && promise.then(

(data) => {

let result = clone({

__token: token,

__status: 0,

}, data);

send(name, result);

},

(message) => {

let sendData = {};

let status = 1;

let result;

if (typeof message === 'object') {

sendData = message;

status = sendData.status || status;

message = sendData.message;

sendData = sendData.data || {};

}

result = clone({

__token: token,

__status: status,

__message: message,

}, sendData);

send(name, result);

},

);

});

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值