Android Implementation of a No‑Tracking User Behavior Analysis SDK (WMDA)
This article details the design, technology selection, and implementation of WMDA, a no‑tracking (no‑annotation) user‑behavior analysis SDK for Android, covering bytecode‑instrumentation via a Gradle plugin, event collection for activities, fragments, and clicks, as well as processing, storage, reporting, and current limitations.
58.com’s WMDA platform provides a no‑tracking (no‑annotation) user‑behavior analysis solution for PC, mobile web, and app products. The Android SDK can be integrated with only a few lines of code, automatically collecting full‑range user events without manual instrumentation.
1. Technology Selection – Three mainstream approaches were evaluated: traditional manual code‑level tracking, dynamic view‑proxy tracking, and compile‑time bytecode instrumentation. The team chose compile‑time instrumentation using a Gradle plugin (ASM) because it offers high performance, data traceability, and low developer effort while allowing supplemental manual points for custom data.
2. Technical Implementation
Instrumentation Entry – The Gradle plugin registers a Transform API to modify class files after Java compilation but before dexing. The required Gradle version is 1.5.0 or higher.
classpath 'com.android.tools.build:gradle:1.5.0' void transform(Context context, Collection<TransformInput> inputs, Collection<TransformInput> referencedInputs, TransformOutputProvider outputProvider, boolean isIncremental) throws IOException, TransformException, InterruptedException { ... }A whitelist file wmda‑rules.properties can exclude specific packages from instrumentation, e.g.:
com/wuba/sdk/
com/wuba/test/Activity Page Events – WMDA injects code into Activity lifecycle callbacks via LifecycleCallback . The onResume method is intercepted and forwarded to the SDK:
@Override
public void onActivityResumed(Activity activity) {
// page view event handling
PageManager.getInstance().onActivityResumed(activity);
}For devices below API 14, a Hook on Instrumentation.callActivityOnResume is used as a fallback.
public void callActivityOnResume(Activity activity) {
PageManager.getInstance().onActivityResumed(activity);
oldInstrumentation.callActivityOnResume(activity);
}Fragment Events – Since Android lacks native fragment callbacks, the plugin inserts calls to WmdaAgent.onFragmentResumed into the compiled Fragment classes (both android/app/Fragment and android/support/v4/app/Fragment ).
@Override
MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
if (mv != null && name.equals("onResume") && desc.equals("()V")) {
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/wuba/wmda/autobury/WmdaAgent", "onFragmentResumed", "(Landroid/app/Fragment;)V", false);
}
return mv;
} public static void onFragmentResumed(Fragment fragment) {
PageManager.getInstance().onFragmentResumed(fragment);
}View Click Events – The SDK originally used Mixpanel’s dynamic proxy approach but switched to compile‑time injection for better performance and compatibility. The plugin injects a call to WmdaAgent.onViewClick(View) into any method named onClick(View) , supporting libraries such as ButterKnife, DataBinding, AndroidAnnotations, and RxBinding.
@Override
MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
if (mv != null && name.equals("onClick") && desc.equals("(Landroid/view/View;)V")) {
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/wuba/wmda/autobury/WmdaAgent", "onViewClick", "(Landroid/view/View;)V", false);
}
return mv;
} public static void onViewClick(View view) {
AutoEventManager.getInstance().onEvent(view);
}Custom events can still be added manually when the no‑tracking approach does not cover a specific scenario.
3. Event Processing – Collected events are handed to a dedicated thread that formats them, extracts page IDs from onCreate , and builds a unique view identifier composed of the page class, view path, and index (e.g., /MainWindow/LinearLayout[0]/.../AppCompatButton ).
com.wuba.wmdademo.MainActivity /MainWindow/LinearLayout[0]/FrameLayout[1]/ActionBarOverlayLayout[0]#decor_content_parent/ContentFrameLayout[0]/LinearLayout[0]/ScrollView[0]/LinearLayout[0]/AppCompatButtonTo avoid UI‑thread stalls, the SDK extracts view data on the UI thread, copies it, and lets a background thread compute the final fingerprint.
4. Event Storage – Processed events are serialized as Protobuf, encrypted with AES‑256, and persisted in a local SQLite database.
5. Event Reporting – When reporting criteria are met, events are uploaded via HttpUrlConnection using GZIP‑compressed Protobuf payloads to reduce bandwidth.
6. Selection (Filtering) Module – After data collection, a selection step filters metrics of interest. The SDK only sends page snapshots when the visual fingerprint changes, minimizing unnecessary traffic.
7. Other Technical Points
Multi‑process Data Collection – Child processes handle only event collection and processing; storage and reporting are centralized in the main process, with inter‑process communication via in‑app broadcasts.
Multi‑process UI Selection – Page snapshot data from child processes is sent to the main process via a socket connection for real‑time selection.
8. Existing Issues
Click listeners defined via android:onClick="method" in XML are not captured because WMDA intercepts only OnClickListener instances.
The compile‑time instrumentation does not currently support React Native or other cross‑platform frameworks.
Hot‑patch updates may not be fully compatible with the injected bytecode.
Conclusion – The article presents the Android side of 58.com’s WMDA no‑tracking data‑collection system, describing bytecode instrumentation, event handling, storage, reporting, and current limitations, and invites further collaboration to address open challenges.
58 Tech
Official tech channel of 58, a platform for tech innovation, sharing, and communication.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.