Android: Refactor Custom Build options in export preset
Instead of reusing the custom_template/ prefix which is actually only used for the prebuilt APK workflow, we add a new custom_build/ prefix. This is a slight compat breakage (users will have to redo their config) but enables us to group the Min SDK and Target SDK options where they make sense, and avoid reusing the previously hardcoded Target SDK 30 from Godot 3.4. Those two options are now strings instead of integers so that we can keep them empty by default, and show their default value using a placeholder. So some validation has been added to make sure they are proper ints. The upper bound on Target SDK was also removed as it's a common use case to use it to try to target newer released SDKs. But we warn the user that this wasn't validated by us. The export info dialog is now exclusive so that when it doesn't auto-close, i.e. when it errors, you don't close it by mistake by clicking outside. Fixes #62465.
This commit is contained in:
parent
4b225acc58
commit
ef4a5cd10b
1 changed files with 66 additions and 28 deletions
|
@ -246,7 +246,6 @@ static const char *AAB_ASSETS_DIRECTORY = "res://android/build/assetPacks/instal
|
|||
|
||||
static const int DEFAULT_MIN_SDK_VERSION = 19; // Should match the value in 'platform/android/java/app/config.gradle#minSdk'
|
||||
static const int DEFAULT_TARGET_SDK_VERSION = 31; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk'
|
||||
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 = static_cast<EditorExportPlatformAndroid *>(ud);
|
||||
|
@ -1682,8 +1681,13 @@ void EditorExportPlatformAndroid::get_preset_features(const Ref<EditorExportPres
|
|||
void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_options) {
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_template/use_custom_build"), false));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "custom_template/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK));
|
||||
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_build/use_custom_build"), false));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "custom_build/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK));
|
||||
// Using String instead of int to default to an empty string (no override) with placeholder for instructions (see GH-62465).
|
||||
// This implies doing validation that the string is a proper int.
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_MIN_SDK_VERSION)), ""));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_build/target_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_TARGET_SDK_VERSION)), ""));
|
||||
|
||||
Vector<PluginConfigAndroid> plugins_configs = get_plugins();
|
||||
for (int i = 0; i < plugins_configs.size(); i++) {
|
||||
|
@ -1710,8 +1714,6 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
|
|||
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name"), "1.0"));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/min_sdk", PROPERTY_HINT_RANGE, SDK_VERSION_RANGE), DEFAULT_MIN_SDK_VERSION));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/target_sdk", PROPERTY_HINT_RANGE, SDK_VERSION_RANGE), DEFAULT_TARGET_SDK_VERSION));
|
||||
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "org.godotengine.$genname"));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name [default if blank]"), ""));
|
||||
|
@ -2039,7 +2041,7 @@ String EditorExportPlatformAndroid::get_apksigner_path() {
|
|||
bool EditorExportPlatformAndroid::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
|
||||
String err;
|
||||
bool valid = false;
|
||||
const bool custom_build_enabled = p_preset->get("custom_template/use_custom_build");
|
||||
const bool custom_build_enabled = p_preset->get("custom_build/use_custom_build");
|
||||
|
||||
// Look for export templates (first official, and if defined custom templates).
|
||||
|
||||
|
@ -2201,43 +2203,73 @@ bool EditorExportPlatformAndroid::can_export(const Ref<EditorExportPreset> &p_pr
|
|||
if (xr_mode_index != XR_MODE_OPENXR) {
|
||||
if (hand_tracking > XR_HAND_TRACKING_NONE) {
|
||||
valid = false;
|
||||
err += TTR("\"Hand Tracking\" is only valid when \"Xr Mode\" is \"OpenXR\".");
|
||||
err += TTR("\"Hand Tracking\" is only valid when \"XR Mode\" is \"OpenXR\".");
|
||||
err += "\n";
|
||||
}
|
||||
|
||||
if (passthrough_mode > XR_PASSTHROUGH_NONE) {
|
||||
valid = false;
|
||||
err += TTR("\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\".");
|
||||
err += TTR("\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\".");
|
||||
err += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (int(p_preset->get("custom_template/export_format")) == EXPORT_FORMAT_AAB &&
|
||||
if (int(p_preset->get("custom_build/export_format")) == EXPORT_FORMAT_AAB &&
|
||||
!custom_build_enabled) {
|
||||
valid = false;
|
||||
err += TTR("\"Export AAB\" is only valid when \"Use Custom Build\" is enabled.");
|
||||
err += "\n";
|
||||
}
|
||||
|
||||
// Check the min sdk version
|
||||
int min_sdk_version = p_preset->get("version/min_sdk");
|
||||
if (min_sdk_version != DEFAULT_MIN_SDK_VERSION && !custom_build_enabled) {
|
||||
valid = false;
|
||||
err += TTR("Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled.");
|
||||
err += "\n";
|
||||
// Check the min sdk version.
|
||||
String min_sdk_str = p_preset->get("custom_build/min_sdk");
|
||||
int min_sdk_int = DEFAULT_MIN_SDK_VERSION;
|
||||
if (!min_sdk_str.is_empty()) { // Empty means no override, nothing to do.
|
||||
if (!custom_build_enabled) {
|
||||
valid = false;
|
||||
err += TTR("\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled.");
|
||||
err += "\n";
|
||||
}
|
||||
if (!min_sdk_str.is_valid_int()) {
|
||||
valid = false;
|
||||
err += vformat(TTR("\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."), min_sdk_str);
|
||||
err += "\n";
|
||||
} else {
|
||||
min_sdk_int = min_sdk_str.to_int();
|
||||
if (min_sdk_int < DEFAULT_MIN_SDK_VERSION) {
|
||||
valid = false;
|
||||
err += vformat(TTR("\"Min SDK\" cannot be lower than %d, which is the version needed by the Godot library."), DEFAULT_MIN_SDK_VERSION);
|
||||
err += "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check the target sdk version
|
||||
int target_sdk_version = p_preset->get("version/target_sdk");
|
||||
if (target_sdk_version != DEFAULT_TARGET_SDK_VERSION && !custom_build_enabled) {
|
||||
valid = false;
|
||||
err += TTR("Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is enabled.");
|
||||
err += "\n";
|
||||
// Check the target sdk version.
|
||||
String target_sdk_str = p_preset->get("custom_build/target_sdk");
|
||||
int target_sdk_int = DEFAULT_TARGET_SDK_VERSION;
|
||||
if (!target_sdk_str.is_empty()) { // Empty means no override, nothing to do.
|
||||
if (!custom_build_enabled) {
|
||||
valid = false;
|
||||
err += TTR("\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled.");
|
||||
err += "\n";
|
||||
}
|
||||
if (!target_sdk_str.is_valid_int()) {
|
||||
valid = false;
|
||||
err += vformat(TTR("\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."), target_sdk_str);
|
||||
err += "\n";
|
||||
} else {
|
||||
target_sdk_int = target_sdk_str.to_int();
|
||||
if (target_sdk_int > DEFAULT_TARGET_SDK_VERSION) {
|
||||
// Warning only, so don't override `valid`.
|
||||
err += vformat(TTR("\"Target SDK\" %d is higher than the default version %d. This may work, but wasn't tested and may be unstable."), target_sdk_int, DEFAULT_TARGET_SDK_VERSION);
|
||||
err += "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (target_sdk_version < min_sdk_version) {
|
||||
if (target_sdk_int < min_sdk_int) {
|
||||
valid = false;
|
||||
err += TTR("\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version.");
|
||||
err += TTR("\"Target SDK\" version must be greater or equal to \"Min SDK\" version.");
|
||||
err += "\n";
|
||||
}
|
||||
|
||||
|
@ -2326,7 +2358,7 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP
|
|||
}
|
||||
|
||||
Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &export_path, EditorProgress &ep) {
|
||||
int export_format = int(p_preset->get("custom_template/export_format"));
|
||||
int export_format = int(p_preset->get("custom_build/export_format"));
|
||||
String export_label = export_format == EXPORT_FORMAT_AAB ? "AAB" : "APK";
|
||||
String release_keystore = p_preset->get("keystore/release");
|
||||
String release_username = p_preset->get("keystore/release_user");
|
||||
|
@ -2482,7 +2514,7 @@ String EditorExportPlatformAndroid::join_list(List<String> parts, const String &
|
|||
}
|
||||
|
||||
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("custom_template/export_format"));
|
||||
int export_format = int(p_preset->get("custom_build/export_format"));
|
||||
bool should_sign = p_preset->get("package/signed");
|
||||
return export_project_helper(p_preset, p_debug, p_path, export_format, should_sign, p_flags);
|
||||
}
|
||||
|
@ -2495,7 +2527,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
|
|||
|
||||
EditorProgress ep("export", TTR("Exporting for Android"), 105, true);
|
||||
|
||||
bool use_custom_build = bool(p_preset->get("custom_template/use_custom_build"));
|
||||
bool use_custom_build = bool(p_preset->get("custom_build/use_custom_build"));
|
||||
bool p_give_internet = p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG);
|
||||
bool apk_expansion = p_preset->get("apk_expansion/enable");
|
||||
Vector<String> enabled_abis = get_enabled_abis(p_preset);
|
||||
|
@ -2623,8 +2655,14 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
|
|||
String package_name = get_package_name(p_preset->get("package/unique_name"));
|
||||
String version_code = itos(p_preset->get("version/code"));
|
||||
String version_name = p_preset->get("version/name");
|
||||
String min_sdk_version = itos(p_preset->get("version/min_sdk"));
|
||||
String target_sdk_version = itos(p_preset->get("version/target_sdk"));
|
||||
String min_sdk_version = p_preset->get("custom_build/min_sdk");
|
||||
if (!min_sdk_version.is_valid_int()) {
|
||||
min_sdk_version = itos(DEFAULT_MIN_SDK_VERSION);
|
||||
}
|
||||
String target_sdk_version = p_preset->get("custom_build/target_sdk");
|
||||
if (!target_sdk_version.is_valid_int()) {
|
||||
target_sdk_version = itos(DEFAULT_TARGET_SDK_VERSION);
|
||||
}
|
||||
String enabled_abi_string = String("|").join(enabled_abis);
|
||||
String sign_flag = should_sign ? "true" : "false";
|
||||
String zipalign_flag = "true";
|
||||
|
|
Loading…
Reference in a new issue