From 64936fe36057b143a7451805359586e325a5e7af Mon Sep 17 00:00:00 2001 From: Fredia Huya-Kouadio Date: Sat, 22 Feb 2025 06:03:10 -0800 Subject: [PATCH] Add support for export plugins to modify the Android prebuilt manifest --- doc/classes/EditorExportPlugin.xml | 8 + editor/export/editor_export_plugin.cpp | 7 + editor/export/editor_export_plugin.h | 2 + platform/android/export/export_plugin.cpp | 347 +++++++++++------- platform/android/export/export_plugin.h | 12 +- .../android/export/gradle_export_util.cpp | 6 +- platform/android/export/gradle_export_util.h | 7 +- platform/android/java/app/AndroidManifest.xml | 9 - platform/android/java/app/build.gradle | 5 - platform/android/java/app/config.gradle | 19 - .../editor/src/horizonos/AndroidManifest.xml | 2 + 11 files changed, 264 insertions(+), 160 deletions(-) diff --git a/doc/classes/EditorExportPlugin.xml b/doc/classes/EditorExportPlugin.xml index 23e3f4139ca2..bc18304c30eb 100644 --- a/doc/classes/EditorExportPlugin.xml +++ b/doc/classes/EditorExportPlugin.xml @@ -241,6 +241,14 @@ Return [code]true[/code] if the plugin supports the given [param platform]. + + + + + + Provide access to the Android prebuilt manifest and allows the plugin to modify it if needed. + + diff --git a/editor/export/editor_export_plugin.cpp b/editor/export/editor_export_plugin.cpp index ddc340ee77fb..dea7c45a7f84 100644 --- a/editor/export/editor_export_plugin.cpp +++ b/editor/export/editor_export_plugin.cpp @@ -264,6 +264,12 @@ String EditorExportPlugin::get_android_manifest_element_contents(const Ref &p_export_platform, const PackedByteArray &p_manifest_data) const { + PackedByteArray ret; + GDVIRTUAL_CALL(_update_android_prebuilt_manifest, p_export_platform, p_manifest_data, ret); + return ret; +} + PackedStringArray EditorExportPlugin::_get_export_features(const Ref &p_platform, bool p_debug) const { PackedStringArray ret; GDVIRTUAL_CALL(_get_export_features, p_platform, p_debug, ret); @@ -369,4 +375,5 @@ void EditorExportPlugin::_bind_methods() { GDVIRTUAL_BIND(_get_android_manifest_activity_element_contents, "platform", "debug"); GDVIRTUAL_BIND(_get_android_manifest_application_element_contents, "platform", "debug"); GDVIRTUAL_BIND(_get_android_manifest_element_contents, "platform", "debug"); + GDVIRTUAL_BIND(_update_android_prebuilt_manifest, "platform", "manifest_data"); } diff --git a/editor/export/editor_export_plugin.h b/editor/export/editor_export_plugin.h index 6d60482687a9..5d60951b69c7 100644 --- a/editor/export/editor_export_plugin.h +++ b/editor/export/editor_export_plugin.h @@ -143,6 +143,7 @@ class EditorExportPlugin : public RefCounted { GDVIRTUAL2RC(String, _get_android_manifest_activity_element_contents, const Ref &, bool); GDVIRTUAL2RC(String, _get_android_manifest_application_element_contents, const Ref &, bool); GDVIRTUAL2RC(String, _get_android_manifest_element_contents, const Ref &, bool); + GDVIRTUAL2RC(PackedByteArray, _update_android_prebuilt_manifest, const Ref &, const PackedByteArray &); virtual bool _begin_customize_resources(const Ref &p_platform, const Vector &p_features); // Return true if this plugin does property export customization virtual Ref _customize_resource(const Ref &p_resource, const String &p_path); // If nothing is returned, it means do not touch (nothing changed). If something is returned (either the same or a different resource) it means changes are made. @@ -174,6 +175,7 @@ class EditorExportPlugin : public RefCounted { virtual String get_android_manifest_activity_element_contents(const Ref &p_export_platform, bool p_debug) const; virtual String get_android_manifest_application_element_contents(const Ref &p_export_platform, bool p_debug) const; virtual String get_android_manifest_element_contents(const Ref &p_export_platform, bool p_debug) const; + virtual PackedByteArray update_android_prebuilt_manifest(const Ref &p_export_platform, const PackedByteArray &p_manifest_data) const; Vector get_ios_frameworks() const; Vector get_ios_embedded_frameworks() const; diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index cc2bdf8d7e71..7bb45c670add 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -30,7 +30,6 @@ #include "export_plugin.h" -#include "gradle_export_util.h" #include "logo_svg.gen.h" #include "run_icon_svg.gen.h" @@ -939,7 +938,7 @@ void EditorExportPlatformAndroid::_create_editor_debug_keystore_if_needed() { print_verbose("Updated editor debug keystore to " + keystore_path); } -void EditorExportPlatformAndroid::_get_permissions(const Ref &p_preset, bool p_give_internet, Vector &r_permissions) { +void EditorExportPlatformAndroid::_get_manifest_info(const Ref &p_preset, bool p_give_internet, Vector &r_permissions, Vector &r_features, Vector &r_metadata) { const char **aperms = ANDROID_PERMS; while (*aperms) { bool enabled = p_preset->get("permissions/" + String(*aperms).to_lower()); @@ -960,6 +959,36 @@ void EditorExportPlatformAndroid::_get_permissions(const Ref r_permissions.push_back("android.permission.INTERNET"); } } + + if (_uses_vulkan()) { + // Require vulkan hardware level 1 support + FeatureInfo vulkan_level = { + "android.hardware.vulkan.level", // name + false, // required + "1" // version + }; + r_features.append(vulkan_level); + + // Require vulkan version 1.0 + FeatureInfo vulkan_version = { + "android.hardware.vulkan.version", // name + true, // required + "0x400003" // version - Encoded value for api version 1.0 + }; + r_features.append(vulkan_version); + } + + MetadataInfo rendering_method_metadata = { + "org.godotengine.rendering.method", + GLOBAL_GET("rendering/renderer/rendering_method.mobile") + }; + r_metadata.append(rendering_method_metadata); + + MetadataInfo editor_version_metadata = { + "org.godotengine.editor.version", + String(VERSION_FULL_CONFIG) + }; + r_metadata.append(editor_version_metadata); } void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref &p_preset, bool p_give_internet, bool p_debug) { @@ -973,7 +1002,9 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref perms; - _get_permissions(p_preset, p_give_internet, perms); + Vector features; + Vector manifest_metadata; + _get_manifest_info(p_preset, p_give_internet, perms, features, manifest_metadata); for (int i = 0; i < perms.size(); i++) { String permission = perms.get(i); if (permission == "android.permission.WRITE_EXTERNAL_STORAGE" || (permission == "android.permission.READ_EXTERNAL_STORAGE" && _has_manage_external_storage_permission(perms))) { @@ -983,9 +1014,8 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref\n"; - manifest_text += " \n"; + for (int i = 0; i < features.size(); i++) { + manifest_text += vformat(" \n", features[i].name, features[i].required, features[i].version); } Vector> export_plugins = EditorExport::get_singleton()->get_export_plugins(); @@ -999,7 +1029,7 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref(this), p_preset, _has_read_write_storage_permission(perms), p_debug); + manifest_text += _get_application_tag(Ref(this), p_preset, _has_read_write_storage_permission(perms), p_debug, manifest_metadata); manifest_text += "\n"; String manifest_path = ExportTemplateManager::get_android_build_directory(p_preset).path_join(vformat("src/%s/AndroidManifest.xml", (p_debug ? "debug" : "release"))); @@ -1101,8 +1131,9 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref &p bool is_resizeable = bool(GLOBAL_GET("display/window/size/resizable")); Vector perms; - // Write permissions into the perms variable. - _get_permissions(p_preset, p_give_internet, perms); + Vector features; + Vector manifest_metadata; + _get_manifest_info(p_preset, p_give_internet, perms, features, manifest_metadata); bool has_read_write_storage_permission = _has_read_write_storage_permission(perms); while (ofs < (uint32_t)p_manifest.size()) { @@ -1246,42 +1277,25 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref &p uint32_t name = decode_uint32(&p_manifest[iofs + 12]); String tname = string_table[name]; - if (tname == "uses-feature") { - Vector feature_names; - Vector feature_required_list; - Vector feature_versions; - - if (_uses_vulkan()) { - // Require vulkan hardware level 1 support - feature_names.push_back("android.hardware.vulkan.level"); - feature_required_list.push_back(false); - feature_versions.push_back(1); - - // Require vulkan version 1.0 - feature_names.push_back("android.hardware.vulkan.version"); - feature_required_list.push_back(true); - feature_versions.push_back(0x400003); // Encoded value for api version 1.0 - } - - if (feature_names.size() > 0) { - ofs += 24; // skip over end tag - - // save manifest ending so we can restore it - Vector manifest_end; - uint32_t manifest_cur_size = p_manifest.size(); + if (tname == "manifest" || tname == "application") { + // save manifest ending so we can restore it + Vector manifest_end; + uint32_t manifest_cur_size = p_manifest.size(); - manifest_end.resize(p_manifest.size() - ofs); - memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size()); + manifest_end.resize(p_manifest.size() - ofs); + memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size()); - int32_t attr_name_string = string_table.find("name"); - ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute."); + int32_t attr_name_string = string_table.find("name"); + ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute."); - int32_t ns_android_string = string_table.find("http://schemas.android.com/apk/res/android"); - if (ns_android_string == -1) { - string_table.push_back("http://schemas.android.com/apk/res/android"); - ns_android_string = string_table.size() - 1; - } + int32_t ns_android_string = string_table.find("http://schemas.android.com/apk/res/android"); + if (ns_android_string == -1) { + string_table.push_back("http://schemas.android.com/apk/res/android"); + ns_android_string = string_table.size() - 1; + } + if (tname == "manifest") { + // Updating manifest features int32_t attr_uses_feature_string = string_table.find("uses-feature"); if (attr_uses_feature_string == -1) { string_table.push_back("uses-feature"); @@ -1294,11 +1308,11 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref &p attr_required_string = string_table.size() - 1; } - for (int i = 0; i < feature_names.size(); i++) { - const String &feature_name = feature_names[i]; - bool feature_required = feature_required_list[i]; - int feature_version = feature_versions[i]; - bool has_version_attribute = feature_version != -1; + for (int i = 0; i < features.size(); i++) { + const String &feature_name = features[i].name; + bool feature_required = features[i].required; + String feature_version = features[i].version; + bool has_version_attribute = !feature_version.is_empty(); print_line("Adding feature " + feature_name); @@ -1326,9 +1340,9 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref &p attr_version_string = string_table.size() - 1; } - version_value = string_table.find(itos(feature_version)); + version_value = string_table.find(feature_version); if (version_value == -1) { - string_table.push_back(itos(feature_version)); + string_table.push_back(feature_version); version_value = string_table.size() - 1; } @@ -1400,79 +1414,149 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref &p ofs += 24; } - memcpy(&p_manifest.write[ofs], manifest_end.ptr(), manifest_end.size()); - ofs -= 24; // go back over back end - } - } - if (tname == "manifest") { - // save manifest ending so we can restore it - Vector manifest_end; - uint32_t manifest_cur_size = p_manifest.size(); - manifest_end.resize(p_manifest.size() - ofs); - memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size()); + // Updating manifest permissions + int32_t attr_uses_permission_string = string_table.find("uses-permission"); + if (attr_uses_permission_string == -1) { + string_table.push_back("uses-permission"); + attr_uses_permission_string = string_table.size() - 1; + } - int32_t attr_name_string = string_table.find("name"); - ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute."); + for (int i = 0; i < perms.size(); ++i) { + print_line("Adding permission " + perms[i]); - int32_t ns_android_string = string_table.find("android"); - ERR_FAIL_COND_MSG(ns_android_string == -1, "Template does not have 'android' namespace."); + manifest_cur_size += 56 + 24; // node + end node + p_manifest.resize(manifest_cur_size); - int32_t attr_uses_permission_string = string_table.find("uses-permission"); - if (attr_uses_permission_string == -1) { - string_table.push_back("uses-permission"); - attr_uses_permission_string = string_table.size() - 1; - } + // Add permission to the string pool + int32_t perm_string = string_table.find(perms[i]); + if (perm_string == -1) { + string_table.push_back(perms[i]); + perm_string = string_table.size() - 1; + } - for (int i = 0; i < perms.size(); ++i) { - print_line("Adding permission " + perms[i]); + // start tag + encode_uint16(0x102, &p_manifest.write[ofs]); // type + encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize + encode_uint32(56, &p_manifest.write[ofs + 4]); // size + encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno + encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment + encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns + encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name + encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start + encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size + encode_uint16(1, &p_manifest.write[ofs + 28]); // num_attrs + encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index + encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index + encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index + + // attribute + encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns + encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name' + encode_uint32(perm_string, &p_manifest.write[ofs + 44]); // raw_value + encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size + p_manifest.write[ofs + 50] = 0; // typedvalue_always0 + p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string) + encode_uint32(perm_string, &p_manifest.write[ofs + 52]); // typedvalue reference - manifest_cur_size += 56 + 24; // node + end node - p_manifest.resize(manifest_cur_size); + ofs += 56; - // Add permission to the string pool - int32_t perm_string = string_table.find(perms[i]); - if (perm_string == -1) { - string_table.push_back(perms[i]); - perm_string = string_table.size() - 1; + // end tag + encode_uint16(0x103, &p_manifest.write[ofs]); // type + encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize + encode_uint32(24, &p_manifest.write[ofs + 4]); // size + encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno + encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment + encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns + encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name + + ofs += 24; + } + } + + if (tname == "application") { + // Updating application meta-data + int32_t attr_meta_data_string = string_table.find("meta-data"); + if (attr_meta_data_string == -1) { + string_table.push_back("meta-data"); + attr_meta_data_string = string_table.size() - 1; } - // start tag - encode_uint16(0x102, &p_manifest.write[ofs]); // type - encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize - encode_uint32(56, &p_manifest.write[ofs + 4]); // size - encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno - encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment - encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns - encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name - encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start - encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size - encode_uint16(1, &p_manifest.write[ofs + 28]); // num_attrs - encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index - encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index - encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index - - // attribute - encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns - encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name' - encode_uint32(perm_string, &p_manifest.write[ofs + 44]); // raw_value - encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size - p_manifest.write[ofs + 50] = 0; // typedvalue_always0 - p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string) - encode_uint32(perm_string, &p_manifest.write[ofs + 52]); // typedvalue reference - - ofs += 56; - - // end tag - encode_uint16(0x103, &p_manifest.write[ofs]); // type - encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize - encode_uint32(24, &p_manifest.write[ofs + 4]); // size - encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno - encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment - encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns - encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name - - ofs += 24; + int32_t attr_value_string = string_table.find("value"); + if (attr_value_string == -1) { + string_table.push_back("value"); + attr_value_string = string_table.size() - 1; + } + + for (int i = 0; i < manifest_metadata.size(); i++) { + String meta_data_name = manifest_metadata[i].name; + String meta_data_value = manifest_metadata[i].value; + + print_line("Adding application metadata " + meta_data_name); + + int32_t meta_data_name_string = string_table.find(meta_data_name); + if (meta_data_name_string == -1) { + string_table.push_back(meta_data_name); + meta_data_name_string = string_table.size() - 1; + } + + int32_t meta_data_value_string = string_table.find(meta_data_value); + if (meta_data_value_string == -1) { + string_table.push_back(meta_data_value); + meta_data_value_string = string_table.size() - 1; + } + + int tag_size = 76; // node and two attrs + end node + int attr_count = 2; + manifest_cur_size += tag_size + 24; + p_manifest.resize(manifest_cur_size); + + // start tag + encode_uint16(0x102, &p_manifest.write[ofs]); // type + encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize + encode_uint32(tag_size, &p_manifest.write[ofs + 4]); // size + encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno + encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment + encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns + encode_uint32(attr_meta_data_string, &p_manifest.write[ofs + 20]); // name + encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start + encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size + encode_uint16(attr_count, &p_manifest.write[ofs + 28]); // num_attrs + encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index + encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index + encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index + + // android:name attribute + encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns + encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name' + encode_uint32(meta_data_name_string, &p_manifest.write[ofs + 44]); // raw_value + encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size + p_manifest.write[ofs + 50] = 0; // typedvalue_always0 + p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string) + encode_uint32(meta_data_name_string, &p_manifest.write[ofs + 52]); // typedvalue reference + + // android:value attribute + encode_uint32(ns_android_string, &p_manifest.write[ofs + 56]); // ns + encode_uint32(attr_value_string, &p_manifest.write[ofs + 60]); // 'value' + encode_uint32(meta_data_value_string, &p_manifest.write[ofs + 64]); // raw_value + encode_uint16(8, &p_manifest.write[ofs + 68]); // typedvalue_size + p_manifest.write[ofs + 70] = 0; // typedvalue_always0 + p_manifest.write[ofs + 71] = 0x03; // typedvalue_type (string) + encode_uint32(meta_data_value_string, &p_manifest.write[ofs + 72]); // typedvalue reference + + ofs += 76; + + // end tag + encode_uint16(0x103, &p_manifest.write[ofs]); // type + encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize + encode_uint32(24, &p_manifest.write[ofs + 4]); // size + encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno + encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment + encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns + encode_uint32(attr_meta_data_string, &p_manifest.write[ofs + 20]); // name + + ofs += 24; + } } // copy footer back in @@ -1484,7 +1568,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref &p ofs += size; } - //create new andriodmanifest binary + // Create new android manifest binary. Vector ret; ret.resize(string_table_begins + string_table.size() * 4); @@ -1864,16 +1948,10 @@ String EditorExportPlatformAndroid::get_export_option_warning(const EditorExport } } else if (p_name == "gradle_build/use_gradle_build") { bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build"); - String enabled_plugins_names = _get_plugins_names(Ref(p_preset)); - if (!enabled_plugins_names.is_empty() && !gradle_build_enabled) { + String enabled_deprecated_plugins_names = _get_deprecated_plugins_names(Ref(p_preset)); + if (!enabled_deprecated_plugins_names.is_empty() && !gradle_build_enabled) { return TTR("\"Use Gradle Build\" must be enabled to use the plugins."); } - } else if (p_name == "xr_features/xr_mode") { - bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build"); - int xr_mode_index = p_preset->get("xr_features/xr_mode"); - if (xr_mode_index == XR_MODE_OPENXR && !gradle_build_enabled) { - return TTR("OpenXR requires \"Use Gradle Build\" to be enabled"); - } } else if (p_name == "gradle_build/compress_native_libraries") { bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build"); if (bool(p_preset->get("gradle_build/compress_native_libraries")) && !gradle_build_enabled) { @@ -2602,6 +2680,7 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref &p_preset) const { + Vector names; + +#ifndef DISABLE_DEPRECATED + PluginConfigAndroid::get_plugins_names(get_enabled_plugins(p_preset), names); +#endif // DISABLE_DEPRECATED + + String plugins_names = String("|").join(names); + return plugins_names; +} + String EditorExportPlatformAndroid::_get_plugins_names(const Ref &p_preset) const { Vector names; @@ -3459,7 +3550,6 @@ Error EditorExportPlatformAndroid::export_project_helper(const Refglobalize_path("res://addons"); - String current_renderer = GLOBAL_GET("rendering/renderer/rendering_method.mobile"); cmdline.push_back("-p"); // argument to specify the start directory. cmdline.push_back(build_path); // start directory. @@ -3476,8 +3566,6 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref> export_plugins = EditorExport::get_singleton()->get_export_plugins(); + for (int i = 0; i < export_plugins.size(); i++) { + if (export_plugins[i]->supports_platform(Ref(this))) { + PackedByteArray export_plugin_data = export_plugins[i]->update_android_prebuilt_manifest(Ref(this), data); + if (!export_plugin_data.is_empty()) { + data = export_plugin_data; + } + } + } } if (file == "resources.arsc") { _fix_resources(p_preset, data); diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h index 4b4753482169..585b1c4b687b 100644 --- a/platform/android/export/export_plugin.h +++ b/platform/android/export/export_plugin.h @@ -34,6 +34,8 @@ #include "godot_plugin_config.h" #endif // DISABLE_DEPRECATED +#include "gradle_export_util.h" + #include "core/io/image.h" #include "core/io/zip_io.h" #include "core/os/os.h" @@ -75,6 +77,12 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { EditorProgress *ep = nullptr; }; + struct FeatureInfo { + String name; + bool required; + String version = ""; + }; + #ifndef DISABLE_DEPRECATED mutable Vector android_plugins; mutable SafeFlag android_plugins_changed; @@ -151,7 +159,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { bool _has_manage_external_storage_permission(const Vector &p_permissions); - void _get_permissions(const Ref &p_preset, bool p_give_internet, Vector &r_permissions); + void _get_manifest_info(const Ref &p_preset, bool p_give_internet, Vector &r_permissions, Vector &r_features, Vector &r_metadata); void _write_tmp_manifest(const Ref &p_preset, bool p_give_internet, bool p_debug); @@ -235,6 +243,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { virtual List get_binary_extensions(const Ref &p_preset) const override; + String _get_deprecated_plugins_names(const Ref &p_preset) const; + String _get_plugins_names(const Ref &p_preset) const; String _resolve_export_plugin_android_library_path(const String &p_android_library_path) const; diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp index 32ad2d44066c..2251a276924e 100644 --- a/platform/android/export/gradle_export_util.cpp +++ b/platform/android/export/gradle_export_util.cpp @@ -306,7 +306,7 @@ String _get_activity_tag(const Ref &p_export_platform, con return manifest_activity_text; } -String _get_application_tag(const Ref &p_export_platform, const Ref &p_preset, bool p_has_read_write_storage_permission, bool p_debug) { +String _get_application_tag(const Ref &p_export_platform, const Ref &p_preset, bool p_has_read_write_storage_permission, bool p_debug, const Vector &p_metadata) { int app_category_index = (int)(p_preset->get("package/app_category")); bool is_game = app_category_index == APP_CATEGORY_GAME; @@ -330,6 +330,10 @@ String _get_application_tag(const Ref &p_export_platform, } manifest_application_text += " tools:ignore=\"GoogleAppIndexingWarning\">\n\n"; + for (int i = 0; i < p_metadata.size(); i++) { + manifest_application_text += vformat(" \n", p_metadata[i].name, p_metadata[i].value); + } + Vector> 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)) { diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index ee95f03ea4dd..340902432a39 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -68,6 +68,11 @@ struct CustomExportData { Vector libs; }; +struct MetadataInfo { + String name; + String value; +}; + int _get_android_orientation_value(DisplayServer::ScreenOrientation screen_orientation); String _get_android_orientation_label(DisplayServer::ScreenOrientation screen_orientation); @@ -105,4 +110,4 @@ String _get_screen_sizes_tag(const Ref &p_preset); String _get_activity_tag(const Ref &p_export_platform, const Ref &p_preset, bool p_debug); -String _get_application_tag(const Ref &p_export_platform, const Ref &p_preset, bool p_has_read_write_storage_permission, bool p_debug); +String _get_application_tag(const Ref &p_export_platform, const Ref &p_preset, bool p_has_read_write_storage_permission, bool p_debug, const Vector &p_metadata); diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml index 1d59d15d560f..e99aaa4a8d9a 100644 --- a/platform/android/java/app/AndroidManifest.xml +++ b/platform/android/java/app/AndroidManifest.xml @@ -29,15 +29,6 @@ android:enabled="true" tools:targetApi="29" /> - - - - - } } -ext.getGodotRenderingMethod = { -> - String renderingMethod = project.hasProperty("godot_rendering_method") ? project.property("godot_rendering_method") : "" - return renderingMethod -} - -ext.getGodotEditorVersion = { -> - String editorVersion = project.hasProperty("godot_editor_version") ? project.property("godot_editor_version") : "" - if (editorVersion == null || editorVersion.isEmpty()) { - // Try the library version first - editorVersion = getGodotLibraryVersionName() - - if (editorVersion.isEmpty()) { - // Fallback value. - editorVersion = "custom_build" - } - } - return editorVersion -} - ext.getGodotLibraryVersionCode = { -> String versionName = "" int versionCode = 1 diff --git a/platform/android/java/editor/src/horizonos/AndroidManifest.xml b/platform/android/java/editor/src/horizonos/AndroidManifest.xml index 3f2b87e04852..3db83340aa1f 100644 --- a/platform/android/java/editor/src/horizonos/AndroidManifest.xml +++ b/platform/android/java/editor/src/horizonos/AndroidManifest.xml @@ -90,6 +90,8 @@ + +