1.2.1.9 打通App与H5
本章内容主要解决混合模式开发App中,H5与App原生内容的数据打通。主要解决问题:1.原生native与H5页面UserID的打通;2.补充部分H5无法拿到的App信息,例如应用版本;3.为了数据发送策略更加准确,新版本中JS数据将会由Native进行发送,此时包括APPKEY在内的数据将替换成APP数据;
1.1. 使用
首先需要打通的页面请引入js-sdk,APP-sdk请引入对应的版本;
1.1.1. Android SDK
V2.1 及之后的版本才支持该功能;备注:Android 2.1~2.1.5虽然打通了native和h5,但是没有完全打通。只有Android 2.1.6以后才完全打通。
在初始化WebView时,调用showUpWebView()
DATracker.getInstance().showUpWebView(mWebView, true);
如果需要传递其它自定义属性,可以按如下方式调用:
try {
JSONObject properties = new JSONObject();
properties.put("testKey", "testValue");
DATracker.getInstance().showUpWebView(webView, isSupportJellyBean, properties);
} catch (Exception ex) {
ex.printStackTrace();
}
isSupportJellyBean: 是否支持API level 16及以下的版本。 因为API level 16及以下的版本, addJavascriptInterface有安全漏洞,请谨慎使用。
1.1.2. iOS SDK
V2.1.4 及之后的版本才支持该功能
为了防止 H5 不在 App 环境下浏览时,track 的事件无法通过 JavaScript SDK 发送。在初始化完 iOS SDK 之后,调用如下接口:
[[DATracker sharedTracker] addWebViewUserAgentFlag];
需要在WebView加载完成时,调用:
- (BOOL)showUpWebView:(id)webView request:(NSURLRequest *)request;
- (BOOL)showUpWebView:(id)webView request:(NSURLRequest *)request properties:(NSDictionary *)properties;
如果是UIWebView
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSMutableDictionary *properties = [[NSMutableDictionary alloc] init];
[properties setValue:@"testValue" forKey:@"testKey"];
if ([[DATracker sharedTracker] showUpWebView:webView request:request properties:properties]) {
return NO;
}
return YES;
}
如果是WKWebView
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSMutableDictionary *properties = [[NSMutableDictionary alloc] init];
[properties setValue:@"testValue" forKey:@"testKey"];
if ([[DATracker sharedTracker] showUpWebView:webView request:navigationAction.request properties:properties]) {
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
1.1.3. JavaScript SDK
使用该功能需要使用 同步引入 JavaScript
方式,即直接用 script 标签引入 SDK 代码(请查看JS SDK使用说明)。
JS SDK 在 v1.4.0 以及之后版本,初始化时新增 use_app_track
配置项,只要配置为 true , 即可支持APP采集H5页面数据。
DATracker.init('xxx', {use_app_track: true});
JS SDK 在 v1.1.0 及之后的版本中提供一个方法 DATracker.get_appStatus 方法来获取 App 传递的信息。调用方式:DATracker.get_appStatus(function(app_info){ ... }); :异步回调
- 在 APP 打通的环境下,会执行回调函数。
- 如果没有打通,回调函数不会被调用。
- 这个方法的主要作用,就是考虑到 iOS 的异步问题,所以会在取到数据后自动回调。
示例
使用回调方式,JS SDK 获取到 AppInfo 之后再执行应用代码,例如:
DATracker.get_appStatus(function(app_info){
//设置 userId
DATracker.login(app_info.userId);
//自定义事件
DATracker.track('ProductSelect'});
});
需要注意的是,这个回调在没有打通时不会触发。因此,如果这个页面既会在 App 打通的环境下使用,又会在未打通的情况下使用,需要参考以下代码来实现:
// 定义一个函数,这个函数根据当前是否在 App 内做出不同的处理
function trackInApp(trackFunc) {
// 这里需要判断是在 App 里还是在普通的浏览器里,例如可以根据 UserAgent 或者 Cookie 来判断
if (isInApp) {
DATracker.get_appStatus(function(app_info){
DATracker.login(app_info.userId);
trackFunc();
});
} else {
trackFunc();
}
}
// 实现实际的埋点逻辑
trackInApp(function() {
DATracker.track('ProductSelect'});
})
// 上述只是针对代码埋点可以独立出来的情况下的处理方式。如果您的埋点代码必须在您的业务代码块中执行,需要考虑下面延迟的方式来处理
主动延迟调用。这种方式会导致数据延迟发送,在某些情况下可能会导致数据丢失,但是不用区分是否在 App 环境下:
setTimeout(function(){
var app_info = DATracker.get_appStatus();
// app_info 可能获取不到,例如非 App 环境,或者 App 端没有启用 AppInfo。
if (app_info) {
DATracker.login(app_info.userId);
}
DATracker.track('ProductSelect'});
}, 500);
1.1.4. 原理
Android
webview初始化时,安卓sdk往页面中注册HubbleData_APP_JS_Bridge对象。
js-sdk获取APP传到页面的信息
var app_info = HubbleData_APP_JS_Bridge.hubbledata_call_app();
js-sdk将采集到数据传递给APP,即APP采集h5页面信息
HubbleData_APP_JS_Bridge.hubbledata_track(data);
iOS
webview初始化时,iOS会在userAgent
中注入hubbledata-sdk-ios
标记
js-sdk获取APP传到页面的信息
a. js-sdk注册 hubbledata_app_js_bridge_call_js
函数JS 在载入成功后,会通知 iOS 来调用hubbledata_app_js_bridge_call_js
方法。经测试,iOS 会在 JS 加载完成之后的 500ms 以内调用这个函数,因此存在调用延迟。
//ios, 获取发给客户端数据
window.hubbledata_app_js_bridge_call_js = function(data){
setAppInfo(data);
};
b. 通知iOS调用该方法
function calliOSData() {
if(/hubbledata-sdk-ios/.test(navigator.userAgent)) {
var iframe = document.createElement("iframe");
iframe.setAttribute("src", "hubbledata://getAppInfo");
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
}
js-sdk将采集到数据传递给APP,即APP采集h5页面信息
// 页面发送给iOS数据
function iOS_hubbledata_track(data) {
var iframe = document.createElement("iframe");
iframe.setAttribute("src", "hubbledata://trackEvent?event=" + encodeURIComponent(data));
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
//js-sdk调用该方法将数据传递给APP
iOS_hubbledata_track(data);