This is an automated email from the ASF dual-hosted git repository.

erisu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cordova-android.git


The following commit(s) were added to refs/heads/master by this push:
     new 510596f  feat!: unify & fix gradle library/tooling overrides (#1212)
510596f is described below

commit 510596f5155c89e1ea911c8677e375c40f3b6646
Author: Norman Breau <nor...@normanbreau.com>
AuthorDate: Tue Jul 6 03:38:28 2021 -0300

    feat!: unify & fix gradle library/tooling overrides (#1212)
    
    * enhancement: Control SDK versions and other default projects in one place
    * fix: target/compile sdk usage
    * refactor: cleanup gradle process
    * chore: cleanup and remove unused changes
    * chore: remove more unneeded FILE_PATH
    * chore: fix lint error
    * revert change intended to be part of a different PR
    * chore: apply changes to revert to fit new changes
    * fix: Ensure proper types
    * breaking: Removed TempateFile class
      * Replaced the one and only usage of it with the properties-parser editor.
      * Breaking change because we are converting a method into an asynchronous 
method.
    * refactor: Use the sync version of properties editor
    * Gh 1178 fix sdk use gradlearg fix (#2)
    * fix: readd gradleArg support
    * fix: variable name
    * refactor: remove unused mock variables
    * Update bin/templates/cordova/lib/builders/ProjectBuilder.js
    * Update bin/lib/create.js
    * fix: const naming (review suggestion)
    * fix: use defaults for framework building
    * chore: apply review suggestion
    * chore: rename config.json & defaults.json (review suggestions)
    * refactor: updateUserProjectGradleConfig method
    * refactor: minor changes in updateUserProjectGradleConfig
    * refactor: major changes in updateUserProjectGradleConfig
    * fix: wrong handling of missing preferences
    * fix: usage of undefined this
    * fix(create.spec): mocking of getPreference
    * test(check_reqs): reduce diff size
    * refactor: add wrapper to load gradle config defaults
    * fix(check_reqs): get_target
      * Reads default SDK from default gradle config now
    * fix(check_reqs.spec): return correct types from mocks
    * revert to using get_target in create
    * fix: e2e test
    
    Co-authored-by: Erisu <ellis.br...@gmail.com>
    Co-authored-by: Raphael von der Grün <raphine...@gmail.com>
---
 .gitignore                                         |   1 +
 bin/lib/create.js                                  |  14 +--
 .../cordova/lib/builders/ProjectBuilder.js         |  11 +-
 bin/templates/cordova/lib/check_reqs.js            |  43 +++----
 .../cordova/lib/gradle-config-defaults.js          |  30 +++++
 bin/templates/cordova/lib/plugin-build.gradle      |   4 +-
 bin/templates/cordova/lib/prepare.js               |  97 ++++++++++++----
 bin/templates/project/app/build.gradle             | 126 +++++----------------
 bin/templates/project/build.gradle                 |  16 +--
 framework/build.gradle                             |  27 ++---
 framework/cdv-gradle-config-defaults.json          |  12 ++
 framework/cordova.gradle                           |  48 +++++++-
 framework/default.properties                       |  14 ---
 framework/gradle/wrapper/gradle-wrapper.properties |   1 -
 framework/project.properties                       |   3 +-
 spec/e2e/plugin.spec.js                            |   7 ++
 spec/unit/check_reqs.spec.js                       |  44 ++-----
 spec/unit/prepare.spec.js                          |   1 +
 test/androidx/app/build.gradle                     |  12 +-
 test/androidx/build.gradle                         |   4 +-
 test/androidx/wrapper.gradle                       |   3 +-
 test/run_java_unit_tests.js                        |   4 +
 22 files changed, 268 insertions(+), 254 deletions(-)

diff --git a/.gitignore b/.gitignore
index e374ee7..ae182f8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,7 @@ example
 /test/androidx/gradle
 /test/androidx/gradlew
 /test/androidx/gradlew.bat
+/test/androidx/cdv-gradle-config.json
 
 /test/assets/www/.tmp*
 /test/assets/www/cordova.js
diff --git a/bin/lib/create.js b/bin/lib/create.js
index a38ecf9..93be111 100755
--- a/bin/lib/create.js
+++ b/bin/lib/create.js
@@ -22,6 +22,7 @@ var fs = require('fs-extra');
 var utils = require('../templates/cordova/lib/utils');
 var check_reqs = require('./../templates/cordova/lib/check_reqs');
 var ROOT = path.join(__dirname, '..', '..');
+const { createEditor } = require('properties-parser');
 
 var CordovaError = require('cordova-common').CordovaError;
 var AndroidManifest = require('../templates/cordova/lib/AndroidManifest');
@@ -42,16 +43,12 @@ function getFrameworkDir (projectPath, shared) {
     return shared ? path.join(ROOT, 'framework') : path.join(projectPath, 
'CordovaLib');
 }
 
-function copyJsAndLibrary (projectPath, shared, projectName, isLegacy) {
+function copyJsAndLibrary (projectPath, shared, projectName, targetAPI) {
     var nestedCordovaLibPath = getFrameworkDir(projectPath, false);
     var srcCordovaJsPath = path.join(ROOT, 'bin', 'templates', 'project', 
'assets', 'www', 'cordova.js');
     var app_path = path.join(projectPath, 'app', 'src', 'main');
     const platform_www = path.join(projectPath, 'platform_www');
 
-    if (isLegacy) {
-        app_path = projectPath;
-    }
-
     fs.copySync(srcCordovaJsPath, path.join(app_path, 'assets', 'www', 
'cordova.js'));
 
     // Copy the cordova.js file to platforms/<platform>/platform_www/
@@ -69,11 +66,14 @@ function copyJsAndLibrary (projectPath, shared, 
projectName, isLegacy) {
     } else {
         fs.ensureDirSync(nestedCordovaLibPath);
         fs.copySync(path.join(ROOT, 'framework', 'AndroidManifest.xml'), 
path.join(nestedCordovaLibPath, 'AndroidManifest.xml'));
-        fs.copySync(path.join(ROOT, 'framework', 'project.properties'), 
path.join(nestedCordovaLibPath, 'project.properties'));
+        const propertiesEditor = createEditor(path.join(ROOT, 'framework', 
'project.properties'));
+        propertiesEditor.set('target', targetAPI);
+        propertiesEditor.save(path.join(nestedCordovaLibPath, 
'project.properties'));
         fs.copySync(path.join(ROOT, 'framework', 'build.gradle'), 
path.join(nestedCordovaLibPath, 'build.gradle'));
         fs.copySync(path.join(ROOT, 'framework', 'cordova.gradle'), 
path.join(nestedCordovaLibPath, 'cordova.gradle'));
         fs.copySync(path.join(ROOT, 'framework', 'repositories.gradle'), 
path.join(nestedCordovaLibPath, 'repositories.gradle'));
         fs.copySync(path.join(ROOT, 'framework', 'src'), 
path.join(nestedCordovaLibPath, 'src'));
+        fs.copySync(path.join(ROOT, 'framework', 
'cdv-gradle-config-defaults.json'), path.join(projectPath, 
'cdv-gradle-config.json'));
     }
 }
 
@@ -277,7 +277,7 @@ exports.create = function (project_path, config, options, 
events) {
             fs.ensureDirSync(path.join(app_path, 'libs'));
 
             // copy cordova.js, cordova.jar
-            exports.copyJsAndLibrary(project_path, options.link, 
safe_activity_name);
+            exports.copyJsAndLibrary(project_path, options.link, 
safe_activity_name, target_api);
 
             // Set up ther Android Studio paths
             var java_path = path.join(app_path, 'java');
diff --git a/bin/templates/cordova/lib/builders/ProjectBuilder.js 
b/bin/templates/cordova/lib/builders/ProjectBuilder.js
index f4be4ae..129a01b 100644
--- a/bin/templates/cordova/lib/builders/ProjectBuilder.js
+++ b/bin/templates/cordova/lib/builders/ProjectBuilder.js
@@ -265,10 +265,11 @@ class ProjectBuilder {
             }).then(function () {
                 return self.prepBuildFiles();
             }).then(() => {
+                const config = this._getCordovaConfig();
                 // update/set the distributionUrl in the 
gradle-wrapper.properties
                 const gradleWrapperPropertiesPath = path.join(self.root, 
'gradle/wrapper/gradle-wrapper.properties');
                 const gradleWrapperProperties = 
createEditor(gradleWrapperPropertiesPath);
-                const distributionUrl = 
process.env.CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL || 
'https://services.gradle.org/distributions/gradle-6.8.3-all.zip';
+                const distributionUrl = 
process.env.CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL || 
`https://services.gradle.org/distributions/gradle-${config.GRADLE_VERSION}-all.zip`;
                 gradleWrapperProperties.set('distributionUrl', 
distributionUrl);
                 gradleWrapperProperties.save();
 
@@ -287,6 +288,14 @@ class ProjectBuilder {
             });
     }
 
+    /**
+     * @private
+     * @returns The user defined configs
+     */
+    _getCordovaConfig () {
+        return fs.readJSONSync(path.join(this.root, 'cdv-gradle-config.json'));
+    }
+
     /*
     * Builds the project with gradle.
     * Returns a promise.
diff --git a/bin/templates/cordova/lib/check_reqs.js 
b/bin/templates/cordova/lib/check_reqs.js
index cc62b6d..3a9ee16 100644
--- a/bin/templates/cordova/lib/check_reqs.js
+++ b/bin/templates/cordova/lib/check_reqs.js
@@ -23,11 +23,10 @@ var fs = require('fs-extra');
 const { forgivingWhichSync, isWindows, isDarwin } = require('./utils');
 const java = require('./env/java');
 var REPO_ROOT = path.join(__dirname, '..', '..', '..', '..');
-var PROJECT_ROOT = path.join(__dirname, '..', '..');
 const { CordovaError, ConfigParser, events } = require('cordova-common');
 var android_sdk = require('./android_sdk');
-const { createEditor } = require('properties-parser');
 const semver = require('semver');
+const { SDK_VERSION } = require('./gradle-config-defaults');
 
 const EXPECTED_JAVA_VERSION = '1.8.x';
 
@@ -36,44 +35,28 @@ const EXPECTED_JAVA_VERSION = '1.8.x';
 Object.assign(module.exports, { isWindows, isDarwin });
 
 /**
- * @description Get valid target from framework/project.properties if run from 
this repo
- *              Otherwise get target from project.properties file within a 
generated cordova-android project
  * @returns {string} The android target in format "android-${target}"
  */
 module.exports.get_target = function () {
-    const projectPropertiesPaths = [
-        path.join(REPO_ROOT, 'framework', 'project.properties'),
-        path.join(PROJECT_ROOT, 'project.properties')
-    ];
-
-    // Get the minimum required target API from the framework.
-    let target = projectPropertiesPaths.filter(filePath => 
fs.existsSync(filePath))
-        .map(filePath => createEditor(filePath).get('target'))
-        .pop();
+    const userTargetSdkVersion = getUserTargetSdkVersion();
 
-    if (!target) {
-        throw new Error(`We could not locate the target from the 
"project.properties" at either "${projectPropertiesPaths.join('", "')}".`);
+    if (userTargetSdkVersion && userTargetSdkVersion < SDK_VERSION) {
+        events.emit('warn', `android-targetSdkVersion should be greater than 
or equal to ${SDK_VERSION}.`);
     }
 
+    return `android-${Math.max(userTargetSdkVersion, SDK_VERSION)}`;
+};
+
+/** @returns {number} target sdk or 0 if undefined */
+function getUserTargetSdkVersion () {
     // If the repo config.xml file exists, find the desired targetSdkVersion.
     const configFile = path.join(REPO_ROOT, 'config.xml');
-    if (!fs.existsSync(configFile)) return target;
+    if (!fs.existsSync(configFile)) return 0;
 
     const configParser = new ConfigParser(configFile);
-    const desiredAPI = 
parseInt(configParser.getPreference('android-targetSdkVersion', 'android'), 10);
-
-    if (!isNaN(desiredAPI)) {
-        const minimumAPI = parseInt(target.split('-').pop(), 10);
-
-        if (desiredAPI >= minimumAPI) {
-            target = `android-${desiredAPI}`;
-        } else {
-            events.emit('warn', `android-targetSdkVersion should be greater 
than or equal to ${minimumAPI}.`);
-        }
-    }
-
-    return target;
-};
+    const targetSdkVersion = 
parseInt(configParser.getPreference('android-targetSdkVersion', 'android'), 10);
+    return isNaN(targetSdkVersion) ? 0 : targetSdkVersion;
+}
 
 module.exports.get_gradle_wrapper = function () {
     var androidStudioPath;
diff --git a/bin/templates/cordova/lib/gradle-config-defaults.js 
b/bin/templates/cordova/lib/gradle-config-defaults.js
new file mode 100644
index 0000000..be3be3a
--- /dev/null
+++ b/bin/templates/cordova/lib/gradle-config-defaults.js
@@ -0,0 +1,30 @@
+/*!
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+const ABS_MODULE_PATH = '/framework/cdv-gradle-config-defaults.json';
+
+try {
+    // Try relative require first, …
+    const REPO_ROOT = '../../../..';
+    module.exports = require(REPO_ROOT + ABS_MODULE_PATH);
+} catch (error) {
+    // … then fall back to installed-package require
+    if (error.code !== 'MODULE_NOT_FOUND') throw error;
+    module.exports = require('cordova-android' + ABS_MODULE_PATH);
+}
diff --git a/bin/templates/cordova/lib/plugin-build.gradle 
b/bin/templates/cordova/lib/plugin-build.gradle
index 0cda9f0..985f1d6 100644
--- a/bin/templates/cordova/lib/plugin-build.gradle
+++ b/bin/templates/cordova/lib/plugin-build.gradle
@@ -42,8 +42,8 @@ dependencies {
 }
 
 android {
-    compileSdkVersion cdvCompileSdkVersion
-    buildToolsVersion cdvBuildToolsVersion
+    compileSdkVersion cordovaConfig.SDK_VERSION
+    buildToolsVersion cordovaConfig.BUILD_TOOLS_VERSION
 
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_6
diff --git a/bin/templates/cordova/lib/prepare.js 
b/bin/templates/cordova/lib/prepare.js
index b01ce9a..9f4b4cf 100644
--- a/bin/templates/cordova/lib/prepare.js
+++ b/bin/templates/cordova/lib/prepare.js
@@ -32,6 +32,7 @@ var PlatformJson = require('cordova-common').PlatformJson;
 var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
 var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
 const utils = require('./utils');
+const gradleConfigDefaults = require('./gradle-config-defaults');
 
 const GradlePropertiesParser = require('./config/GradlePropertiesParser');
 
@@ -55,29 +56,11 @@ module.exports.prepare = function (cordovaProject, options) 
{
 
     this._config = updateConfigFilesFrom(cordovaProject.projectConfig, munger, 
this.locations);
 
-    // Get the min SDK version from config.xml
-    const minSdkVersion = this._config.getPreference('android-minSdkVersion', 
'android');
-    const maxSdkVersion = this._config.getPreference('android-maxSdkVersion', 
'android');
-    const targetSdkVersion = 
this._config.getPreference('android-targetSdkVersion', 'android');
-    const isGradlePluginKotlinEnabled = 
this._config.getPreference('GradlePluginKotlinEnabled', 'android');
-    const gradlePluginKotlinCodeStyle = 
this._config.getPreference('GradlePluginKotlinCodeStyle', 'android');
-    const androidXAppCompatVersion = 
this._config.getPreference('AndroidXAppCompatVersion', 'android');
-
-    const gradlePropertiesUserConfig = {};
-    if (minSdkVersion) gradlePropertiesUserConfig.cdvMinSdkVersion = 
minSdkVersion;
-    if (maxSdkVersion) gradlePropertiesUserConfig.cdvMaxSdkVersion = 
maxSdkVersion;
-    if (targetSdkVersion) gradlePropertiesUserConfig.cdvTargetSdkVersion = 
targetSdkVersion;
-    if (args.jvmargs) gradlePropertiesUserConfig['org.gradle.jvmargs'] = 
args.jvmargs;
-    if (isGradlePluginKotlinEnabled) {
-        gradlePropertiesUserConfig['kotlin.code.style'] = 
gradlePluginKotlinCodeStyle || 'official';
-    }
-
-    if (androidXAppCompatVersion) {
-        gradlePropertiesUserConfig.cdvAndroidXAppCompatVersion = 
androidXAppCompatVersion;
-    }
+    // Update Gradle cdv-gradle-config.json
+    updateUserProjectGradleConfig(this);
 
-    const gradlePropertiesParser = new 
GradlePropertiesParser(this.locations.root);
-    gradlePropertiesParser.configure(gradlePropertiesUserConfig);
+    // Update Project's Gradle Properties
+    updateUserProjectGradlePropertiesConfig(this, args);
 
     // Update own www dir with project's www assets and plugins' assets and 
js-files
     return Promise.resolve(updateWww(cordovaProject, 
this.locations)).then(function () {
@@ -92,6 +75,76 @@ module.exports.prepare = function (cordovaProject, options) {
     });
 };
 
+/** @param {PlatformApi} project */
+function updateUserProjectGradleConfig (project) {
+    // Generate project gradle config
+    const projectGradleConfig = {
+        ...gradleConfigDefaults,
+        ...getUserGradleConfig(project._config)
+    };
+
+    // Write out changes
+    const projectGradleConfigPath = path.join(project.root, 
'cdv-gradle-config.json');
+    fs.writeJSONSync(projectGradleConfigPath, projectGradleConfig, { spaces: 2 
});
+}
+
+function getUserGradleConfig (configXml) {
+    const configXmlToGradleMapping = [
+        { xmlKey: 'android-minSdkVersion', gradleKey: 'MIN_SDK_VERSION', type: 
Number },
+        { xmlKey: 'android-maxSdkVersion', gradleKey: 'MAX_SDK_VERSION', type: 
Number },
+        { xmlKey: 'android-targetSdkVersion', gradleKey: 'SDK_VERSION', type: 
Number },
+        { xmlKey: 'android-buildToolsVersion', gradleKey: 
'BUILD_TOOLS_VERSION', type: String },
+        { xmlKey: 'GradleVersion', gradleKey: 'GRADLE_VERSION', type: String },
+        { xmlKey: 'AndroidGradlePluginVersion', gradleKey: 'AGP_VERSION', 
type: String },
+        { xmlKey: 'GradlePluginKotlinVersion', gradleKey: 'KOTLIN_VERSION', 
type: String },
+        { xmlKey: 'AndroidXAppCompatVersion', gradleKey: 
'ANDROIDX_APP_COMPAT_VERSION', type: String },
+        { xmlKey: 'GradlePluginGoogleServicesVersion', gradleKey: 
'GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION', type: String },
+        { xmlKey: 'GradlePluginGoogleServicesEnabled', gradleKey: 
'IS_GRADLE_PLUGIN_GOOGLE_SERVICES_ENABLED', type: Boolean },
+        { xmlKey: 'GradlePluginKotlinEnabled', gradleKey: 
'IS_GRADLE_PLUGIN_KOTLIN_ENABLED', type: Boolean }
+    ];
+
+    return configXmlToGradleMapping.reduce((config, mapping) => {
+        const rawValue = configXml.getPreference(mapping.xmlKey, 'android');
+
+        // ignore missing preferences (which occur as '')
+        if (rawValue) {
+            config[mapping.gradleKey] = parseStringAsType(rawValue, 
mapping.type);
+        }
+
+        return config;
+    }, {});
+}
+
+/** Converts given string to given type */
+function parseStringAsType (value, type) {
+    switch (type) {
+    case String:
+        return String(value);
+    case Number:
+        return parseFloat(value);
+    case Boolean:
+        return value.toLowerCase() === 'true';
+    default:
+        throw new CordovaError('Invalid type: ' + type);
+    }
+}
+
+function updateUserProjectGradlePropertiesConfig (project, args) {
+    const gradlePropertiesUserConfig = {};
+
+    // Get the min SDK version from config.xml
+    if (args.jvmargs) gradlePropertiesUserConfig['org.gradle.jvmargs'] = 
args.jvmargs;
+
+    const isGradlePluginKotlinEnabled = 
project._config.getPreference('GradlePluginKotlinEnabled', 'android');
+    if (isGradlePluginKotlinEnabled) {
+        const gradlePluginKotlinCodeStyle = 
project._config.getPreference('GradlePluginKotlinCodeStyle', 'android');
+        gradlePropertiesUserConfig['kotlin.code.style'] = 
gradlePluginKotlinCodeStyle || 'official';
+    }
+
+    const gradlePropertiesParser = new GradlePropertiesParser(project.root);
+    gradlePropertiesParser.configure(gradlePropertiesUserConfig);
+}
+
 module.exports.clean = function (options) {
     // A cordovaProject isn't passed into the clean() function, because it 
might have
     // been called from the platform shell script rather than the CLI. Check 
for the
diff --git a/bin/templates/project/app/build.gradle 
b/bin/templates/project/app/build.gradle
index 580a0af..8854fea 100644
--- a/bin/templates/project/app/build.gradle
+++ b/bin/templates/project/app/build.gradle
@@ -19,7 +19,7 @@
 
 apply plugin: 'com.android.application'
 
-if (cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 
'false').toBoolean()) {
+if (cordovaConfig.IS_GRADLE_PLUGIN_KOTLIN_ENABLED) {
     apply plugin: 'kotlin-android'
     apply plugin: 'kotlin-android-extensions'
 }
@@ -27,50 +27,31 @@ if 
(cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 'false').toBoole
 buildscript {
     apply from: '../CordovaLib/cordova.gradle'
 
-    if(cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 
'false').toBoolean()) {
-        String defaultGradlePluginKotlinVersion = kotlin_version
-
-        /**
-         * Fetches the user's defined Kotlin Version from config.xml.
-         * If the version is not set or invalid, it will default to the 
${defaultGradlePluginKotlinVersion}
-         */
-        String gradlePluginKotlinVersion = 
cdvHelpers.getConfigPreference('GradlePluginKotlinVersion', 
defaultGradlePluginKotlinVersion)
-        if(!cdvHelpers.isVersionValid(gradlePluginKotlinVersion)) {
-            println("The defined Kotlin version (${gradlePluginKotlinVersion}) 
does not appear to be a valid version. Falling back to version: 
${defaultGradlePluginKotlinVersion}.")
-            gradlePluginKotlinVersion = defaultGradlePluginKotlinVersion
+    // Checks if the kotlin version format is valid.
+    if(cordovaConfig.IS_GRADLE_PLUGIN_KOTLIN_ENABLED) {
+        if(!cdvHelpers.isVersionValid(cordovaConfig.KOTLIN_VERSION)) {
+            throw new GradleException("The defined Kotlin version 
(${cordovaConfig.KOTLIN_VERSION}) does not appear to be a valid version.")
         }
-
-        // Change the version to be used.
-        ext.kotlin_version = gradlePluginKotlinVersion
     }
 
     apply from: 'repositories.gradle'
     repositories repos
 
     dependencies {
-        apply from: '../CordovaLib/cordova.gradle'
-
-        classpath 'com.android.tools.build:gradle:4.2.1'
+        classpath "com.android.tools.build:gradle:${cordovaConfig.AGP_VERSION}"
 
-        if (cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 
'false').toBoolean()) {
-            classpath 
"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+        if (cordovaConfig.IS_GRADLE_PLUGIN_KOTLIN_ENABLED) {
+            classpath 
"org.jetbrains.kotlin:kotlin-gradle-plugin:${cordovaConfig.KOTLIN_VERSION}"
         }
 
-        if(cdvHelpers.getConfigPreference('GradlePluginGoogleServicesEnabled', 
'false').toBoolean()) {
-            String defaultGradlePluginGoogleServicesVersion = '4.3.5'
-
-            /**
-             * Fetches the user's defined Google Services Plugin Version from 
config.xml.
-             * If the version is not set or invalid, it will default to the 
${defaultGradlePluginGoogleServicesVersion}
-             */
-            String gradlePluginGoogleServicesVersion = 
cdvHelpers.getConfigPreference('GradlePluginGoogleServicesVersion', 
defaultGradlePluginGoogleServicesVersion)
+        if(cordovaConfig.IS_GRADLE_PLUGIN_GOOGLE_SERVICES_ENABLED) {
+            // Checks if the kotlin version format is valid.
             if(!cdvHelpers.isVersionValid(gradlePluginGoogleServicesVersion)) {
-                println("The defined Google Services plugin version 
(${gradlePluginGoogleServicesVersion}) does not appear to be a valid version. 
Falling back to version: ${defaultGradlePluginGoogleServicesVersion}.")
-                gradlePluginGoogleServicesVersion = 
defaultGradlePluginGoogleServicesVersion
+                throw new GradleException("The defined Google Services plugin 
version (${cordovaConfig.GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION}) does not 
appear to be a valid version.")
             }
 
             // Create the Google Services classpath and set it.
-            String gradlePluginGoogleServicesClassPath = 
"com.google.gms:google-services:${gradlePluginGoogleServicesVersion}"
+            String gradlePluginGoogleServicesClassPath = 
"com.google.gms:google-services:${cordovaConfig.GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION}"
             println "Adding classpath: ${gradlePluginGoogleServicesClassPath}"
             classpath gradlePluginGoogleServicesClassPath
         }
@@ -84,7 +65,7 @@ allprojects {
 }
 
 task wrapper(type: Wrapper) {
-    gradleVersion = '6.8.3'
+    gradleVersion = cordovaConfig.GRADLE_VERSION
 }
 
 // Configuration properties. Set these via environment variables, 
build-extras.gradle, or gradle.properties.
@@ -92,30 +73,10 @@ task wrapper(type: Wrapper) {
 ext {
     apply from: '../CordovaLib/cordova.gradle'
 
-    // The value for android.compileSdkVersion.
-    if (!project.hasProperty('cdvCompileSdkVersion')) {
-        cdvCompileSdkVersion = null;
-    }
-    // The value for android.buildToolsVersion.
-    if (!project.hasProperty('cdvBuildToolsVersion')) {
-        cdvBuildToolsVersion = null;
-    }
     // Sets the versionCode to the given value.
     if (!project.hasProperty('cdvVersionCode')) {
         cdvVersionCode = null
     }
-    // Sets the minSdkVersion to the given value.
-    if (!project.hasProperty('cdvMinSdkVersion')) {
-        cdvMinSdkVersion = null
-    }
-    // Sets the maxSdkVersion to the given value.
-    if (!project.hasProperty('cdvMaxSdkVersion')) {
-        cdvMaxSdkVersion = null
-    }
-    // The value for android.targetSdkVersion.
-    if (!project.hasProperty('cdvTargetSdkVersion')) {
-        cdvTargetSdkVersion = null;
-    }
     // Whether to build architecture-specific APKs.
     if (!project.hasProperty('cdvBuildMultipleApks')) {
         cdvBuildMultipleApks = null
@@ -137,11 +98,6 @@ ext {
         cdvBuildArch = null
     }
 
-    // Sets the default cdvAndroidXAppCompatVersion to the given value.
-    if (!project.hasProperty('cdvAndroidXAppCompatVersion')) {
-        cdvAndroidXAppCompatVersion = null
-    }
-
     // Plugin gradle extensions can append to this to have code run at the end.
     cdvPluginPostBuildExtras = []
 }
@@ -159,17 +115,10 @@ if (hasBuildExtras2) {
     apply from: '../build-extras.gradle'
 }
 
+// Apply updates that might come from build-extra.
+privateHelpers.applyCordovaConfigCustomization()
+
 // Set property defaults after extension .gradle files.
-ext.cdvCompileSdkVersion = cdvCompileSdkVersion == null ? (
-    defaultCompileSdkVersion == null
-        ? privateHelpers.getProjectTarget()
-        : defaultCompileSdkVersion
-) : Integer.parseInt('' + cdvCompileSdkVersion);
-
-if (ext.cdvBuildToolsVersion == null) {
-    ext.cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
-    //ext.cdvBuildToolsVersion = project.ext.defaultBuildToolsVersion
-}
 if (ext.cdvDebugSigningPropertiesFile == null && 
file('../debug-signing.properties').exists()) {
     ext.cdvDebugSigningPropertiesFile = '../debug-signing.properties'
 }
@@ -180,18 +129,8 @@ if (ext.cdvReleaseSigningPropertiesFile == null && 
file('../release-signing.prop
 // Cast to appropriate types.
 ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : 
cdvBuildMultipleApks.toBoolean();
 ext.cdvVersionCodeForceAbiDigit = cdvVersionCodeForceAbiDigit == null ? false 
: cdvVersionCodeForceAbiDigit.toBoolean();
-
-// minSdkVersion, maxSdkVersion and targetSdkVersion
-ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? defaultMinSdkVersion : 
Integer.parseInt('' + cdvMinSdkVersion)
-if (cdvMaxSdkVersion != null) {
-    ext.cdvMaxSdkVersion = Integer.parseInt('' + cdvMaxSdkVersion)
-}
-ext.cdvTargetSdkVersion = cdvTargetSdkVersion == null ? 
defaultTargetSdkVersion  : Integer.parseInt('' + cdvTargetSdkVersion)
-
 ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + 
cdvVersionCode)
 
-ext.cdvAndroidXAppCompatVersion = cdvAndroidXAppCompatVersion == null ? 
defaultAndroidXAppCompatVersion : cdvAndroidXAppCompatVersion
-
 def computeBuildTargetName(debugBuild) {
     def ret = 'assemble'
     if (cdvBuildMultipleApks && cdvBuildArch) {
@@ -214,13 +153,12 @@ cdvBuildRelease.dependsOn {
 
 task cdvPrintProps {
     doLast {
-        println('cdvCompileSdkVersion=' + cdvCompileSdkVersion)
         println('cdvBuildToolsVersion=' + cdvBuildToolsVersion)
         println('cdvVersionCode=' + cdvVersionCode)
         println('cdvVersionCodeForceAbiDigit=' + cdvVersionCodeForceAbiDigit)
+        println('cdvSdkVersion=' + cdvSdkVersion)
         println('cdvMinSdkVersion=' + cdvMinSdkVersion)
         println('cdvMaxSdkVersion=' + cdvMaxSdkVersion)
-        println('cdvTargetSdkVersion=' + cdvTargetSdkVersion)
         println('cdvBuildMultipleApks=' + cdvBuildMultipleApks)
         println('cdvReleaseSigningPropertiesFile=' + 
cdvReleaseSigningPropertiesFile)
         println('cdvDebugSigningPropertiesFile=' + 
cdvDebugSigningPropertiesFile)
@@ -238,25 +176,19 @@ android {
         versionCode cdvVersionCode ?: new BigInteger("" + 
privateHelpers.extractIntFromManifest("versionCode"))
         applicationId privateHelpers.extractStringFromManifest("package")
 
-        if (cdvMinSdkVersion != null) {
-            minSdkVersion cdvMinSdkVersion
-        }
-
-        if (cdvMaxSdkVersion != null) {
-            maxSdkVersion cdvMaxSdkVersion
-        }
-
-        if(cdvTargetSdkVersion != null) {
-            targetSdkVersion cdvTargetSdkVersion
+        minSdkVersion cordovaConfig.MIN_SDK_VERSION
+        if (cordovaConfig.MAX_SDK_VERSION != null) {
+            maxSdkVersion cordovaConfig.MAX_SDK_VERSION
         }
+        targetSdkVersion cordovaConfig.SDK_VERSION
+        compileSdkVersion cordovaConfig.SDK_VERSION
     }
 
     lintOptions {
-      abortOnError false;
+      abortOnError false
     }
 
-    compileSdkVersion cdvCompileSdkVersion
-    buildToolsVersion cdvBuildToolsVersion
+    buildToolsVersion cordovaConfig.LATEST_INSTALLED_BUILD_TOOLS
 
     // This code exists for Crosswalk and other Native APIs.
     // By default, we multiply the existing version code in the
@@ -347,10 +279,10 @@ android {
 
 dependencies {
     implementation fileTree(dir: 'libs', include: '*.jar')
-    implementation "androidx.appcompat:appcompat:$cdvAndroidXAppCompatVersion"
+    implementation 
"androidx.appcompat:appcompat:${cordovaConfig.ANDROIDX_APP_COMPAT_VERSION}"
 
-    if (cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 
'false').toBoolean()) {
-        implementation 
"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+    if (cordovaConfig.IS_GRADLE_PLUGIN_KOTLIN_ENABLED) {
+        implementation 
"org.jetbrains.kotlin:kotlin-stdlib-jdk7:${cordovaConfig.KOTLIN_VERSION}"
     }
 
     // SUB-PROJECT DEPENDENCIES START
@@ -379,7 +311,7 @@ def addSigningProps(propsFilePath, signingConfig) {
     signingConfig.storePassword = props.get('storePassword', 
props.get('key.store.password', signingConfig.storePassword))
     def storeType = props.get('storeType', props.get('key.store.type', ''))
     if (!storeType) {
-        def filename = storeFile.getName().toLowerCase();
+        def filename = storeFile.getName().toLowerCase()
         if (filename.endsWith('.p12') || filename.endsWith('.pfx')) {
             storeType = 'pkcs12'
         } else {
@@ -399,6 +331,6 @@ if (hasProperty('postBuildExtras')) {
     postBuildExtras()
 }
 
-if (cdvHelpers.getConfigPreference('GradlePluginGoogleServicesEnabled', 
'false').toBoolean()) {
+if (cordovaConfig.IS_GRADLE_PLUGIN_GOOGLE_SERVICES_ENABLED) {
     apply plugin: 'com.google.gms.google-services'
 }
diff --git a/bin/templates/project/build.gradle 
b/bin/templates/project/build.gradle
index 62a82e8..1e01f06 100644
--- a/bin/templates/project/build.gradle
+++ b/bin/templates/project/build.gradle
@@ -17,14 +17,13 @@
 */
 
 // Top-level build file where you can add configuration options common to all 
sub-projects/modules.
-
 buildscript {
-    ext.kotlin_version = '1.4.32'
+    apply from: 'CordovaLib/cordova.gradle'
     apply from: 'repositories.gradle'
     repositories repos
     dependencies {
-        classpath 'com.android.tools.build:gradle:4.2.1'
-        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+        classpath "com.android.tools.build:gradle:${cordovaConfig.AGP_VERSION}"
+        classpath 
"org.jetbrains.kotlin:kotlin-gradle-plugin:${cordovaConfig.KOTLIN_VERSION}"
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
     }
@@ -33,15 +32,6 @@ buildscript {
 allprojects {
     apply from: 'repositories.gradle'
     repositories repos
-
-    //This replaces project.properties w.r.t. build settings
-    project.ext {
-      defaultBuildToolsVersion="30.0.3" //String
-      defaultMinSdkVersion=22 //Integer - Minimum requirement is Android 5.1
-      defaultTargetSdkVersion=30 //Integer - We ALWAYS target the latest by 
default
-      defaultCompileSdkVersion=30 //Integer - We ALWAYS compile with the 
latest by default
-      defaultAndroidXAppCompatVersion="1.2.0" //String - We ALWAYS compile 
with the latest stable by default
-    }
 }
 
 task clean(type: Delete) {
diff --git a/framework/build.gradle b/framework/build.gradle
index 8296fca..55dd4e0 100644
--- a/framework/build.gradle
+++ b/framework/build.gradle
@@ -18,30 +18,17 @@
 
 ext {
     apply from: 'cordova.gradle'
-    cdvCompileSdkVersion = privateHelpers.getProjectTarget()
-    cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
-    if (project.hasProperty('cdvMinSdkVersion') && 
cdvMinSdkVersion.isInteger()) {
-        cdvMinSdkVersion = cdvMinSdkVersion as int
-        println '[Cordova] cdvMinSdkVersion is overridden, try it at your own 
risk.'
-    } else {
-        cdvMinSdkVersion = 22; // current Cordova's default
-    }
-
-    if (project.hasProperty('cdvAndroidXAppCompatVersion')) {
-        cdvAndroidXAppCompatVersion = cdvAndroidXAppCompatVersion
-        println '[Cordova] cdvAndroidXAppCompatVersion is overridden, try it 
at your own risk.'
-    } else {
-        cdvAndroidXAppCompatVersion = "1.2.0"; // current Cordova's default
-    }
 }
 
 buildscript {
+    apply from: 'cordova.gradle'
     apply from: 'repositories.gradle'
+
     repositories repos
 
     dependencies {
         // Android Gradle Plugin (AGP) Build Tools
-        classpath 'com.android.tools.build:gradle:4.2.1'
+        classpath "com.android.tools.build:gradle:${cordovaConfig.AGP_VERSION}"
 
         // @todo remove this abandoned plugin. maven-publish-plugin is now 
supported by Android Gradle plugin 3.6.0 and higher
         classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
@@ -62,8 +49,8 @@ group = 'org.apache.cordova'
 version = '10.0.0-dev'
 
 android {
-    compileSdkVersion cdvCompileSdkVersion
-    buildToolsVersion cdvBuildToolsVersion
+    compileSdkVersion cordovaConfig.SDK_VERSION
+    buildToolsVersion cordovaConfig.BUILD_TOOLS_VERSION
 
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_8
@@ -72,7 +59,7 @@ android {
 
     // For the Android Cordova Lib, we allow changing the minSdkVersion, but 
it is at the users own risk
     defaultConfig {
-        minSdkVersion cdvMinSdkVersion
+        minSdkVersion cordovaConfig.MIN_SDK_VERSION
     }
 
     sourceSets {
@@ -132,7 +119,7 @@ task sourcesJar(type: Jar) {
 }
 
 dependencies {
-    implementation "androidx.appcompat:appcompat:$cdvAndroidXAppCompatVersion"
+    implementation 
"androidx.appcompat:appcompat:${cordovaConfig.ANDROIDX_APP_COMPAT_VERSION}"
 }
 
 artifacts {
diff --git a/framework/cdv-gradle-config-defaults.json 
b/framework/cdv-gradle-config-defaults.json
new file mode 100644
index 0000000..daf912a
--- /dev/null
+++ b/framework/cdv-gradle-config-defaults.json
@@ -0,0 +1,12 @@
+{
+    "MIN_SDK_VERSION": 22,
+    "SDK_VERSION": 30,
+    "GRADLE_VERSION": "6.8.3",
+    "BUILD_TOOLS_VERSION": "30.0.3",
+    "AGP_VERSION": "4.2.1",
+    "KOTLIN_VERSION": "1.4.32",
+    "ANDROIDX_APP_COMPAT_VERSION": "1.2.0",
+    "GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION": "4.3.5",
+    "IS_GRADLE_PLUGIN_GOOGLE_SERVICES_ENABLED": false,
+    "IS_GRADLE_PLUGIN_KOTLIN_ENABLED": false
+}
diff --git a/framework/cordova.gradle b/framework/cordova.gradle
index 19d4be5..915357e 100644
--- a/framework/cordova.gradle
+++ b/framework/cordova.gradle
@@ -18,7 +18,6 @@
 */
 
 import java.util.regex.Pattern
-import groovy.swing.SwingBuilder
 import io.github.g00fy2.versioncompare.Version
 
 String doEnsureValueExists(filePath, props, key) {
@@ -151,12 +150,57 @@ def doGetConfigPreference(name, defaultValue) {
     return ret
 }
 
+def doApplyCordovaConfigCustomization() {
+    // Apply user overide properties that comes from the "--gradleArg=-P" 
parameters
+    if (project.hasProperty('cdvMinSdkVersion')) {
+        cordovaConfig.MIN_SDK_VERSION = Integer.parseInt('' + cdvMinSdkVersion)
+    }
+    if (project.hasProperty('cdvSdkVersion')) {
+        cordovaConfig.SDK_VERSION = Integer.parseInt('' + cdvSdkVersion)
+    }
+    if (project.hasProperty('cdvMaxSdkVersion')) {
+        cordovaConfig.MAX_SDK_VERSION = Integer.parseInt('' + cdvMaxSdkVersion)
+    }
+    if (project.hasProperty('cdvBuildToolsVersion')) {
+        cordovaConfig.BUILD_TOOLS_VERSION = cdvBuildToolsVersion
+    }
+    if (project.hasProperty('cdvAndroidXAppCompatVersion')) {
+        cordovaConfig.ANDROIDX_APP_COMPAT_VERSION = cdvAndroidXAppCompatVersion
+    }
+
+    // Ensure the latest installed build tools is selected, with or without 
defined override
+    cordovaConfig.LATEST_INSTALLED_BUILD_TOOLS = 
doFindLatestInstalledBuildTools(
+        cordovaConfig.BUILD_TOOLS_VERSION
+    )
+}
+
 // Properties exported here are visible to all plugins.
 ext {
+    def defaultsFilePath = './cdv-gradle-config-defaults.json'
+    def projectConfigFilePath = "$rootDir/cdv-gradle-config.json"
+    def targetConfigFilePath = null
+
+    /**
+     * Check if the project config file path exists. This file will exist if 
coming from CLI project.
+     * If this file does not exist, falls back onto the default file.
+     * This scenario can occur if building the framework's AAR package for 
publishing.
+     */
+    if(file(projectConfigFilePath).exists()) {
+        targetConfigFilePath = projectConfigFilePath
+    } else {
+        targetConfigFilePath = defaultsFilePath
+    }
+
+    def jsonFile = new File(targetConfigFilePath)
+    cordovaConfig = new groovy.json.JsonSlurper().parseText(jsonFile.text)
+
+    // Apply Gradle Properties
+    doApplyCordovaConfigCustomization()
+
     // These helpers are shared, but are not guaranteed to be stable / 
unchanged.
     privateHelpers = {}
     privateHelpers.getProjectTarget = { doGetProjectTarget() }
-    privateHelpers.findLatestInstalledBuildTools = { 
doFindLatestInstalledBuildTools('19.1.0') }
+    privateHelpers.applyCordovaConfigCustomization = { 
doApplyCordovaConfigCustomization() }
     privateHelpers.extractIntFromManifest = { name -> 
doExtractIntFromManifest(name) }
     privateHelpers.extractStringFromManifest = { name -> 
doExtractStringFromManifest(name) }
     privateHelpers.ensureValueExists = { filePath, props, key -> 
doEnsureValueExists(filePath, props, key) }
diff --git a/framework/default.properties b/framework/default.properties
deleted file mode 100644
index d4e24dc..0000000
--- a/framework/default.properties
+++ /dev/null
@@ -1,14 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system use,
-# "build.properties", and override values to adapt the script to your
-# project structure.
-
-# Indicates whether an apk should be generated for each density.
-split.density=false
-# Project target.
-target=android-14
-apk-configurations=
diff --git a/framework/gradle/wrapper/gradle-wrapper.properties 
b/framework/gradle/wrapper/gradle-wrapper.properties
index d4c7ae1..46d87b8 100644
--- a/framework/gradle/wrapper/gradle-wrapper.properties
+++ b/framework/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,3 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
diff --git a/framework/project.properties b/framework/project.properties
index 52d09c3..8532755 100644
--- a/framework/project.properties
+++ b/framework/project.properties
@@ -1,3 +1,5 @@
+# GENERATED FILE! DO NOT EDIT!
+
 # This file was originally created by the Android Tools, but is now
 # used by cordova-android to manage the project configuration.
 
@@ -5,7 +7,6 @@
 split.density=false
 
 # Project target.
-target=android-30
 apk-configurations=
 renderscript.opt.level=O0
 android.library=true
diff --git a/spec/e2e/plugin.spec.js b/spec/e2e/plugin.spec.js
index 88e74be..7debf88 100644
--- a/spec/e2e/plugin.spec.js
+++ b/spec/e2e/plugin.spec.js
@@ -46,6 +46,13 @@ describe('plugin add', function () {
         return Promise.resolve()
             .then(() => execa(createBin, [projectPath, projectid, 
projectname]))
             .then(() => {
+                // Allow test project to find the `cordova-android` module
+                fs.ensureSymlinkSync(
+                    path.join(__dirname, '../..'),
+                    path.join(projectPath, 'node_modules/cordova-android'),
+                    'junction'
+                );
+
                 const Api = require(path.join(projectPath, 'cordova/Api.js'));
                 return new Api('android', projectPath).addPlugin(pluginInfo);
             });
diff --git a/spec/unit/check_reqs.spec.js b/spec/unit/check_reqs.spec.js
index 6547200..dba0017 100644
--- a/spec/unit/check_reqs.spec.js
+++ b/spec/unit/check_reqs.spec.js
@@ -281,30 +281,15 @@ describe('check_reqs', function () {
             check_reqs.__set__('ConfigParser', ConfigParser);
         });
 
-        it('should retrieve target from framework project.properties file', 
function () {
+        it('should retrieve DEFAULT_TARGET_API', function () {
             var target = check_reqs.get_target();
             expect(target).toBeDefined();
             expect(target).toContain('android-' + DEFAULT_TARGET_API);
         });
 
-        it('should throw error if target cannot be found', function () {
-            spyOn(fs, 'existsSync').and.returnValue(false);
-            expect(function () {
-                check_reqs.get_target();
-            }).toThrow();
-        });
-
         it('should override target from config.xml preference', () => {
-            var realExistsSync = fs.existsSync;
-            spyOn(fs, 'existsSync').and.callFake(function (path) {
-                if (path.indexOf('config.xml') > -1) {
-                    return true;
-                } else {
-                    return realExistsSync.call(fs, path);
-                }
-            });
-
-            getPreferenceSpy.and.returnValue(DEFAULT_TARGET_API + 1);
+            spyOn(fs, 'existsSync').and.returnValue(true);
+            getPreferenceSpy.and.returnValue(String(DEFAULT_TARGET_API + 1));
 
             var target = check_reqs.get_target();
 
@@ -313,16 +298,8 @@ describe('check_reqs', function () {
         });
 
         it('should fallback to default target if config.xml has invalid 
preference', () => {
-            var realExistsSync = fs.existsSync;
-            spyOn(fs, 'existsSync').and.callFake(function (path) {
-                if (path.indexOf('config.xml') > -1) {
-                    return true;
-                } else {
-                    return realExistsSync.call(fs, path);
-                }
-            });
-
-            getPreferenceSpy.and.returnValue(NaN);
+            spyOn(fs, 'existsSync').and.returnValue(true);
+            getPreferenceSpy.and.returnValue('android-99');
 
             var target = check_reqs.get_target();
 
@@ -331,18 +308,11 @@ describe('check_reqs', function () {
         });
 
         it('should warn if target sdk preference is lower than the minimum 
required target SDK', () => {
-            var realExistsSync = fs.existsSync;
-            spyOn(fs, 'existsSync').and.callFake(function (path) {
-                if (path.indexOf('config.xml') > -1) {
-                    return true;
-                } else {
-                    return realExistsSync.call(fs, path);
-                }
-            });
+            spyOn(fs, 'existsSync').and.returnValue(true);
 
             spyOn(events, 'emit');
 
-            getPreferenceSpy.and.returnValue(DEFAULT_TARGET_API - 1);
+            getPreferenceSpy.and.returnValue(String(DEFAULT_TARGET_API - 1));
 
             var target = check_reqs.get_target();
 
diff --git a/spec/unit/prepare.spec.js b/spec/unit/prepare.spec.js
index a16130a..3b19708 100644
--- a/spec/unit/prepare.spec.js
+++ b/spec/unit/prepare.spec.js
@@ -809,6 +809,7 @@ describe('prepare', () => {
             prepare.__set__('events', {
                 emit: jasmine.createSpy('emit')
             });
+            prepare.__set__('updateUserProjectGradleConfig', 
jasmine.createSpy());
             prepare.__set__('updateWww', jasmine.createSpy());
             prepare.__set__('updateProjectAccordingTo', 
jasmine.createSpy('updateProjectAccordingTo')
                 .and.returnValue(Promise.resolve()));
diff --git a/test/androidx/app/build.gradle b/test/androidx/app/build.gradle
index e6921dc..747cecb 100644
--- a/test/androidx/app/build.gradle
+++ b/test/androidx/app/build.gradle
@@ -18,14 +18,16 @@
 
 apply plugin: 'com.android.application'
 
+apply from: '../../../framework/cordova.gradle'
+
 android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.3"
+    compileSdkVersion cordovaConfig.SDK_VERSION
+    buildToolsVersion cordovaConfig.BUILD_TOOLS_VERSION
 
     defaultConfig {
         applicationId "org.apache.cordova.unittests"
-        minSdkVersion 22
-        targetSdkVersion 30
+        minSdkVersion cordovaConfig.MIN_SDK_VERSION
+        targetSdkVersion cordovaConfig.SDK_VERSION
         versionCode 1
         versionName "1.0"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -42,7 +44,7 @@ android {
 dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
     implementation project(path: ':CordovaLib')
-    implementation 'androidx.appcompat:appcompat:1.0.2'
+    implementation 
"androidx.appcompat:appcompat:${cordovaConfig.ANDROIDX_APP_COMPAT_VERSION}"
 
     testImplementation 'org.json:json:20140107'
     testImplementation 'junit:junit:4.12'
diff --git a/test/androidx/build.gradle b/test/androidx/build.gradle
index 160d352..24ef1dc 100644
--- a/test/androidx/build.gradle
+++ b/test/androidx/build.gradle
@@ -19,6 +19,8 @@
 // Top-level build file where you can add configuration options common to all 
sub-projects/modules.
 
 buildscript {
+    apply from: '../../framework/cordova.gradle'
+    
     repositories {
         google()
         mavenCentral()
@@ -28,7 +30,7 @@ buildscript {
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
 
-        classpath 'com.android.tools.build:gradle:4.2.1'
+        classpath "com.android.tools.build:gradle:${cordovaConfig.AGP_VERSION}"
     }
 }
 
diff --git a/test/androidx/wrapper.gradle b/test/androidx/wrapper.gradle
index 80394fa..6cef605 100644
--- a/test/androidx/wrapper.gradle
+++ b/test/androidx/wrapper.gradle
@@ -17,5 +17,6 @@
 */
 
 wrapper {
-    gradleVersion = '6.8.3'
+  apply from: '../../framework/cordova.gradle'
+  gradleVersion = cordovaConfig.GRADLE_VERSION
 }
diff --git a/test/run_java_unit_tests.js b/test/run_java_unit_tests.js
index 752dbca..acab1e6 100644
--- a/test/run_java_unit_tests.js
+++ b/test/run_java_unit_tests.js
@@ -21,6 +21,7 @@
 
 const path = require('path');
 const execa = require('execa');
+const fs = require('fs-extra');
 const ProjectBuilder = 
require('../bin/templates/cordova/lib/builders/ProjectBuilder');
 
 class AndroidTestRunner {
@@ -48,6 +49,9 @@ class AndroidTestRunner {
     run () {
         return Promise.resolve()
             .then(_ => console.log(`[${this.testTitle}] Preparing Gradle 
wrapper for Java unit tests.`))
+            .then(_ => {
+                fs.copyFileSync(path.resolve(this.projectDir, 
'../../framework/cdv-gradle-config-defaults.json'), 
path.resolve(this.projectDir, 'cdv-gradle-config.json'));
+            })
             .then(_ => this._createProjectBuilder())
             .then(_ => this._gradlew('--version'))
             .then(_ => console.log(`[${this.testTitle}] Gradle wrapper is 
ready. Running tests now.`))

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cordova.apache.org
For additional commands, e-mail: commits-h...@cordova.apache.org

Reply via email to