Re-architect how Android plugins are packaged and handled at export time

The previous packaging format for Godot Android plugins consisted of the plugin's `gdap` config file accompanied by binaries defined in the `gdap` file.
This format is now deprecated (starting with Godot 4.2), and instead Godot Android plugins are now packaged as `EditorExportPlugin` plugins.

The `EditorExportPlugin` class has been updated with the following methods to provide the necessary set of functionality:
- `_supports_platform`: returns true if the plugin supports the given platform
- `_get_android_dependencies`: retrieve the set of android dependencies (e.g: `org.godot.example:my-plugin:0.0.0`) provided by the plugin
- `_get_android_dependencies_maven_repos`: retrieve the urls of the maven repos for the provided android dependencies
- `_get_android_libraries`: retrieve the local paths of the android libraries (AAR files) provided by the plugin
- `_get_android_manifest_activity_element_contents`: update the contents of the `<activity>` element in the generated Android manifest
- `_get_android_manifest_application_element_contents`: update the contents of the `<application>` element in the generated Android manifest
- `_get_android_manifest_element_contents`: update the contents of the `<manifest>` element in the generated Android manifest
This commit is contained in:
Fredia Huya-Kouadio 2023-07-02 11:14:29 -07:00 committed by Yuri Sizov
parent 279732539f
commit d17811c814
19 changed files with 457 additions and 108 deletions

View file

@ -8,6 +8,7 @@
To use [EditorExportPlugin], register it using the [method EditorPlugin.add_export_plugin] method first.
</description>
<tutorials>
<link title="Export Android plugins">$DOCS_URL/tutorials/platform/android/android_plugin.html</link>
</tutorials>
<methods>
<method name="_begin_customize_resources" qualifiers="virtual const">
@ -84,6 +85,64 @@
Calling [method skip] inside this callback will make the file not included in the export.
</description>
</method>
<method name="_get_android_dependencies" qualifiers="virtual const">
<return type="PackedStringArray" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="debug" type="bool" />
<description>
Virtual method to be overridden by the user. This is called to retrieve the set of Android dependencies provided by this plugin. Each returned Android dependency should have the format of an Android remote binary dependency: [code]org.godot.example:my-plugin:0.0.0[/code]
For more information see [url=https://developer.android.com/build/dependencies?agpversion=4.1#dependency-types]Android documentation on dependencies[/url].
[b]Note:[/b] Only supported on Android and requires [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] to be enabled.
</description>
</method>
<method name="_get_android_dependencies_maven_repos" qualifiers="virtual const">
<return type="PackedStringArray" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="debug" type="bool" />
<description>
Virtual method to be overridden by the user. This is called to retrieve the URLs of Maven repositories for the set of Android dependencies provided by this plugin.
For more information see [url=https://docs.gradle.org/current/userguide/dependency_management.html#sec:maven_repo]Gradle documentation on dependency management[/url].
[b]Note:[/b] Google's Maven repo and the Maven Central repo are already included by default.
[b]Note:[/b] Only supported on Android and requires [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] to be enabled.
</description>
</method>
<method name="_get_android_libraries" qualifiers="virtual const">
<return type="PackedStringArray" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="debug" type="bool" />
<description>
Virtual method to be overridden by the user. This is called to retrieve the local paths of the Android libraries archive (AAR) files provided by this plugin.
[b]Note:[/b] Relative paths **must** be relative to Godot's [code]res://addons/[/code] directory. For example, an AAR file located under [code]res://addons/hello_world_plugin/HelloWorld.release.aar[/code] can be returned as an absolute path using [code]res://addons/hello_world_plugin/HelloWorld.release.aar[/code] or a relative path using [code]hello_world_plugin/HelloWorld.release.aar[/code].
[b]Note:[/b] Only supported on Android and requires [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] to be enabled.
</description>
</method>
<method name="_get_android_manifest_activity_element_contents" qualifiers="virtual const">
<return type="String" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="debug" type="bool" />
<description>
Virtual method to be overridden by the user. This is used at export time to update the contents of the [code]activity[/code] element in the generated Android manifest.
[b]Note:[/b] Only supported on Android and requires [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] to be enabled.
</description>
</method>
<method name="_get_android_manifest_application_element_contents" qualifiers="virtual const">
<return type="String" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="debug" type="bool" />
<description>
Virtual method to be overridden by the user. This is used at export time to update the contents of the [code]application[/code] element in the generated Android manifest.
[b]Note:[/b] Only supported on Android and requires [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] to be enabled.
</description>
</method>
<method name="_get_android_manifest_element_contents" qualifiers="virtual const">
<return type="String" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="debug" type="bool" />
<description>
Virtual method to be overridden by the user. This is used at export time to update the contents of the [code]manifest[/code] element in the generated Android manifest.
[b]Note:[/b] Only supported on Android and requires [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] to be enabled.
</description>
</method>
<method name="_get_customization_configuration_hash" qualifiers="virtual const">
<return type="int" />
<description>
@ -99,6 +158,15 @@
Return a [PackedStringArray] of additional features this preset, for the given [param platform], should have.
</description>
</method>
<method name="_get_export_option_warning" qualifiers="virtual const">
<return type="String" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="option" type="String" />
<description>
Check the requirements for the given [param option] and return a non-empty warning string if they are not met.
[b]Note:[/b] Use [method get_option] to check the value of the export options.
</description>
</method>
<method name="_get_export_options" qualifiers="virtual const">
<return type="Dictionary[]" />
<param index="0" name="platform" type="EditorExportPlatform" />
@ -124,6 +192,13 @@
Return [code]true[/code], if the result of [method _get_export_options] has changed and the export options of preset corresponding to [param platform] should be updated.
</description>
</method>
<method name="_supports_platform" qualifiers="virtual const">
<return type="bool" />
<param index="0" name="platform" type="EditorExportPlatform" />
<description>
Return [code]true[/code] if the plugin supports the given [param platform].
</description>
</method>
<method name="add_file">
<return type="void" />
<param index="0" name="path" type="String" />

View file

@ -569,6 +569,12 @@
Returns the [PopupMenu] under [b]Scene &gt; Export As...[/b].
</description>
</method>
<method name="get_plugin_version" qualifiers="const">
<return type="String" />
<description>
Provide the version of the plugin declared in the [code]plugin.cfg[/code] config file.
</description>
</method>
<method name="get_script_create_dialog">
<return type="ScriptCreateDialog" />
<description>

View file

@ -3363,6 +3363,11 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled,
return;
}
String plugin_version;
if (cf->has_section_key("plugin", "version")) {
plugin_version = cf->get_value("plugin", "version");
}
if (!cf->has_section_key("plugin", "script")) {
show_warning(vformat(TTR("Unable to find script field for addon plugin at: '%s'."), addon_path));
return;
@ -3408,6 +3413,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled,
EditorPlugin *ep = memnew(EditorPlugin);
ep->set_script(scr);
ep->set_plugin_version(plugin_version);
addon_name_to_plugin[addon_path] = ep;
add_editor_plugin(ep, p_config_changed);

View file

@ -307,6 +307,14 @@ const Ref<Texture2D> EditorPlugin::get_icon() const {
return icon;
}
String EditorPlugin::get_plugin_version() const {
return plugin_version;
}
void EditorPlugin::set_plugin_version(const String &p_version) {
plugin_version = p_version;
}
bool EditorPlugin::has_main_screen() const {
bool success = false;
GDVIRTUAL_CALL(_has_main_screen, success);
@ -583,6 +591,7 @@ void EditorPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_script_create_dialog"), &EditorPlugin::get_script_create_dialog);
ClassDB::bind_method(D_METHOD("add_debugger_plugin", "script"), &EditorPlugin::add_debugger_plugin);
ClassDB::bind_method(D_METHOD("remove_debugger_plugin", "script"), &EditorPlugin::remove_debugger_plugin);
ClassDB::bind_method(D_METHOD("get_plugin_version"), &EditorPlugin::get_plugin_version);
GDVIRTUAL_BIND(_forward_canvas_gui_input, "event");
GDVIRTUAL_BIND(_forward_canvas_draw_over_viewport, "viewport_control");

View file

@ -61,6 +61,7 @@ class EditorPlugin : public Node {
bool force_draw_over_forwarding_enabled = false;
String last_main_screen_name;
String plugin_version;
void _editor_project_settings_changed();
@ -168,6 +169,8 @@ public:
virtual String get_name() const;
virtual const Ref<Texture2D> get_icon() const;
virtual String get_plugin_version() const;
virtual void set_plugin_version(const String &p_version);
virtual bool has_main_screen() const;
virtual void make_visible(bool p_visible);
virtual void selected_notify() {} //notify that it was raised by the user, not the editor

View file

@ -990,7 +990,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
struct SortByName {
bool operator()(const Ref<EditorExportPlugin> &left, const Ref<EditorExportPlugin> &right) const {
return left->_get_name() < right->_get_name();
return left->get_name() < right->get_name();
}
};
@ -1033,14 +1033,14 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
if (export_plugins.write[i]->_begin_customize_resources(Ref<EditorExportPlatform>(this), features_psa)) {
customize_resources_plugins.push_back(export_plugins[i]);
custom_resources_hash = hash_murmur3_one_64(export_plugins[i]->_get_name().hash64(), custom_resources_hash);
custom_resources_hash = hash_murmur3_one_64(export_plugins[i]->get_name().hash64(), custom_resources_hash);
uint64_t hash = export_plugins[i]->_get_customization_configuration_hash();
custom_resources_hash = hash_murmur3_one_64(hash, custom_resources_hash);
}
if (export_plugins.write[i]->_begin_customize_scenes(Ref<EditorExportPlatform>(this), features_psa)) {
customize_scenes_plugins.push_back(export_plugins[i]);
custom_resources_hash = hash_murmur3_one_64(export_plugins[i]->_get_name().hash64(), custom_resources_hash);
custom_resources_hash = hash_murmur3_one_64(export_plugins[i]->get_name().hash64(), custom_resources_hash);
uint64_t hash = export_plugins[i]->_get_customization_configuration_hash();
custom_scene_hash = hash_murmur3_one_64(hash, custom_scene_hash);
}
@ -1800,6 +1800,24 @@ bool EditorExportPlatform::can_export(const Ref<EditorExportPreset> &p_preset, S
if (!templates_error.is_empty()) {
r_error += templates_error;
}
String export_plugins_warning;
Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();
for (int i = 0; i < export_plugins.size(); i++) {
Ref<EditorExportPlatform> export_platform = Ref<EditorExportPlatform>(this);
if (!export_plugins[i]->supports_platform(export_platform)) {
continue;
}
String plugin_warning = export_plugins.write[i]->_has_valid_export_configuration(export_platform, p_preset);
if (!plugin_warning.is_empty()) {
export_plugins_warning += plugin_warning;
}
}
if (!export_plugins_warning.is_empty()) {
r_error += export_plugins_warning;
}
#endif
String project_configuration_error;

View file

@ -132,6 +132,27 @@ Variant EditorExportPlugin::get_option(const StringName &p_name) const {
return export_preset->get(p_name);
}
String EditorExportPlugin::_has_valid_export_configuration(const Ref<EditorExportPlatform> &p_export_platform, const Ref<EditorExportPreset> &p_preset) {
String warning;
if (!supports_platform(p_export_platform)) {
warning += vformat(TTR("Plugin \"%s\" is not supported on \"%s\""), get_name(), p_export_platform->get_name());
warning += "\n";
return warning;
}
set_export_preset(p_preset);
List<EditorExportPlatform::ExportOption> options;
_get_export_options(p_export_platform, &options);
for (const EditorExportPlatform::ExportOption &E : options) {
String option_warning = _get_export_option_warning(p_export_platform, E.option.name);
if (!option_warning.is_empty()) {
warning += option_warning + "\n";
}
}
return warning;
}
void EditorExportPlugin::_export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features) {
GDVIRTUAL_CALL(_export_file, p_path, p_type, p_features);
}
@ -184,12 +205,54 @@ void EditorExportPlugin::_end_customize_resources() {
GDVIRTUAL_CALL(_end_customize_resources);
}
String EditorExportPlugin::_get_name() const {
String EditorExportPlugin::get_name() const {
String ret;
GDVIRTUAL_REQUIRED_CALL(_get_name, ret);
return ret;
}
bool EditorExportPlugin::supports_platform(const Ref<EditorExportPlatform> &p_export_platform) const {
bool ret = false;
GDVIRTUAL_CALL(_supports_platform, p_export_platform, ret);
return ret;
}
PackedStringArray EditorExportPlugin::get_android_dependencies(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const {
PackedStringArray ret;
GDVIRTUAL_CALL(_get_android_dependencies, p_export_platform, p_debug, ret);
return ret;
}
PackedStringArray EditorExportPlugin::get_android_dependencies_maven_repos(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const {
PackedStringArray ret;
GDVIRTUAL_CALL(_get_android_dependencies_maven_repos, p_export_platform, p_debug, ret);
return ret;
}
PackedStringArray EditorExportPlugin::get_android_libraries(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const {
PackedStringArray ret;
GDVIRTUAL_CALL(_get_android_libraries, p_export_platform, p_debug, ret);
return ret;
}
String EditorExportPlugin::get_android_manifest_activity_element_contents(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const {
String ret;
GDVIRTUAL_CALL(_get_android_manifest_activity_element_contents, p_export_platform, p_debug, ret);
return ret;
}
String EditorExportPlugin::get_android_manifest_application_element_contents(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const {
String ret;
GDVIRTUAL_CALL(_get_android_manifest_application_element_contents, p_export_platform, p_debug, ret);
return ret;
}
String EditorExportPlugin::get_android_manifest_element_contents(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const {
String ret;
GDVIRTUAL_CALL(_get_android_manifest_element_contents, p_export_platform, p_debug, ret);
return ret;
}
PackedStringArray EditorExportPlugin::_get_export_features(const Ref<EditorExportPlatform> &p_platform, bool p_debug) const {
PackedStringArray ret;
GDVIRTUAL_CALL(_get_export_features, p_platform, p_debug, ret);
@ -216,6 +279,12 @@ bool EditorExportPlugin::_should_update_export_options(const Ref<EditorExportPla
return ret;
}
String EditorExportPlugin::_get_export_option_warning(const Ref<EditorExportPlatform> &p_export_platform, const String &p_option_name) const {
String ret;
GDVIRTUAL_CALL(_get_export_option_warning, p_export_platform, p_option_name, ret);
return ret;
}
void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {
}
@ -257,9 +326,19 @@ void EditorExportPlugin::_bind_methods() {
GDVIRTUAL_BIND(_get_export_options, "platform");
GDVIRTUAL_BIND(_should_update_export_options, "platform");
GDVIRTUAL_BIND(_get_export_option_warning, "platform", "option");
GDVIRTUAL_BIND(_get_export_features, "platform", "debug");
GDVIRTUAL_BIND(_get_name);
GDVIRTUAL_BIND(_supports_platform, "platform");
GDVIRTUAL_BIND(_get_android_dependencies, "platform", "debug");
GDVIRTUAL_BIND(_get_android_dependencies_maven_repos, "platform", "debug");
GDVIRTUAL_BIND(_get_android_libraries, "platform", "debug");
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");
}
EditorExportPlugin::EditorExportPlugin() {

View file

@ -42,6 +42,7 @@ class EditorExportPlugin : public RefCounted {
friend class EditorExport;
friend class EditorExportPlatform;
friend class EditorExportPreset;
Ref<EditorExportPreset> export_preset;
@ -85,6 +86,8 @@ class EditorExportPlugin : public RefCounted {
void _export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags);
void _export_end_script();
String _has_valid_export_configuration(const Ref<EditorExportPlatform> &p_export_platform, const Ref<EditorExportPreset> &p_preset);
protected:
void set_export_preset(const Ref<EditorExportPreset> &p_preset);
Ref<EditorExportPreset> get_export_preset() const;
@ -125,9 +128,19 @@ protected:
GDVIRTUAL2RC(PackedStringArray, _get_export_features, const Ref<EditorExportPlatform> &, bool);
GDVIRTUAL1RC(TypedArray<Dictionary>, _get_export_options, const Ref<EditorExportPlatform> &);
GDVIRTUAL1RC(bool, _should_update_export_options, const Ref<EditorExportPlatform> &);
GDVIRTUAL2RC(String, _get_export_option_warning, const Ref<EditorExportPlatform> &, String);
GDVIRTUAL0RC(String, _get_name)
GDVIRTUAL1RC(bool, _supports_platform, const Ref<EditorExportPlatform> &);
GDVIRTUAL2RC(PackedStringArray, _get_android_dependencies, const Ref<EditorExportPlatform> &, bool);
GDVIRTUAL2RC(PackedStringArray, _get_android_dependencies_maven_repos, const Ref<EditorExportPlatform> &, bool);
GDVIRTUAL2RC(PackedStringArray, _get_android_libraries, const Ref<EditorExportPlatform> &, bool);
GDVIRTUAL2RC(String, _get_android_manifest_activity_element_contents, const Ref<EditorExportPlatform> &, bool);
GDVIRTUAL2RC(String, _get_android_manifest_application_element_contents, const Ref<EditorExportPlatform> &, bool);
GDVIRTUAL2RC(String, _get_android_manifest_element_contents, const Ref<EditorExportPlatform> &, bool);
virtual bool _begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features); // Return true if this plugin does property export customization
virtual Ref<Resource> _customize_resource(const Ref<Resource> &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.
@ -142,10 +155,20 @@ protected:
virtual PackedStringArray _get_export_features(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const;
virtual void _get_export_options(const Ref<EditorExportPlatform> &p_export_platform, List<EditorExportPlatform::ExportOption> *r_options) const;
virtual bool _should_update_export_options(const Ref<EditorExportPlatform> &p_export_platform) const;
virtual String _get_name() const;
virtual String _get_export_option_warning(const Ref<EditorExportPlatform> &p_export_platform, const String &p_option_name) const;
public:
virtual String get_name() const;
virtual bool supports_platform(const Ref<EditorExportPlatform> &p_export_platform) const;
virtual PackedStringArray get_android_dependencies(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const;
virtual PackedStringArray get_android_dependencies_maven_repos(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const;
virtual PackedStringArray get_android_libraries(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const;
virtual String get_android_manifest_activity_element_contents(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const;
virtual String get_android_manifest_application_element_contents(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const;
virtual String get_android_manifest_element_contents(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const;
Vector<String> get_ios_frameworks() const;
Vector<String> get_ios_embedded_frameworks() const;
Vector<String> get_ios_project_static_libs() const;

View file

@ -57,7 +57,26 @@ void EditorExportPreset::_bind_methods() {
}
String EditorExportPreset::_get_property_warning(const StringName &p_name) const {
return platform->get_export_option_warning(this, p_name);
String warning = platform->get_export_option_warning(this, p_name);
if (!warning.is_empty()) {
warning += "\n";
}
// Get property warning from editor export plugins.
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(platform)) {
continue;
}
export_plugins.write[i]->set_export_preset(Ref<EditorExportPreset>(this));
String plugin_warning = export_plugins[i]->_get_export_option_warning(platform, p_name);
if (!plugin_warning.is_empty()) {
warning += plugin_warning + "\n";
}
}
return warning;
}
void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const {

View file

@ -669,11 +669,8 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_
f->store_line(VERSION_FULL_CONFIG);
}
// Create the android plugins directory.
Error err = da->make_dir_recursive("android/plugins");
ERR_FAIL_COND_V(err != OK, err);
err = da->make_dir_recursive("android/build");
// Create the android build directory.
Error err = da->make_dir_recursive("android/build");
ERR_FAIL_COND_V(err != OK, err);
{
// Add an empty .gdignore file to avoid scan.

View file

@ -40,7 +40,7 @@ private:
EditorExportPreset::FileExportMode _get_export_mode_for_path(const String &p_path);
protected:
String _get_name() const override { return "DedicatedServer"; }
String get_name() const override { return "DedicatedServer"; }
PackedStringArray _get_export_features(const Ref<EditorExportPlatform> &p_platform, bool p_debug) const override;
uint64_t _get_customization_configuration_hash() const override;

View file

@ -36,7 +36,7 @@
class GDExtensionExportPlugin : public EditorExportPlugin {
protected:
virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features);
virtual String _get_name() const { return "GDExtension"; }
virtual String get_name() const { return "GDExtension"; }
};
void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {

View file

@ -98,7 +98,7 @@ public:
return;
}
virtual String _get_name() const override { return "GDScript"; }
virtual String get_name() const override { return "GDScript"; }
};
static void _editor_init() {

View file

@ -261,30 +261,32 @@ void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) {
EditorExportPlatformAndroid *ea = static_cast<EditorExportPlatformAndroid *>(ud);
while (!ea->quit_request.is_set()) {
// Check for plugins updates
#ifndef DISABLE_DEPRECATED
// Check for android plugins updates
{
// Nothing to do if we already know the plugins have changed.
if (!ea->plugins_changed.is_set()) {
if (!ea->android_plugins_changed.is_set()) {
Vector<PluginConfigAndroid> loaded_plugins = get_plugins();
MutexLock lock(ea->plugins_lock);
MutexLock lock(ea->android_plugins_lock);
if (ea->plugins.size() != loaded_plugins.size()) {
ea->plugins_changed.set();
if (ea->android_plugins.size() != loaded_plugins.size()) {
ea->android_plugins_changed.set();
} else {
for (int i = 0; i < ea->plugins.size(); i++) {
if (ea->plugins[i].name != loaded_plugins[i].name) {
ea->plugins_changed.set();
for (int i = 0; i < ea->android_plugins.size(); i++) {
if (ea->android_plugins[i].name != loaded_plugins[i].name) {
ea->android_plugins_changed.set();
break;
}
}
}
if (ea->plugins_changed.is_set()) {
ea->plugins = loaded_plugins;
if (ea->android_plugins_changed.is_set()) {
ea->android_plugins = loaded_plugins;
}
}
}
#endif // DISABLE_DEPRECATED
// Check for devices updates
String adb = get_adb_path();
@ -628,6 +630,7 @@ Vector<EditorExportPlatformAndroid::ABI> EditorExportPlatformAndroid::get_abis()
return abis;
}
#ifndef DISABLE_DEPRECATED
/// List the gdap files in the directory specified by the p_path parameter.
Vector<String> EditorExportPlatformAndroid::list_gdap_files(const String &p_path) {
Vector<String> dir_files;
@ -694,6 +697,7 @@ Vector<PluginConfigAndroid> EditorExportPlatformAndroid::get_enabled_plugins(con
return enabled_plugins;
}
#endif // DISABLE_DEPRECATED
Error EditorExportPlatformAndroid::store_in_apk(APKExportData *ed, const String &p_path, const Vector<uint8_t> &p_data, int compression_method) {
zip_fileinfo zipfi = get_zip_fileinfo();
@ -861,8 +865,24 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref<EditorExportPres
}
}
manifest_text += _get_xr_features_tag(p_preset, _uses_vulkan());
manifest_text += _get_application_tag(p_preset, _has_read_write_storage_permission(perms));
if (_uses_vulkan()) {
manifest_text += " <uses-feature tools:node=\"replace\" android:name=\"android.hardware.vulkan.level\" android:required=\"false\" android:version=\"1\" />\n";
manifest_text += " <uses-feature tools:node=\"replace\" android:name=\"android.hardware.vulkan.version\" android:required=\"true\" android:version=\"0x400003\" />\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(Ref<EditorExportPlatform>(this))) {
const String contents = export_plugins[i]->get_android_manifest_element_contents(Ref<EditorExportPlatform>(this), p_debug);
if (!contents.is_empty()) {
manifest_text += contents;
manifest_text += "\n";
}
}
}
manifest_text += _get_xr_features_tag(p_preset);
manifest_text += _get_application_tag(Ref<EditorExportPlatform>(this), p_preset, _has_read_write_storage_permission(perms), p_debug);
manifest_text += "</manifest>\n";
String manifest_path = vformat("res://android/build/src/%s/AndroidManifest.xml", (p_debug ? "debug" : "release"));
@ -1721,7 +1741,7 @@ 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 = PluginConfigAndroid::get_plugins_names(get_enabled_plugins(Ref<EditorExportPreset>(p_preset)));
String enabled_plugins_names = _get_plugins_names(Ref<EditorExportPreset>(p_preset));
if (!enabled_plugins_names.is_empty() && !gradle_build_enabled) {
return TTR("\"Use Gradle Build\" must be enabled to use the plugins.");
}
@ -1808,12 +1828,14 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", VULKAN_MIN_SDK_VERSION)), "", false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/target_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_TARGET_SDK_VERSION)), "", false, true));
#ifndef DISABLE_DEPRECATED
Vector<PluginConfigAndroid> plugins_configs = get_plugins();
for (int i = 0; i < plugins_configs.size(); i++) {
print_verbose("Found Android plugin " + plugins_configs[i].name);
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("plugins"), plugins_configs[i].name)), false));
}
plugins_changed.clear();
android_plugins_changed.clear();
#endif // DISABLE_DEPRECATED
// Android supports multiple architectures in an app bundle, so
// we expose each option as a checkbox in the export dialog.
@ -1892,12 +1914,14 @@ Ref<Texture2D> EditorExportPlatformAndroid::get_logo() const {
}
bool EditorExportPlatformAndroid::should_update_export_options() {
bool export_options_changed = plugins_changed.is_set();
if (export_options_changed) {
#ifndef DISABLE_DEPRECATED
if (android_plugins_changed.is_set()) {
// don't clear unless we're reporting true, to avoid race
plugins_changed.clear();
android_plugins_changed.clear();
return true;
}
return export_options_changed;
#endif // DISABLE_DEPRECATED
return false;
}
bool EditorExportPlatformAndroid::poll_export() {
@ -2697,6 +2721,64 @@ String EditorExportPlatformAndroid::join_abis(const Vector<EditorExportPlatformA
return ret;
}
String EditorExportPlatformAndroid::_get_plugins_names(const Ref<EditorExportPreset> &p_preset) const {
Vector<String> names;
#ifndef DISABLE_DEPRECATED
PluginConfigAndroid::get_plugins_names(get_enabled_plugins(p_preset), names);
#endif // DISABLE_DEPRECATED
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(Ref<EditorExportPlatform>(this))) {
names.push_back(export_plugins[i]->get_name());
}
}
String plugins_names = String("|").join(names);
return plugins_names;
}
String EditorExportPlatformAndroid::_resolve_export_plugin_android_library_path(const String &p_android_library_path) const {
String absolute_path;
if (!p_android_library_path.is_empty()) {
if (p_android_library_path.is_absolute_path()) {
absolute_path = ProjectSettings::get_singleton()->globalize_path(p_android_library_path);
} else {
const String export_plugin_absolute_path = String("res://addons/").path_join(p_android_library_path);
absolute_path = ProjectSettings::get_singleton()->globalize_path(export_plugin_absolute_path);
}
}
return absolute_path;
}
bool EditorExportPlatformAndroid::_is_clean_build_required(const Ref<EditorExportPreset> &p_preset) {
bool first_build = last_gradle_build_time == 0;
bool have_plugins_changed = false;
String plugin_names = _get_plugins_names(p_preset);
if (!first_build) {
have_plugins_changed = plugin_names != last_plugin_names;
#ifndef DISABLE_DEPRECATED
if (!have_plugins_changed) {
Vector<PluginConfigAndroid> enabled_plugins = get_enabled_plugins(p_preset);
for (int i = 0; i < enabled_plugins.size(); i++) {
if (enabled_plugins.get(i).last_updated > last_gradle_build_time) {
have_plugins_changed = true;
break;
}
}
}
#endif // DISABLE_DEPRECATED
}
last_gradle_build_time = OS::get_singleton()->get_unix_time();
last_plugin_names = plugin_names;
return have_plugins_changed || first_build;
}
Error EditorExportPlatformAndroid::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
int export_format = int(p_preset->get("gradle_build/export_format"));
bool should_sign = p_preset->get("package/signed");
@ -2854,11 +2936,40 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
String sign_flag = should_sign ? "true" : "false";
String zipalign_flag = "true";
Vector<String> android_libraries;
Vector<String> android_dependencies;
Vector<String> android_dependencies_maven_repos;
#ifndef DISABLE_DEPRECATED
Vector<PluginConfigAndroid> enabled_plugins = get_enabled_plugins(p_preset);
String local_plugins_binaries = PluginConfigAndroid::get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_LOCAL, enabled_plugins);
String remote_plugins_binaries = PluginConfigAndroid::get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_REMOTE, enabled_plugins);
String custom_maven_repos = PluginConfigAndroid::get_plugins_custom_maven_repos(enabled_plugins);
bool clean_build_required = is_clean_build_required(enabled_plugins);
PluginConfigAndroid::get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_LOCAL, enabled_plugins, android_libraries);
PluginConfigAndroid::get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_REMOTE, enabled_plugins, android_dependencies);
PluginConfigAndroid::get_plugins_custom_maven_repos(enabled_plugins, android_dependencies_maven_repos);
#endif // DISABLE_DEPRECATED
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(Ref<EditorExportPlatform>(this))) {
PackedStringArray export_plugin_android_libraries = export_plugins[i]->get_android_libraries(Ref<EditorExportPlatform>(this), p_debug);
for (int k = 0; k < export_plugin_android_libraries.size(); k++) {
const String resolved_android_library_path = _resolve_export_plugin_android_library_path(export_plugin_android_libraries[k]);
if (!resolved_android_library_path.is_empty()) {
android_libraries.push_back(resolved_android_library_path);
}
}
PackedStringArray export_plugin_android_dependencies = export_plugins[i]->get_android_dependencies(Ref<EditorExportPlatform>(this), p_debug);
android_dependencies.append_array(export_plugin_android_dependencies);
PackedStringArray export_plugin_android_dependencies_maven_repos = export_plugins[i]->get_android_dependencies_maven_repos(Ref<EditorExportPlatform>(this), p_debug);
android_dependencies_maven_repos.append_array(export_plugin_android_dependencies_maven_repos);
}
}
bool clean_build_required = _is_clean_build_required(p_preset);
String combined_android_libraries = String("|").join(android_libraries);
String combined_android_dependencies = String("|").join(android_dependencies);
String combined_android_dependencies_maven_repos = String("|").join(android_dependencies_maven_repos);
List<String> cmdline;
if (clean_build_required) {
@ -2882,9 +2993,9 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
cmdline.push_back("-Pexport_version_min_sdk=" + min_sdk_version); // argument to specify the min sdk.
cmdline.push_back("-Pexport_version_target_sdk=" + target_sdk_version); // argument to specify the target sdk.
cmdline.push_back("-Pexport_enabled_abis=" + enabled_abi_string); // argument to specify enabled ABIs.
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_maven_repos=" + custom_maven_repos); // argument to specify the list of custom maven repos for the plugins dependencies.
cmdline.push_back("-Pplugins_local_binaries=" + combined_android_libraries); // argument to specify the list of android libraries provided by plugins.
cmdline.push_back("-Pplugins_remote_binaries=" + combined_android_dependencies); // argument to specify the list of android dependencies provided by plugins.
cmdline.push_back("-Pplugins_maven_repos=" + combined_android_dependencies_maven_repos); // argument to specify the list of maven repos for android dependencies provided by plugins.
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.
cmdline.push_back("-Pgodot_editor_version=" + String(VERSION_FULL_CONFIG));
@ -3310,7 +3421,9 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
#endif
devices_changed.set();
plugins_changed.set();
#ifndef DISABLE_DEPRECATED
android_plugins_changed.set();
#endif // DISABLE_DEPRECATED
#ifndef ANDROID_ENABLED
check_for_changes_thread.start(_check_for_changes_poll_thread, this);
#endif

View file

@ -31,7 +31,9 @@
#ifndef ANDROID_EXPORT_PLUGIN_H
#define ANDROID_EXPORT_PLUGIN_H
#ifndef DISABLE_DEPRECATED
#include "godot_plugin_config.h"
#endif // DISABLE_DEPRECATED
#include "core/io/zip_io.h"
#include "core/os/os.h"
@ -81,11 +83,14 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
EditorProgress *ep = nullptr;
};
mutable Vector<PluginConfigAndroid> plugins;
#ifndef DISABLE_DEPRECATED
mutable Vector<PluginConfigAndroid> android_plugins;
mutable SafeFlag android_plugins_changed;
Mutex android_plugins_lock;
#endif // DISABLE_DEPRECATED
String last_plugin_names;
uint64_t last_gradle_build_time = 0;
mutable SafeFlag plugins_changed;
Mutex plugins_lock;
Vector<Device> devices;
SafeFlag devices_changed;
Mutex device_lock;
@ -128,12 +133,14 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
static Vector<ABI> get_abis();
#ifndef DISABLE_DEPRECATED
/// List the gdap files in the directory specified by the p_path parameter.
static Vector<String> list_gdap_files(const String &p_path);
static Vector<PluginConfigAndroid> get_plugins();
static Vector<PluginConfigAndroid> get_enabled_plugins(const Ref<EditorExportPreset> &p_presets);
#endif // DISABLE_DEPRECATED
static Error store_in_apk(APKExportData *ed, const String &p_path, const Vector<uint8_t> &p_data, int compression_method = Z_DEFLATED);
@ -224,28 +231,11 @@ public:
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
inline bool is_clean_build_required(Vector<PluginConfigAndroid> enabled_plugins) {
String plugin_names = PluginConfigAndroid::get_plugins_names(enabled_plugins);
bool first_build = last_gradle_build_time == 0;
bool have_plugins_changed = false;
String _get_plugins_names(const Ref<EditorExportPreset> &p_preset) const;
if (!first_build) {
have_plugins_changed = plugin_names != last_plugin_names;
if (!have_plugins_changed) {
for (int i = 0; i < enabled_plugins.size(); i++) {
if (enabled_plugins.get(i).last_updated > last_gradle_build_time) {
have_plugins_changed = true;
break;
}
}
}
}
String _resolve_export_plugin_android_library_path(const String &p_android_library_path) const;
last_gradle_build_time = OS::get_singleton()->get_unix_time();
last_plugin_names = plugin_names;
return have_plugins_changed || first_build;
}
bool _is_clean_build_required(const Ref<EditorExportPreset> &p_preset);
String get_apk_expansion_fullpath(const Ref<EditorExportPreset> &p_preset, const String &p_path);

View file

@ -30,6 +30,8 @@
#include "godot_plugin_config.h"
#ifndef DISABLE_DEPRECATED
/*
* Set of prebuilt plugins.
* Currently unused, this is just for future reference:
@ -145,10 +147,8 @@ PluginConfigAndroid PluginConfigAndroid::load_plugin_config(Ref<ConfigFile> conf
return plugin_config;
}
String PluginConfigAndroid::get_plugins_binaries(String binary_type, Vector<PluginConfigAndroid> plugins_configs) {
String plugins_binaries;
void PluginConfigAndroid::get_plugins_binaries(String binary_type, Vector<PluginConfigAndroid> plugins_configs, Vector<String> &r_result) {
if (!plugins_configs.is_empty()) {
Vector<String> binaries;
for (int i = 0; i < plugins_configs.size(); i++) {
PluginConfigAndroid config = plugins_configs[i];
if (!config.valid_config) {
@ -156,56 +156,44 @@ String PluginConfigAndroid::get_plugins_binaries(String binary_type, Vector<Plug
}
if (config.binary_type == binary_type) {
binaries.push_back(config.binary);
r_result.push_back(config.binary);
}
if (binary_type == PluginConfigAndroid::BINARY_TYPE_LOCAL) {
binaries.append_array(config.local_dependencies);
r_result.append_array(config.local_dependencies);
}
if (binary_type == PluginConfigAndroid::BINARY_TYPE_REMOTE) {
binaries.append_array(config.remote_dependencies);
r_result.append_array(config.remote_dependencies);
}
}
plugins_binaries = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(binaries);
}
return plugins_binaries;
}
String PluginConfigAndroid::get_plugins_custom_maven_repos(Vector<PluginConfigAndroid> plugins_configs) {
String custom_maven_repos;
void PluginConfigAndroid::get_plugins_custom_maven_repos(Vector<PluginConfigAndroid> plugins_configs, Vector<String> &r_result) {
if (!plugins_configs.is_empty()) {
Vector<String> repos_urls;
for (int i = 0; i < plugins_configs.size(); i++) {
PluginConfigAndroid config = plugins_configs[i];
if (!config.valid_config) {
continue;
}
repos_urls.append_array(config.custom_maven_repos);
r_result.append_array(config.custom_maven_repos);
}
custom_maven_repos = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(repos_urls);
}
return custom_maven_repos;
}
String PluginConfigAndroid::get_plugins_names(Vector<PluginConfigAndroid> plugins_configs) {
String plugins_names;
void PluginConfigAndroid::get_plugins_names(Vector<PluginConfigAndroid> plugins_configs, Vector<String> &r_result) {
if (!plugins_configs.is_empty()) {
Vector<String> names;
for (int i = 0; i < plugins_configs.size(); i++) {
PluginConfigAndroid config = plugins_configs[i];
if (!config.valid_config) {
continue;
}
names.push_back(config.name);
r_result.push_back(config.name);
}
plugins_names = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(names);
}
return plugins_names;
}
#endif // DISABLE_DEPRECATED

View file

@ -31,6 +31,8 @@
#ifndef ANDROID_GODOT_PLUGIN_CONFIG_H
#define ANDROID_GODOT_PLUGIN_CONFIG_H
#ifndef DISABLE_DEPRECATED
#include "core/config/project_settings.h"
#include "core/error/error_list.h"
#include "core/io/config_file.h"
@ -67,8 +69,6 @@ struct PluginConfigAndroid {
inline static const char *BINARY_TYPE_LOCAL = "local";
inline static const char *BINARY_TYPE_REMOTE = "remote";
inline static const char *PLUGIN_VALUE_SEPARATOR = "|";
// Set to true when the config file is properly loaded.
bool valid_config = false;
// Unix timestamp of last change to this plugin.
@ -96,11 +96,13 @@ struct PluginConfigAndroid {
static PluginConfigAndroid load_plugin_config(Ref<ConfigFile> config_file, const String &path);
static String get_plugins_binaries(String binary_type, Vector<PluginConfigAndroid> plugins_configs);
static void get_plugins_binaries(String binary_type, Vector<PluginConfigAndroid> plugins_configs, Vector<String> &r_result);
static String get_plugins_custom_maven_repos(Vector<PluginConfigAndroid> plugins_configs);
static void get_plugins_custom_maven_repos(Vector<PluginConfigAndroid> plugins_configs, Vector<String> &r_result);
static String get_plugins_names(Vector<PluginConfigAndroid> plugins_configs);
static void get_plugins_names(Vector<PluginConfigAndroid> plugins_configs, Vector<String> &r_result);
};
#endif // DISABLE_DEPRECATED
#endif // ANDROID_GODOT_PLUGIN_CONFIG_H

View file

@ -254,7 +254,7 @@ String _get_screen_sizes_tag(const Ref<EditorExportPreset> &p_preset) {
return manifest_screen_sizes;
}
String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses_vulkan) {
String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset) {
String manifest_xr_features;
int xr_mode_index = (int)(p_preset->get("xr_features/xr_mode"));
bool uses_xr = xr_mode_index == XR_MODE_OPENXR;
@ -273,15 +273,10 @@ String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses
manifest_xr_features += " <uses-feature tools:node=\"replace\" android:name=\"com.oculus.feature.PASSTHROUGH\" android:required=\"true\" />\n";
}
}
if (p_uses_vulkan) {
manifest_xr_features += " <uses-feature tools:node=\"replace\" android:name=\"android.hardware.vulkan.level\" android:required=\"false\" android:version=\"1\" />\n";
manifest_xr_features += " <uses-feature tools:node=\"replace\" android:name=\"android.hardware.vulkan.version\" android:required=\"true\" android:version=\"0x400003\" />\n";
}
return manifest_xr_features;
}
String _get_activity_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses_xr) {
String _get_activity_tag(const Ref<EditorExportPlatform> &p_export_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug) {
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\" "
@ -298,7 +293,9 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses_xr
" <action android:name=\"android.intent.action.MAIN\" />\n"
" <category android:name=\"android.intent.category.LAUNCHER\" />\n";
if (p_uses_xr) {
int xr_mode_index = (int)(p_preset->get("xr_features/xr_mode"));
bool uses_xr = xr_mode_index == XR_MODE_OPENXR;
if (uses_xr) {
manifest_activity_text += "\n"
" <!-- Enable access to OpenXR on Oculus mobile devices, no-op on other Android\n"
" platforms. -->\n"
@ -323,12 +320,24 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses_xr
manifest_activity_text += " <category android:name=\"android.intent.category.DEFAULT\" />\n";
}
manifest_activity_text += " </intent-filter>\n"
" </activity>\n";
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";
return manifest_activity_text;
}
String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_read_write_storage_permission) {
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) {
int app_category_index = (int)(p_preset->get("package/app_category"));
bool is_game = app_category_index == APP_CATEGORY_GAME;
@ -362,7 +371,19 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_
manifest_application_text += " <meta-data tools:node=\"replace\" android:name=\"com.oculus.handtracking.version\" android:value=\"V2.0\" />\n";
}
}
manifest_application_text += _get_activity_tag(p_preset, uses_xr);
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);
manifest_application_text += " </application>\n";
return manifest_application_text;
}

View file

@ -116,10 +116,10 @@ String _get_gles_tag();
String _get_screen_sizes_tag(const Ref<EditorExportPreset> &p_preset);
String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses_vulkan);
String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset);
String _get_activity_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses_xr);
String _get_activity_tag(const Ref<EditorExportPlatform> &p_export_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug);
String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_read_write_storage_permission);
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);
#endif // ANDROID_GRADLE_EXPORT_UTIL_H