30

InstrumentationTestCase2为了纯粹的测试目的,我尝试在派生的测试用例中将文件写入外部 SD 卡。android.permission.WRITE_EXTERNAL_STORAGE当在被测应用程序的文件中配置时,这一切正常,但如果此设置仅存在于测试项目AndroidManifest.xml的文件中,则不起作用。AndroidManifest.xml

自然,我不想将此权限添加到主清单中,因为我只在功能测试期间需要此功能。我怎样才能做到这一点?

4

3 回答 3

38

简而言之,您应该android:sharedUserId为应用程序的清单和测试项目的清单添加相同的内容,并为测试项目声明必要的权限。

这种解决方法来自这样一个事实,即 Android 实际上将权限分配给 linux 用户帐户 (uid) 而不是应用程序本身(默认情况下,每个应用程序都有自己的 uid,因此看起来权限是为每个应用程序设置的)。

但是,使用相同证书签名的应用程序可以共享相同的 uid。因此,它们具有一组共同的权限。例如,我可以拥有请求 WRITE_EXTERNAL_STORAGE 权限的应用程序 A 和请求 INTERNET 权限的应用程序 B。A 和 B 都由同一个证书签名(比如说调试一个)。在 A 和 B 的 AndroidManifest.xml 文件中,android:sharedUserId="test.shared.id"<manifest>标记中声明。然后 A 和 B 都可以访问网络并写入 sdcard,即使他们只声明了部分所需权限,因为权限是按 uid 分配的。当然,这只有在实际安装了 A 和 B 时才有效。

这是一个如何设置测试项目的示例。应用程序的 AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testproject"
    android:versionCode="1"
    android:versionName="1.0"
    android:sharedUserId="com.example.testproject.uid">

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="16" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name">
        <activity
            android:name="com.example.testproject.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />    
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

以及用于测试项目的 AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testproject.test"
    android:sharedUserId="com.example.testproject.uid"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="com.example.testproject" />

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <uses-library android:name="android.test.runner" />
    </application>

</manifest>

此解决方案的缺点是,在安装测试包时,应用程序也能够写入外部存储。如果它不小心将某些内容写入存储,它可能会一直被忽视,直到发布时,包将使用不同的密钥进行签名。

可以在http://developer.android.com/guide/topics/security/permissions.html#userid找到有关共享 UID 的一些附加信息。

于 2013-01-07T13:00:07.687 回答
13

还有另一个简单的答案。

中设置权限src/debug/AndroidManifest.xml。如果该文件不存在,请创建它。

默认情况下,debugAndroidTest 用作 BuildType,因此如果您在此处定义测试权限,那么清单合并过程会将这些权限添加到您的 UI 测试构建中。

这是具有新权限的清单。请注意,我没有包含该package属性,因为它将继承自较低优先级的清单。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</manifest>

此外,如果您想将这些权限应用于除 之外的 buildType debug,那么只需将您的新权限移动AndroidManifest.xml到您想要的文件夹中,然后使用:

android {
   ...
   testBuildType 'release' // or other buildType you might have like 'testUI'
}
于 2017-04-11T13:07:45.843 回答
-5

以编程方式进行,因为生成的调试类的调试模式将在这些条件下进行调试。

于 2013-01-07T11:41:37.997 回答