Mobile Development 10 min read

Using ContentProvider for Cross‑Process Communication with UIAutomator 1.0 on Android

This article explains how to keep UIAutomator 1.0 test cases running on Android 11+ by implementing a server‑side ContentProvider, accessing it via reflection from the UIAutomator or shell process, and demonstrates the complete Java code for provider creation and invocation.

360 Quality & Efficiency
360 Quality & Efficiency
360 Quality & Efficiency
Using ContentProvider for Cross‑Process Communication with UIAutomator 1.0 on Android

Background – UIAutomator 1.0 is deprecated after Android 11, but test cases can still be executed by launching the UIAutomator 1.0 service through reflection. The article proposes using a ContentProvider in a server app to expose services even when the server app is not running, allowing UIAutomator 1.0 to communicate via the provider.

Implementation – server app ContentProvider

package com.xxxx.xxxx.ticker.server;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;

/**
 * @author walker
 * @date 2021/1/29.
 * @description Provides a ContentProvider interface for external calls
 */
public class CommonProvider_tme extends ContentProvider {
    @Override
    public boolean onCreate() {
        init();
        return false;
    }
    private void init() {}
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; }
    @Override
    public String getType(Uri uri) { return null; }
    @Override
    public Uri insert(Uri uri, ContentValues values) { return null; }
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; }
    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; }

    public static final String RES_DATA = "data";
    public static final String RES_CODE = "code";
    public static final String RES_INFO = "info";

    @Override
    public Bundle call(String authority, String method, String arg, Bundle extras) {
        Bundle resBundle = new Bundle();
        System.out.println("®®® call contentprovider  authority=" + authority + "; method=" + method + "; arg=" + arg + "; extras" + extras);
        try {
            if (method == null || method.trim().length() == 0) {
                resBundle.putString(RES_DATA, "");
                resBundle.putInt(RES_CODE, 404);
                resBundle.putString(RES_INFO, "Provider错误:必须指定调用方法名");
                return resBundle;
            }
            if (!"com.xxxx.xxxx.xxxx".equals(authority)) {
                resBundle.putString(RES_DATA, "");
                resBundle.putInt(RES_CODE, 100);
                resBundle.putString(RES_INFO, "Provider错误:必须指定有效authorities信息");
                return resBundle;
            }
            resBundle.putString(RES_INFO, "ok");
            resBundle.putInt(RES_CODE, 200);
            boolean res = true;
            // switch(method) { ... }
            if (!res) {
                resBundle.putInt(RES_CODE, 500);
            }
        } catch (Exception e) {
            resBundle.putInt(RES_CODE, 501);
            resBundle.putString(RES_INFO, e.getMessage());
        }
        return resBundle;
    }
}

In the Android manifest, declare the provider with matching android:authorities:

<application ...>
    <provider android:name=".server.CommonProvider"
              android:authorities="com.xxxx.xxxx.xxxx"
              android:exported="true"
              android:enabled="true" />
</application>

Accessing the ContentProvider from a Shell or UIAutomator process

Obtain IActivityManager via ActivityManagerNative.getDefault().

Use reflection to call getContentProviderExternal (different signatures for SDK >28 and ≤28) to retrieve a ContentProviderHolder.

Extract the actual IContentProvider instance from the holder's provider field.

Invoke the provider's call method with appropriate parameters ( calling_package, authority, method, arg, extras), handling SDK version differences.

// Example of obtaining the provider (SDK > 28)
IActivityManager activityManager = (IActivityManager) ActivityManagerNative.getDefault();
Method method = activityManager.getClass().getDeclaredMethod(
    "getContentProviderExternal", String.class, int.class, IBinder.class, String.class);
Object holder = method.invoke(activityManager, authority, USER_SYSTEM, token, null);
Field field = holder.getClass().getDeclaredField("provider");
field.setAccessible(true);
IContentProvider provider = (IContentProvider) field.get(holder);

Calling the provider (SDK ≥30 example):

Method callMethod = provider.getClass().getDeclaredMethod(
    "call", String.class, String.class, String.class, String.class,
    String.class, String.class, Bundle.class);
Bundle result = (Bundle) callMethod.invoke(provider, calling_package, attributionTag,
    authority, method, arg, extras);

Full helper class – The article provides a ShellContentProvider class that encapsulates the above steps, exposing callProvider methods for convenient use.

public class ShellContentProvider {
    int USER_SYSTEM = 0;
    String calling_package = "com.android.shell";
    String authority = "com.xxxx.xxxx.xxxx";
    IContentProvider provider = null;
    // initProvider(), callProvider(...) implementations as shown in the article
}

Finally, an example of invoking a custom method:

Bundle bundle = new Bundle();
bundle.putBoolean("isCalled", true);
bundle.putInt("callFlag", 1);
bundle.putString("arg", "test");
Bundle res = new ShellContentProvider().callProvider("testMethod", "hello", bundle);

The ContentProvider architecture is a core Android IPC mechanism, and the presented solution enables UIAutomator 1.0 test cases to continue working on newer Android versions by leveraging this mechanism.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

AndroidReflectionCross-ProcessContentProviderUIAutomator
360 Quality & Efficiency
Written by

360 Quality & Efficiency

360 Quality & Efficiency focuses on seamlessly integrating quality and efficiency in R&D, sharing 360’s internal best practices with industry peers to foster collaboration among Chinese enterprises and drive greater efficiency value.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.