52

Is it possible to set a different minSdkVersion for tests than for the app itself? I ask because I want to use the new Test Support Library and UI Automator for testing. However, this is only available on API 18+. At the same time, I still want to support older versions of Android, albeit not as thoroughly tested. What do I need to add to my build.gradle file in order to do this?

To clarify, I am using Android Studio and the "new" Gradle-based project structure.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • I think there is an acceptable answer here. – theblang Nov 03 '16 at 15:34
  • @mattblang My apologies for not accepting an answer yet. I ended up just changing `minSdkVersion` for the entire app and have not yet verified the answers given. I have not forgot, though, and will accept an answer when I have s chance to test the answers myself. – Code-Apprentice Nov 04 '16 at 03:14

11 Answers11

71

I got this from the new testing template from Google.

Create a new AndroidManifest.xml file in your test or androidTest folder.

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:tools="http://schemas.android.com/tools"
    package="your.package.name">

    <uses-sdk tools:overrideLibrary="android.support.test.uiautomator.v18"/>
</manifest>
theblang
  • 10,215
  • 9
  • 69
  • 120
  • This can cause an error ("The minSdk version should not be declared in the android manifest file. You can move the version from the manifest to the defaultConfig in the build.gradle file.") in newer tools (I haven't been able to determine which tool, version and with which other settings). See ["minsdk and targetsdk in Androidmanifest and build.gradle both?"](https://stackoverflow.com/q/34234841/90527), ["Android Studio:Min SDK in my project"](https://stackoverflow.com/q/49864179/90527) – outis Aug 01 '18 at 05:37
  • It works indeed, but I am not sure this is the best way to do it. It is not recommended. Android Studio suggestion: "use a compatible library with a minSdk of at most 17, or increase this project's minSdk version to at least 18, or use tools:overrideLibrary="android.support.test.uiautomator.v18" to force usage (may lead to runtime failures)" – NayMak Dec 19 '19 at 09:40
  • For `androidTestImplementation "androidx.test.uiautomator:uiautomator:2.2.0"` , use: `` . Also `"your.package.name"` should be the `testApplicationId` string. – Mr-IDE Sep 02 '20 at 13:20
10

try this one.

defaultConfig {
    applicationId "com.test"
    if (gradle.startParameter.taskNames.contains(":app:assembleDebug")) {
        minSdkVersion 21
    }else{
        minSdkVersion 14
    }
    targetSdkVersion 22
    versionCode Integer.parseInt(VERSION_CODE)
    versionName VERSION_NAME
}



updated 2020-04-16


You can also set with productFlavors

android {
    compileSdkVersion 29

    defaultConfig {
        applicationId "com.test"
        targetSdkVersion 29
        versionCode 1
        versionName "1.0.0"
    }

    buildTypes {
        debug {
        }
        release {
            minifyEnabled true
        }
    }

    flavorDimensions "default"

    productFlavors {
        development {
            minSdkVersion 21
        }
        production {
            minSdkVersion 16
        }
    }
}
Soo Chun Jung
  • 595
  • 3
  • 14
  • Can't I just do the same thing inside the `debug` and `release` blocks without an `if` statement? – Code-Apprentice Feb 11 '17 at 02:58
  • I don't know exactly how gradle works, but if you do that **dubug** and **release** will be called both, so last one will be set. You can see the result with log. 'debug { logger.error("debug!!") minifyEnabled false signingConfig signingConfigs.debug } release { logger.error("release!!") minifyEnabled true signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' }' – Soo Chun Jung Feb 13 '17 at 01:30
  • I was having issues with the first "solution". See more details [here](https://stackoverflow.com/questions/63936013/is-there-an-inherent-problem-with-using-if-statements-to-define-the-minsdkversio) – topher217 Sep 18 '20 at 04:59
7

With androidx you can force usage of UI automator in version < 18 with tools:overrideLibrary="android_libs.ub_uiautomator"

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:tools="http://schemas.android.com/tools" package="..." >

    <uses-sdk tools:overrideLibrary="android_libs.ub_uiautomator"/>
</manifest> 

But it may lead to runtime failures if you are running your tests on version < 18

Stéphane
  • 1,528
  • 14
  • 21
6

I've uploaded an example of the solution to mauricegavin/android-testing as I couldn't find a working one myself.

The module of interest is ui/uiautomator/BasicSample/app. You'll notice that there is an AndroidManifest.xml in the androidTests directory. The minSdkVersion you specify in your app/build.gradle will still be used for debug and release builds.

You'll see that the minSdkVersion in the sample project's build.gradle specifies api 17 which is not supported by uiautomator and would usually cause the build to fail.

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.android.testing.uiautomator.BasicSample" >

    <uses-sdk tools:overrideLibrary="android.support.test.uiautomator.v18"/>
</manifest>

Thanks to mattblang for his answer which I used for this example.

Community
  • 1
  • 1
Maurice Gavin
  • 2,047
  • 1
  • 20
  • 26
6

I got the following conflict, for testing i needed a higher minSdkVersion.

The solution i found was taken from the following document using the buildType change the test build type and it did the job for me

The following is the solution:

android {
  defaultConfig {
    applicationId "com.doronkettner.ilikemovies"
    ...
    minSdkVersion 18
    ...
    testBuildType "staging"
    ...
    }
    ...
  buildTypes {
    release {...}

    debug {...}

    staging {
        initWith(buildTypes.debug) // keep versionName and PIN from 'debug'
        defaultConfig.minSdkVersion 19
    }
}

Change the buildType to stage and it should be ok

Kamran Ahmed
  • 7,661
  • 4
  • 30
  • 55
dogood
  • 331
  • 2
  • 5
6

When you run androidTest there will be a task containing "AndroidTest" at the end. That's why I filter my tasks based on this pattern.

My task name was - :app:assembleMyFlavourDebugAndroidTest.

defaultConfig {

    gradle.startParameter.taskNames.each {
        if (it.contains("AndroidTest")) {
            minSdkVersion 18
        } else {
            minSdkVersion 16
        }
    }
}
Sattar Hummatli
  • 1,360
  • 1
  • 15
  • 26
  • 1
    This is a great solution. I think it needs a small tweak to account for the base `androidTest` task that runs all tests for all flavors and builds. – Code-Apprentice Apr 14 '20 at 15:05
2

Yes, you can. You should put test-specific manifest entries in src/androidTest/AndroidManifest.xml. When building your tests the manifest merger will combine both manifests, but when building your app only the main AndroidManifest.xml will be used.

See this answer for more details.

Community
  • 1
  • 1
Allen Hair
  • 1,021
  • 2
  • 10
  • 21
2

This is the hackiest version. It took me almost a day to create this script. Please take note of this for keepsake, but only use this as a last resort.

android.applicationVariants.all { variant ->

//Making specific variant disablements for faster build
if (variant.buildType.name.contains("debug")) {
    println "Making min version to 21 and disabling multidex"
    variant.mergedFlavor.setMultiDexEnabled false

    def versionMin = new com.android.builder.core.DefaultApiVersion(21)
    variant.mergedFlavor.setMinSdkVersion versionMin
    }
}
Pier Betos
  • 1,038
  • 9
  • 17
1

After posting this question, I also had the idea to set minSdkVersion to different values for the debug and release builds. However, I haven't had a chance to test if this works or not.

I also found one possible work around from this blog post. Create separate test and production flavors:

productFlavors {
    // The actual application flavor 
    production {
        minSdkVersion 14
    }
    // Test application flavor for uiautomatior tests
    test {
        minSdkVersion 18
    }
}
Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
1

@Code-Apprentice is almost there. But you can not name a product flavor to "test", "androidTest" or "release". They are like keyword, and you cannot use these names.

So the answer is

    productFlavors {
        product{
            minSdkVersion 15
        }
        uiautoTest {
            minSdkVersion 18
        }
    }
songzhw
  • 272
  • 3
  • 11
  • Gradle 2.14-1 indeed suggests that `ProductFlavor names cannot start with 'test'` – kit Aug 23 '16 at 17:59
0

My solution based on flavor configuration:

  1. split to two flavor:
buildTypes {
  release {...}
  debug {...}
}

productFlavors {
   dev { ... }
   autoTest {
      minSdkVersion 18 // set to 18 only in this flavor
      multiDexEnabled true // if you got dex index overflow error
      testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
   }
}
  1. move your test related dependencies into "autoTestCompile"
// for test
autoTestCompile 'com.android.support.test:runner:0.5', {
    exclude group: 'com.android.support', module: 'support-annotations'
}
autoTestCompile 'com.android.support.test:rules:0.5', {
    exclude group: 'com.android.support', module: 'support-annotations'
}
autoTestCompile 'com.android.support.test.espresso:espresso-web:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
}
autoTestCompile 'com.android.support.test.espresso:espresso-contrib:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
    exclude group: 'com.android.support', module: 'support-v4'
    exclude group: 'com.android.support', module: 'design'
    exclude group: 'com.android.support', module: 'recyclerview-v7'
}
autoTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
}
  1. Run Test

Build Variant Screenshot

Community
  • 1
  • 1
Lin Yu Cheng
  • 667
  • 9
  • 21