Browse Source

Merge pull request #87588 from m4gr3d/update_android_dependencies_3x

[3.x] Update Android dependencies for the project
Rémi Verschelde 1 year ago
parent
commit
d1b6b6f725

+ 2 - 2
.github/workflows/android_builds.yml

@@ -27,11 +27,11 @@ jobs:
           sudo cp -f misc/ci/sources.list /etc/apt/sources.list
           sudo apt-get update
 
-      - name: Set up Java 11
+      - name: Set up Java 17
         uses: actions/setup-java@v3
         with:
           distribution: temurin
-          java-version: 11
+          java-version: 17
 
       - name: Setup Godot build cache
         uses: ./.github/actions/godot-cache

+ 2 - 0
platform/android/export/export.cpp

@@ -36,6 +36,8 @@
 
 void register_android_exporter() {
 #ifndef ANDROID_ENABLED
+	EDITOR_DEF("export/android/java_sdk_path", OS::get_singleton()->get_environment("JAVA_HOME"));
+	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/java_sdk_path", PROPERTY_HINT_GLOBAL_DIR));
 	EDITOR_DEF("export/android/android_sdk_path", OS::get_singleton()->get_environment("ANDROID_SDK_ROOT"));
 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/android_sdk_path", PROPERTY_HINT_GLOBAL_DIR));
 	EDITOR_DEF("export/android/debug_keystore", "");

+ 45 - 2
platform/android/export/export_plugin.cpp

@@ -226,7 +226,7 @@ static const char *APK_ASSETS_DIRECTORY = "res://android/build/assets";
 static const char *AAB_ASSETS_DIRECTORY = "res://android/build/assetPacks/installTime/src/main/assets";
 
 static const int DEFAULT_MIN_SDK_VERSION = 19; // Should match the value in 'platform/android/java/app/config.gradle#minSdk'
-static const int DEFAULT_TARGET_SDK_VERSION = 33; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk'
+static const int DEFAULT_TARGET_SDK_VERSION = 34; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk'
 
 #ifndef ANDROID_ENABLED
 void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) {
@@ -2012,6 +2012,15 @@ Ref<Texture> EditorExportPlatformAndroid::get_run_icon() const {
 	return run_icon;
 }
 
+String EditorExportPlatformAndroid::get_java_path() {
+	String exe_ext = "";
+	if (OS::get_singleton()->get_name() == "Windows") {
+		exe_ext = ".exe";
+	}
+	String java_sdk_path = EditorSettings::get_singleton()->get("export/android/java_sdk_path");
+	return java_sdk_path.plus_file("bin/java" + exe_ext);
+}
+
 String EditorExportPlatformAndroid::get_adb_path() {
 	String exe_ext = "";
 	if (OS::get_singleton()->get_name() == "Windows") {
@@ -2142,6 +2151,32 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<Edito
 		err += TTR("Release keystore incorrectly configured in the export preset.") + "\n";
 	}
 
+	String java_sdk_path = EditorSettings::get_singleton()->get("export/android/java_sdk_path");
+	if (java_sdk_path == "") {
+		err += TTR("A valid Java SDK path is required in Editor Settings.") + "\n";
+		valid = false;
+	} else {
+		// Validate the given path by checking that `java` is present under the `bin` directory.
+		Error errn;
+		// Check for the bin directory.
+		DirAccessRef da = DirAccess::open(java_sdk_path.plus_file("bin"), &errn);
+		if (errn != OK) {
+			err += TTR("Invalid Java SDK path in Editor Settings.");
+			err += TTR("Missing 'bin' directory!");
+			err += "\n";
+			valid = false;
+		} else {
+			// Check for the `java` command.
+			String java_path = get_java_path();
+			if (!FileAccess::exists(java_path)) {
+				err += TTR("Unable to find 'java' command using the Java SDK path.");
+				err += TTR("Please check the Java SDK directory specified in Editor Settings.");
+				err += "\n";
+				valid = false;
+			}
+		}
+	}
+
 	String sdk_path = EditorSettings::get_singleton()->get("export/android/android_sdk_path");
 	if (sdk_path == "") {
 		err += TTR("A valid Android SDK path is required in Editor Settings.") + "\n";
@@ -2931,6 +2966,10 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
 			}
 		}
 		const String assets_directory = get_assets_directory(p_preset, export_format);
+		String java_sdk_path = EDITOR_GET("export/android/java_sdk_path");
+		ERR_FAIL_COND_V_MSG(java_sdk_path.empty(), ERR_UNCONFIGURED, "Java SDK path must be configured in Editor Settings at 'export/android/java_sdk_path'.");
+		print_verbose("Java sdk path: " + java_sdk_path);
+
 		String sdk_path = EDITOR_GET("export/android/android_sdk_path");
 		ERR_FAIL_COND_V_MSG(sdk_path.empty(), ERR_UNCONFIGURED, "Android SDK path must be configured in Editor Settings at 'export/android/android_sdk_path'.");
 		print_verbose("Android sdk path: " + sdk_path);
@@ -2975,8 +3014,11 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
 		print_verbose("Storing command line flags..");
 		store_file_at_path(assets_directory + "/_cl_", command_line_flags);
 
+		print_verbose("Updating JAVA_HOME environment to " + java_sdk_path);
+		OS::get_singleton()->set_environment("JAVA_HOME", java_sdk_path);
+
 		print_verbose("Updating ANDROID_HOME environment to " + sdk_path);
-		OS::get_singleton()->set_environment("ANDROID_HOME", sdk_path); //set and overwrite if required
+		OS::get_singleton()->set_environment("ANDROID_HOME", sdk_path);
 		String build_command;
 
 #ifdef WINDOWS_ENABLED
@@ -3010,6 +3052,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
 		bool clean_build_required = is_clean_build_required(enabled_plugins);
 
 		List<String> cmdline;
+		cmdline.push_back("validateJavaVersion");
 		if (clean_build_required) {
 			cmdline.push_back("clean");
 		}

+ 2 - 0
platform/android/export/export_plugin.h

@@ -206,6 +206,8 @@ public:
 
 	static String get_apksigner_path();
 
+	static String get_java_path();
+
 	virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const;
 	virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const;
 

+ 0 - 1
platform/android/java/app/AndroidManifest.xml

@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
-    package="com.godot.game"
     android:versionCode="1"
     android:versionName="1.0"
     android:installLocation="auto" >

+ 3 - 1
platform/android/java/app/assetPacks/installTime/build.gradle

@@ -1,4 +1,6 @@
-apply plugin: 'com.android.asset-pack'
+plugins {
+    id 'com.android.asset-pack'
+}
 
 assetPack {
     packName = "installTime" // Directory name for the asset pack

+ 32 - 4
platform/android/java/app/build.gradle

@@ -8,12 +8,14 @@ buildscript {
     repositories {
         google()
         mavenCentral()
+        gradlePluginPortal()
+        maven { url "https://plugins.gradle.org/m2/" }
 //CHUNK_BUILDSCRIPT_REPOSITORIES_BEGIN
 //CHUNK_BUILDSCRIPT_REPOSITORIES_END
     }
     dependencies {
-        classpath libraries.androidGradlePlugin
-        classpath libraries.kotlinGradlePlugin
+        classpath "com.android.tools.build:gradle:$versions.androidGradlePlugin"
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlinVersion"
 //CHUNK_BUILDSCRIPT_DEPENDENCIES_BEGIN
 //CHUNK_BUILDSCRIPT_DEPENDENCIES_END
     }
@@ -30,6 +32,8 @@ allprojects {
     repositories {
         google()
         mavenCentral()
+        gradlePluginPortal()
+        maven { url "https://plugins.gradle.org/m2/" }
 //CHUNK_ALLPROJECTS_REPOSITORIES_BEGIN
 //CHUNK_ALLPROJECTS_REPOSITORIES_END
 
@@ -51,8 +55,7 @@ configurations {
 }
 
 dependencies {
-    implementation libraries.kotlinStdLib
-    implementation libraries.androidxFragment
+    implementation "androidx.fragment:fragment:$versions.fragmentVersion"
 
     if (rootProject.findProject(":lib")) {
         implementation project(":lib")
@@ -100,6 +103,8 @@ android {
 
     assetPacks = [":assetPacks:installTime"]
 
+    namespace = 'com.godot.game'
+
     defaultConfig {
         // The default ignore pattern for the 'assets' directory includes hidden files and directories which are used by Godot projects.
         aaptOptions {
@@ -284,5 +289,28 @@ task copyAndRenameReleaseAab(type: Copy) {
     rename "build-release.aab", getExportFilename()
 }
 
+/**
+ * Used to validate the version of the Java SDK used for the Godot gradle builds.
+ */
+task validateJavaVersion {
+    if (JavaVersion.current() != versions.javaVersion) {
+        throw new GradleException("Invalid Java version ${JavaVersion.current()}. Version ${versions.javaVersion} is the required Java version for Godot gradle builds.")
+    }
+}
+
+/*
+When they're scheduled to run, the copy*AARToAppModule tasks generate dependencies for the 'app'
+module, so we're ensuring the ':app:preBuild' task is set to run after those tasks.
+ */
+if (rootProject.tasks.findByPath("copyDebugAARToAppModule") != null) {
+    preBuild.mustRunAfter(rootProject.tasks.named("copyDebugAARToAppModule"))
+}
+if (rootProject.tasks.findByPath("copyDevAARToAppModule") != null) {
+    preBuild.mustRunAfter(rootProject.tasks.named("copyDevAARToAppModule"))
+}
+if (rootProject.tasks.findByPath("copyReleaseAARToAppModule") != null) {
+    preBuild.mustRunAfter(rootProject.tasks.named("copyReleaseAARToAppModule"))
+}
+
 //CHUNK_GLOBAL_BEGIN
 //CHUNK_GLOBAL_END

+ 8 - 15
platform/android/java/app/config.gradle

@@ -1,24 +1,17 @@
 ext.versions = [
-    androidGradlePlugin: '7.2.1',
-    compileSdk         : 33,
+    androidGradlePlugin: '8.2.0',
+    compileSdk         : 34,
     minSdk             : 19, // Also update 'platform/android/export/export_plugin.cpp#DEFAULT_MIN_SDK_VERSION'
-    targetSdk          : 33, // Also update 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION'
-    buildTools         : '33.0.2',
-    kotlinVersion      : '1.7.0',
-    fragmentVersion    : '1.3.6',
-    nexusPublishVersion: '1.1.0',
-    javaVersion        : 11,
+    targetSdk          : 34, // Also update 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION'
+    buildTools         : '34.0.0',
+    kotlinVersion      : '1.9.20',
+    fragmentVersion    : '1.6.2',
+    nexusPublishVersion: '1.3.0',
+    javaVersion        : JavaVersion.VERSION_17,
     ndkVersion         : '23.2.8568313' // Also update 'platform/android/detect.py#get_ndk_version' when this is updated.
 
 ]
 
-ext.libraries = [
-    androidGradlePlugin: "com.android.tools.build:gradle:$versions.androidGradlePlugin",
-    kotlinGradlePlugin : "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlinVersion",
-    kotlinStdLib       : "org.jetbrains.kotlin:kotlin-stdlib:$versions.kotlinVersion",
-    androidxFragment   : "androidx.fragment:fragment:$versions.fragmentVersion",
-]
-
 ext.getExportPackageName = { ->
     // Retrieve the app id from the project property set by the Godot build command.
     String appId = project.hasProperty("export_package_name") ? project.property("export_package_name") : ""

+ 3 - 1
platform/android/java/app/settings.gradle

@@ -7,8 +7,10 @@ pluginManagement {
         id 'org.jetbrains.kotlin.android' version versions.kotlinVersion
     }
     repositories {
-        gradlePluginPortal()
         google()
+        mavenCentral()
+        gradlePluginPortal()
+        maven { url "https://plugins.gradle.org/m2/" }
     }
 }
 

+ 52 - 49
platform/android/java/build.gradle

@@ -1,18 +1,3 @@
-buildscript {
-    apply from: 'app/config.gradle'
-
-    repositories {
-        google()
-        mavenCentral()
-        maven { url "https://plugins.gradle.org/m2/" }
-    }
-    dependencies {
-        classpath libraries.androidGradlePlugin
-        classpath libraries.kotlinGradlePlugin
-        classpath 'io.github.gradle-nexus:publish-plugin:1.3.0'
-    }
-}
-
 plugins {
     id 'io.github.gradle-nexus.publish-plugin'
 }
@@ -31,6 +16,8 @@ allprojects {
     repositories {
         google()
         mavenCentral()
+        gradlePluginPortal()
+        maven { url "https://plugins.gradle.org/m2/" }
     }
 }
 
@@ -173,10 +160,21 @@ task zipCustomBuild(type: Zip) {
     destinationDirectory = file(binDir)
 }
 
+/**
+ * Returns true if the scons build tasks responsible for generating the Godot native shared
+ * libraries should be excluded.
+ */
+def excludeSconsBuildTasks() {
+    return !isAndroidStudio() && !project.hasProperty("generateNativeLibs")
+}
+
+/**
+ * Generates the list of build tasks that should be excluded from the build process.\
+ */
 def templateExcludedBuildTask() {
     // We exclude these gradle tasks so we can run the scons command manually.
     def excludedTasks = []
-    if (!isAndroidStudio()) {
+    if (excludeSconsBuildTasks()) {
         logger.lifecycle("Excluding Android studio build tasks")
         for (String flavor : supportedFlavors) {
             for (String buildType : supportedTargetsMapByFlavors[flavor].keySet()) {
@@ -189,23 +187,42 @@ def templateExcludedBuildTask() {
     return excludedTasks
 }
 
-def templateBuildTasks() {
+/**
+ * Generates the build tasks for the given flavor
+ * @param flavor Must be one of the supported flavors ('template' / 'editor')
+ */
+def generateBuildTasks(String flavor = "template") {
+    if (!supportedFlavors.contains(flavor)) {
+        throw new GradleException("Invalid build flavor: $flavor")
+    }
+
     def tasks = []
 
-    // Only build the apks and aar files for which we have native shared libraries.
-    for (String target : supportedTargetsMapByFlavors["template"].keySet()) {
-        File targetLibs = new File("lib/libs/" + target)
-        if (targetLibs != null
+    // Only build the apks and aar files for which we have native shared libraries unless we intend
+    // to run the scons build tasks.
+    boolean excludeSconsBuildTasks = excludeSconsBuildTasks()
+    boolean isTemplate = flavor == "template"
+    String libsDir = isTemplate ? "lib/libs/" : "lib/libs/tools/"
+    for (String target : supportedTargetsMapByFlavors[flavor].keySet()) {
+        File targetLibs = new File(libsDir + target)
+        if (!excludeSconsBuildTasks || (targetLibs != null
             && targetLibs.isDirectory()
             && targetLibs.listFiles() != null
-            && targetLibs.listFiles().length > 0) {
+            && targetLibs.listFiles().length > 0)) {
             String capitalizedTarget = target.capitalize()
-            // Copy the generated aar library files to the custom build directory.
-            tasks += "copy" + capitalizedTarget + "AARToAppModule"
-            // Copy the generated aar library files to the bin directory.
-            tasks += "copy" + capitalizedTarget + "AARToBin"
-            // Copy the prebuilt binary templates to the bin directory.
-            tasks += "copy" + capitalizedTarget + "BinaryToBin"
+            if (isTemplate) {
+                // Copy the generated aar library files to the build directory.
+                tasks += "copy${capitalizedTarget}AARToAppModule"
+                // Copy the generated aar library files to the bin directory.
+                tasks += "copy${capitalizedTarget}AARToBin"
+                // Copy the prebuilt binary templates to the bin directory.
+                tasks += "copy${capitalizedTarget}BinaryToBin"
+            } else {
+                // Copy the generated editor apk to the bin directory.
+                tasks += "copyEditor${capitalizedTarget}ApkToBin"
+                // Copy the generated editor aab to the bin directory.
+                tasks += "copyEditor${capitalizedTarget}AabToBin"
+            }
         } else {
             logger.lifecycle("No native shared libs for target $target. Skipping build.")
         }
@@ -264,27 +281,13 @@ task copyEditorDevAabToBin(type: Copy) {
 /**
  * Generate the Godot Editor Android apk.
  *
- * Note: The Godot 'tools' shared libraries must have been generated (via scons) prior to running
- * this gradle task. The task will only build the apk(s) for which the shared libraries is
- * available.
+ * Note: Unless the 'generateNativeLibs` argument is specified, the Godot 'tools' shared libraries
+ * must have been generated (via scons) prior to running this gradle task.
+ * The task will only build the apk(s) for which the shared libraries is available.
  */
 task generateGodotEditor {
     gradle.startParameter.excludedTaskNames += templateExcludedBuildTask()
-
-    def tasks = []
-
-    for (String target : supportedTargetsMapByFlavors["editor"].keySet()) {
-        File targetLibs = new File("lib/libs/tools/" + target)
-        if (targetLibs != null
-            && targetLibs.isDirectory()
-            && targetLibs.listFiles() != null
-            && targetLibs.listFiles().length > 0) {
-            tasks += "copyEditor${target.capitalize()}ApkToBin"
-            tasks += "copyEditor${target.capitalize()}AabToBin"
-        }
-    }
-
-    dependsOn = tasks
+    dependsOn = generateBuildTasks("editor")
 }
 
 /**
@@ -292,7 +295,7 @@ task generateGodotEditor {
  */
 task generateGodotTemplates {
     gradle.startParameter.excludedTaskNames += templateExcludedBuildTask()
-    dependsOn = templateBuildTasks()
+    dependsOn = generateBuildTasks("template")
 
     finalizedBy 'zipCustomBuild'
 }
@@ -302,10 +305,10 @@ task generateGodotTemplates {
  */
 task generateDevTemplate {
     // add parameter to set symbols to true
-    gradle.startParameter.projectProperties += [doNotStrip: true]
+    gradle.startParameter.projectProperties += [doNotStrip: "true"]
 
     gradle.startParameter.excludedTaskNames += templateExcludedBuildTask()
-    dependsOn = templateBuildTasks()
+    dependsOn = generateBuildTasks("template")
 
     finalizedBy 'zipCustomBuild'
 }

+ 13 - 4
platform/android/java/editor/build.gradle

@@ -2,14 +2,14 @@
 plugins {
     id 'com.android.application'
     id 'org.jetbrains.kotlin.android'
+    id 'base'
 }
 
 dependencies {
-    implementation libraries.kotlinStdLib
-    implementation libraries.androidxFragment
+    implementation "androidx.fragment:fragment:$versions.fragmentVersion"
     implementation project(":lib")
 
-    implementation "androidx.window:window:1.0.0"
+    implementation "androidx.window:window:1.2.0"
 }
 
 ext {
@@ -81,6 +81,8 @@ android {
     buildToolsVersion versions.buildTools
     ndkVersion versions.ndkVersion
 
+    namespace = "org.godotengine.editor"
+
     defaultConfig {
         // The 'applicationId' suffix allows to install Godot 3.x(v3) and 4.x(v4) on the same device
         applicationId "org.godotengine.editor.v3"
@@ -90,7 +92,10 @@ android {
         targetSdkVersion versions.targetSdk
 
         missingDimensionStrategy 'products', 'editor'
-        setProperty("archivesBaseName", "android_editor")
+    }
+
+    base {
+        archivesName = "android_editor"
     }
 
     compileOptions {
@@ -111,6 +116,10 @@ android {
         }
     }
 
+    buildFeatures {
+        buildConfig = true
+    }
+
     buildTypes {
         dev {
             initWith debug

+ 0 - 1
platform/android/java/editor/src/main/AndroidManifest.xml

@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
-    package="org.godotengine.editor"
     android:installLocation="auto">
 
     <supports-screens

+ 1 - 1
platform/android/java/gradle/wrapper/gradle-wrapper.properties

@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists

+ 0 - 1
platform/android/java/lib/AndroidManifest.xml

@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="org.godotengine.godot"
     android:versionCode="1"
     android:versionName="1.0">
 

+ 6 - 2
platform/android/java/lib/build.gradle

@@ -10,8 +10,7 @@ ext {
 apply from: "../scripts/publish-module.gradle"
 
 dependencies {
-    implementation libraries.kotlinStdLib
-    implementation libraries.androidxFragment
+    implementation "androidx.fragment:fragment:$versions.fragmentVersion"
 }
 
 def pathToRootDir = "../../../../"
@@ -39,6 +38,11 @@ android {
         jvmTarget = versions.javaVersion
     }
 
+    buildFeatures {
+        aidl = true
+        buildConfig = true
+    }
+
     buildTypes {
         dev {
             initWith debug

+ 11 - 9
platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt

@@ -210,21 +210,23 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi
 	}
 
 	override fun onScroll(
-		originEvent: MotionEvent,
+		originEvent: MotionEvent?,
 		terminusEvent: MotionEvent,
 		distanceX: Float,
 		distanceY: Float
 	): Boolean {
 		if (scaleInProgress) {
 			if (dragInProgress) {
-				// Cancel the drag
-				GodotInputHandler.handleMotionEvent(
-					originEvent.source,
-					MotionEvent.ACTION_CANCEL,
-					originEvent.buttonState,
-					originEvent.x,
-					originEvent.y
-				)
+				if (originEvent != null) {
+					// Cancel the drag
+					GodotInputHandler.handleMotionEvent(
+						originEvent.source,
+						MotionEvent.ACTION_CANCEL,
+						originEvent.buttonState,
+						originEvent.x,
+						originEvent.y
+					)
+				}
 				dragInProgress = false
 			}
 		}

+ 1 - 1
platform/android/java/nativeSrcsConfigs/AndroidManifest.xml

@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="utf-8"?>
-<manifest package="org.godotengine.godot" />
+<manifest />

+ 2 - 0
platform/android/java/nativeSrcsConfigs/build.gradle

@@ -9,6 +9,8 @@ android {
     buildToolsVersion versions.buildTools
     ndkVersion versions.ndkVersion
 
+    namespace = "org.godotengine.godot"
+
     defaultConfig {
         minSdkVersion versions.minSdk
         targetSdkVersion versions.targetSdk

+ 4 - 1
platform/android/java/settings.gradle

@@ -5,12 +5,15 @@ pluginManagement {
     plugins {
         id 'com.android.application' version versions.androidGradlePlugin
         id 'com.android.library' version versions.androidGradlePlugin
+        id 'com.android.asset-pack' version versions.androidGradlePlugin
         id 'org.jetbrains.kotlin.android' version versions.kotlinVersion
         id 'io.github.gradle-nexus.publish-plugin' version versions.nexusPublishVersion
     }
     repositories {
-        gradlePluginPortal()
         google()
+        mavenCentral()
+        gradlePluginPortal()
+        maven { url "https://plugins.gradle.org/m2/" }
     }
 }