当前位置:网站首页>How does H5 communicate with native apps?
How does H5 communicate with native apps?
2022-06-23 22:14:00 【User 9253515】
Preface
To improve development efficiency , Developers tend to use native app Nested front end inside h5 The rapid development of pages , This is about h5 And native inter calls , Transfer data to each other , Next, make a simple record and share about the interaction mode in the practice project , I don't say much nonsense , Direct to the text :
Thanks to Android and ios It's not the same way , So we have to deal with it separately First, paste the code to judge the access terminal
// Judge the access terminal
function browserVersion(){
var u = navigator.userAgent;
return { trident: u.indexOf('Trident') > -1, //IE kernel presto: u.indexOf('Presto') > -1, //opera kernel webKit: u.indexOf('AppleWebKit') > -1, // Apple 、 Google kernel gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1,// Firefox kernel mobile: !!u.match(/AppleWebKit.*Mobile.*/), // Is it a mobile terminal
ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios terminal
android: u.indexOf('Android') > -1 || u.indexOf('Adr') > -1, //android terminal iPhone: u.indexOf('iPhone') > -1 , // Is it iPhone perhaps QQHD browser iPad: u.indexOf('iPad') > -1, // whether iPad webApp: u.indexOf('Safari') == -1, // whether web It should be programmed , No head and bottom weixin: u.indexOf('MicroMessenger') > -1, // Wechat or not (2015-01-22 newly added )qq: u.match(/\sQQ/i) == " qq" // whether QQ
};
Understand the principle of communication first webview
IOS Containers stay IOS The client , The first thing we want to mention is a man named UIWebView The container of , Apple introduced him as :
UIWebView Is an object that can load web pages , It has the function of browsing records , And the loaded web page content is programmable . To put it bluntly UIWebView It has browser like functions , We can use it to open the page , And do some customized functions , If you can let js Call a method to get the mobile phone GPS Information .
But it should be noted that ,Safari Browser controls used by the browser and UIwebView Components are not the same , There is a big gap in performance between the two . Fortunately, , Apple released iOS8 When , I added a new one WKWebView Component containers , If your APP Only consider supporting iOS8 And above , Then you can use this new browser control .
WKWebView Reconstruct the original UIWebView Of 14 Classes ,3 Agreements , While improving performance , It gives developers more detailed configuration ( These configurations are for clients only IOS Development , For front-end H5 Come on , It is important to keep the two container invocation methods consistent ).
Android Containers In the Android client ,webView The container is consistent with the browser kernel of the mobile phone , Mostly for android-chrome. There are no compatibility and performance issues .
RN Containers stay react-native In development , from rn 0.37 The version officially introduced components , Call the native browser in Android , stay IOS Is called by default UIWebView Containers . from IOS12 Start , Apple was officially abandoned UIWebView, Unified adoption WKWebView.
RN from 0.57 rise , It can be specified that WKWebView As WebView The implementation of the
// rn js code
<WebView useWebKit={true} source={{ url: 'https://m.douyu.com' }} />
WebView Components should not be nested in or native click components , Can cause H5 Inner page scrolling failure
h5 towards ios Client sends message ;
stay ios in , There is no ready-made api Give Way js To call native Methods , however UIWebView And WKWebView Be able to intercept h5 All network requests initiated within . So our thinking is through h5 Initiate a network request for a specific protocol agreed in , Such as 'jsbridge://bridge2.native?params=' + encodeURIComponent(obj) Then take it with you and pass it on to ios Parameters of ; After the request with the specified protocol header is intercepted in the client, the request is blocked and parsed url Parameters on , Execute the corresponding logic
stay H5 There are two ways to initiate this specific protocol request in :
adopt localtion.href;
adopt location.href There is a problem , That is, if we modify it many times in a row window.location.href Value , stay Native The layer can only receive the last request , All previous requests will be ignored .
adopt iframe The way ;
Use iframe The way , To evoke Native; Take the evocation sharing component as an example
// h5 js code Encapsulate it
function createIframe(url){
var url = 'jsbridge://getShare?title= Share the title &desc= Share description &link=http%3A%2F%2Fwww.douyu.com&cbName=jsCallClientBack';
var iframe = document.createElement('iframe');iframe.style.width = '1px';
iframe.style.height = '1px';
iframe.style.display = 'none';
iframe.src = https://segmentfault.com/a/url;
document.body.appendChild(iframe);
setTimeout(function() {iframe.remove();
}, 100);
}
The client then intercepts the request , And the corresponding methods and parameters are analyzed : Here we use ios For example :
// IOS swift code
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
let url = request.URL
let scheme = url?.scheme
let method = url?.host
let query = url?.query
if url != nil && scheme == "jsbridge" { switch method! {case "getShare":
self.getShare()
default:
print("default")}
return false
} else {return true
}
}
If you don't understand, just skip , Non emphasis .....
Here we add cbName=jsCallClientBack, This jsCallClientBack by JS Call the callback function defined by the client , At the business level jsBridge In package , We pass in an anonymous function as a callback , The bottom layer binds this function to window Of jsbridge Object and define a unique key, This key Namely jsCallClientBack, After the client has processed the logic , The method described above will be used to call back window The way to go .
ps: After binding the callback to window Next time , Pay special attention to using bind Keep inside the function this The original direction of is unchanged
IOS Client calls H5 Method
Native call Javascript Language , It's through UIWebView Component's stringByEvaluatingJavaScriptFromString Method to achieve , This method returns js The execution result of the script .
// IOS swift code
webview.stringByEvaluatingJavaScriptFromString("window.methodName()")
From the above code, we can see that it actually implements a string js Code , Called window Next object , If we want to let native To call us js The method of writing , Then this method should be in window You can access . But from the overall point of view , We just expose an object such as JSBridge to native Just call .
The callback function that calls the client's native method will also be bound to window For the client to successfully counter call , In fact, the final result of a single call to a client method is a two-way call to each other .
H5 call Android Client method
On Android webView There are three calls in native The way :
adopt schema The way , Client side usage shouldOverrideUrlLoading Method pair url Request the protocol to parse . such js The method of calling and ios The same as , Use iframe To call native Method . By means of webview The page is directly injected with native js Code mode , Use addJavascriptInterface Method to implement .
// android JAVA code
class JSInterface {
@JavascriptInterface
public String getShare() {//...
return "share";
}
}
webView.addJavascriptInterface(new JSInterface(), "AndroidNativeApi");
The above code is in the page window Objects are injected with AndroidNativeApi object . stay js You can call native methods directly in .
Use prompt,console.log,alert The way , These three methods are right js Li is a native property , stay android webview This layer can override these three methods . Generally we use prompt, Because this is js It's not used much in , For and native Communication side effects are less .
// android JAVA code
class WebChromeClient extends WebChromeClient {
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {// rewrite window Under the prompt, adopt result Return results
}
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {}
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {}
}
Generally speaking, Android clients choose 1、2 One of the schemes to communicate , From the front-end level , It is recommended that all clients use schema The way of agreement , Convenient for front end jsBridge Maintenance and iteration of the underlying code .
Android Client calls H5 Method
On Android APP in , Client pass webview Of loadUrl To call :
// android JAVA code
webView.loadUrl("javascript:window.jsBridge.getShare()");
H5 The client binds the method to window The object under the , There is no need to communicate with IOS Make a distinction
H5 call RN client
We know RN Of webView A component is actually a secondary encapsulation of a native container , So we don't need to go directly through schema Protocol to communicate , Just use the browser postMessage、onMessage To deliver a message , Be similar to iframe, And the real communication process RN It's already done for us .
// h5 js code
window.postMessage(data);
// rn js code
<WebView
ref="webView"
source={require('../html/index.html')} injectedJavaScript={'window.androidConfig = {}'} // Through this props Can be in webView Inject attribute methods during initialization onMessage={e => { let { data } = e.nativeEvent;//...
}}
/>
RN Client calls H5
postMessage It's two-way , So it can also be in RN Inside message ,H5 Receive a message to trigger the corresponding callback
this.refs.webView.postMessage({
cbName: 'xxx',
param: {}});
front end jsBridge Encapsulation
In understanding js After the communication principle with the client bottom , We can IOS、 Android is packaged into jsBridge It is provided to the business layer to develop calls .
class JsBridge {
static lastCallTime
constructor() { if (UA.isReactNative()) { document.addEventListener('message', function(e) {window.jsClientCallBack[e.data.cbName](e.data.param);
});
}
}
// Universal callNtive Method
callClient(functionName, data, callback) {// Avoid continuous calls
if (JsBridge.lastCallTime && (Date.now() - JsBridge.lastCallTime) < 100) { setTimeout(() => {this.callClient(functionName, data, callback);
}, 100);
return;
}
JsBridge.lastCallTime = Date.now();
data = data || {}; if (callback) {const cbName = randomName();
Object.assign(data, { cbName });window.jsClientCallBack[cbName] = callBack.bind(this);
}
if (UA.isIOS()) { data.forEach((key, value) => { try {data[key] = JSON.stringify(value);
} catch(e) { }});
var url = 'jsbridge://' + functionName + '?' parseJSON(data);
var iframe = document.createElement('iframe');iframe.style.width = '1px';
iframe.style.height = '1px';
iframe.style.display = 'none';
iframe.src = url;
document.body.appendChild(iframe);
setTimeout(() => {iframe.remove();
}, 100);
} else if (UA.isAndroid()) { // The Android client uses the second communication method mentioned above window.AndroidNativeApi &&
window.AndroidNativeApi[functionName] &&
window.AndroidNativeApi[functionName](JSON.stringify(data));
} else if (UA.isReactNative()) { //rn Of <webView> Components can be set props.userAgent To make the H5 distinguish window.postMessage(
JSON.stringify(data);
);
} else { console.error(' Not obtained platform Information , Transfer api Failure ');}
}
// Business layer custom methods
getShare(data, callBack) {//..
}
}
On the basis of core encapsulation , We can do more optimization , For example, each callback function is self destructed to release memory after being called
Four 、 debugging
Use the android chrome://inspect debug , Need to climb over the wall IOS Use mac safari Of develop Option to debug Use RN Of http://localhost:8081/debugger-ui Only debugging RN Code , Unable to debug webView Code ,RN Next webView Debugging and corresponding native identical , But in chrome://inspect There will be style problems under . Unless it is pure RN To write , Pack it directly into APP, Otherwise, it is not recommended to RN Call down webView Components
Related courses
Android Basic series of tutorials : Android basic course U- Summary _ Bili, Bili _bilibiliAndroid basic course UI- Layout _ Bili, Bili _bilibiliAndroid basic course UI- Control _ Bili, Bili _bilibiliAndroid basic course UI- Animation _ Bili, Bili _bilibiliAndroid basic course -activity Use _ Bili, Bili _bilibiliAndroid basic course -Fragment Usage method _ Bili, Bili _bilibiliAndroid basic course - Hot repair / The principle of thermal renewal technology _ Bili, Bili _bilibili
In this paper, from https://juejin.cn/post/6885988193402159118, If there is any infringement , Please contact to delete .
边栏推荐
- Performance optimization of database 5- database, table and data migration
- How to select Poe, poe+, and poe++ switches? One article will show you!
- Apt attack
- 微信小程序中发送网络请求
- What is zero copy?
- How to deploy the API gateway? Is it OK not to use the API gateway?
- How to deal with high memory in API gateway how to maintain API gateway
- How do API gateways set up dynamic routing? What are the benefits of dynamic routing?
- Summary of redis Functions PHP version
- To develop AI face comparison, how to output multiple faces with comparative similarity?
猜你喜欢

Error running PyUIC: Cannot start process, the working directory ‘-m PyQt5. uic. pyuic register. ui -o

微信小程序中发送网络请求

The latest research progress of domain generalization from CVPR 2022

HDLBits-&gt;Circuits-&gt;Arithmetic Circuitd-&gt;3-bit binary adder
Performance optimization of database 5- database, table and data migration

CAD图在线Web测量工具代码实现(测量距离、面积、角度等)

Code implementation of CAD drawing online web measurement tool (measuring distance, area, angle, etc.)

北大、加州伯克利大學等聯合| Domain-Adaptive Text Classification with Structured Knowledge from Unlabeled Data(基於未標記數據的結構化知識的領域自適應文本分類)

Intel openvino tool suite advanced course & experiment operation record and learning summary

MySQL de duplication query only keeps one latest record
随机推荐
How to open a stock account? What are the main considerations for opening an account? Is there a security risk in opening an account online?
Benchclock: a benchmark for evaluating semantic analysis language models
Polar cycle graph and polar fan graph of high order histogram
Go language core 36 lectures (go language practice and application 26) -- learning notes
HDLBits-&gt; Circuits-&gt; Arithmetic Circuitd-&gt; 3-bit binary adder
ICML2022 | 基于对比学习的离线元强化学习的鲁棒任务表示
Basic concepts and common methods of syntactic dependency analysis
Take you to understand the lazy loading of pictures
Flink practical tutorial: advanced 4-window top n
Deep understanding of leakcanary
Experiment 5 module, package and Library
New high-speed random graph API interface, the first sci-fi graph API interface
Acl2022 | MVR: multi view document representation for open domain retrieval
How to use the serial port assistant in STC ISP?
Devops sharing: how to hold the meeting?
什么是股票线上开户?手机开户安全么?
Summary of redis Functions PHP version
Performance optimization of database 5- database, table and data migration
Using barcode software to make certificates
Tencent cloud server ubuntu18 installs MySQL and logs in remotely