无法从浓缩咖啡测试访问内容提供者

Can't access content provider from espresso test

我有一个包含更多模块的应用程序。在模块 A 中,我有一个 ContentProvider。在模块 B 中,我正在访问那个 ContentProvider。该应用程序运行良好,我可以访问数据。我的问题是当我试图为某个 activity 编写 android 仪器测试时。在 onCreate 方法中的那个 activity 中,我调用了一个需要通过 ContentProvider 访问数据库并用该数据填充 activity 的 AsyncTask。此刻我收到一个错误:

E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.mycompany.dashboardlight.test, PID: 19196
java.lang.RuntimeException: An error occurred while executing doInBackground()
    at android.os.AsyncTask.done(AsyncTask.java:318)
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
    at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:243)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
    at java.lang.Thread.run(Thread.java:762)
 Caused by: java.lang.SecurityException: Permission Denial: opening provider com.mycompany.data.provider.HibpAccountProvider from ProcessRecord{7e4d57b 19196:com.mycompany.dashboardlight.test/u0a265} (pid=19196, uid=10265) that is not exported from uid 10264
    at android.os.Parcel.readException(Parcel.java:1693)
    at android.os.Parcel.readException(Parcel.java:1646)
    at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:4912)
    at android.app.ActivityThread.acquireProvider(ActivityThread.java:6043)
    at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2474)
    at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1521)
    at android.content.ContentResolver.query(ContentResolver.java:520)
    at android.content.ContentResolver.query(ContentResolver.java:478)

我已经尝试让两个模块具有相同的 shareUserId、读写权限分离,但没有任何效果。

这在内容提供者所在的清单中:

<provider
    android:name="com.mycompany.data.provider.MyProvider"
    android:authorities="${applicationId}.data.MyProvider"
    android:enabled="true"
    android:exported="false" />

这是访问数据的模块中的清单:

<uses-permission android:name="${applicationId}.data.MyProvider" />

为未访问的活动创建其他测试ContentProvider 工作正常。

这是测试:

@RunWith(AndroidJUnit4.class)
public class MyActivityTest {

    @Rule
    public final ActivityTestRule<MyActivity> breachMain = 
        new ActivityTestRule<>(MyActivity.class);

    @Test
    public void isLaunchScreenDetected() {
        onView(withText("No Data Breach Found"))
            .check(ViewAssertions.matches(isDisplayed()));
    }
}

终于有办法了。问题在于如何定义权限。安装应用程序时和尝试测试应用程序时,applicationId 是不同的。在测试应用程序时,您可能会注意到在您的包名称上附加了 .test,在我的例子中,因为我在代码中使用了硬编码值 com.mypackage,这导致了权限被拒绝。所以我以不同的权限结束,因为安装应用程序和运行测试时applicationId不同。

我的建议是,如果您也在 java 类 中定义 AUTHORITY,请避免 ${applicationId} 没有这样的混合。