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.

AndroidtestingReflectionCross-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

login 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.