| 
									
										
										
										
											2023-01-05 13:25:55 +01:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*  gradle_export_util.cpp                                                */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         This file is part of:                          */ | 
					
						
							|  |  |  | /*                             GODOT ENGINE                               */ | 
					
						
							|  |  |  | /*                        https://godotengine.org                         */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining  */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the        */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including    */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,    */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to     */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to  */ | 
					
						
							|  |  |  | /* the following conditions:                                              */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be         */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.        */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "gradle_export_util.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-12 02:46:22 +01:00
										 |  |  | #include "core/config/project_settings.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | int _get_android_orientation_value(DisplayServer::ScreenOrientation screen_orientation) { | 
					
						
							|  |  |  | 	switch (screen_orientation) { | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_PORTRAIT: | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_REVERSE_LANDSCAPE: | 
					
						
							|  |  |  | 			return 8; | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_REVERSE_PORTRAIT: | 
					
						
							|  |  |  | 			return 9; | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_SENSOR_LANDSCAPE: | 
					
						
							|  |  |  | 			return 11; | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_SENSOR_PORTRAIT: | 
					
						
							|  |  |  | 			return 12; | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_SENSOR: | 
					
						
							|  |  |  | 			return 13; | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_LANDSCAPE: | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String _get_android_orientation_label(DisplayServer::ScreenOrientation screen_orientation) { | 
					
						
							|  |  |  | 	switch (screen_orientation) { | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_PORTRAIT: | 
					
						
							|  |  |  | 			return "portrait"; | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_REVERSE_LANDSCAPE: | 
					
						
							|  |  |  | 			return "reverseLandscape"; | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_REVERSE_PORTRAIT: | 
					
						
							|  |  |  | 			return "reversePortrait"; | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_SENSOR_LANDSCAPE: | 
					
						
							|  |  |  | 			return "userLandscape"; | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_SENSOR_PORTRAIT: | 
					
						
							|  |  |  | 			return "userPortrait"; | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_SENSOR: | 
					
						
							|  |  |  | 			return "fullUser"; | 
					
						
							|  |  |  | 		case DisplayServer::SCREEN_LANDSCAPE: | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			return "landscape"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-01 10:19:22 +08:00
										 |  |  | int _get_app_category_value(int category_index) { | 
					
						
							|  |  |  | 	switch (category_index) { | 
					
						
							|  |  |  | 		case APP_CATEGORY_ACCESSIBILITY: | 
					
						
							|  |  |  | 			return 8; | 
					
						
							|  |  |  | 		case APP_CATEGORY_AUDIO: | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		case APP_CATEGORY_IMAGE: | 
					
						
							|  |  |  | 			return 3; | 
					
						
							|  |  |  | 		case APP_CATEGORY_MAPS: | 
					
						
							|  |  |  | 			return 6; | 
					
						
							|  |  |  | 		case APP_CATEGORY_NEWS: | 
					
						
							|  |  |  | 			return 5; | 
					
						
							|  |  |  | 		case APP_CATEGORY_PRODUCTIVITY: | 
					
						
							|  |  |  | 			return 7; | 
					
						
							|  |  |  | 		case APP_CATEGORY_SOCIAL: | 
					
						
							|  |  |  | 			return 4; | 
					
						
							|  |  |  | 		case APP_CATEGORY_VIDEO: | 
					
						
							|  |  |  | 			return 2; | 
					
						
							|  |  |  | 		case APP_CATEGORY_GAME: | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String _get_app_category_label(int category_index) { | 
					
						
							|  |  |  | 	switch (category_index) { | 
					
						
							|  |  |  | 		case APP_CATEGORY_ACCESSIBILITY: | 
					
						
							|  |  |  | 			return "accessibility"; | 
					
						
							|  |  |  | 		case APP_CATEGORY_AUDIO: | 
					
						
							|  |  |  | 			return "audio"; | 
					
						
							|  |  |  | 		case APP_CATEGORY_IMAGE: | 
					
						
							|  |  |  | 			return "image"; | 
					
						
							|  |  |  | 		case APP_CATEGORY_MAPS: | 
					
						
							|  |  |  | 			return "maps"; | 
					
						
							|  |  |  | 		case APP_CATEGORY_NEWS: | 
					
						
							|  |  |  | 			return "news"; | 
					
						
							|  |  |  | 		case APP_CATEGORY_PRODUCTIVITY: | 
					
						
							|  |  |  | 			return "productivity"; | 
					
						
							|  |  |  | 		case APP_CATEGORY_SOCIAL: | 
					
						
							|  |  |  | 			return "social"; | 
					
						
							|  |  |  | 		case APP_CATEGORY_VIDEO: | 
					
						
							|  |  |  | 			return "video"; | 
					
						
							|  |  |  | 		case APP_CATEGORY_GAME: | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			return "game"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | // Utility method used to create a directory.
 | 
					
						
							|  |  |  | Error create_directory(const String &p_dir) { | 
					
						
							|  |  |  | 	if (!DirAccess::exists(p_dir)) { | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 		Ref<DirAccess> filesystem_da = DirAccess::create(DirAccess::ACCESS_RESOURCES); | 
					
						
							|  |  |  | 		ERR_FAIL_COND_V_MSG(filesystem_da.is_null(), ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'."); | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 		Error err = filesystem_da->make_dir_recursive(p_dir); | 
					
						
							|  |  |  | 		ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'."); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Writes p_data into a file at p_path, creating directories if necessary.
 | 
					
						
							|  |  |  | // Note: this will overwrite the file at p_path if it already exists.
 | 
					
						
							|  |  |  | Error store_file_at_path(const String &p_path, const Vector<uint8_t> &p_data) { | 
					
						
							|  |  |  | 	String dir = p_path.get_base_dir(); | 
					
						
							|  |  |  | 	Error err = create_directory(dir); | 
					
						
							|  |  |  | 	if (err != OK) { | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 	Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE); | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + "'."); | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 	fa->store_buffer(p_data.ptr(), p_data.size()); | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Writes string p_data into a file at p_path, creating directories if necessary.
 | 
					
						
							|  |  |  | // Note: this will overwrite the file at p_path if it already exists.
 | 
					
						
							|  |  |  | Error store_string_at_path(const String &p_path, const String &p_data) { | 
					
						
							|  |  |  | 	String dir = p_path.get_base_dir(); | 
					
						
							|  |  |  | 	Error err = create_directory(dir); | 
					
						
							|  |  |  | 	if (err != OK) { | 
					
						
							|  |  |  | 		if (OS::get_singleton()->is_stdout_verbose()) { | 
					
						
							|  |  |  | 			print_error("Unable to write data into " + p_path); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 	Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE); | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + "'."); | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 	fa->store_string(p_data); | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Implementation of EditorExportSaveFunction.
 | 
					
						
							|  |  |  | // This method will only be called as an input to export_project_files.
 | 
					
						
							|  |  |  | // It is used by the export_project_files method to save all the asset files into the gradle project.
 | 
					
						
							|  |  |  | // It's functionality mirrors that of the method save_apk_file.
 | 
					
						
							| 
									
										
										
										
											2023-02-01 15:17:06 -08:00
										 |  |  | // This method will be called ONLY when gradle build is enabled.
 | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { | 
					
						
							| 
									
										
										
										
											2022-04-05 13:40:26 +03:00
										 |  |  | 	CustomExportData *export_data = static_cast<CustomExportData *>(p_userdata); | 
					
						
							| 
									
										
										
										
											2021-09-09 19:55:42 -07:00
										 |  |  | 	String dst_path = p_path.replace_first("res://", export_data->assets_directory + "/"); | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 	print_verbose("Saving project files from " + p_path + " into " + dst_path); | 
					
						
							|  |  |  | 	Error err = store_file_at_path(dst_path, p_data); | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-26 09:25:42 +02:00
										 |  |  | String _android_xml_escape(const String &p_string) { | 
					
						
							|  |  |  | 	// Android XML requires strings to be both valid XML (`xml_escape()`) but also
 | 
					
						
							|  |  |  | 	// to escape characters which are valid XML but have special meaning in Android XML.
 | 
					
						
							|  |  |  | 	// https://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling
 | 
					
						
							|  |  |  | 	// Note: Didn't handle U+XXXX unicode chars, could be done if needed.
 | 
					
						
							|  |  |  | 	return p_string | 
					
						
							|  |  |  | 			.replace("@", "\\@") | 
					
						
							|  |  |  | 			.replace("?", "\\?") | 
					
						
							|  |  |  | 			.replace("'", "\\'") | 
					
						
							|  |  |  | 			.replace("\"", "\\\"") | 
					
						
							|  |  |  | 			.replace("\n", "\\n") | 
					
						
							|  |  |  | 			.replace("\t", "\\t") | 
					
						
							|  |  |  | 			.xml_escape(false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | // Creates strings.xml files inside the gradle project for different locales.
 | 
					
						
							|  |  |  | Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset, const String &project_name) { | 
					
						
							|  |  |  | 	print_verbose("Creating strings resources for supported locales for project " + project_name); | 
					
						
							|  |  |  | 	// Stores the string into the default values directory.
 | 
					
						
							| 
									
										
										
										
											2021-10-26 09:25:42 +02:00
										 |  |  | 	String processed_default_xml_string = vformat(godot_project_name_xml_string, _android_xml_escape(project_name)); | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 	store_string_at_path("res://android/build/res/values/godot_project_name_string.xml", processed_default_xml_string); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Searches the Gradle project res/ directory to find all supported locales
 | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 	Ref<DirAccess> da = DirAccess::open("res://android/build/res"); | 
					
						
							|  |  |  | 	if (da.is_null()) { | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 		if (OS::get_singleton()->is_stdout_verbose()) { | 
					
						
							|  |  |  | 			print_error("Unable to open Android resources directory."); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return ERR_CANT_OPEN; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	da->list_dir_begin(); | 
					
						
							| 
									
										
										
										
											2022-10-18 16:43:37 +02:00
										 |  |  | 	Dictionary appnames = GLOBAL_GET("application/config/name_localized"); | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 	while (true) { | 
					
						
							|  |  |  | 		String file = da->get_next(); | 
					
						
							| 
									
										
										
										
											2021-12-09 03:42:46 -06:00
										 |  |  | 		if (file.is_empty()) { | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!file.begins_with("values-")) { | 
					
						
							|  |  |  | 			// NOTE: This assumes all directories that start with "values-" are for localization.
 | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		String locale = file.replace("values-", "").replace("-r", "_"); | 
					
						
							|  |  |  | 		String locale_directory = "res://android/build/res/" + file + "/godot_project_name_string.xml"; | 
					
						
							| 
									
										
										
										
											2022-03-04 15:04:59 +02:00
										 |  |  | 		if (appnames.has(locale)) { | 
					
						
							|  |  |  | 			String locale_project_name = appnames[locale]; | 
					
						
							| 
									
										
										
										
											2021-10-26 09:25:42 +02:00
										 |  |  | 			String processed_xml_string = vformat(godot_project_name_xml_string, _android_xml_escape(locale_project_name)); | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 			print_verbose("Storing project name for locale " + locale + " under " + locale_directory); | 
					
						
							|  |  |  | 			store_string_at_path(locale_directory, processed_xml_string); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// TODO: Once the legacy build system is deprecated we don't need to have xml files for this else branch
 | 
					
						
							|  |  |  | 			store_string_at_path(locale_directory, processed_default_xml_string); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	da->list_dir_end(); | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String bool_to_string(bool v) { | 
					
						
							|  |  |  | 	return v ? "true" : "false"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String _get_gles_tag() { | 
					
						
							| 
									
										
										
										
											2022-09-07 17:44:36 -07:00
										 |  |  | 	return "    <uses-feature android:glEsVersion=\"0x00030000\" android:required=\"true\" />\n"; | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String _get_screen_sizes_tag(const Ref<EditorExportPreset> &p_preset) { | 
					
						
							|  |  |  | 	String manifest_screen_sizes = "    <supports-screens \n        tools:node=\"replace\""; | 
					
						
							|  |  |  | 	String sizes[] = { "small", "normal", "large", "xlarge" }; | 
					
						
							|  |  |  | 	size_t num_sizes = sizeof(sizes) / sizeof(sizes[0]); | 
					
						
							|  |  |  | 	for (size_t i = 0; i < num_sizes; i++) { | 
					
						
							|  |  |  | 		String feature_name = vformat("screen/support_%s", sizes[i]); | 
					
						
							|  |  |  | 		String feature_support = bool_to_string(p_preset->get(feature_name)); | 
					
						
							|  |  |  | 		String xml_entry = vformat("\n        android:%sScreens=\"%s\"", sizes[i], feature_support); | 
					
						
							|  |  |  | 		manifest_screen_sizes += xml_entry; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	manifest_screen_sizes += " />\n"; | 
					
						
							|  |  |  | 	return manifest_screen_sizes; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-02 11:14:29 -07:00
										 |  |  | String _get_activity_tag(const Ref<EditorExportPlatform> &p_export_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug) { | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 	String orientation = _get_android_orientation_label(DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation")))); | 
					
						
							|  |  |  | 	String manifest_activity_text = vformat( | 
					
						
							|  |  |  | 			"        <activity android:name=\"com.godot.game.GodotApp\" " | 
					
						
							| 
									
										
										
										
											2022-04-04 00:22:02 -07:00
										 |  |  | 			"tools:replace=\"android:screenOrientation,android:excludeFromRecents,android:resizeableActivity\" " | 
					
						
							| 
									
										
										
										
											2023-02-01 14:05:39 -08:00
										 |  |  | 			"tools:node=\"mergeOnlyAttributes\" " | 
					
						
							| 
									
										
										
										
											2021-12-09 08:49:32 -08:00
										 |  |  | 			"android:excludeFromRecents=\"%s\" " | 
					
						
							| 
									
										
										
										
											2022-04-04 00:22:02 -07:00
										 |  |  | 			"android:screenOrientation=\"%s\" " | 
					
						
							|  |  |  | 			"android:resizeableActivity=\"%s\">\n", | 
					
						
							| 
									
										
										
										
											2021-12-09 08:49:32 -08:00
										 |  |  | 			bool_to_string(p_preset->get("package/exclude_from_recents")), | 
					
						
							| 
									
										
										
										
											2022-04-04 00:22:02 -07:00
										 |  |  | 			orientation, | 
					
						
							| 
									
										
										
										
											2022-04-04 09:18:07 -07:00
										 |  |  | 			bool_to_string(bool(GLOBAL_GET("display/window/size/resizable")))); | 
					
						
							| 
									
										
										
										
											2023-02-01 14:05:39 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-12 20:50:31 -05:00
										 |  |  | 	manifest_activity_text += "            <intent-filter>\n" | 
					
						
							|  |  |  | 							  "                <action android:name=\"android.intent.action.MAIN\" />\n" | 
					
						
							|  |  |  | 							  "                <category android:name=\"android.intent.category.LAUNCHER\" />\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool uses_leanback_category = p_preset->get("package/show_in_android_tv"); | 
					
						
							|  |  |  | 	if (uses_leanback_category) { | 
					
						
							|  |  |  | 		manifest_activity_text += "                <category android:name=\"android.intent.category.LEANBACK_LAUNCHER\" />\n"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool uses_home_category = p_preset->get("package/show_as_launcher_app"); | 
					
						
							|  |  |  | 	if (uses_home_category) { | 
					
						
							|  |  |  | 		manifest_activity_text += "                <category android:name=\"android.intent.category.HOME\" />\n"; | 
					
						
							|  |  |  | 		manifest_activity_text += "                <category android:name=\"android.intent.category.DEFAULT\" />\n"; | 
					
						
							| 
									
										
										
										
											2023-02-01 14:05:39 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-02 11:14:29 -07:00
										 |  |  | 	manifest_activity_text += "            </intent-filter>\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); | 
					
						
							|  |  |  | 	for (int i = 0; i < export_plugins.size(); i++) { | 
					
						
							|  |  |  | 		if (export_plugins[i]->supports_platform(p_export_platform)) { | 
					
						
							|  |  |  | 			const String contents = export_plugins[i]->get_android_manifest_activity_element_contents(p_export_platform, p_debug); | 
					
						
							|  |  |  | 			if (!contents.is_empty()) { | 
					
						
							|  |  |  | 				manifest_activity_text += contents; | 
					
						
							|  |  |  | 				manifest_activity_text += "\n"; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	manifest_activity_text += "        </activity>\n"; | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 	return manifest_activity_text; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-02 11:14:29 -07:00
										 |  |  | String _get_application_tag(const Ref<EditorExportPlatform> &p_export_platform, const Ref<EditorExportPreset> &p_preset, bool p_has_read_write_storage_permission, bool p_debug) { | 
					
						
							| 
									
										
										
										
											2023-01-01 10:19:22 +08:00
										 |  |  | 	int app_category_index = (int)(p_preset->get("package/app_category")); | 
					
						
							|  |  |  | 	bool is_game = app_category_index == APP_CATEGORY_GAME; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 	String manifest_application_text = vformat( | 
					
						
							|  |  |  | 			"    <application android:label=\"@string/godot_project_name_string\"\n" | 
					
						
							|  |  |  | 			"        android:allowBackup=\"%s\"\n" | 
					
						
							|  |  |  | 			"        android:icon=\"@mipmap/icon\"\n" | 
					
						
							| 
									
										
										
										
											2023-01-01 10:19:22 +08:00
										 |  |  | 			"        android:appCategory=\"%s\"\n" | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 			"        android:isGame=\"%s\"\n" | 
					
						
							| 
									
										
										
										
											2021-08-12 22:16:14 -07:00
										 |  |  | 			"        android:hasFragileUserData=\"%s\"\n" | 
					
						
							| 
									
										
										
										
											2021-07-10 18:39:31 -07:00
										 |  |  | 			"        android:requestLegacyExternalStorage=\"%s\"\n" | 
					
						
							| 
									
										
										
										
											2023-01-01 10:19:22 +08:00
										 |  |  | 			"        tools:replace=\"android:allowBackup,android:appCategory,android:isGame,android:hasFragileUserData,android:requestLegacyExternalStorage\"\n" | 
					
						
							| 
									
										
										
										
											2023-02-01 14:05:39 -08:00
										 |  |  | 			"        tools:ignore=\"GoogleAppIndexingWarning\">\n\n", | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 			bool_to_string(p_preset->get("user_data_backup/allow")), | 
					
						
							| 
									
										
										
										
											2023-01-01 10:19:22 +08:00
										 |  |  | 			_get_app_category_label(app_category_index), | 
					
						
							|  |  |  | 			bool_to_string(is_game), | 
					
						
							| 
									
										
										
										
											2021-07-10 18:39:31 -07:00
										 |  |  | 			bool_to_string(p_preset->get("package/retain_data_on_uninstall")), | 
					
						
							| 
									
										
										
										
											2021-07-10 18:39:31 -07:00
										 |  |  | 			bool_to_string(p_has_read_write_storage_permission)); | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-02 11:14:29 -07:00
										 |  |  | 	Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); | 
					
						
							|  |  |  | 	for (int i = 0; i < export_plugins.size(); i++) { | 
					
						
							|  |  |  | 		if (export_plugins[i]->supports_platform(p_export_platform)) { | 
					
						
							|  |  |  | 			const String contents = export_plugins[i]->get_android_manifest_application_element_contents(p_export_platform, p_debug); | 
					
						
							|  |  |  | 			if (!contents.is_empty()) { | 
					
						
							|  |  |  | 				manifest_application_text += contents; | 
					
						
							|  |  |  | 				manifest_application_text += "\n"; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	manifest_application_text += _get_activity_tag(p_export_platform, p_preset, p_debug); | 
					
						
							| 
									
										
										
										
											2021-07-13 23:30:53 +03:00
										 |  |  | 	manifest_application_text += "    </application>\n"; | 
					
						
							|  |  |  | 	return manifest_application_text; | 
					
						
							|  |  |  | } |