13

I think I must be missing something here, as far as I'm aware I've tried these approaches after reading a number of articles and I can't seem to get things working. I'm triggering these builds manually at the moment, using the command that detox would use which is ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug though I've also tried using npx detox build --configuration android.emu.debug directly too.

My error is a typical minSdkVersion mismatch:

uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared in library [com.facebook.react:react-native:0.64.0] /home/iw651/.gradle/caches/transforms-2/files-2.1/354c8f3d479b5a1203bfff874da058bc/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)

build.gradle
So the things that are confusing me somewhat, are firstly my project's minSdkVersion is set to at least 21... This is the top of my /android/build.gradle file:

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

Within my android/app/build.gradle I have the following:

defaultConfig {
     minSdkVersion rootProject.ext.minSdkVersion
     targetSdkVersion rootProject.ext.targetSdkVersion
     multiDexEnabled true
     ...
}

So really I believe the following has been done. But it's obviously still throwing an error.

or increase this project's minSdk version to at least 2

tools:overrideLibrary
I'm not exactly sure how to do this, I've tried setting this in my /android/app/src/debug/AndroidManifest.xml file. I've tried a few permutations:

<uses-sdk minSdkVersion="16" tools:overrideLibrary="com.facebook.react"/>
<uses-sdk minSdkVersion="21" tools:overrideLibrary="com.facebook.react"/>
<uses-sdk tools:overrideLibrary="com.facebook.react"/>

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

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <uses-sdk minSdkVersion="16" tools:overrideLibrary="com.facebook.react"/>
    <application
            android:usesCleartextTraffic="true"
            tools:targetApi="28"
            tools:ignore="GoogleAppIndexingWarning">
        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>
</manifest>

None of those permutations seem to help either.

use a compatible library with a minSdk of at most 16
This just leaves me with this option, for which I'm going to raise a PR against the package in question. But it still doesn't help me build until a new release is made.

Can anyone see what I'm missing? Or could some caching be getting in the way between builds?

Ian
  • 33,605
  • 26
  • 118
  • 198
  • I believe if you are using a library, Facebook React in this case from what I can tell, and they have the library set to minimum 21, then your own app has to be minimum of 21 as well, you can't support an older android version if a library you are using doesn't. You don't need to put the minSDK in the manifest, this should only be in the Gradle file – Boardy Apr 09 '21 at 13:28
  • @Boardy but I'm targeting a minSdkVersion of 23, which is > 21. Are you suggesting they have to exactly match and that I can't define a subset? – Ian Apr 09 '21 at 13:33
  • @Boardy just as a note I removed the entry from the `AndroidManifest.xml` and tried setting a `minSdkVersion = 21` in the `build.gradle` file but that didn't seem to make any difference either. – Ian Apr 09 '21 at 13:38
  • ah sorry missed that, what do you have under defaultConfig in build.gradle as there's a min sdk version in there which might be overriding what you have in ext (not sure how ext section gets used). – Boardy Apr 09 '21 at 16:43
  • @Boardy no problem, I've updated the question with both my build.gradle file contents – Ian Apr 09 '21 at 17:43
  • Hmm strange, the only thing I can think of is it has cached something. Maybe try deleting the build and gradle folder (maybe backup just to be safe) and then in android studio from the file menu go to Invalidate Caches & Restart and then reload your project and it should do a full gradle resync/build – Boardy Apr 09 '21 at 18:00
  • @Boardy thanks, I don't know much about the java side, but I agree it does seem odd from the docs I've read. I've tried re-cloning the rep to a fresh directory and cleaned the local (home directory) grade caches to no avail. A colleague is in exactly the same boat, while another can't get his too fail, so it does feel cache related but I can't find anymore to clear. – Ian Apr 09 '21 at 18:21
  • 1
    Unfortunately I'm out of ideas, normally when I've had something similar, invalidating the caches and/or clearing the gradle folder fixes it – Boardy Apr 09 '21 at 18:38
  • @Boardy no worries thanks for the suggestions. I'll keep trying and maybe add a bounty Monday if still stuck :) – Ian Apr 09 '21 at 18:45
  • 1
    I'm pleased to announce we've updated Detox' minimal SDK version to 21 in Detox `18.5.0`. @Ian please try to upgrade and see whether this solves your issue entirely. – d4vidi May 27 '21 at 14:29

4 Answers4

11

The issue is that RN 0.64 increased its minSdkVersion from 16 to 21. Many RN libraries have minSdkVersion hard-coded at 16, which is causing Detox Android builds to fail.

I am unsure why regular Android builds succeed and Detox builds fail, but the fix is to edit the library's android/build.gradle and change it to read minSdkVersion from the root project:

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

Ideally this will be fixed in the core library through a PR (don't forget to make one). In the meanwhile, you can fork the project yourself, fix the bug and use the fixed project by referencing it in package.json:

"<lib-name>": "github:<username>/<lib-name>"

Alternatively you can use patch-package to apply the fix to node_modules/<libname>/android/build.gradle when running npm install.

This seems to be a quite common error in RN libraries. In our mid-sized RN project I've had to patch three libraries, including react-native-webview.

Sampo
  • 4,308
  • 6
  • 35
  • 51
  • Thanks - `patch-package` looks really interesting, and for the time being the approach you've suggested is what we've done. – Ian Apr 16 '21 at 09:38
  • What I ended up doing is sending PRs to fix the libraries, and then use patch-package in our project. This way `npm update` still updates packages as expected, and the patch will fail and be removed once the upstream package has released the fix. – Sampo Apr 17 '21 at 18:28
0

In the code you provided the configuration is set under the ext key. The minSdkVersion is usually set under the defaultConfig key:

defaultConfig {
    minSdkVersion 23
    targetSdkVersion 30
    ...
}

Maybe this is the reason?

Adi Oz
  • 257
  • 1
  • 4
  • 8
  • I wonder if that's because the app `build.gradle` has this in it? `defaultConfig { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion` – Ian Apr 09 '21 at 14:37
  • Seems to be the way the `create-react-native-app` works. Here's an example https://github.com/launchdarkly/hello-react-native/blob/master/android/build.gradle – Ian Apr 09 '21 at 14:58
  • 1
    Got it, so my suggestion is irrelevant – Adi Oz Apr 09 '21 at 15:02
0

Modify your android/app/build.gradle as follows

defaultConfig {
     minSdkVersion 23
     targetSdkVersion 29
     multiDexEnabled true
}

Remove any uses-sdk from Manifest file.

Eyosiyas
  • 1,422
  • 1
  • 9
  • 25
0

Build your android app by adding app: before assembleDebug & assembleAndroidTest in that build command

=> ./gradlew app:assembleDebug app:assembleAndroidTest -DtestBuildType=debug

or change the build command in your .detoxrc.js file like below

build: 'cd android && ./gradlew app:assembleDebug app:assembleAndroidTest -DtestBuildType=Debug'

What's happening here : assembleRelease executes the assembleRelease task of each module while app:assembleRelease executes the assembleRelease task in the app module.

Obviously the task graph is populated correctly for both, it means that app:assembleRelease for Android depends on the assembleRelease of the other modules used as dependencies in app.

Ref : Difference between app:assembleRelease and assembleRelease

Thanhal P A
  • 4,097
  • 3
  • 18
  • 38