mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-03 23:21:15 +00:00 
			
		
		
		
	Add GDNative libraries to Android custom Gradle builds
This commit is contained in:
		
							parent
							
								
									45b66e91e7
								
							
						
					
					
						commit
						7b63f0a22d
					
				
					 2 changed files with 66 additions and 9 deletions
				
			
		| 
						 | 
					@ -34,6 +34,7 @@
 | 
				
			||||||
#include "core/io/dir_access.h"
 | 
					#include "core/io/dir_access.h"
 | 
				
			||||||
#include "core/io/file_access.h"
 | 
					#include "core/io/file_access.h"
 | 
				
			||||||
#include "core/io/image_loader.h"
 | 
					#include "core/io/image_loader.h"
 | 
				
			||||||
 | 
					#include "core/io/json.h"
 | 
				
			||||||
#include "core/io/marshalls.h"
 | 
					#include "core/io/marshalls.h"
 | 
				
			||||||
#include "core/io/zip_io.h"
 | 
					#include "core/io/zip_io.h"
 | 
				
			||||||
#include "core/os/os.h"
 | 
					#include "core/os/os.h"
 | 
				
			||||||
| 
						 | 
					@ -206,6 +207,7 @@ static const char *LEGACY_BUILD_SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi-v
 | 
				
			||||||
static const char *SPLASH_BG_COLOR_PATH = "res/drawable-nodpi/splash_bg_color.png";
 | 
					static const char *SPLASH_BG_COLOR_PATH = "res/drawable-nodpi/splash_bg_color.png";
 | 
				
			||||||
static const char *LEGACY_BUILD_SPLASH_BG_COLOR_PATH = "res/drawable-nodpi-v4/splash_bg_color.png";
 | 
					static const char *LEGACY_BUILD_SPLASH_BG_COLOR_PATH = "res/drawable-nodpi-v4/splash_bg_color.png";
 | 
				
			||||||
static const char *SPLASH_CONFIG_PATH = "res://android/build/res/drawable/splash_drawable.xml";
 | 
					static const char *SPLASH_CONFIG_PATH = "res://android/build/res/drawable/splash_drawable.xml";
 | 
				
			||||||
 | 
					static const char *GDNATIVE_LIBS_PATH = "res://android/build/libs/gdnativelibs.json";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(<?xml version="1.0" encoding="utf-8"?>
 | 
					const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
 | 
					<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
 | 
				
			||||||
| 
						 | 
					@ -277,6 +279,11 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
 | 
				
			||||||
		EditorProgress *ep = nullptr;
 | 
							EditorProgress *ep = nullptr;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct CustomExportData {
 | 
				
			||||||
 | 
							bool debug;
 | 
				
			||||||
 | 
							Vector<String> libs;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Vector<PluginConfigAndroid> plugins;
 | 
						Vector<PluginConfigAndroid> plugins;
 | 
				
			||||||
	String last_plugin_names;
 | 
						String last_plugin_names;
 | 
				
			||||||
	uint64_t last_custom_build_time = 0;
 | 
						uint64_t last_custom_build_time = 0;
 | 
				
			||||||
| 
						 | 
					@ -757,6 +764,33 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
 | 
				
			||||||
		return OK;
 | 
							return OK;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static Error copy_gradle_so(void *p_userdata, const SharedObject &p_so) {
 | 
				
			||||||
 | 
							ERR_FAIL_COND_V_MSG(!p_so.path.get_file().begins_with("lib"), FAILED,
 | 
				
			||||||
 | 
									"Android .so file names must start with \"lib\", but got: " + p_so.path);
 | 
				
			||||||
 | 
							Vector<String> abis = get_abis();
 | 
				
			||||||
 | 
							CustomExportData *export_data = (CustomExportData *)p_userdata;
 | 
				
			||||||
 | 
							bool exported = false;
 | 
				
			||||||
 | 
							for (int i = 0; i < p_so.tags.size(); ++i) {
 | 
				
			||||||
 | 
								int abi_index = abis.find(p_so.tags[i]);
 | 
				
			||||||
 | 
								if (abi_index != -1) {
 | 
				
			||||||
 | 
									exported = true;
 | 
				
			||||||
 | 
									String base = "res://android/build/libs";
 | 
				
			||||||
 | 
									String type = export_data->debug ? "debug" : "release";
 | 
				
			||||||
 | 
									String abi = abis[abi_index];
 | 
				
			||||||
 | 
									String filename = p_so.path.get_file();
 | 
				
			||||||
 | 
									String dst_path = base.plus_file(type).plus_file(abi).plus_file(filename);
 | 
				
			||||||
 | 
									Vector<uint8_t> data = FileAccess::get_file_as_array(p_so.path);
 | 
				
			||||||
 | 
									print_verbose("Copying .so file from " + p_so.path + " to " + dst_path);
 | 
				
			||||||
 | 
									Error err = store_file_at_path(dst_path, data);
 | 
				
			||||||
 | 
									ERR_FAIL_COND_V_MSG(err, err, "Failed to copy .so file from " + p_so.path + " to " + dst_path);
 | 
				
			||||||
 | 
									export_data->libs.push_back(dst_path);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ERR_FAIL_COND_V_MSG(!exported, FAILED,
 | 
				
			||||||
 | 
									"Cannot determine ABI for library \"" + p_so.path + "\". One of the supported ABIs must be used as a tag: " + String(" ").join(abis));
 | 
				
			||||||
 | 
							return OK;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void _get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions) {
 | 
						void _get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions) {
 | 
				
			||||||
		const char **aperms = android_perms;
 | 
							const char **aperms = android_perms;
 | 
				
			||||||
		while (*aperms) {
 | 
							while (*aperms) {
 | 
				
			||||||
| 
						 | 
					@ -2380,6 +2414,28 @@ public:
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void _remove_copied_libs() {
 | 
				
			||||||
 | 
							print_verbose("Removing previously installed libraries...");
 | 
				
			||||||
 | 
							Error error;
 | 
				
			||||||
 | 
							String libs_json = FileAccess::get_file_as_string(GDNATIVE_LIBS_PATH, &error);
 | 
				
			||||||
 | 
							if (error || libs_json.is_empty()) {
 | 
				
			||||||
 | 
								print_verbose("No previously installed libraries found");
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							JSON json;
 | 
				
			||||||
 | 
							error = json.parse(libs_json);
 | 
				
			||||||
 | 
							ERR_FAIL_COND_MSG(error, "Error parsing \"" + libs_json + "\" on line " + itos(json.get_error_line()) + ": " + json.get_error_message());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Vector<String> libs = json.get_data();
 | 
				
			||||||
 | 
							DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 | 
				
			||||||
 | 
							for (int i = 0; i < libs.size(); i++) {
 | 
				
			||||||
 | 
								print_verbose("Removing previously installed library " + libs[i]);
 | 
				
			||||||
 | 
								da->remove(libs[i]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							da->remove(GDNATIVE_LIBS_PATH);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	String join_list(List<String> parts, const String &separator) const {
 | 
						String join_list(List<String> parts, const String &separator) const {
 | 
				
			||||||
		String ret;
 | 
							String ret;
 | 
				
			||||||
		for (int i = 0; i < parts.size(); ++i) {
 | 
							for (int i = 0; i < parts.size(); ++i) {
 | 
				
			||||||
| 
						 | 
					@ -2491,13 +2547,22 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			//stores all the project files inside the Gradle project directory. Also includes all ABIs
 | 
								//stores all the project files inside the Gradle project directory. Also includes all ABIs
 | 
				
			||||||
			_clear_assets_directory();
 | 
								_clear_assets_directory();
 | 
				
			||||||
 | 
								_remove_copied_libs();
 | 
				
			||||||
			if (!apk_expansion) {
 | 
								if (!apk_expansion) {
 | 
				
			||||||
				print_verbose("Exporting project files..");
 | 
									print_verbose("Exporting project files..");
 | 
				
			||||||
				err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, nullptr, ignore_so_file);
 | 
									CustomExportData user_data;
 | 
				
			||||||
 | 
									user_data.debug = p_debug;
 | 
				
			||||||
 | 
									err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so);
 | 
				
			||||||
				if (err != OK) {
 | 
									if (err != OK) {
 | 
				
			||||||
					EditorNode::add_io_error("Could not export project files to gradle project\n");
 | 
										EditorNode::add_io_error("Could not export project files to gradle project\n");
 | 
				
			||||||
					return err;
 | 
										return err;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									if (user_data.libs.size() > 0) {
 | 
				
			||||||
 | 
										FileAccessRef fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE);
 | 
				
			||||||
 | 
										JSON json;
 | 
				
			||||||
 | 
										fa->store_string(json.stringify(user_data.libs, "\t"));
 | 
				
			||||||
 | 
										fa->close();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				print_verbose("Saving apk expansion file..");
 | 
									print_verbose("Saving apk expansion file..");
 | 
				
			||||||
				err = save_apk_expansion_file(p_preset, p_path);
 | 
									err = save_apk_expansion_file(p_preset, p_path);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -96,14 +96,6 @@ Error create_directory(const String &p_dir) {
 | 
				
			||||||
	return OK;
 | 
						return OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Implementation of EditorExportSaveSharedObject.
 | 
					 | 
				
			||||||
// This method will only be called as an input to export_project_files.
 | 
					 | 
				
			||||||
// This method lets the .so files for all ABIs to be copied
 | 
					 | 
				
			||||||
// into the gradle project from the .AAR file
 | 
					 | 
				
			||||||
Error ignore_so_file(void *p_userdata, const SharedObject &p_so) {
 | 
					 | 
				
			||||||
	return OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Writes p_data into a file at p_path, creating directories if necessary.
 | 
					// 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.
 | 
					// 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) {
 | 
					Error store_file_at_path(const String &p_path, const Vector<uint8_t> &p_data) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue