1. 适用场景

本章内容主要解决混合模式开发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){ ... }); :异步回调

  1. 在 APP 打通的环境下,会执行回调函数。
  2. 如果没有打通,回调函数不会被调用。
  3. 这个方法的主要作用,就是考虑到 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);

results matching ""

    No results matching ""