I have a project employing React-Native. I'm building the RN module from source, so my project has the ReactAndroid module as a dependency.
I was trying to upgrade the project to Android gradle build tools >=2.3.2, so I could use intant-run:
buildscript {
repositories {
jcenter()
mavenLocal()
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.2'
...
}
}
This change forced me to upgrade gradle itself from 3.1 to 3.5 (latest stable).
Doing so opened pandora's hell box.
No such property: sdkHandler for class: com.android.build.gradle.AppPlugin
Upgrading gradle to 3.5 and trying to build the project from scratch produced the following gradle error from the RN module:
No such property: sdkHandler for class: com.android.build.gradle.AppPlugin
The fix
This was easy. It seemed that starting with gradle 3.3, the build script looks for the environment variable ANDROID_NDK
for the NDK location. Not being able to locate the NDK directory causes gradle to miss some mandatory properties, such as sdkHandler
.
So all I had to do was set ANDROID_NDK
correctly:
ANDROID_NDK=C:\dev\google\android-sdk\ndk-bundle\
Could not get unknown property 'repositoryUrl' for project
Building the project now produces the another gradle error:
Could not get unknown property 'repositoryUrl' for project ':ReactAndroid' of type org.gradle.api.Project.
Reserching the issue
I did manage to find a GitHub pull request thread where Facebook's own team members are lamenting about the issue here. However they themselves didn't seem to like their fix, so who am I to argue.
The error pointed to the this line at the React-Native module's release.gradle
:
def getRepositoryUrl() {
return hasProperty('repositoryUrl') ? property('repositoryUrl') : 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
}
Strangely enough, the problem is that hasProperty('repositoryUrl')
returns true
, while property('repositoryUrl')
causes the error.
On gradle 3.1, hasProperty('repositoryUrl')
returns false
.
Apparently, in gradle 3.5 hasProperty()
does return true
in cases where the property is indeed missing: when it still has a getter. In our case the getter is this overriding method that the error points to:
def getRepositoryUrl() {...}
This is vaguely explained here.
There is however another method of checking for properties, which ignores getters, named findProperty.
The fix
So the fix was to change the following block from release.gradle
:
def getRepositoryUrl() {
return hasProperty('repositoryUrl') ? property('repositoryUrl') : 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
}
def getRepositoryUsername() {
return hasProperty('repositoryUsername') ? property('repositoryUsername') : ''
}
def getRepositoryPassword() {
return hasProperty('repositoryPassword') ? property('repositoryPassword') : ''
}
To this:
def getRepositoryUrl() {
return findProperty('repositoryUrl') != null ? property('repositoryUrl') : 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
}
def getRepositoryUsername() {
return findProperty('repositoryUsername') !=null ? property('repositoryUsername') : ''
}
def getRepositoryPassword() {
return findProperty('repositoryPassword') != null ? property('repositoryPassword') : ''
}
Now my RN project finally compiles again.