wix/Detox

Android build fails for libs with minSdkVersion 17 with react-native 0.64

Closed this issue ยท 38 comments

Describe the bug

The following command fails after upgrading to RN 0.64

./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug

With the following message (only this library seems to fail).

> Task :react-native-pager-view:processDebugAndroidTestManifest FAILED
[androidx.vectordrawable:vectordrawable-animated:1.0.0] /.gradle/caches/transforms-2/files-2.1/3050775700026023c1db3db79ab19a97/vectordrawable-animated-1.0.0/AndroidManifest.xml Warning:
        Package name 'androidx.vectordrawable' used in: androidx.vectordrawable:vectordrawable-animated:1.0.0, androidx.vectordrawable:vectordrawable:1.0.1.
/node_modules/react-native-pager-view/android/build/intermediates/tmp/manifest/androidTest/debug/manifestMerger2807704319365703146.xml:5:5-74 Error:
        uses-sdk:minSdkVersion 17 cannot be smaller than version 21 declared in library [com.facebook.react:react-native:0.64.0] /.gradle/caches/transforms-2/files-2.1/4e32a44ca1590525038237dd6b47cd32/jetified-react-native-0.64.0/AndroidManifest.xml as the library might be using APIs not available in 17
        Suggestion: use a compatible library with a minSdk of at most 17,
                or increase this project's minSdk version to at least 21,
                or use tools:overrideLibrary="com.facebook.react" to force usage (may lead to runtime failures)

See http://g.co/androidstudio/manifest-merger for more information about the manifest merger.

Running ./gradlew assembleDebug or ./gradlew bundleRelease then npx react-native run-android --variant=release works fine.

Maybe this issue should be posted in the react-native-pager-view repo but as I can only reproduce when running the detox build command I'm asking here first.

Steps To Reproduce

  • I have tested this issue on the latest Detox release and it still reproduces

Expected behavior

Build should not fail with this error.

Detox Trace-Logs

NA

Device logs (adb logcat)

NA

Environment (please complete the following information):

  • Detox: 18.9.0
  • React Native: 0.64.0
  • Node: v14.8.0
  • Device: NA
  • OS: KDE neon User Edition 5.21
  • Test-runner (select one): jest-circus

I'm wondering @Andarius (seen we're using the same reps). Did you close this because you felt the issue was down to the dependencies?

What I've found interesting here is that:

  1. Detox builds in a different way to the actual build of the app (which works and runs fine).
  2. Despite the error the workarounds it suggests don't work
    • the minSdkVersion defined in your project build.gradle seems to be ignored
    • Adding a <uses-sdk> in an AndroidManfiest.xml doesn't seem to fix the issue either

We're left with just hacking/trying to get libraries we're relying upon updated. Which is one answer, but I don't understand why Detox builds differently/these fixes don't work.

@IPWright83, yes, I felt that the issue was more related to react-native-pager-view and not Detox.
I'm not sure why it only failed with Detox indeed.

@LeoNatan I know you've shared your views on this library in the past - I'd be interested to know though if you could share any insight into why builds via Detox might fail in this way and why all the suggested workarounds don't work?

I've got a StackOverflow question where no one has been able to understand the nuances of the Detox build and why we're unable to resolve it. So far the only thing I've found works is to hack the build.gradle file within dependent packages (thanks to @Andarius's suggestion) but it's obviously not a great solution :/ While I appreciate the version mis-matches are not Detox's issue, something about the way Detox works exasperates trying to fix the problem and more insight may be helpful :)

plaa commented

I'm facing the same issue after upgrading RN 0.63.3 --> 0.64. I think it's related to the fact that RN 0.64 has dropped support for Android versions 16-20, even though I have minSdkVersion = 23.

> Task :appcenter:processDebugAndroidTestManifest FAILED
[androidx.vectordrawable:vectordrawable-animated:1.0.0] /Users/vincit/.gradle/caches/transforms-2/files-2.1/b90c4dc3713aaccab0722db6535196af/vectordrawable-animated-1.0.0/AndroidManifest.xml Warning:
        Package name 'androidx.vectordrawable' used in: androidx.vectordrawable:vectordrawable-animated:1.0.0, androidx.vectordrawable:vectordrawable:1.0.1.
/Users/vincit/workspace/xxx/node_modules/appcenter/android/build/intermediates/tmp/manifest/androidTest/debug/manifestMerger15792560754909726717.xml:5:5-74 Error:
        uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared in library [com.facebook.react:react-native:0.64.0] /Users/vincit/.gradle/caches/transforms-2/files-2.1/a3af935f4b0522fde8a7a26e8948e10a/jetified-react-native-0.64.0/AndroidManifest.xml as the library might be using APIs not available in 16
        Suggestion: use a compatible library with a minSdk of at most 16,
                or increase this project's minSdk version to at least 21,
                or use tools:overrideLibrary="com.facebook.react" to force usage (may lead to runtime failures)

After I upgraded appcenter (the newer version also happens to require API level 21) it didn't fail there, but on the next package (in my case react-native-haptic-feedback):

> Task :react-native-haptic-feedback:processDebugAndroidTestManifest FAILED
[androidx.vectordrawable:vectordrawable-animated:1.0.0] /Users/vincit/.gradle/caches/transforms-2/files-2.1/b90c4dc3713aaccab0722db6535196af/vectordrawable-animated-1.0.0/AndroidManifest.xml Warning:
        Package name 'androidx.vectordrawable' used in: androidx.vectordrawable:vectordrawable-animated:1.0.0, androidx.vectordrawable:vectordrawable:1.0.1.
/Users/vincit/workspace/xxx/node_modules/react-native-haptic-feedback/android/build/intermediates/tmp/manifest/androidTest/debug/manifestMerger827925727068678095.xml:5:5-74 Error:
        uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared in library [com.facebook.react:react-native:0.64.0] /Users/vincit/.gradle/caches/transforms-2/files-2.1/a3af935f4b0522fde8a7a26e8948e10a/jetified-react-native-0.64.0/AndroidManifest.xml as the library might be using APIs not available in 16
        Suggestion: use a compatible library with a minSdk of at most 16,
                or increase this project's minSdk version to at least 21,
                or use tools:overrideLibrary="com.facebook.react" to force usage (may lead to runtime failures)

If you've managed to fix it, any assistance would be appreciated!

@plaa for us the fix was to make sure that the library we were using (react-native-pager-view) had the right configuration (https://github.com/callstack/react-native-pager-view/pull/319/files#diff-197b190e4a3512994d2cebed8aff5479ff88e136b8cc7a4b148ec9c3945bd65a) in the android/build.gradle file.

Looking at the library you are using you are facing the same issue.
In this file https://github.com/junina-de/react-native-haptic-feedback/blob/master/android/build.gradle, replace
minSdkVersion 16 with rootProject.hasProperty('minSdkVersion') ? rootProject.minSdkVersion : 16

plaa commented

The rabbit hole gets deeper than I thought... ๐Ÿ˜ฑ

@Andarius 's instructions fixed the react-native-haptic-feedback library, thanks a lot for that. Then the next library, react-native-navigation-bar-color failed, but that library does check the root project minSdkVersion. However, it uses rootProject.ext.minSdkVersion instead of rootProject.minSdkVersion, which doesn't work. After I forked and fixed that, the same is in react-native-webview.

It seems that pretty much every RN native library checks the values from rootProject.ext.minSdkVersion which doesn't work. Even both RN native library scaffold generators do it (bug reports by me):
callstack/react-native-builder-bob#158
brodybits/create-react-native-module#445
(EDIT: Now that I understand better how they work these bugs are invalid. Root cause for confusion was gradle/gradle#16853)

It seems to me that this issue will bite every user who tries to use Detox on RN 0.64, while normal RN builds work just fine. It also seems weird why a library requiring a lower minSdkVersion is causing the build to fail.

Does @LeoNatan have any idea why the Detox builds fail, while the regular builds don't?

I think this bug should be reopened.

@plaan, I don't have issues when the library is using rootProject.ext.get(prop) (for instance https://github.com/software-mansion/react-native-gesture-handler/blob/master/android/build.gradle).
Maybe there is something else wrong with your configuration ?

@plaa I think that depends on the root build.gradle file in your project. Normally located in /android/build.gradle. Mine has an ext section, created with the create-react-native-app script.

buildscript {
    ext {
        buildToolsVersion = "29.0.3"
        minSdkVersion = 23
        compileSdkVersion = 29
        targetSdkVersion = 29
        kotlinVersion = '1.3.61'
        ndkVersion = "20.1.5948944"
    }
plaa commented

Yes, I have exactly the same:

buildscript {
    ext {
        buildToolsVersion = "29.0.3"
        minSdkVersion = 23
        compileSdkVersion = 29
        targetSdkVersion = 29
        ndkVersion = "20.1.5948944"
        kotlinVersion = '1.3.41'
    }

I even tried adding an embedded ext dictionary in the hope of making rootProject.ext work, but it didn't:

buildscript {
    ext {
        buildToolsVersion = "29.0.3"
        minSdkVersion = 23
        compileSdkVersion = 29
        targetSdkVersion = 29
        ndkVersion = "20.1.5948944"
        kotlinVersion = '1.3.41'
        ext {
            minSdkVersion = 23
        }
    }

When I add println statements to the libraries' gradle files, it shows the minSdkVersion in rootProject.minSdkVersion but not in rootProject.ext.minSdkVersion (both in Detox builds AND regular builds):

    println "minSdkVersion"
    println rootProject.ext.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 0
    println rootProject.hasProperty('minSdkVersion') ? rootProject.minSdkVersion : 0
plaa commented

This is actually even weirder than I thought:

    println rootProject.hasProperty('minSdkVersion')      // true
    println rootProject.minSdkVersion                     // 23
    println rootProject.ext.hasProperty('minSdkVersion')  // null ?!?
    println rootProject.ext.minSdkVersion                 // 23

So rootProject.ext.minSdkVersion is defined correctly, but for some reason rootProject.ext.hasProperty('minSdkVersion') returns null indicating that the property does not exist.

@plaa, maybe ext has custom getProperty which delegates it to the owner, but hasProperty is just using ext's own metaClass to check inside it? I don't think that is very weird, it is just Groovy.

plaa commented

Yeah, I was able to dig out that ext is of type DefaultExtraPropertiesExtension, which implements getProperty but does not implement hasProperty.

This basically means that rootProject.ext.hasProperty does not work at all. Next trying to figure out how to fix by Detox build without forking every RN library out there...

Still no idea why the minSdkVersion causes the failure in Detox build and not normal builds.

plaa commented

After much digging around I figured out that rootProject.ext.hasProperty always returns null (bug report by me), which caused me a lot of confusion. It's not documented to work, but it's very confusing that it doesn't throw an exception.

Essentially RN libraries that either have a hard-coded minSdkVersion or which use the incorrect rootProject.ext.hasProperty("minSdkVersion") will cause Detox builds to fail for anyone using RN 0.64. For me this was three libraries, react-native-webview (!), react-native-haptic-feedback and react-native-navigation-bar-color.

This will be a major painpoint for anyone using Detox on RN 0.64. Still no idea what is different in the Detox build to cause it to fail.

This is also now an issue for us after upgrading to RN 0.64.x. Is there a workaround or just need to wait for the fix?

plaa commented

@josephbaylon The library needs to be fixed so that

minSdkVersion 16

(or similar) in android/build.gradle is replaced with with

minSdkVersion rootProject.hasProperty('minSdkVersion') ? rootProject.minSdkVersion : 16

You have three options:

  1. Create a bug report / PR and wait for the fix to be released
  2. Create a fork of the library and reference it in package.json using an https/github URL
  3. Patch it during installation using patch-package

@plaa Thanks for the tips!

All, I'm pleased to say we've migrated our internal projects and now Detox seems to work well on Android with React Native 0.64.x!

Among other things, we've updated the library's minimal SDK to 21, so as to match RN's specs (those that have been giving you headaches...).

Please try to upgrade to Detox 18.5.0+ and remove your hacks ๐Ÿ™๐Ÿป
@Andarius please close this issue if it work for you.

Thanks @d4vidi !

I'm still seem to be facing this issue.
"detox": "^18.15.0",

buildscript {
    ext {
        buildToolsVersion = "29.0.3"
        minSdkVersion = 21
        compileSdkVersion = 29
        targetSdkVersion = 29
        ndkVersion = "20.1.5948944"
        kotlinVersion = "1.3.61"
    }
    repositories {
        google()
        jcenter()
    }
    ext.kotlinVersion = '1.3.61' // (check what the latest version is!)
    dependencies {
        classpath("com.android.tools.build:gradle:4.1.0")
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
> Task :appcenter:processDebugAndroidTestManifest FAILED
[androidx.vectordrawable:vectordrawable-animated:1.0.0] /Users/mkelly/.gradle/caches/transforms-2/files-2.1/7db194964415ec513e75fcad1bfcf177/vectordrawable-animated-1.0.0/AndroidManifest.xml Warning:
        Package name 'androidx.vectordrawable' used in: androidx.vectordrawable:vectordrawable-animated:1.0.0, androidx.vectordrawable:vectordrawable:1.0.1.
/Users/mkelly/aLifeLivedReactNative/node_modules/appcenter/android/build/intermediates/tmp/manifest/androidTest/debug/manifestMerger8791020369522696725.xml:5:5-74 Error:
        uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared in library [com.facebook.react:react-native:0.64.0] /Users/mkelly/.gradle/caches/transforms-2/files-2.1/3c51cfc9aca591c4cb5239f8f9999dec/jetified-react-native-0.64.0/AndroidManifest.xml as the library might be using APIs not available in 16
        Suggestion: use a compatible library with a minSdk of at most 16,
                or increase this project's minSdk version to at least 21,
                or use tools:overrideLibrary="com.facebook.react" to force usage (may lead to runtime failures)

See http://g.co/androidstudio/manifest-merger for more information about the manifest merger.

@maxckelly please try to completely delete all intermediate build artifacts under your project's build/ and app/build/ directories, and clean up all of Gradle's cache.

Please don't spam other modules with requests to pass things through. There is no way the whole ecosystem will support this in a timely manner, and there is a much cleaner way to do this:

take control of your own dependencies using buitt-in gradle features

Here's what I mean

In your android/build.gradle put these lines:

subprojects {
  task listAllDependencies(type: DependencyReportTask) {}


  // Force all subprojects to use one and only one set of versions
  ext {
    compileSdk = rootProject.ext.compileSdkVersion
    buildTools = rootProject.ext.buildToolsVersion
    minSdk = rootProject.ext.minSdkVersion
    targetSdk = rootProject.ext.targetSdkVersion
  }
  afterEvaluate { project ->
    if (!project.name.equalsIgnoreCase("app")
      && project.hasProperty("android")) {
      android {
        compileSdkVersion compileSdk
        buildToolsVersion buildTools
        defaultConfig {
          minSdkVersion minSdk
          targetSdkVersion targetSdk
        }
      }
    }

Example taken from a project that is open source and uses both detox and react-native 0.64.2, you can see it in action

@mikehardy thanks for the suggestion but still failing, could you share the project's url? thanks!

Yeah I saw there this piece of code, thanks. No lucky in my project ๐Ÿ˜”

Then you are doing something wrong. Keep trying. It definitely works. I use it in all my projects.

@mikehardy I'm not sure, this is a basic project and still failing https://github.com/bsalesc/detox-build-failing

yarn e2e:android:build

------------------------------------------------------------
Gradle 6.7
------------------------------------------------------------
Build time:   2020-10-14 16:13:12 UTC

Kotlin:       1.3.72
Groovy:       2.5.12
Ant:          Apache Ant(TM) version 1.10.8 compiled on May 10 2020
JVM:          1.8.0_282 (AdoptOpenJDK 25.282-b08)
OS:           Mac OS X 10.16 x86_64

I'm not going to troubleshoot your project. I've linked one that works. Build off that.

Still reproduces on detox 18.18.1. In case that the build works for release build, but not with assembleAndroidTest -DtestBuildType=release this is clearly a detox issue.

> Task :react-native-orientation:processDebugAndroidTestManifest FAILED
[androidx.vectordrawable:vectordrawable-animated:1.0.0] /home/archy/.gradle/caches/transforms-2/files-2.1/c28ce94f9a9493d57b340c03217afa75/vectordrawable-animated-1.0.0/AndroidManifest.xml Warning:
        Package name 'androidx.vectordrawable' used in: androidx.vectordrawable:vectordrawable-animated:1.0.0, androidx.vectordrawable:vectordrawable:1.0.1.
/home/archy/projects/holdmytable-mobile/node_modules/react-native-orientation/android/build/intermediates/tmp/manifest/androidTest/debug/manifestMerger1033645375276737899.xml:5:5-74 Error:
        uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared in library [com.facebook.react:react-native:0.64.0] /home/archy/.gradle/caches/transforms-2/files-2.1/d03f9268e1d230f1c549d23beb5a95d5/jetified-react-native-0.64.0/AndroidManifest.xml as the library might be using APIs not available in 16
        Suggestion: use a compatible library with a minSdk of at most 16,
                or increase this project's minSdk version to at least 21,
                or use tools:overrideLibrary="com.facebook.react" to force usage (may lead to runtime failures)

This reproduces even after a full clean:

# Cleanup project dependencies.
cleanup:
	rm ~/.gradle -R ;\
	rm android/.gradle -R ;\
	rm android/.gradle_home -R ;\
	rm android/build -R ;\
	rm android/app/build -R ;\
	npm ci ;\
	(cd android && ./gradlew clean) ;\

ANY LIBRARY CAN HAVE ANY minSdkVersion! It's not unique to this library. And if the libraries move to 21, then how would all the people still using react-native 0.63 to support API16 feel?

It's not a bug.

TAKE CONTROL OF YOUR DEPENDENCIES by using gradle to raise them during the build.

or use patch-package if you want a hackier solution than gradle - https://github.com/ds300/patch-package

@mikehardy I still would expect an explanation why the default release build works correctly (in contrast to detox build)? All I am saying is that the no solution is the best solution. I believe lots of people will lose time and struggle on this.


Anyways I opted in using @mikehardy `s gradle solution. At first it was not working, so I decided to investigate the repository in which he said it worked. I noticed I had some different versions to some dependencies. I went down the rabbit hole to update starting from gradle. In the end I am not sure what fixed it, but I am mostly certain it was either gradle or react-native update. Here is a diff of what changes I needed to make:

diff --git a/android/app/build.gradle b/android/app/build.gradle
index 61b1580..44d943d 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -1,3 +1,4 @@
+apply plugin: 'com.android.application'
 apply plugin: "com.github.triplet.play"
 apply plugin: "com.android.application"
 apply plugin: 'com.google.gms.google-services'
diff --git a/android/build.gradle b/android/build.gradle
index 0afd430..7cb3ca0 100755
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -2,7 +2,6 @@
 
 buildscript {
     ext {
-        buildToolsVersion = "29.0.3"
         minSdkVersion = 21
         compileSdkVersion = 29
         targetSdkVersion = 29
@@ -19,8 +18,8 @@ buildscript {
         mavenCentral()
     }
     dependencies {
-        classpath "com.github.triplet.gradle:play-publisher:3.4.0"
-        classpath "com.android.tools.build:gradle:4.1.0"
+        classpath "com.github.triplet.gradle:play-publisher:3.4.0-agp4.2"
+        classpath "com.android.tools.build:gradle:4.2.1"
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
         classpath 'com.google.gms:google-services:4.3.3'
         // NOTE: Do not place your application dependencies here; they belong
@@ -48,3 +47,24 @@ allprojects {
         maven { url 'https://www.jitpack.io' }
     }
 }
+
+subprojects {
+    // Force all subprojects to use one and only one set of versions
+    ext {
+        compileSdk = rootProject.ext.compileSdkVersion
+        minSdk = rootProject.ext.minSdkVersion
+        targetSdk = rootProject.ext.targetSdkVersion
+    }
+    afterEvaluate { project ->
+        if (!project.name.equalsIgnoreCase("app") && project.hasProperty("android")) {
+            android {
+                compileSdkVersion compileSdk
+                buildToolsVersion "30.0.2"
+                defaultConfig {
+                    minSdkVersion minSdk
+                    targetSdkVersion targetSdk
+                }
+            }
+        }
+    }
+}
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index 14e30f7..1f3fdbc 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
index bba7a0c..23a3b97 100644
--- a/package.json
+++ b/package.json
@@ -33,7 +33,7 @@
     "@babel/register": "^7.9.0",
     "@babel/runtime": "^7.12.5",
-    "@react-native-community/async-storage": "^1.9.0",
+    "@react-native-async-storage/async-storage": "^1.15.5",
     "@react-native-community/google-signin": "^4.0.3",
     "@react-native-community/masked-view": "^0.1.7",
     "@react-native-community/netinfo": "^5.9.4",
@@ -71,7 +71,7 @@
     "react": "17.0.1",
     "react-dom": "^16.13.1",
     "react-intl": "^4.7.6",
-    "react-native": "0.64.0",
+    "react-native": "0.64.2",
     "react-native-calendars": "^1.265.0",
     "react-native-device-info": "^5.5.7",
     "react-native-dotenv": "^0.2.0",
@@ -98,14 +98,14 @@
   "devDependencies": {
     "@react-native-community/eslint-config": "^2.0.0",
     "@types/chai": "^4.2.11",
-    "@types/detox": "^16.4.1",
+    "@types/detox": "^17.14.0",
     "@types/mocha": "^8.0.3",
     "@types/react-test-renderer": "17.0.1",
     "@typescript-eslint/eslint-plugin": "^2.23.0",
     "@typescript-eslint/parser": "^2.23.0",
     "better-npm-audit": "^1.1.1",
     "chalk": "^4.0.0",
-    "detox": "^17.4.5",
+    "detox": "^18.18.1",
     "dotenv": "^8.2.0",
     "eslint": "7.14.0",
     "eslint-config-prettier": "^6.10.0",
diff --git a/src/Localization/LocalizationProvider.tsx b/src/Localization/LocalizationProvider.tsx
index e6766f3..0328fcc 100644
--- a/src/Localization/LocalizationProvider.tsx
+++ b/src/Localization/LocalizationProvider.tsx
@@ -1,5 +1,5 @@
 import React, { useState, FunctionComponent, useCallback } from 'react';
-import AsyncStorage from '@react-native-community/async-storage';
+import AsyncStorage from '@react-native-async-storage/async-storage';
 import { DEFAULT_LANGUAGE, languages } from './Translations';
 import * as RNLocalize from 'react-native-localize';
 import LanguageSetContext from './LanguageSetterContext';
diff --git a/test/integration/mocha/init.js b/test/integration/mocha/init.js
index 29a4d98..6fb10d9 100644
--- a/test/integration/mocha/init.js
+++ b/test/integration/mocha/init.js
@@ -25,6 +25,7 @@ before(async () => {
     await detox.init(config);
     global.isDetoxInitialized = true;
   }
+  await device.launchApp();
 });
 
 beforeEach(async function () {
plaa commented

@mikehardy That's a neat workaround. (Haven't tested it myself though.)

Still, it's best practice that libraries pass through minSdkVersion. Every module template / generator I've seen does it. It's the way things "just work" instead of having to have deep knowledge of gradle. I recommend sending PR's to projects to make them better. It's a minority of modules that don't have pass-through already.

In the interim I already suggested either forking or patch-package'ing the module. Gradle override is fine as well.

Had the same problem, I was able to fix it by adding this in android/build.gradle:

subprojects { 
    ext {
        compileSdk = rootProject.ext.compileSdkVersion
        minSdk = rootProject.ext.minSdkVersion
        targetSdk = rootProject.ext.targetSdkVersion
    }
    afterEvaluate { subproject ->
        if((subproject.plugins.hasPlugin('android') || subproject.plugins.hasPlugin('android-library'))) {
            android {
                compileSdkVersion rootProject.ext.compileSdkVersion
                buildToolsVersion rootProject.ext.buildToolsVersion
                defaultConfig {
                    minSdkVersion rootProject.ext.minSdkVersion
                    targetSdkVersion rootProject.ext.targetSdkVersion
                }
            }
        }
    }
}

Reference: uxcam/react-native-ux-cam#24 (comment)

It's quite interesting suggestion. In my team, we had a little discussion about its safety. We came up with that trade-off solution:

subprojects { project ->
  afterEvaluate {
        // Added to Fix Detox build command for libs with minSdk < required one.
        if (gradle.startParameter.taskNames.contains("assembleDebug")) {
          defaultConfig {
            minSdkVersion rootProject.ext.minSdkVersion
          }
        }
      }
}

You might ask why? Just to be sure that these older modules still have their versions during building a release type.

subprojects { project ->
    afterEvaluate {
        if (gradle.startParameter.taskNames.contains("assembleAndroidTest")) {
            android {
                compileSdkVersion rootProject.ext.compileSdkVersion
                buildToolsVersion rootProject.ext.buildToolsVersion
                defaultConfig {
                    minSdkVersion rootProject.ext.minSdkVersion
                    targetSdkVersion rootProject.ext.targetSdkVersion
                }
            }
        }
    }
}

I tried this command and the build passed

cd android ; ./gradlew app:assembleRelease app:assembleAndroidTest -DtestBuildType=release ; cd -

Do the same for debug build. Add 'app' before assembleRelease and assembleAndroidTest

I tried this command and the build passed

cd android ; ./gradlew app:assembleRelease app:assembleAndroidTest -DtestBuildType=release ; cd -

Do the same for debug build. Add 'app' before assembleRelease and assembleAndroidTest

Thanks for this

I tried this command and the build passed

cd android ; ./gradlew app:assembleRelease app:assembleAndroidTest -DtestBuildType=release ; cd -

Do the same for debug build. Add 'app' before assembleRelease and assembleAndroidTest

worked for me!