Skip to content

Commit

Permalink
fix: ANDROID_SDK_ROOT variable
Browse files Browse the repository at this point in the history
This commit does the following:
- Makes ANDROID_SDK_ROOT the primary variable to look for the Android SDK location.
- Makes ANDROID_HOME the fallback variable, if ANDROID_SDK_ROOT is not present/valid.

Gradle updates:
Note that the following gradle updates were required, otherwise the android gradle plugin did not honour the ANDROID_SDK_ROOT variable.

- Updates the framework's android studio's gradle plugin from version 3.3.0 to 3.5.3.
	Not only this is required for android's gradle to obey ANDROID_SDK_ROOT, it is now in sync with the Android test project/
- Updates the Androidx test project to use gralde plugin from version 3.3.0 to 3.5.3, to match Android Test & framework.
	- Consequentially, this required to also upgrade AndroidX test project to use Gradle 6.1, which also matches both the Android test project & framework

These changes above fixes apache#949

Additionally, since we update the environment variables dynamically, the environment variable printout produced misleading information.
The environment variable printout will now print out the variable as defined by the user (before the tooling messes with them). An additional log
is printed that tells the user exactly what Cordova is going to use for the Android SDK path. This should fix apache#670
  • Loading branch information
breautek committed Apr 13, 2020
1 parent 6402e7b commit 7634087
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 51 deletions.
91 changes: 56 additions & 35 deletions bin/templates/cordova/lib/check_reqs.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,10 @@ module.exports.get_gradle_wrapper = function () {

// Returns a promise. Called only by build and clean commands.
module.exports.check_gradle = function () {
var sdkDir = process.env['ANDROID_HOME'];
var sdkDir = process.env['ANDROID_SDK_ROOT'] || process.env['ANDROID_HOME'];
if (!sdkDir) {
return Promise.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' +
'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.'));
'Might need to install Android SDK or set up \'ANDROID_SDK_ROOT\' env variable.'));
}

var gradlePath = module.exports.get_gradle_wrapper();
Expand Down Expand Up @@ -242,40 +242,58 @@ module.exports.check_java = function () {
// Returns a promise.
module.exports.check_android = function () {
return Promise.resolve().then(function () {
var androidCmdPath = forgivingWhichSync('android');
var adbInPath = forgivingWhichSync('adb');
var avdmanagerInPath = forgivingWhichSync('avdmanager');
var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']);
function maybeSetAndroidHome (value) {
if (!hasAndroidHome && fs.existsSync(value)) {
hasAndroidHome = true;
process.env['ANDROID_HOME'] = value;
process.env['ANDROID_SDK_ROOT'] = value;
}
}

var androidCmdPath = forgivingWhichSync('android');
var adbInPath = forgivingWhichSync('adb');
var avdmanagerInPath = forgivingWhichSync('avdmanager');
var hasAndroidHome = false;

if (process.env['ANDROID_SDK_ROOT']) {
maybeSetAndroidHome(path.resolve(process.env['ANDROID_SDK_ROOT']));
}

// First ensure ANDROID_HOME is set
// If we have no hints (nothing in PATH), try a few default locations
if (!hasAndroidHome && !androidCmdPath && !adbInPath && !avdmanagerInPath) {
if (process.env['ANDROID_SDK_ROOT']) {
// Quick fix to set ANDROID_HOME according to ANDROID_SDK_ROOT
// if ANDROID_HOME is **not** defined and
// ANDROID_SDK_ROOT **is** defined
// according to environment variables as documented in:
// https://developer.android.com/studio/command-line/variables
maybeSetAndroidHome(path.join(process.env['ANDROID_SDK_ROOT']));
if (process.env['ANDROID_HOME']) {
// Fallback to deprecated `ANDROID_HOME` variable
maybeSetAndroidHome(path.join(process.env['ANDROID_HOME']));
}
if (module.exports.isWindows()) {
// Android Studio 1.0 installer
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk'));
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'sdk'));
if (process.env['LOCALAPPDATA']) {
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk'));
}
if (process.env['ProgramFiles']) {
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'sdk'));
}

// Android Studio pre-1.0 installer
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk'));
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk'));
if (process.env['LOCALAPPDATA']) {
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk'));
}
if (process.env['ProgramFiles']) {
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk'));
}

// Stand-alone installer
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk'));
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk'));
if (process.env['LOCALAPPDATA']) {
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk'));
}
if (process.env['ProgramFiles']) {
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk'));
}
} else if (module.exports.isDarwin()) {
// Android Studio 1.0 installer
maybeSetAndroidHome(path.join(process.env['HOME'], 'Library', 'Android', 'sdk'));
if (process.env['HOME']) {
maybeSetAndroidHome(path.join(process.env['HOME'], 'Library', 'Android', 'sdk'));
}
// Android Studio pre-1.0 installer
maybeSetAndroidHome('/Applications/Android Studio.app/sdk');
// Stand-alone zip file that user might think to put under /Applications
Expand All @@ -288,16 +306,17 @@ module.exports.check_android = function () {
maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk'));
}
}

if (!hasAndroidHome) {
// If we dont have ANDROID_HOME, but we do have some tools on the PATH, try to infer from the tooling PATH.
// If we dont have ANDROID_SDK_ROOT, but we do have some tools on the PATH, try to infer from the tooling PATH.
var parentDir, grandParentDir;
if (androidCmdPath) {
parentDir = path.dirname(androidCmdPath);
grandParentDir = path.dirname(parentDir);
if (path.basename(parentDir) === 'tools' || fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
maybeSetAndroidHome(grandParentDir);
} else {
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
throw new CordovaError('Failed to find \'ANDROID_SDK_ROOT\' environment variable. Try setting it manually.\n' +
'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' +
'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'tools directory.');
}
Expand All @@ -308,7 +327,7 @@ module.exports.check_android = function () {
if (path.basename(parentDir) === 'platform-tools') {
maybeSetAndroidHome(grandParentDir);
} else {
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
throw new CordovaError('Failed to find \'ANDROID_SDK_ROOT\' environment variable. Try setting it manually.\n' +
'Detected \'adb\' command at ' + parentDir + ' but no \'platform-tools\' directory found near.\n' +
'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'platform-tools directory.');
}
Expand All @@ -319,29 +338,29 @@ module.exports.check_android = function () {
if (path.basename(parentDir) === 'bin' && path.basename(grandParentDir) === 'tools') {
maybeSetAndroidHome(path.dirname(grandParentDir));
} else {
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
throw new CordovaError('Failed to find \'ANDROID_SDK_ROOT\' environment variable. Try setting it manually.\n' +
'Detected \'avdmanager\' command at ' + parentDir + ' but no \'tools' + path.sep + 'bin\' directory found near.\n' +
'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'tools' + path.sep + 'bin directory.');
}
}
}
if (!process.env['ANDROID_HOME']) {
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
if (!process.env['ANDROID_SDK_ROOT']) {
throw new CordovaError('Failed to find \'ANDROID_SDK_ROOT\' environment variable. Try setting it manually.\n' +
'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.');
}
if (!fs.existsSync(process.env['ANDROID_HOME'])) {
throw new CordovaError('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env['ANDROID_HOME'] +
if (!fs.existsSync(process.env['ANDROID_SDK_ROOT'])) {
throw new CordovaError('\'ANDROID_SDK_ROOT\' environment variable is set to non-existent path: ' + process.env['ANDROID_SDK_ROOT'] +
'\nTry update it manually to point to valid SDK directory.');
}
// Next let's make sure relevant parts of the SDK tooling is in our PATH
if (hasAndroidHome && !androidCmdPath) {
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools');
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_SDK_ROOT'], 'tools');
}
if (hasAndroidHome && !adbInPath) {
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools');
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_SDK_ROOT'], 'platform-tools');
}
if (hasAndroidHome && !avdmanagerInPath) {
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools', 'bin');
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_SDK_ROOT'], 'tools', 'bin');
}
return hasAndroidHome;
});
Expand Down Expand Up @@ -386,10 +405,12 @@ module.exports.check_android_target = function (originalError) {

// Returns a promise.
module.exports.run = function () {
console.log('Checking Java JDK and Android SDK versions');
console.log('ANDROID_SDK_ROOT=' + process.env['ANDROID_SDK_ROOT'] + ' (recommended setting)');
console.log('ANDROID_HOME=' + process.env['ANDROID_HOME'] + ' (DEPRECATED)');

return Promise.all([this.check_java(), this.check_android()]).then(function (values) {
console.log('Checking Java JDK and Android SDK versions');
console.log('ANDROID_SDK_ROOT=' + process.env['ANDROID_SDK_ROOT'] + ' (recommended setting)');
console.log('ANDROID_HOME=' + process.env['ANDROID_HOME'] + ' (DEPRECATED)');
console.log('Using Android SDK: ' + process.env['ANDROID_SDK_ROOT']);

if (!String(values[0]).startsWith('1.8.')) {
throw new CordovaError(
Expand Down
2 changes: 1 addition & 1 deletion framework/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ buildscript {
dependencies {
// The gradle plugin and the maven plugin have to be updated after each version of Android
// studio comes out
classpath 'com.android.tools.build:gradle:3.3.0'
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
}
Expand Down
6 changes: 5 additions & 1 deletion framework/cordova.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ String doFindLatestInstalledBuildTools(String minBuildToolsVersionString) {
String getAndroidSdkDir() {
def rootDir = project.rootDir
def androidSdkDir = null
String envVar = System.getenv("ANDROID_HOME")
String envVar = System.getenv("ANDROID_SDK_ROOT")
if (envVar == null) {
envVar = System.getenv("ANDROID_HOME")
}

def localProperties = new File(rootDir, 'local.properties')
String systemProperty = System.getProperty("android.home")
if (envVar != null) {
Expand Down
Loading

0 comments on commit 7634087

Please sign in to comment.