Browse Source

Update gradle build files to automatically perform signing and zipalign tasks for custom builds.

Fredia Huya-Kouadio 4 years ago
parent
commit
d13d29240c

+ 19 - 95
platform/android/export/export.cpp

@@ -2034,15 +2034,6 @@ public:
 					err += "\n";
 					err += "\n";
 					valid = false;
 					valid = false;
 				}
 				}
-
-				// Check for the build-tools directory.
-				DirAccessRef build_tools_da = DirAccess::open(sdk_path.plus_file("build-tools"), &errn);
-				if (errn != OK) {
-					err += TTR("Invalid Android SDK path for custom build in Editor Settings.");
-					err += TTR("Missing 'build-tools' directory!");
-					err += "\n";
-					valid = false;
-				}
 			}
 			}
 
 
 			if (!FileAccess::exists("res://android/build/build.gradle")) {
 			if (!FileAccess::exists("res://android/build/build.gradle")) {
@@ -2628,65 +2619,6 @@ public:
 		}
 		}
 	}
 	}
 
 
-	Error _zip_align_project(const String &sdk_path, const String &unaligned_file_path, const String &aligned_file_path) {
-		// Look for the zipalign tool.
-		String zipalign_command_name;
-#ifdef WINDOWS_ENABLED
-		zipalign_command_name = "zipalign.exe";
-#else
-		zipalign_command_name = "zipalign";
-#endif
-
-		String zipalign_command;
-		Error errn;
-		String build_tools_dir = sdk_path.plus_file("build-tools");
-		DirAccessRef da = DirAccess::open(build_tools_dir, &errn);
-		if (errn != OK) {
-			return errn;
-		}
-
-		// There are additional versions directories we need to go through.
-		da->list_dir_begin();
-		String sub_dir = da->get_next();
-		while (!sub_dir.empty()) {
-			if (!sub_dir.begins_with(".") && da->current_is_dir()) {
-				// Check if the tool is here.
-				String tool_path = build_tools_dir.plus_file(sub_dir).plus_file(zipalign_command_name);
-				if (FileAccess::exists(tool_path)) {
-					zipalign_command = tool_path;
-					break;
-				}
-			}
-			sub_dir = da->get_next();
-		}
-		da->list_dir_end();
-
-		if (zipalign_command.empty()) {
-			EditorNode::get_singleton()->show_warning(TTR("Unable to find the zipalign tool."));
-			return ERR_CANT_CREATE;
-		}
-
-		List<String> zipalign_args;
-		zipalign_args.push_back("-f");
-		zipalign_args.push_back("-v");
-		zipalign_args.push_back("4");
-		zipalign_args.push_back(unaligned_file_path); // source file
-		zipalign_args.push_back(aligned_file_path); // destination file
-
-		int result = EditorNode::get_singleton()->execute_and_show_output(TTR("Aligning APK..."), zipalign_command, zipalign_args);
-		if (result != 0) {
-			EditorNode::get_singleton()->show_warning(TTR("Unable to complete APK alignment."));
-			return ERR_CANT_CREATE;
-		}
-
-		// Delete the unaligned path.
-		errn = da->remove(unaligned_file_path);
-		if (errn != OK) {
-			EditorNode::get_singleton()->show_warning(TTR("Unable to delete unaligned APK."));
-		}
-		return OK;
-	}
-
 	virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) {
 	virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) {
 
 
 		ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
 		ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
@@ -2799,6 +2731,8 @@ public:
 			String version_code = itos(p_preset->get("version/code"));
 			String version_code = itos(p_preset->get("version/code"));
 			String version_name = p_preset->get("version/name");
 			String version_name = p_preset->get("version/name");
 			String enabled_abi_string = String("|").join(enabled_abis);
 			String enabled_abi_string = String("|").join(enabled_abis);
+			String sign_flag = _signed ? "true" : "false";
+			String zipalign_flag = "true";
 
 
 			Vector<PluginConfig> enabled_plugins = get_enabled_plugins(p_preset);
 			Vector<PluginConfig> enabled_plugins = get_enabled_plugins(p_preset);
 			String local_plugins_binaries = get_plugins_binaries(BINARY_TYPE_LOCAL, enabled_plugins);
 			String local_plugins_binaries = get_plugins_binaries(BINARY_TYPE_LOCAL, enabled_plugins);
@@ -2827,15 +2761,25 @@ public:
 			cmdline.push_back("-Pplugins_local_binaries=" + local_plugins_binaries); // argument to specify the list of plugins local dependencies.
 			cmdline.push_back("-Pplugins_local_binaries=" + local_plugins_binaries); // argument to specify the list of plugins local dependencies.
 			cmdline.push_back("-Pplugins_remote_binaries=" + remote_plugins_binaries); // argument to specify the list of plugins remote dependencies.
 			cmdline.push_back("-Pplugins_remote_binaries=" + remote_plugins_binaries); // argument to specify the list of plugins remote dependencies.
 			cmdline.push_back("-Pplugins_maven_repos=" + custom_maven_repos); // argument to specify the list of custom maven repos for the plugins dependencies.
 			cmdline.push_back("-Pplugins_maven_repos=" + custom_maven_repos); // argument to specify the list of custom maven repos for the plugins dependencies.
+			cmdline.push_back("-Pperform_zipalign=" + zipalign_flag); // argument to specify whether the build should be zipaligned.
+			cmdline.push_back("-Pperform_signing=" + sign_flag); // argument to specify whether the build should be signed.
+			if (_signed && !p_debug) {
+				// Pass the release keystore info as well
+				String release_keystore = p_preset->get("keystore/release");
+				String release_username = p_preset->get("keystore/release_user");
+				String release_password = p_preset->get("keystore/release_password");
+				if (!FileAccess::exists(release_keystore)) {
+					EditorNode::add_io_error("Could not find keystore, unable to export.");
+					return ERR_FILE_CANT_OPEN;
+				}
+
+				cmdline.push_back("-Prelease_keystore_file=" + release_keystore); // argument to specify the release keystore file.
+				cmdline.push_back("-Prelease_keystore_alias=" + release_username); // argument to specify the release keystore alias.
+				cmdline.push_back("-Prelease_keystore_password=" + release_password); // argument to specity the release keystore password.
+			}
 			cmdline.push_back("-p"); // argument to specify the start directory.
 			cmdline.push_back("-p"); // argument to specify the start directory.
 			cmdline.push_back(build_path); // start directory.
 			cmdline.push_back(build_path); // start directory.
-			/*{ used for debug
-				int ec;
-				String pipe;
-				OS::get_singleton()->execute(build_command, cmdline, true, NULL, NULL, &ec);
-				print_line("exit code: " + itos(ec));
-			}
-			*/
+
 			int result = EditorNode::get_singleton()->execute_and_show_output(TTR("Building Android Project (gradle)"), build_command, cmdline);
 			int result = EditorNode::get_singleton()->execute_and_show_output(TTR("Building Android Project (gradle)"), build_command, cmdline);
 			if (result != 0) {
 			if (result != 0) {
 				EditorNode::get_singleton()->show_warning(TTR("Building of Android project failed, check output for the error.\nAlternatively visit docs.godotengine.org for Android build documentation."));
 				EditorNode::get_singleton()->show_warning(TTR("Building of Android project failed, check output for the error.\nAlternatively visit docs.godotengine.org for Android build documentation."));
@@ -2856,16 +2800,11 @@ public:
 			copy_args.push_back(build_path); // start directory.
 			copy_args.push_back(build_path); // start directory.
 
 
 			String export_filename = p_path.get_file();
 			String export_filename = p_path.get_file();
-			if (export_format == 0) {
-				// By default, generated apk are not aligned.
-				export_filename += ".unaligned";
-			}
 			String export_path = p_path.get_base_dir();
 			String export_path = p_path.get_base_dir();
 			if (export_path.is_rel_path()) {
 			if (export_path.is_rel_path()) {
 				export_path = OS::get_singleton()->get_resource_dir().plus_file(export_path);
 				export_path = OS::get_singleton()->get_resource_dir().plus_file(export_path);
 			}
 			}
 			export_path = ProjectSettings::get_singleton()->globalize_path(export_path).simplify_path();
 			export_path = ProjectSettings::get_singleton()->globalize_path(export_path).simplify_path();
-			String export_file_path = export_path.plus_file(export_filename);
 
 
 			copy_args.push_back("-Pexport_path=file:" + export_path);
 			copy_args.push_back("-Pexport_path=file:" + export_path);
 			copy_args.push_back("-Pexport_filename=" + export_filename);
 			copy_args.push_back("-Pexport_filename=" + export_filename);
@@ -2876,21 +2815,6 @@ public:
 				return ERR_CANT_CREATE;
 				return ERR_CANT_CREATE;
 			}
 			}
 
 
-			if (_signed) {
-				err = sign_apk(p_preset, p_debug, export_file_path, ep);
-				if (err != OK) {
-					return err;
-				}
-			}
-
-			if (export_format == 0) {
-				// Perform zip alignment
-				err = _zip_align_project(sdk_path, export_file_path, export_path.plus_file(p_path.get_file()));
-				if (err != OK) {
-					return err;
-				}
-			}
-
 			return OK;
 			return OK;
 		}
 		}
 		// This is the start of the Legacy build system
 		// This is the start of the Legacy build system

+ 1 - 1
platform/android/export/gradle_export_util.h

@@ -279,7 +279,7 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, const Strin
 	String manifest_application_text =
 	String manifest_application_text =
 			"    <application android:label=\"@string/godot_project_name_string\"\n"
 			"    <application android:label=\"@string/godot_project_name_string\"\n"
 			"        android:allowBackup=\"false\" tools:ignore=\"GoogleAppIndexingWarning\"\n"
 			"        android:allowBackup=\"false\" tools:ignore=\"GoogleAppIndexingWarning\"\n"
-			"        android:icon=\"@mipmap/icon\">)\n\n"
+			"        android:icon=\"@mipmap/icon\">\n\n"
 			"        <meta-data tools:node=\"remove\" android:name=\"xr_mode_metadata_name\" />\n";
 			"        <meta-data tools:node=\"remove\" android:name=\"xr_mode_metadata_name\" />\n";
 
 
 	manifest_application_text += _get_plugins_tag(plugins_names);
 	manifest_application_text += _get_plugins_tag(plugins_names);

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

@@ -120,10 +120,41 @@ android {
         // doNotStrip '**/*.so'
         // doNotStrip '**/*.so'
     }
     }
 
 
-    // Both signing and zip-aligning will be done at export time
-    buildTypes.all { buildType ->
-        buildType.zipAlignEnabled false
-        buildType.signingConfig null
+    signingConfigs {
+        release {
+            File keystoreFile = new File(getReleaseKeystoreFile())
+            if (keystoreFile.isFile()) {
+                storeFile keystoreFile
+                storePassword getReleaseKeystorePassword()
+                keyAlias getReleaseKeyAlias()
+                keyPassword getReleaseKeystorePassword()
+            }
+        }
+    }
+
+    buildTypes {
+
+        debug {
+            // Signing and zip-aligning are skipped for prebuilt builds, but
+            // performed for custom builds.
+            zipAlignEnabled shouldZipAlign()
+            if (shouldSign()) {
+                signingConfig signingConfigs.debug
+            } else {
+                signingConfig null
+            }
+        }
+
+        release {
+            // Signing and zip-aligning are skipped for prebuilt builds, but
+            // performed for custom builds.
+            zipAlignEnabled shouldZipAlign()
+            if (shouldSign()) {
+                signingConfig signingConfigs.release
+            } else {
+                signingConfig null
+            }
+        }
     }
     }
 
 
     sourceSets {
     sourceSets {

+ 39 - 1
platform/android/java/app/config.gradle

@@ -34,7 +34,11 @@ ext.getExportVersionCode = { ->
     if (versionCode == null || versionCode.isEmpty()) {
     if (versionCode == null || versionCode.isEmpty()) {
         versionCode = "1"
         versionCode = "1"
     }
     }
-    return Integer.parseInt(versionCode)
+    try {
+        return Integer.parseInt(versionCode)
+    } catch (NumberFormatException ignored) {
+        return 1
+    }
 }
 }
 
 
 ext.getExportVersionName = { ->
 ext.getExportVersionName = { ->
@@ -136,3 +140,37 @@ ext.getGodotPluginsLocalBinaries = { ->
 
 
     return binDeps
     return binDeps
 }
 }
+
+ext.getReleaseKeystoreFile = { ->
+    String keystoreFile = project.hasProperty("release_keystore_file") ? project.property("release_keystore_file") : ""
+    if (keystoreFile == null || keystoreFile.isEmpty()) {
+        keystoreFile = "."
+    }
+    return keystoreFile
+}
+
+ext.getReleaseKeystorePassword = { ->
+    String keystorePassword = project.hasProperty("release_keystore_password") ? project.property("release_keystore_password") : ""
+    return keystorePassword
+}
+
+ext.getReleaseKeyAlias = { ->
+    String keyAlias = project.hasProperty("release_keystore_alias") ? project.property("release_keystore_alias") : ""
+    return keyAlias
+}
+
+ext.shouldZipAlign = { ->
+    String zipAlignFlag = project.hasProperty("perform_zipalign") ? project.property("perform_zipalign") : ""
+    if (zipAlignFlag == null || zipAlignFlag.isEmpty()) {
+        zipAlignFlag = "false"
+    }
+    return Boolean.parseBoolean(zipAlignFlag)
+}
+
+ext.shouldSign = { ->
+    String signFlag = project.hasProperty("perform_signing") ? project.property("perform_signing") : ""
+    if (signFlag == null || signFlag.isEmpty()) {
+        signFlag = "false"
+    }
+    return Boolean.parseBoolean(signFlag)
+}