Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android test-only permissions with gradle

I run ./gradlew connectedAndroidTest and I need my test APK to have a permission which should not be in any non-testing APK (debug, release). I have created a manifest with permission:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.mypackage">
    <uses-permission android:name="android.permission.SET_ANIMATION_SCALE"/>
</manifest>

Then I have copied this manifest to src/androidTest directory, as release notes from gradle android plugin suggest:

0.13.0 (2014/09/18) Requires Gradle 2.1 It is now possible to provide a manifest for test apps (src/androidTest/AndroidManifest.xml)

However, the permission is not applied during my connected tests.

If I create a src/debug directory and move this manifest there -- the permission is applied correctly during connected tests (but also during regular debug builds, which is undesirable).

Am I doing something wrong or is there a bug?

like image 513
Denis Kniazhev Avatar asked Jan 07 '15 19:01

Denis Kniazhev


1 Answers

The problem stems from my misunderstanding of how connectedAndroidTest gradle task works. It creates and deploys 2 android applications - a testable (your project) and a tester (an app which simulates a user who interacts with the testable app). My intent was to add the permission to the testable app. However, adding a manifest to src/androidTest resulted in adding the permission to the tester app. Here's how I figured that out:

If I execute

adb shell pm list packages -f -3

(-3 means to list only third-party packages) I can see something like this

package:/data/app/SmokeTestApp.apk=com.android.smoketest package:/data/app/GestureBuilder.apk=com.android.gesture.builder package:/data/app/com.mycompany.myapp-2.apk=com.mycompany.myapp package:/data/app/SoftKeyboard.apk=com.example.android.softkeyboard package:/data/app/org.libsdl.app-2.apk=org.libsdl.app package:/data/app/SmokeTest.apk=com.android.smoketest.tests package:/data/app/com.mycompany.myapp.test-1.apk=com.mycompany.myapp.test

The app with test-1 suffix is the tester app, another one is my testable app. Checking their permission gives:

root@generic_x86:/ # aapt d permissions /data/app/com.mycompany.myapp-2.apk

package: com.spredfast.android
uses-permission: android.permission.INTERNET
uses-permission: android.permission.WRITE_EXTERNAL_STORAGE

root@generic_x86:/ # aapt d permissions /data/app/com.mycompany.myapp.test-1.apk

package: com.spredfast.android
uses-permission: android.permission.SET_ANIMATION_SCALE

So the permission, SET_ANIMATION_SCALE, which I was intending to put into my testable app is put into the tester app. No wonder that moving the manifest from src/androidTest to src/debug would put the permission into the testable app (correct, but too broad).


Here's how I solved the original problem - putting the permission into the application only in case of the application being run inside connectedAndroidTest task.

  1. I have created an empty build flavor to be used with integration tests:

    productFlavors {
        /**
         * This flavor is to be run only using connectedAndroidTestAnimcontrol
         */
        animcontrol {}
    
        regular {}
    }
    
  2. Moved src/androidTest/AndroidManifest.xml with the single permission into src/animcontrol/AndroidManifest.xml

  3. Executed connected tests as

    ./gradlew connectedAnimcontrolDebugAndroidTest
    

That did the trick, now I have AndroidManifest.xml which will be merged with main app's manifest only when being run as connectedAndroidTest.

Hope this helps someone.

like image 110
Denis Kniazhev Avatar answered Nov 06 '22 00:11

Denis Kniazhev