summaryrefslogtreecommitdiffstats
path: root/platform/android/export/export_plugin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android/export/export_plugin.cpp')
-rw-r--r--platform/android/export/export_plugin.cpp155
1 files changed, 91 insertions, 64 deletions
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 70b36f2350..d357cd586e 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,6 +30,26 @@
#include "export_plugin.h"
+#include "gradle_export_util.h"
+
+#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
+#include "core/io/image_loader.h"
+#include "core/io/json.h"
+#include "core/io/marshalls.h"
+#include "core/version.h"
+#include "drivers/png/png_driver_common.h"
+#include "editor/editor_log.h"
+#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
+#include "editor/editor_settings.h"
+#include "main/splash.gen.h"
+#include "platform/android/logo.gen.h"
+#include "platform/android/run_icon.gen.h"
+
+#include <string.h>
+
static const char *android_perms[] = {
"ACCESS_CHECKIN_PROPERTIES",
"ACCESS_COARSE_LOCATION",
@@ -229,7 +249,7 @@ static const int DEFAULT_TARGET_SDK_VERSION = 30; // Should match the value in '
const String SDK_VERSION_RANGE = vformat("%s,%s,1", DEFAULT_MIN_SDK_VERSION, DEFAULT_TARGET_SDK_VERSION);
void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) {
- EditorExportPlatformAndroid *ea = (EditorExportPlatformAndroid *)ud;
+ EditorExportPlatformAndroid *ea = static_cast<EditorExportPlatformAndroid *>(ud);
while (!ea->quit_request.is_set()) {
// Check for plugins updates
@@ -416,10 +436,10 @@ String EditorExportPlatformAndroid::get_package_name(const String &p_package) co
bool first = true;
for (int i = 0; i < basename.length(); i++) {
char32_t c = basename[i];
- if (c >= '0' && c <= '9' && first) {
+ if (is_digit(c) && first) {
continue;
}
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) {
+ if (is_ascii_alphanumeric_char(c)) {
name += String::chr(c);
first = false;
}
@@ -462,19 +482,19 @@ bool EditorExportPlatformAndroid::is_package_name_valid(const String &p_package,
first = true;
continue;
}
- if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_')) {
+ if (!is_ascii_identifier_char(c)) {
if (r_error) {
*r_error = vformat(TTR("The character '%s' is not allowed in Android application package names."), String::chr(c));
}
return false;
}
- if (first && (c >= '0' && c <= '9')) {
+ if (first && is_digit(c)) {
if (r_error) {
*r_error = TTR("A digit cannot be the first character in a package segment.");
}
return false;
}
- if (first && c == '_') {
+ if (first && is_underscore(c)) {
if (r_error) {
*r_error = vformat(TTR("The character '%s' cannot be the first character in a package segment."), String::chr(c));
}
@@ -523,7 +543,7 @@ bool EditorExportPlatformAndroid::_should_compress_asset(const String &p_path, c
".webp", // Same reasoning as .png
".cfb", // Don't let small config files slow-down startup
".scn", // Binary scenes are usually already compressed
- ".stex", // Streamable textures are usually already compressed
+ ".ctex", // Streamable textures are usually already compressed
// Trailer for easier processing
nullptr
};
@@ -576,8 +596,8 @@ Vector<String> EditorExportPlatformAndroid::get_abis() {
/// 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;
- DirAccessRef da = DirAccess::open(p_path);
- if (da) {
+ Ref<DirAccess> da = DirAccess::open(p_path);
+ if (da.is_valid()) {
da->list_dir_begin();
while (true) {
String file = da->get_next();
@@ -665,7 +685,7 @@ Error EditorExportPlatformAndroid::save_apk_so(void *p_userdata, const SharedObj
ERR_PRINT(err);
return FAILED;
}
- APKExportData *ed = (APKExportData *)p_userdata;
+ APKExportData *ed = static_cast<APKExportData *>(p_userdata);
Vector<String> abis = get_abis();
bool exported = false;
for (int i = 0; i < p_so.tags.size(); ++i) {
@@ -690,7 +710,7 @@ Error EditorExportPlatformAndroid::save_apk_so(void *p_userdata, const SharedObj
}
Error EditorExportPlatformAndroid::save_apk_file(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) {
- APKExportData *ed = (APKExportData *)p_userdata;
+ APKExportData *ed = static_cast<APKExportData *>(p_userdata);
String dst_path = p_path.replace_first("res://", "assets/");
store_in_apk(ed, dst_path, p_data, _should_compress_asset(p_path, p_data) ? Z_DEFLATED : 0);
@@ -705,7 +725,7 @@ Error EditorExportPlatformAndroid::copy_gradle_so(void *p_userdata, const Shared
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;
+ CustomExportData *export_data = static_cast<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]);
@@ -843,6 +863,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
bool classify_as_game = p_preset->get("package/classify_as_game");
bool retain_data_on_uninstall = p_preset->get("package/retain_data_on_uninstall");
bool exclude_from_recents = p_preset->get("package/exclude_from_recents");
+ bool is_resizeable = bool(GLOBAL_GET("display/window/size/resizable"));
Vector<String> perms;
// Write permissions into the perms variable.
@@ -960,6 +981,10 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
encode_uint32(exclude_from_recents, &p_manifest.write[iofs + 16]);
}
+ if (tname == "activity" && attrname == "resizeableActivity") {
+ encode_uint32(is_resizeable, &p_manifest.write[iofs + 16]);
+ }
+
if (tname == "supports-screens") {
if (attrname == "smallScreens") {
encode_uint32(screen_support_small ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]);
@@ -975,29 +1000,22 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
}
}
- if (tname == "meta-data" && attrname == "name" && value == "xr_mode_metadata_name") {
- // Update the meta-data 'android:name' attribute based on the selected XR mode.
- if (xr_mode_index == XR_MODE_OPENXR) {
- string_table.write[attr_value] = "com.samsung.android.vr.application.mode";
+ // Hand tracking related configurations
+ if (xr_mode_index == XR_MODE_OPENXR && hand_tracking_index > XR_HAND_TRACKING_NONE) {
+ if (tname == "meta-data" && attrname == "name" && value == "xr_hand_tracking_metadata_name") {
+ string_table.write[attr_value] = "com.oculus.handtracking.frequency";
}
- }
- if (tname == "meta-data" && attrname == "value" && value == "xr_mode_metadata_value") {
- // Update the meta-data 'android:value' attribute based on the selected XR mode.
- if (xr_mode_index == XR_MODE_OPENXR) {
- string_table.write[attr_value] = "vr_only";
+ if (tname == "meta-data" && attrname == "value" && value == "xr_hand_tracking_metadata_value") {
+ string_table.write[attr_value] = (hand_tracking_frequency_index == XR_HAND_TRACKING_FREQUENCY_LOW ? "LOW" : "HIGH");
}
- }
- if (tname == "meta-data" && attrname == "name" && value == "xr_hand_tracking_metadata_name") {
- if (xr_mode_index == XR_MODE_OPENXR && hand_tracking_index > XR_HAND_TRACKING_NONE) {
- string_table.write[attr_value] = "com.oculus.handtracking.frequency";
+ if (tname == "meta-data" && attrname == "name" && value == "xr_hand_tracking_version_name") {
+ string_table.write[attr_value] = "com.oculus.handtracking.version";
}
- }
- if (tname == "meta-data" && attrname == "value" && value == "xr_hand_tracking_metadata_value") {
- if (xr_mode_index == XR_MODE_OPENXR && hand_tracking_index > XR_HAND_TRACKING_NONE) {
- string_table.write[attr_value] = (hand_tracking_frequency_index == XR_HAND_TRACKING_FREQUENCY_LOW ? "LOW" : "HIGH");
+ if (tname == "meta-data" && attrname == "name" && value == "xr_hand_tracking_version_value") {
+ string_table.write[attr_value] = "V2.0";
}
}
@@ -1381,6 +1399,7 @@ void EditorExportPlatformAndroid::_fix_resources(const Ref<EditorExportPreset> &
Vector<String> string_table;
String package_name = p_preset->get("package/name");
+ Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
for (uint32_t i = 0; i < string_count; i++) {
uint32_t offset = decode_uint32(&r_manifest[string_table_begins + i * 4]);
@@ -1395,9 +1414,8 @@ void EditorExportPlatformAndroid::_fix_resources(const Ref<EditorExportPreset> &
} else {
String lang = str.substr(str.rfind("-") + 1, str.length()).replace("-", "_");
- String prop = "application/config/name_" + lang;
- if (ProjectSettings::get_singleton()->has_setting(prop)) {
- str = ProjectSettings::get_singleton()->get(prop);
+ if (appnames.has(lang)) {
+ str = appnames[lang];
} else {
str = get_project_name(package_name);
}
@@ -1514,7 +1532,7 @@ String EditorExportPlatformAndroid::load_splash_refs(Ref<Image> &splash_image, R
}
if (scale_splash) {
- Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
+ Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/viewport_width"), ProjectSettings::get_singleton()->get("display/window/size/viewport_height"));
int width, height;
if (screen_size.width > screen_size.height) {
// scale horizontally
@@ -1997,7 +2015,7 @@ String EditorExportPlatformAndroid::get_apksigner_path() {
Error errn;
String build_tools_dir = sdk_path.plus_file("build-tools");
- DirAccessRef da = DirAccess::open(build_tools_dir, &errn);
+ Ref<DirAccess> da = DirAccess::open(build_tools_dir, &errn);
if (errn != OK) {
print_error("Unable to open Android 'build-tools' directory.");
return apksigner_path;
@@ -2114,7 +2132,7 @@ bool EditorExportPlatformAndroid::can_export(const Ref<EditorExportPreset> &p_pr
} else {
Error errn;
// Check for the platform-tools directory.
- DirAccessRef da = DirAccess::open(sdk_path.plus_file("platform-tools"), &errn);
+ Ref<DirAccess> da = DirAccess::open(sdk_path.plus_file("platform-tools"), &errn);
if (errn != OK) {
err += TTR("Invalid Android SDK path in Editor Settings.");
err += TTR("Missing 'platform-tools' directory!");
@@ -2132,7 +2150,7 @@ bool EditorExportPlatformAndroid::can_export(const Ref<EditorExportPreset> &p_pr
}
// Check for the build-tools directory.
- DirAccessRef build_tools_da = DirAccess::open(sdk_path.plus_file("build-tools"), &errn);
+ Ref<DirAccess> build_tools_da = DirAccess::open(sdk_path.plus_file("build-tools"), &errn);
if (errn != OK) {
err += TTR("Invalid Android SDK path in Editor Settings.");
err += TTR("Missing 'build-tools' directory!");
@@ -2250,9 +2268,9 @@ String EditorExportPlatformAndroid::get_apk_expansion_fullpath(const Ref<EditorE
return fullpath;
}
-Error EditorExportPlatformAndroid::save_apk_expansion_file(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
+Error EditorExportPlatformAndroid::save_apk_expansion_file(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) {
String fullpath = get_apk_expansion_fullpath(p_preset, p_path);
- Error err = save_pack(p_preset, fullpath);
+ Error err = save_pack(p_preset, p_debug, fullpath);
return err;
}
@@ -2411,12 +2429,12 @@ Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_pre
}
void EditorExportPlatformAndroid::_clear_assets_directory() {
- DirAccessRef da_res = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da_res = DirAccess::create(DirAccess::ACCESS_RESOURCES);
// Clear the APK assets directory
if (da_res->dir_exists(APK_ASSETS_DIRECTORY)) {
print_verbose("Clearing APK assets directory..");
- DirAccessRef da_assets = DirAccess::open(APK_ASSETS_DIRECTORY);
+ Ref<DirAccess> da_assets = DirAccess::open(APK_ASSETS_DIRECTORY);
da_assets->erase_contents_recursive();
da_res->remove(APK_ASSETS_DIRECTORY);
}
@@ -2424,7 +2442,7 @@ void EditorExportPlatformAndroid::_clear_assets_directory() {
// Clear the AAB assets directory
if (da_res->dir_exists(AAB_ASSETS_DIRECTORY)) {
print_verbose("Clearing AAB assets directory..");
- DirAccessRef da_assets = DirAccess::open(AAB_ASSETS_DIRECTORY);
+ Ref<DirAccess> da_assets = DirAccess::open(AAB_ASSETS_DIRECTORY);
da_assets->erase_contents_recursive();
da_res->remove(AAB_ASSETS_DIRECTORY);
}
@@ -2444,7 +2462,7 @@ void EditorExportPlatformAndroid::_remove_copied_libs() {
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);
+ Ref<DirAccess> 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]);
@@ -2533,14 +2551,13 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
//test that installed build version is alright
{
print_verbose("Checking build version..");
- FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open("res://android/.build_version", FileAccess::READ);
+ if (f.is_null()) {
EditorNode::get_singleton()->show_warning(TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu."));
return ERR_UNCONFIGURED;
}
String version = f->get_line().strip_edges();
print_verbose("- build version: " + version);
- f->close();
if (version != VERSION_FULL_CONFIG) {
EditorNode::get_singleton()->show_warning(vformat(TTR("Android build version mismatch:\n Template installed: %s\n Godot Version: %s\nPlease reinstall Android build template from 'Project' menu."), version, VERSION_FULL_CONFIG));
return ERR_UNCONFIGURED;
@@ -2570,20 +2587,19 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
CustomExportData user_data;
user_data.assets_directory = assets_directory;
user_data.debug = p_debug;
- err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so);
+ err = export_project_files(p_preset, p_debug, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so);
if (err != OK) {
EditorNode::add_io_error(TTR("Could not export project files to gradle project\n"));
return err;
}
if (user_data.libs.size() > 0) {
- FileAccessRef fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE);
+ Ref<FileAccess> fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE);
JSON json;
fa->store_string(json.stringify(user_data.libs, "\t"));
- fa->close();
}
} else {
print_verbose("Saving apk expansion file..");
- err = save_apk_expansion_file(p_preset, p_path);
+ err = save_apk_expansion_file(p_preset, p_debug, p_path);
if (err != OK) {
EditorNode::add_io_error(TTR("Could not write expansion package file!"));
return err;
@@ -2666,6 +2682,13 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
debug_password = EditorSettings::get_singleton()->get("export/android/debug_keystore_pass");
debug_user = EditorSettings::get_singleton()->get("export/android/debug_keystore_user");
}
+ if (debug_keystore.is_relative_path()) {
+ debug_keystore = OS::get_singleton()->get_resource_dir().plus_file(debug_keystore).simplify_path();
+ }
+ if (!FileAccess::exists(debug_keystore)) {
+ EditorNode::add_io_error(TTR("Could not find keystore, unable to export."));
+ return ERR_FILE_CANT_OPEN;
+ }
cmdline.push_back("-Pdebug_keystore_file=" + debug_keystore); // argument to specify the debug keystore file.
cmdline.push_back("-Pdebug_keystore_alias=" + debug_user); // argument to specify the debug keystore alias.
@@ -2675,6 +2698,9 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
String release_keystore = p_preset->get("keystore/release");
String release_username = p_preset->get("keystore/release_user");
String release_password = p_preset->get("keystore/release_password");
+ if (release_keystore.is_relative_path()) {
+ release_keystore = OS::get_singleton()->get_resource_dir().plus_file(release_keystore).simplify_path();
+ }
if (!FileAccess::exists(release_keystore)) {
EditorNode::add_io_error(TTR("Could not find keystore, unable to export."));
return ERR_FILE_CANT_OPEN;
@@ -2749,8 +2775,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
return ERR_FILE_BAD_PATH;
}
- FileAccess *src_f = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
if (ep.step(TTR("Creating APK..."), 0)) {
return ERR_SKIP;
@@ -2764,9 +2789,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
int ret = unzGoToFirstFile(pkg);
- zlib_filefunc_def io2 = io;
- FileAccess *dst_f = nullptr;
- io2.opaque = &dst_f;
+ zlib_filefunc_def io2 = zipio_create_io();
String tmp_unaligned_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpexport-unaligned." + uitos(OS::get_singleton()->get_unix_time()) + ".apk");
@@ -2791,10 +2814,13 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
unz_file_info info;
char fname[16384];
ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
+ if (ret != UNZ_OK) {
+ break;
+ }
bool skip = false;
- String file = fname;
+ String file = String::utf8(fname);
Vector<uint8_t> data;
data.resize(info.uncompressed_size);
@@ -2899,10 +2925,10 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
APKExportData ed;
ed.ep = &ep;
ed.apk = unaligned_apk;
- err = export_project_files(p_preset, ignore_apk_file, &ed, save_apk_so);
+ err = export_project_files(p_preset, p_debug, ignore_apk_file, &ed, save_apk_so);
} else {
if (apk_expansion) {
- err = save_apk_expansion_file(p_preset, p_path);
+ err = save_apk_expansion_file(p_preset, p_debug, p_path);
if (err != OK) {
EditorNode::add_io_error(TTR("Could not write expansion package file!"));
return err;
@@ -2911,7 +2937,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
APKExportData ed;
ed.ep = &ep;
ed.apk = unaligned_apk;
- err = export_project_files(p_preset, save_apk_file, &ed, save_apk_so);
+ err = export_project_files(p_preset, p_debug, save_apk_file, &ed, save_apk_so);
}
}
@@ -2959,9 +2985,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
ret = unzGoToFirstFile(tmp_unaligned);
- io2 = io;
- dst_f = nullptr;
- io2.opaque = &dst_f;
+ io2 = zipio_create_io();
zipFile final_apk = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io2);
// Take files from the unaligned APK and write them out to the aligned one
@@ -2975,8 +2999,11 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
char fname[16384];
char extra[16384];
ret = unzGetCurrentFileInfo(tmp_unaligned, &info, fname, 16384, extra, 16384 - ZIP_ALIGNMENT, nullptr, 0);
+ if (ret != UNZ_OK) {
+ break;
+ }
- String file = fname;
+ String file = String::utf8(fname);
Vector<uint8_t> data;
data.resize(info.compressed_size);