One, foreword

In recent years, hybrid development is becoming more and more popular, and the need to connect App and H5 is becoming more and more urgent.

What is the connection between App and H5?

The so-called “get through” means that after H5 integrates the JavaScript data acquisition SDK, the events triggered by H5 are not synchronized to the server directly, but first sent to the App data acquisition SDK, which is processed by the App data acquisition SDK and then stored in the local cache for synchronization.

The content of this article is mainly to answer the following two questions:

  • Why should App and H5 be connected?
  • How to get through App and H5?

2. Reasons for the connection between App and H5

Why should App connect with H5? We mainly consider it from the following perspectives:

  • Data loss rate
  • Data accuracy
  • The user id
  • Basis function

The following are introductions for you.

2.1 Data loss rate

In the industry, the loss rate of data collected by App terminal is generally around 1%, while that collected by H5 is generally around 5% (mainly due to cache, network or page switching etc.).

Therefore, if App and H5 are connected, all events triggered by H5 can be first sent to the App data acquisition SDK and stored in the local cache after secondary processing by App. Data loss can be reduced from 5% to about 1% by synchronizing data after conforming to a specific policy.

2.2 Data accuracy

As is known to all, H5 cannot obtain device information directly. It can only obtain limited information by parsing the UserAgent value. However, parsing the UserAgent value may cause at least two problems:

  • Some information is not available by parsing the UserAgent value, such as the version number of the application;
  • Some information can be obtained by parsing the UserAgent value, but the content may be incorrect.

If App and H5 are connected, the data acquisition SDK on the App side can supplement these information to ensure the accuracy and integrity of the event information.

2.3 User ID

Anonymous IDS are generally used to identify users before they register or log in to the App. However, the rules of App and H5 to identify anonymous users are different (Android generally uses Android ID and H5 generally uses Cookie), resulting in two anonymous ids for one user.

If App gets through to H5, the two anonymous ids can be normalized (the anonymous ID of App end shall prevail).

2.4 Basic Functions

Through App and H5, more advanced functions such as visualization of full buried points can be realized.

After introducing the reason for getting through, let’s take a look at how App and H5 get through.

3. Get through the scheme evolution

In the aspect of getting through, God policy has accumulated rich experience, but also stepped on many pits. At present, we have explored three ways to get through the program. We will introduce these ways one by one according to the order of technological evolution, and analyze their background, principles and shortcomings.

3.1 Earlier Version (1.0)

3.1.1 Background and Principles

The last section introduced why H5 connection should be made, among which there is a key point: “If App and H5 are connected, the two anonymous ids can be normalized”. Simply speaking, the user ID of App is used to identify the behavior of H5. Add the user ID of App to the data transmitted from H5 to the server, and then upload it to the server, so as to unify the user behavior of the mobile terminal.

In order to make the event data generated by H5 use the user ID of the App, the first thought is to send the user information of the App to H5, which is exactly what Shence did in the early opening scheme.

The basic principle is to inject JSBridge into the WebView (see the official Building Web Apps in WebView[1] to see how Android and H5 pages call each other). JSBridge provides methods for JS calls in H5 that return is_login (identifying whether the customer is logged in to the App), distinct_id (user ID), and so on. As shown in Figure 3-1:

Figure 3-1 Solution of earlier versions

Figure 3-1 describes the opening scheme of the early version, that is, the user information of App is transmitted to H5 through JSBridge, and then H5 adds the user information to the event to realize the unification of the user identity of App and H5 page. The code snippet for this approach is as follows:

Injection JSBridge

webView.addJavascriptInterface(new AppWebViewInterface(mContext, properties), "SensorsData_APP_JS_Bridge");
Copy the code

JSBridge class

class AppWebViewInterface {
    private static final String TAG = "SA.AppWebViewInterface";
    private Context mContext;
    private JSONObject properties;
 
    AppWebViewInterface(Context c, JSONObject p) {
        this.mContext = c;
        this.properties = p;
    }
 
    @JavascriptInterface
    public String sensorsdata_call_app() {
        try {
            if (properties == null) {
                properties = new JSONObject();
            }
            properties.put("type", "Android");
            String loginId = SensorsDataAPI.sharedInstance(mContext).getLoginId();
            if (!TextUtils.isEmpty(loginId)) {
                properties.put("distinct_id", loginId);
                properties.put("is_login", true);
            } else {
                properties.put("distinct_id", SensorsDataAPI.sharedInstance(mContext).getAnonymousId());
                properties.put("is_login", false);
            }
            return properties.toString();
        } catch (JSONException e) {
            SALog.i(TAG, e.getMessage());
        }
        return null;
    }
}
Copy the code

3.1.2 Scheme Defects

Once you have seen this approach, you may have noticed that H5 sends data directly to the server. This is the opposite of what we described in Chapter 1: H5 calls reduce data loss. You may also notice that once the WebView is injected into the JSBridge object, So all H5 loaded by this WebView (specifically, pages that integrate with the Web JS SDK) will use is_LOGIN and DISTINCt_ID fields provided by the App.

If the WebView loads another H5 page integrated with The Shence Web JS SDK, there will be a big problem, because the information provided by the App is added to another customer’s H5, which will bring great trouble to another customer.

Note:

Shengce Web JS SDK provides flag bits for whether the H5 page is opened or not, which can be selectively opened for some H5 pages. This point is not reflected in the above flow chart. By default, the flag bits of H5 are opened for this article.

3.2 Mid-term Version (2.0)

3.2.1 Background and Principles

The 1.0 scheme introduces the implementation of the early version of H5 and the existing two problems: first, the data is sent through the H5 page; Second, the indiscriminate treatment will bring great trouble to other customers’ H5. To address both of these issues, we modified the 1.0 schema.

First, we send the data generated on the H5 page to the App, and then the App side provides a verification identifier to judge whether to verify the data receiving address of the H5 data and the data receiving address of the App side. Modify the above flowchart, as shown in Figure 3-2:

Figure 3-2 Solution of clearing through in the mid-term version

Figure 3-2 illustrates the logic in version 2.0. First, the JSBridge object provides a Boolean sensorsDatA_verify (String event) method to receive and verify H5 data. Note that the return value of this method is true, indicating that the verification has passed. The data will be sent through the App; False indicates that the verification fails and data is sent through H5.

In this way, the customer’s own H5 data can be sent through App. For other H5 pages integrated with Shence Web JS SDK, because the verification server_URL does not pass, H5 sends its own data.

With that in mind, let’s look at the code implementation:

Injection JSBridge

Copy the code

This code injects a JSBridge object into the WebView. Note that the AppWebViewInterface constructor has an enableVerify parameter, which controls whether the verification is required on the App side. Let’s look at the code for AppWebViewInterface:

AppWebViewInterface class

class AppWebViewInterface { private static final String TAG = "SA.AppWebViewInterface"; private Context mContext; private boolean enableVerify; AppWebViewInterface(Context c, boolean b) { this.mContext = c; this.enableVerify = b; } @JavascriptInterface public boolean sensorsdata_verify(String event) { try { if (! enableVerify) { sensorsdata_track(event); return true; } return SensorsDataAPI.sharedInstance(mContext)._trackEventFromH5(event); } catch (Exception e) { SALog.printStackTrace(e); return false; }}}Copy the code

Note that the sensorsdatA_verify method is not verified when enableVerify is false.

Therefore, as long as any data sent by H5 is sent through App, and the return value of H5 calling this method is true, it means that the data has been processed in App and H5 will not send this data again. If enableVerify is true, the App checks whether the server_URL for H5 to send data is the same as the server_url for the App.

If they are the same, it will return true to indicate that App processes this data; if they are different, it will return false to indicate that verification fails and data is still sent through H5 terminal.

3.2.2 Scheme Defects

From the principles and code shown in the previous section, several problems can be identified:

  • Suppose the App side calls the following code to inject JSBridge into the WebView:
Copy the code

If enableVerify is always set to false, the H5 data of the Web JS SDK integrated by other customers will still be sent to the App, resulting in the loss of data of other customers and the increase of dirty data of current customers.

  • If the client’s App has a lot of WebViews to get through, then we need to call the above code for each WebView, which is not elegant enough;

  • There is another reason that we must improve, that is, our visual full buried point function depends on the open function, or even if not open, we hope to enable customers to use the visual full buried point function to prompt customers to open. For the function of visualization full buried point, please refer to “Introduction to Visualization full buried Point” on our official website [2].

3.3 Mature Version (3.0)

3.3.1 Background and Principles

It can be seen that version 2.0 is an improvement on the defects of version 1.0, but it does not solve the problem that when customers do not verify data, “other customers integrate the H5 page of The Web JS SDK of God policy and send it to the App, resulting in the loss of data of other customers and the increase of dirty data of current customers”.

If there are many WebViews in the App, JSBridge has to be injected into each WebView, which will cause a lot of work for the client. At the same time, you need to be technically ready to visualize full buried points. In order to solve these problems, Shenpolicy has upgraded version 2.0. The specific solution is divided into two steps:

  • Create a channel for each WebView. Inject AppWebViewInterfaceBridge channels, can also be injected into other JSBridge, such as visual JSBridge buried point feature requires all;

  • Change data verification rules. In version 2.0, the verification is placed on App side. Now, the verification is placed on H5 side. H5 side determines whether data needs to be sent to App.

Figure 3-3 shows the process of this solution:

The first step of the solution is to establish the channel, which needs to be realized from the bytecode level by using the SDK plug-in [3] of Shence. The plugin scans a class file for methods like webView.loadURL (String URL). . We will use to replace it into SensorsDataAutoTrackHelper loadUrl (webview, url), this method is that we establish the channel, the code is as follows:

SensorsDataAutoTrackHelper

Public static void loadUrl(View webView, String url) {//webView can be a native Android webView or Tencent X5WebView, set the type to View, If (webView == null) {throw new NullPointerException(" webView has not initialized. } setupH5Bridge(webView); // Set JSBridge //... JSBridge invokeWebViewLoad(webView, "loadUrl", new Object[]{url}, new Class[]{string.class}); / / by reflection calls webview. LoadUrl} private static void setupH5Bridge (View webview) {if (SensorsDataAPI. SharedInstance () instanceof SensorsDataAPIEmptyImplementation) { return; } if (isSupportJellyBean() && SensorsDataAPI.sharedInstance().getConfigOptions() ! = null && SensorsDataAPI.sharedInstance().getConfigOptions().isAutoTrackWebView) { setupWebView(webView); } if (isSupportJellyBean()) { addWebViewVisualInterface(webView); } } private static void invokeWebViewLoad(View webView, String methodName, Object[] params, Class[] paramTypes) { try { Class<? > clazz = webView.getClass(); Method loadMethod = clazz.getMethod(methodName, paramTypes); loadMethod.invoke(webView, params); } catch (Exception e) { SALog.printStackTrace(e); }}Copy the code

The code above is god SensorsDataAutoTrackHelper class code fragment in the Android SDK. When integrated with the Shenze Android SDK plug-in, the plug-in replaces the following code:

H5Activity

class H5Activity : BaseActivity() { private val TAG: String = "H5Activity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_h5) AndroidWebView. LoadUrl (" https://www.sensorsdata.cn ") the code here will be plug-in replace SensorsDataAutoTrackHelper. LoadUrl (androidWebView, "https://www.sensorsdata.cn") } }Copy the code

By doing this, we replace the original page loading method with the channel method, and in the channel method we call the logic that originally loaded the page by reflection. Of course, we can inject not only the JSBridge that gets through in the channel, but also the JSBridge that other businesses need without the customer having to write the code to do so.

JSBridge = H5; JSBridge = H5; JSBridge = H5;

AppWebViewInterface

class AppWebViewInterface { private static final String TAG = "SA.AppWebViewInterface"; AppWebViewInterface() {} Server_url @javascriptInterface Public String SensorsDatA_get_server_URL () {return SensorsDataAPI.sharedInstance().getConfigOptions().isAutoTrackWebView ? SensorsDataAPI.sharedInstance().getServerUrl() : ""; }}Copy the code

As you can see, we only provided a sensorsDatA_get_server_URL method, which H5 will call to get the App server_URL and compare it with its own whitelist list.

If the server_URL exists in the whitelist, the verification is considered to pass and the data will be sent to App. If App server_URL is empty or does not match its own whitelist, the verification fails and H5 sends data directly. In this way, the initiative of verification is placed on the H5 end, which solves the problem that “other customers integrate the H5 page of The Web JS SDK of Shengce and send it to the App, resulting in the loss of data of other customers and the increase of dirty data of current customers”. Please refer to the technical guide [4] for information about the Shenze Web JS SDK.

3.3.2 Scheme Defects

As you can see from the previous section, the Android plugin needs to scan the code in the method, which increases the plug-in compilation time, but there is currently no better way. In the future, more configurations that need to be completed on the SDK side will be completed by plug-ins, so that customers can use our SDK functions without writing or with as little code as possible.

Four,

Android SDK H5 solution evolution can be said to be built on the basis of business drivers and requirements continue to evolve, now to version 3.0. From the current point of view, this version of the idea is better, better scalability. Whether there is a better plan in the future depends on the specific business needs, and we will continue to explore to see if there is a better plan. If you have better ideas, please join the open source community and share them with us.

Reference: [1] developer.android.com/guide/webap… [2] manual. Sensorsdata. Cn/sa/latest / %… [3] github.com/sensorsdata… [4] manual. Sensorsdata. Cn/sa/latest/t…

Article source: Shence Technology Community