【问题标题】:How can I add additional Android permissions for my UI test project only?如何仅为我的 UI 测试项目添加额外的 Android 权限?
【发布时间】:2013-01-03 16:21:54
【问题描述】:

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

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

【问题讨论】:

    标签: android testing


    【解决方案1】:

    简而言之,您应该为应用程序的清单和测试项目的清单添加相同的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>
    

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

    有关共享 UID 的更多信息,请访问 http://developer.android.com/guide/topics/security/permissions.html#userid

    【讨论】:

    • 完美全面的答案!现在,对于其他“已弃用”的共享用户 ID,这是一个非常好的用例。我可以忍受你提到的缺点,这里最重要的是真正将测试与生产权限分开,这已经完成。再次感谢!
    • 不错的解决方法,但我仍然没有得到,当 test.apk 拥有它所需的所有权限时,为什么它仍然抛出错误?
    • 嗨!很好的解决方法,谢谢!但是,似乎从 Android 6(API 级别 23)开始可能是由于新的权限系统,权限不再合并。我个人没有找到任何解释这一点的文档,所以我的假设可能不正确。除了我还有人遇到这个问题吗?
    • 你拯救了我的一天!
    • 不幸的是,从 API 29 开始,sharedUserIddeprecated。在旧版本上使用 sharedUserId 安装应用程序时,我也会收到 an error,这意味着我无法部署新版本的由于用户将无法升级,因此我的应用将升级到生产环境。
    【解决方案2】:

    还有一个简单的答案。

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

    默认情况下,AndroidTest 使用debug 作为 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>
    

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

    android {
       ...
       testBuildType 'release' // or other buildType you might have like 'testUI'
    }
    

    【讨论】:

    • 我已经尝试过这个解决方案,但没有运气。我仍然收到错误为“java.io.IOException:打开失败:EACCES(权限被拒绝)”
    • 你把 testBuildType 改成 release 了吗?
    • 当我更改我的testBuildType 时,我的测试代码将不再构建。在build.gradle 中定义的测试库,如androidTestImplementation 'androidx.test:core:1.2.0',我的Java 测试代码无法再引用这些库。是否需要其他步骤才能使其正常工作?
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2015-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-03
      • 2021-12-01
      • 2020-10-05
      • 2015-03-05
      相关资源
      最近更新 更多