Browse Source

Automatically generate the Android debug keystore

Automatically generate the Android debug keystore when the Java SDK path is specified.
Fredia Huya-Kouadio 1 year ago
parent
commit
a8c9b59f3f

+ 4 - 0
editor/editor_paths.cpp

@@ -70,6 +70,10 @@ String EditorPaths::get_export_templates_dir() const {
 	return get_data_dir().path_join(export_templates_folder);
 	return get_data_dir().path_join(export_templates_folder);
 }
 }
 
 
+String EditorPaths::get_debug_keystore_path() const {
+	return get_data_dir().path_join("keystores/debug.keystore");
+}
+
 String EditorPaths::get_project_settings_dir() const {
 String EditorPaths::get_project_settings_dir() const {
 	return get_project_data_dir().path_join("editor");
 	return get_project_data_dir().path_join("editor");
 }
 }

+ 1 - 0
editor/editor_paths.h

@@ -63,6 +63,7 @@ public:
 	String get_cache_dir() const;
 	String get_cache_dir() const;
 	String get_project_data_dir() const;
 	String get_project_data_dir() const;
 	String get_export_templates_dir() const;
 	String get_export_templates_dir() const;
+	String get_debug_keystore_path() const;
 	String get_project_settings_dir() const;
 	String get_project_settings_dir() const;
 	String get_text_editor_themes_dir() const;
 	String get_text_editor_themes_dir() const;
 	String get_script_templates_dir() const;
 	String get_script_templates_dir() const;

+ 7 - 0
editor/export/editor_export.cpp

@@ -32,6 +32,7 @@
 
 
 #include "core/config/project_settings.h"
 #include "core/config/project_settings.h"
 #include "core/io/config_file.h"
 #include "core/io/config_file.h"
+#include "editor/editor_settings.h"
 
 
 EditorExport *EditorExport::singleton = nullptr;
 EditorExport *EditorExport::singleton = nullptr;
 
 
@@ -191,6 +192,12 @@ void EditorExport::_notification(int p_what) {
 				export_platforms.write[i]->cleanup();
 				export_platforms.write[i]->cleanup();
 			}
 			}
 		} break;
 		} break;
+
+		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+			for (int i = 0; i < export_platforms.size(); i++) {
+				export_platforms.write[i]->notification(p_what);
+			}
+		} break;
 	}
 	}
 }
 }
 
 

+ 4 - 3
platform/android/export/export.cpp

@@ -33,6 +33,7 @@
 #include "export_plugin.h"
 #include "export_plugin.h"
 
 
 #include "core/os/os.h"
 #include "core/os/os.h"
+#include "editor/editor_paths.h"
 #include "editor/editor_settings.h"
 #include "editor/editor_settings.h"
 #include "editor/export/editor_export.h"
 #include "editor/export/editor_export.h"
 
 
@@ -46,10 +47,10 @@ void register_android_exporter() {
 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/java_sdk_path", PROPERTY_HINT_GLOBAL_DIR));
 	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_HOME"));
 	EDITOR_DEF("export/android/android_sdk_path", OS::get_singleton()->get_environment("ANDROID_HOME"));
 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/android_sdk_path", PROPERTY_HINT_GLOBAL_DIR));
 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/android_sdk_path", PROPERTY_HINT_GLOBAL_DIR));
-	EDITOR_DEF("export/android/debug_keystore", "");
+	EDITOR_DEF("export/android/debug_keystore", EditorPaths::get_singleton()->get_debug_keystore_path());
 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"));
 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"));
-	EDITOR_DEF("export/android/debug_keystore_user", "androiddebugkey");
-	EDITOR_DEF("export/android/debug_keystore_pass", "android");
+	EDITOR_DEF("export/android/debug_keystore_user", DEFAULT_ANDROID_KEYSTORE_DEBUG_USER);
+	EDITOR_DEF("export/android/debug_keystore_pass", DEFAULT_ANDROID_KEYSTORE_DEBUG_PASSWORD);
 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore_pass", PROPERTY_HINT_PASSWORD));
 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore_pass", PROPERTY_HINT_PASSWORD));
 	EDITOR_DEF("export/android/force_system_user", false);
 	EDITOR_DEF("export/android/force_system_user", false);
 
 

+ 82 - 4
platform/android/export/export_plugin.cpp

@@ -831,14 +831,82 @@ bool EditorExportPlatformAndroid::_uses_vulkan() {
 
 
 void EditorExportPlatformAndroid::_notification(int p_what) {
 void EditorExportPlatformAndroid::_notification(int p_what) {
 #ifndef ANDROID_ENABLED
 #ifndef ANDROID_ENABLED
-	if (p_what == NOTIFICATION_POSTINITIALIZE) {
-		if (EditorExport::get_singleton()) {
-			EditorExport::get_singleton()->connect_presets_runnable_updated(callable_mp(this, &EditorExportPlatformAndroid::_update_preset_status));
-		}
+	switch (p_what) {
+		case NOTIFICATION_POSTINITIALIZE: {
+			if (EditorExport::get_singleton()) {
+				EditorExport::get_singleton()->connect_presets_runnable_updated(callable_mp(this, &EditorExportPlatformAndroid::_update_preset_status));
+			}
+		} break;
+
+		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+			if (EditorSettings::get_singleton()->check_changed_settings_in_group("export/android")) {
+				_create_editor_debug_keystore_if_needed();
+			}
+		} break;
 	}
 	}
 #endif
 #endif
 }
 }
 
 
+void EditorExportPlatformAndroid::_create_editor_debug_keystore_if_needed() {
+	// Check if we have a valid keytool path.
+	String keytool_path = get_keytool_path();
+	if (!FileAccess::exists(keytool_path)) {
+		return;
+	}
+
+	// Check if the current editor debug keystore exists.
+	String editor_debug_keystore = EDITOR_GET("export/android/debug_keystore");
+	if (FileAccess::exists(editor_debug_keystore)) {
+		return;
+	}
+
+	// Generate the debug keystore.
+	String keystore_path = EditorPaths::get_singleton()->get_debug_keystore_path();
+	String keystores_dir = keystore_path.get_base_dir();
+	if (!DirAccess::exists(keystores_dir)) {
+		Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+		Error err = dir_access->make_dir_recursive(keystores_dir);
+		if (err != OK) {
+			WARN_PRINT(TTR("Error creating keystores directory:") + "\n" + keystores_dir);
+			return;
+		}
+	}
+
+	if (!FileAccess::exists(keystore_path)) {
+		String output;
+		List<String> args;
+		args.push_back("-genkey");
+		args.push_back("-keystore");
+		args.push_back(keystore_path);
+		args.push_back("-storepass");
+		args.push_back("android");
+		args.push_back("-alias");
+		args.push_back(DEFAULT_ANDROID_KEYSTORE_DEBUG_USER);
+		args.push_back("-keypass");
+		args.push_back(DEFAULT_ANDROID_KEYSTORE_DEBUG_PASSWORD);
+		args.push_back("-keyalg");
+		args.push_back("RSA");
+		args.push_back("-keysize");
+		args.push_back("2048");
+		args.push_back("-validity");
+		args.push_back("10000");
+		args.push_back("-dname");
+		args.push_back("cn=Godot, ou=Godot Engine, o=Stichting Godot, c=NL");
+		Error error = OS::get_singleton()->execute(keytool_path, args, &output, nullptr, true);
+		print_verbose(output);
+		if (error != OK) {
+			WARN_PRINT("Error: Unable to create debug keystore");
+			return;
+		}
+	}
+
+	// Update the editor settings.
+	EditorSettings::get_singleton()->set("export/android/debug_keystore", keystore_path);
+	EditorSettings::get_singleton()->set("export/android/debug_keystore_user", DEFAULT_ANDROID_KEYSTORE_DEBUG_USER);
+	EditorSettings::get_singleton()->set("export/android/debug_keystore_pass", DEFAULT_ANDROID_KEYSTORE_DEBUG_PASSWORD);
+	print_verbose("Updated editor debug keystore to " + keystore_path);
+}
+
 void EditorExportPlatformAndroid::_get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions) {
 void EditorExportPlatformAndroid::_get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions) {
 	const char **aperms = android_perms;
 	const char **aperms = android_perms;
 	while (*aperms) {
 	while (*aperms) {
@@ -2202,6 +2270,15 @@ String EditorExportPlatformAndroid::get_java_path() {
 	return java_sdk_path.path_join("bin/java" + exe_ext);
 	return java_sdk_path.path_join("bin/java" + exe_ext);
 }
 }
 
 
+String EditorExportPlatformAndroid::get_keytool_path() {
+	String exe_ext;
+	if (OS::get_singleton()->get_name() == "Windows") {
+		exe_ext = ".exe";
+	}
+	String java_sdk_path = EDITOR_GET("export/android/java_sdk_path");
+	return java_sdk_path.path_join("bin/keytool" + exe_ext);
+}
+
 String EditorExportPlatformAndroid::get_adb_path() {
 String EditorExportPlatformAndroid::get_adb_path() {
 	String exe_ext;
 	String exe_ext;
 	if (OS::get_singleton()->get_name() == "Windows") {
 	if (OS::get_singleton()->get_name() == "Windows") {
@@ -3647,6 +3724,7 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
 		android_plugins_changed.set();
 		android_plugins_changed.set();
 #endif // DISABLE_DEPRECATED
 #endif // DISABLE_DEPRECATED
 #ifndef ANDROID_ENABLED
 #ifndef ANDROID_ENABLED
+		_create_editor_debug_keystore_if_needed();
 		_update_preset_status();
 		_update_preset_status();
 		check_for_changes_thread.start(_check_for_changes_poll_thread, this);
 		check_for_changes_thread.start(_check_for_changes_poll_thread, this);
 #endif
 #endif

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

@@ -60,6 +60,9 @@ const String ENV_ANDROID_KEYSTORE_RELEASE_PATH = "GODOT_ANDROID_KEYSTORE_RELEASE
 const String ENV_ANDROID_KEYSTORE_RELEASE_USER = "GODOT_ANDROID_KEYSTORE_RELEASE_USER";
 const String ENV_ANDROID_KEYSTORE_RELEASE_USER = "GODOT_ANDROID_KEYSTORE_RELEASE_USER";
 const String ENV_ANDROID_KEYSTORE_RELEASE_PASS = "GODOT_ANDROID_KEYSTORE_RELEASE_PASSWORD";
 const String ENV_ANDROID_KEYSTORE_RELEASE_PASS = "GODOT_ANDROID_KEYSTORE_RELEASE_PASSWORD";
 
 
+const String DEFAULT_ANDROID_KEYSTORE_DEBUG_USER = "androiddebugkey";
+const String DEFAULT_ANDROID_KEYSTORE_DEBUG_PASSWORD = "android";
+
 struct LauncherIcon {
 struct LauncherIcon {
 	const char *export_path;
 	const char *export_path;
 	int dimensions = 0;
 	int dimensions = 0;
@@ -186,6 +189,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
 			const Ref<Image> &foreground,
 			const Ref<Image> &foreground,
 			const Ref<Image> &background);
 			const Ref<Image> &background);
 
 
+	static void _create_editor_debug_keystore_if_needed();
+
 	static Vector<ABI> get_enabled_abis(const Ref<EditorExportPreset> &p_preset);
 	static Vector<ABI> get_enabled_abis(const Ref<EditorExportPreset> &p_preset);
 
 
 	static bool _uses_vulkan();
 	static bool _uses_vulkan();
@@ -234,6 +239,8 @@ public:
 
 
 	static String get_java_path();
 	static String get_java_path();
 
 
+	static String get_keytool_path();
+
 	virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
 	virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
 	virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
 	virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
 	static bool has_valid_username_and_password(const Ref<EditorExportPreset> &p_preset, String &r_error);
 	static bool has_valid_username_and_password(const Ref<EditorExportPreset> &p_preset, String &r_error);