Skip to content

Commit a1e8c10

Browse files
committed
Automate Android SDK setup
1 parent 45a9806 commit a1e8c10

8 files changed

Lines changed: 983 additions & 236 deletions

File tree

editor/export/android_sdk_manager.cpp

Lines changed: 802 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**************************************************************************/
2+
/* android_sdk_manager.h */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#pragma once
32+
33+
#include "scene/gui/dialogs.h"
34+
#include "scene/main/http_request.h"
35+
36+
class Label;
37+
class ProgressBar;
38+
class RichTextLabel;
39+
40+
class AndroidSdkManager : public AcceptDialog {
41+
GDCLASS(AndroidSdkManager, AcceptDialog)
42+
43+
enum SetupStatus {
44+
IDLE,
45+
DOWNLOADING_ANDROID_SDK,
46+
DOWNLOADING_JAVA_SDK,
47+
INSTALLING_ANDROID_SDK,
48+
INSTALLING_JAVA_SDK,
49+
};
50+
51+
void _cancel_setup();
52+
void _on_download_completed(int p_result, int p_code, const PackedStringArray &p_headers, const PackedByteArray &p_body);
53+
54+
void _setup_android_sdk();
55+
void _download_android_cli();
56+
void _android_cli_downloaded(const PackedByteArray &p_body);
57+
void _install_android_sdk_packages();
58+
void _android_sdk_installed(int p_exit_code);
59+
60+
void _setup_java_sdk();
61+
void _download_java_sdk();
62+
void _java_sdk_downloaded(const PackedByteArray &p_body);
63+
Error _extract_java_sdk(const String &p_file, const String &p_target_path);
64+
65+
void _show_setup_dialog(SetupStatus p_status);
66+
void _hide_setup_dialog(SetupStatus p_status);
67+
68+
static String get_android_cli_path();
69+
static bool is_java_sdk_setup(String *r_error = nullptr);
70+
71+
Callable on_setup_completed;
72+
Dictionary setup_process_data;
73+
Label *setup_label = nullptr;
74+
RichTextLabel *execute_outputs = nullptr;
75+
ProgressBar *setup_progress_bar = nullptr;
76+
HTTPRequest *downloader = nullptr;
77+
SetupStatus current_setup_status = IDLE;
78+
79+
protected:
80+
void _notification(int p_what);
81+
static void _bind_methods();
82+
83+
public:
84+
constexpr static const int DEFAULT_MIN_SDK_VERSION = 24; // Should match the value in 'platform/android/java/app/config.gradle#minSdk'
85+
constexpr static const int VULKAN_MIN_SDK_VERSION = 29; // Minimum recommended sdk version for Vulkan 1.1 support. See https://developer.android.com/games/develop/vulkan/native-engine-support#recommendations
86+
constexpr static const int DEFAULT_TARGET_SDK_VERSION = 36; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk'
87+
88+
void run_setup();
89+
90+
/// Returns true if the Android SDK (and its dependencies) are set up.
91+
static bool is_android_sdk_setup(String *r_error = nullptr);
92+
93+
static String get_java_path();
94+
static String get_adb_path();
95+
static String get_apksigner_path(int p_target_sdk = -1, bool p_check_executes = false);
96+
97+
AndroidSdkManager();
98+
~AndroidSdkManager();
99+
};

editor/export/export_template_manager.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@
6262
#include "servers/display/display_server.h"
6363
#include "servers/rendering/rendering_server.h"
6464

65+
#ifndef ANDROID_ENABLED
66+
#include "editor/export/android_sdk_manager.h"
67+
#endif
68+
6569
void ExportTemplateManager::_request_mirrors() {
6670
mirrors_list->clear();
6771
mirrors_empty = true;
@@ -170,6 +174,10 @@ void ExportTemplateManager::_update_online_mode() {
170174
mirrors_list->clear();
171175
_set_empty_mirror_list();
172176
}
177+
178+
#ifndef ANDROID_ENABLED
179+
_update_android_sdk_setup_button();
180+
#endif
173181
}
174182

175183
bool ExportTemplateManager::_is_online() const {
@@ -808,6 +816,13 @@ void ExportTemplateManager::_fill_template_tree(Tree *p_tree, const HashMap<Temp
808816
}
809817
}
810818

819+
#ifndef ANDROID_ENABLED
820+
void ExportTemplateManager::_update_android_sdk_setup_button() {
821+
bool should_be_enabled = _is_online() && !AndroidSdkManager::is_android_sdk_setup();
822+
setup_android_sdk->set_disabled(!should_be_enabled);
823+
}
824+
#endif
825+
811826
void ExportTemplateManager::_update_install_button() {
812827
if (is_downloading()) {
813828
install_button->set_text(TTRC("Downloading templates..."));
@@ -1344,6 +1359,9 @@ void ExportTemplateManager::_notification(int p_what) {
13441359
open_mirror->set_button_icon(get_editor_theme_icon("ExternalLink"));
13451360
delete_all_button->set_button_icon(get_editor_theme_icon("Remove"));
13461361
tpz_button->set_button_icon(get_editor_theme_icon("FileBrowse"));
1362+
#ifndef ANDROID_ENABLED
1363+
setup_android_sdk->set_button_icon(get_editor_theme_icon("AssetStore"));
1364+
#endif
13471365

13481366
offline_mode_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("warning_color"), EditorStringName(Editor)));
13491367

@@ -1377,7 +1395,7 @@ void ExportTemplateManager::_notification(int p_what) {
13771395
}
13781396
progress += indeterminate_count;
13791397
EditorNode::get_bottom_panel()->get_progress_indicator()->set_value(progress / download_count);
1380-
}
1398+
} break;
13811399
}
13821400
}
13831401

@@ -1559,6 +1577,13 @@ ExportTemplateManager::ExportTemplateManager() {
15591577
set_title(TTRC("Export Template Manager"));
15601578
set_ok_button_text(TTRC("Close"));
15611579

1580+
#ifndef ANDROID_ENABLED
1581+
android_sdk_manager = memnew(AndroidSdkManager);
1582+
add_child(android_sdk_manager);
1583+
android_sdk_manager->connect("java_sdk_installed", callable_mp(this, &ExportTemplateManager::_update_android_sdk_setup_button));
1584+
android_sdk_manager->connect("android_sdk_installed", callable_mp(this, &ExportTemplateManager::_update_android_sdk_setup_button));
1585+
#endif
1586+
15621587
VBoxContainer *main_vb = memnew(VBoxContainer);
15631588
add_child(main_vb);
15641589

@@ -1670,6 +1695,15 @@ ExportTemplateManager::ExportTemplateManager() {
16701695
installed_templates_container->add_child(installed_templates_tree);
16711696
installed_templates_tree->connect("button_clicked", callable_mp(this, &ExportTemplateManager::_tree_button_clicked));
16721697

1698+
#ifndef ANDROID_ENABLED
1699+
setup_android_sdk = memnew(Button);
1700+
setup_android_sdk->set_tooltip_text(TTRC("Install and configure the Android SDK for Gradle builds."));
1701+
setup_android_sdk->set_text(TTRC("Setup Android SDK"));
1702+
setup_android_sdk->set_h_size_flags(Control::SIZE_SHRINK_END | Control::SIZE_EXPAND);
1703+
setup_android_sdk->connect(SceneStringName(pressed), callable_mp(android_sdk_manager, &AndroidSdkManager::run_setup));
1704+
main_vb->add_child(setup_android_sdk);
1705+
#endif
1706+
16731707
offline_container = memnew(HBoxContainer);
16741708
offline_container->set_alignment(BoxContainer::ALIGNMENT_CENTER);
16751709
offline_container->hide();

editor/export/export_template_manager.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
#include "scene/gui/dialogs.h"
3434
#include "scene/main/http_request.h"
3535

36+
#ifndef ANDROID_ENABLED
37+
class AndroidSdkManager;
38+
#endif
3639
class Button;
3740
class EditorExportPreset;
3841
class EditorFileDialog;
@@ -221,6 +224,13 @@ class ExportTemplateManager : public AcceptDialog {
221224
ConfirmationDialog *confirm_delete = nullptr;
222225
EditorFileDialog *tpz_selection_dialog = nullptr;
223226

227+
#ifndef ANDROID_ENABLED
228+
Button *setup_android_sdk = nullptr;
229+
AndroidSdkManager *android_sdk_manager = nullptr;
230+
231+
void _update_android_sdk_setup_button();
232+
#endif
233+
224234
void _request_mirrors();
225235
void _mirrors_request_completed(int p_result, int p_response_code, const PackedStringArray &p_headers, const PackedByteArray &p_body);
226236
void _set_empty_mirror_list();
@@ -238,7 +248,6 @@ class ExportTemplateManager : public AcceptDialog {
238248
void _update_version_list();
239249
void _update_template_tree();
240250
void _fill_template_tree(Tree *p_tree, const HashMap<TemplateID, LocalVector<String>> &p_installed_template_files, bool p_is_current_version);
241-
void _update_template_tree_with_folding();
242251
void _update_install_button();
243252
bool _can_download_templates();
244253

platform/android/export/export.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "editor/settings/editor_settings.h"
4040

4141
String get_default_android_sdk_path();
42+
String get_default_java_sdk_path();
4243

4344
void register_android_exporter_types() {
4445
GDREGISTER_VIRTUAL_CLASS(EditorExportPlatformAndroid);
@@ -55,10 +56,10 @@ void register_android_exporter() {
5556
#ifdef ANDROID_ENABLED
5657
EDITOR_DEF_BASIC("export/android/install_exported_apk", !OS::get_singleton()->has_feature("horizonos"));
5758
#else
58-
EDITOR_DEF_BASIC("export/android/java_sdk_path", OS::get_singleton()->get_environment("JAVA_HOME"));
59+
EDITOR_DEF("export/android/java_sdk_path", OS::get_singleton()->has_environment("JAVA_HOME") ? OS::get_singleton()->get_environment("JAVA_HOME") : get_default_java_sdk_path());
5960
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/java_sdk_path", PROPERTY_HINT_GLOBAL_DIR));
6061

61-
EDITOR_DEF_BASIC("export/android/android_sdk_path", OS::get_singleton()->has_environment("ANDROID_HOME") ? OS::get_singleton()->get_environment("ANDROID_HOME") : get_default_android_sdk_path());
62+
EDITOR_DEF("export/android/android_sdk_path", OS::get_singleton()->has_environment("ANDROID_HOME") ? OS::get_singleton()->get_environment("ANDROID_HOME") : get_default_android_sdk_path());
6263
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/android_sdk_path", PROPERTY_HINT_GLOBAL_DIR));
6364

6465
EDITOR_DEF_BASIC("export/android/scrcpy/path", "");
@@ -99,3 +100,7 @@ inline String get_default_android_sdk_path() {
99100
return String();
100101
#endif
101102
}
103+
104+
inline String get_default_java_sdk_path() {
105+
return EditorPaths::get_singleton()->get_cache_dir().path_join("java-sdk");
106+
}

0 commit comments

Comments
 (0)