summaryrefslogtreecommitdiffstats
path: root/platform/android
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android')
-rw-r--r--platform/android/android_input_handler.cpp1
-rw-r--r--platform/android/android_keys_utils.cpp9
-rw-r--r--platform/android/android_keys_utils.h20
-rw-r--r--platform/android/detect.py2
-rw-r--r--platform/android/export/export.cpp3
-rw-r--r--platform/android/export/export_plugin.cpp123
-rw-r--r--platform/android/export/export_plugin.h3
-rw-r--r--platform/android/file_access_android.cpp81
-rw-r--r--platform/android/file_access_android.h6
-rw-r--r--platform/android/file_access_filesystem_jandroid.cpp51
-rw-r--r--platform/android/file_access_filesystem_jandroid.h6
-rw-r--r--platform/android/java/app/AndroidManifest.xml1
-rw-r--r--platform/android/java/app/assetPacks/installTime/build.gradle4
-rw-r--r--platform/android/java/app/build.gradle43
-rw-r--r--platform/android/java/app/config.gradle23
-rw-r--r--platform/android/java/app/settings.gradle4
-rw-r--r--platform/android/java/build.gradle19
-rw-r--r--platform/android/java/editor/build.gradle17
-rw-r--r--platform/android/java/editor/src/main/AndroidManifest.xml1
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt4
-rw-r--r--platform/android/java/gradle/wrapper/gradle-wrapper.properties3
-rw-r--r--platform/android/java/lib/AndroidManifest.xml1
-rw-r--r--platform/android/java/lib/build.gradle8
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.kt16
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt8
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java26
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java44
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java8
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java44
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java16
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt20
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java14
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt4
-rw-r--r--platform/android/java/nativeSrcsConfigs/AndroidManifest.xml2
-rw-r--r--platform/android/java/nativeSrcsConfigs/build.gradle2
-rw-r--r--platform/android/java/settings.gradle5
-rw-r--r--platform/android/java_godot_lib_jni.cpp2
-rw-r--r--platform/android/java_godot_wrapper.cpp2
-rw-r--r--platform/android/java_godot_wrapper.h2
40 files changed, 495 insertions, 158 deletions
diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp
index bd194478d9..8e7f355114 100644
--- a/platform/android/android_input_handler.cpp
+++ b/platform/android/android_input_handler.cpp
@@ -124,6 +124,7 @@ void AndroidInputHandler::process_key_event(int p_physical_keycode, int p_unicod
ev->set_physical_keycode(physical_keycode);
ev->set_key_label(fix_key_label(p_key_label, keycode));
ev->set_unicode(fix_unicode(unicode));
+ ev->set_location(godot_location_from_android_code(p_physical_keycode));
ev->set_pressed(p_pressed);
ev->set_echo(p_echo);
diff --git a/platform/android/android_keys_utils.cpp b/platform/android/android_keys_utils.cpp
index f50437e82a..83ee98e8bc 100644
--- a/platform/android/android_keys_utils.cpp
+++ b/platform/android/android_keys_utils.cpp
@@ -38,3 +38,12 @@ Key godot_code_from_android_code(unsigned int p_code) {
}
return Key::UNKNOWN;
}
+
+KeyLocation godot_location_from_android_code(unsigned int p_code) {
+ for (int i = 0; android_godot_location_pairs[i].android_code != AKEYCODE_MAX; i++) {
+ if (android_godot_location_pairs[i].android_code == p_code) {
+ return android_godot_location_pairs[i].godot_code;
+ }
+ }
+ return KeyLocation::UNSPECIFIED;
+}
diff --git a/platform/android/android_keys_utils.h b/platform/android/android_keys_utils.h
index 5cf5628a8b..77c0911f2b 100644
--- a/platform/android/android_keys_utils.h
+++ b/platform/android/android_keys_utils.h
@@ -177,4 +177,24 @@ static AndroidGodotCodePair android_godot_code_pairs[] = {
Key godot_code_from_android_code(unsigned int p_code);
+// Key location determination.
+struct AndroidGodotLocationPair {
+ unsigned int android_code = 0;
+ KeyLocation godot_code = KeyLocation::UNSPECIFIED;
+};
+
+static AndroidGodotLocationPair android_godot_location_pairs[] = {
+ { AKEYCODE_ALT_LEFT, KeyLocation::LEFT },
+ { AKEYCODE_ALT_RIGHT, KeyLocation::RIGHT },
+ { AKEYCODE_SHIFT_LEFT, KeyLocation::LEFT },
+ { AKEYCODE_SHIFT_RIGHT, KeyLocation::RIGHT },
+ { AKEYCODE_CTRL_LEFT, KeyLocation::LEFT },
+ { AKEYCODE_CTRL_RIGHT, KeyLocation::RIGHT },
+ { AKEYCODE_META_LEFT, KeyLocation::LEFT },
+ { AKEYCODE_META_RIGHT, KeyLocation::RIGHT },
+ { AKEYCODE_MAX, KeyLocation::UNSPECIFIED }
+};
+
+KeyLocation godot_location_from_android_code(unsigned int p_code);
+
#endif // ANDROID_KEYS_UTILS_H
diff --git a/platform/android/detect.py b/platform/android/detect.py
index a417ef454b..b396e5eb2d 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -200,7 +200,7 @@ def configure(env: "Environment"):
env.Append(LIBS=["OpenSLES", "EGL", "android", "log", "z", "dl"])
if env["vulkan"]:
- env.Append(CPPDEFINES=["VULKAN_ENABLED"])
+ env.Append(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"])
if not env["use_volk"]:
env.Append(LIBS=["vulkan"])
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index ee1ec2790d..138714634f 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -42,12 +42,15 @@ void register_android_exporter_types() {
void register_android_exporter() {
#ifndef ANDROID_ENABLED
+ EDITOR_DEF("export/android/java_sdk_path", OS::get_singleton()->get_environment("JAVA_HOME"));
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/java_sdk_path", PROPERTY_HINT_GLOBAL_DIR));
EDITOR_DEF("export/android/android_sdk_path", OS::get_singleton()->get_environment("ANDROID_HOME"));
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/android_sdk_path", PROPERTY_HINT_GLOBAL_DIR));
EDITOR_DEF("export/android/debug_keystore", "");
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"));
EDITOR_DEF("export/android/debug_keystore_user", "androiddebugkey");
EDITOR_DEF("export/android/debug_keystore_pass", "android");
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore_pass", PROPERTY_HINT_PASSWORD));
EDITOR_DEF("export/android/force_system_user", false);
EDITOR_DEF("export/android/shutdown_adb_on_exit", true);
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 10d54e8d97..459f5a5983 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -45,9 +45,9 @@
#include "editor/editor_log.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/import/resource_importer_texture_settings.h"
+#include "editor/themes/editor_scale.h"
#include "main/splash.gen.h"
#include "scene/resources/image_texture.h"
@@ -255,7 +255,7 @@ static const char *AAB_ASSETS_DIRECTORY = "res://android/build/assetPacks/instal
static const int OPENGL_MIN_SDK_VERSION = 21; // Should match the value in 'platform/android/java/app/config.gradle#minSdk'
static const int VULKAN_MIN_SDK_VERSION = 24;
-static const int DEFAULT_TARGET_SDK_VERSION = 33; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk'
+static const int DEFAULT_TARGET_SDK_VERSION = 34; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk'
#ifndef ANDROID_ENABLED
void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) {
@@ -1111,7 +1111,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
}
for (int i = 0; i < feature_names.size(); i++) {
- String feature_name = feature_names[i];
+ const String &feature_name = feature_names[i];
bool feature_required = feature_required_list[i];
int feature_version = feature_versions[i];
bool has_version_attribute = feature_version != -1;
@@ -1605,7 +1605,11 @@ void EditorExportPlatformAndroid::load_icon_refs(const Ref<EditorExportPreset> &
print_verbose("Loading regular icon from " + path);
if (path.is_empty() || ImageLoader::load_image(path, icon) != OK) {
print_verbose("- falling back to project icon: " + project_icon_path);
- ImageLoader::load_image(project_icon_path, icon);
+ if (!project_icon_path.is_empty()) {
+ ImageLoader::load_image(project_icon_path, icon);
+ } else {
+ ERR_PRINT("No project icon specified. Please specify one in the Project Settings under Application -> Config -> Icon");
+ }
}
// Adaptive foreground: user selection -> regular icon (user selection -> project icon -> default).
@@ -1823,10 +1827,10 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_user", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password", PROPERTY_HINT_PASSWORD, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_user", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_password", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_password", PROPERTY_HINT_PASSWORD, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
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", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), ""));
@@ -2111,8 +2115,17 @@ Ref<Texture2D> EditorExportPlatformAndroid::get_run_icon() const {
return run_icon;
}
+String EditorExportPlatformAndroid::get_java_path() {
+ String exe_ext;
+ if (OS::get_singleton()->get_name() == "Windows") {
+ exe_ext = ".exe";
+ }
+ String java_sdk_path = EDITOR_GET("export/android/java_sdk_path");
+ return java_sdk_path.path_join("bin/java" + exe_ext);
+}
+
String EditorExportPlatformAndroid::get_adb_path() {
- String exe_ext = "";
+ String exe_ext;
if (OS::get_singleton()->get_name() == "Windows") {
exe_ext = ".exe";
}
@@ -2124,13 +2137,13 @@ String EditorExportPlatformAndroid::get_apksigner_path(int p_target_sdk, bool p_
if (p_target_sdk == -1) {
p_target_sdk = DEFAULT_TARGET_SDK_VERSION;
}
- String exe_ext = "";
+ String exe_ext;
if (OS::get_singleton()->get_name() == "Windows") {
exe_ext = ".bat";
}
String apksigner_command_name = "apksigner" + exe_ext;
String sdk_path = EDITOR_GET("export/android/android_sdk_path");
- String apksigner_path = "";
+ String apksigner_path;
Error errn;
String build_tools_dir = sdk_path.path_join("build-tools");
@@ -2229,6 +2242,54 @@ String EditorExportPlatformAndroid::get_apksigner_path(int p_target_sdk, bool p_
return apksigner_path;
}
+static bool has_valid_keystore_credentials(String &r_error_str, const String &p_keystore, const String &p_username, const String &p_password, const String &p_type) {
+ String output;
+ List<String> args;
+ args.push_back("-list");
+ args.push_back("-keystore");
+ args.push_back(p_keystore);
+ args.push_back("-storepass");
+ args.push_back(p_password);
+ args.push_back("-alias");
+ args.push_back(p_username);
+ Error error = OS::get_singleton()->execute("keytool", args, &output, nullptr, true);
+ String keytool_error = "keytool error:";
+ bool valid = output.substr(0, keytool_error.length()) != keytool_error;
+
+ if (error != OK) {
+ r_error_str = TTR("Error: There was a problem validating the keystore username and password");
+ return false;
+ }
+ if (!valid) {
+ r_error_str = TTR(p_type + " Username and/or Password is invalid for the given " + p_type + " Keystore");
+ return false;
+ }
+ r_error_str = "";
+ return true;
+}
+
+bool EditorExportPlatformAndroid::has_valid_username_and_password(const Ref<EditorExportPreset> &p_preset, String &r_error) {
+ String dk = p_preset->get_or_env("keystore/debug", ENV_ANDROID_KEYSTORE_DEBUG_PATH);
+ String dk_user = p_preset->get_or_env("keystore/debug_user", ENV_ANDROID_KEYSTORE_DEBUG_USER);
+ String dk_password = p_preset->get_or_env("keystore/debug_password", ENV_ANDROID_KEYSTORE_DEBUG_PASS);
+ String rk = p_preset->get_or_env("keystore/release", ENV_ANDROID_KEYSTORE_RELEASE_PATH);
+ String rk_user = p_preset->get_or_env("keystore/release_user", ENV_ANDROID_KEYSTORE_RELEASE_USER);
+ String rk_password = p_preset->get_or_env("keystore/release_password", ENV_ANDROID_KEYSTORE_RELEASE_PASS);
+
+ bool valid = true;
+ if (!dk.is_empty() && !dk_user.is_empty() && !dk_password.is_empty()) {
+ String err = "";
+ valid = has_valid_keystore_credentials(err, dk, dk_user, dk_password, "Debug");
+ r_error += err;
+ }
+ if (!rk.is_empty() && !rk_user.is_empty() && !rk_password.is_empty()) {
+ String err = "";
+ valid = has_valid_keystore_credentials(err, rk, rk_user, rk_password, "Release");
+ r_error += err;
+ }
+ return valid;
+}
+
bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const {
String err;
bool valid = false;
@@ -2329,6 +2390,32 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<Edito
err += TTR("Release keystore incorrectly configured in the export preset.") + "\n";
}
+ String java_sdk_path = EDITOR_GET("export/android/java_sdk_path");
+ if (java_sdk_path.is_empty()) {
+ err += TTR("A valid Java SDK path is required in Editor Settings.") + "\n";
+ valid = false;
+ } else {
+ // Validate the given path by checking that `java` is present under the `bin` directory.
+ Error errn;
+ // Check for the bin directory.
+ Ref<DirAccess> da = DirAccess::open(java_sdk_path.path_join("bin"), &errn);
+ if (errn != OK) {
+ err += TTR("Invalid Java SDK path in Editor Settings.");
+ err += TTR("Missing 'bin' directory!");
+ err += "\n";
+ valid = false;
+ } else {
+ // Check for the `java` command.
+ String java_path = get_java_path();
+ if (!FileAccess::exists(java_path)) {
+ err += TTR("Unable to find 'java' command using the Java SDK path.");
+ err += TTR("Please check the Java SDK directory specified in Editor Settings.");
+ err += "\n";
+ valid = false;
+ }
+ }
+ }
+
String sdk_path = EDITOR_GET("export/android/android_sdk_path");
if (sdk_path.is_empty()) {
err += TTR("A valid Android SDK path is required in Editor Settings.") + "\n";
@@ -2842,6 +2929,11 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Unsupported export format!"));
return ERR_UNCONFIGURED;
}
+ String err_string;
+ if (!has_valid_username_and_password(p_preset, err_string)) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR(err_string));
+ return ERR_UNCONFIGURED;
+ }
if (use_gradle_build) {
print_verbose("Starting gradle build...");
@@ -2861,6 +2953,13 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
}
}
const String assets_directory = get_assets_directory(p_preset, export_format);
+ String java_sdk_path = EDITOR_GET("export/android/java_sdk_path");
+ if (java_sdk_path.is_empty()) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Java SDK path must be configured in Editor Settings at 'export/android/java_sdk_path'."));
+ return ERR_UNCONFIGURED;
+ }
+ print_verbose("Java sdk path: " + java_sdk_path);
+
String sdk_path = EDITOR_GET("export/android/android_sdk_path");
if (sdk_path.is_empty()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Android SDK path must be configured in Editor Settings at 'export/android/android_sdk_path'."));
@@ -2911,8 +3010,11 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
print_verbose("Storing command line flags...");
store_file_at_path(assets_directory + "/_cl_", command_line_flags);
+ print_verbose("Updating JAVA_HOME environment to " + java_sdk_path);
+ OS::get_singleton()->set_environment("JAVA_HOME", java_sdk_path);
+
print_verbose("Updating ANDROID_HOME environment to " + sdk_path);
- OS::get_singleton()->set_environment("ANDROID_HOME", sdk_path); //set and overwrite if required
+ OS::get_singleton()->set_environment("ANDROID_HOME", sdk_path);
String build_command;
#ifdef WINDOWS_ENABLED
@@ -2975,6 +3077,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
String combined_android_dependencies_maven_repos = String("|").join(android_dependencies_maven_repos);
List<String> cmdline;
+ cmdline.push_back("validateJavaVersion");
if (clean_build_required) {
cmdline.push_back("clean");
}
diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h
index a2d0417c5d..c282055fba 100644
--- a/platform/android/export/export_plugin.h
+++ b/platform/android/export/export_plugin.h
@@ -226,8 +226,11 @@ public:
static String get_apksigner_path(int p_target_sdk = -1, bool p_check_executes = false);
+ static String get_java_path();
+
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
+ static bool has_valid_username_and_password(const Ref<EditorExportPreset> &p_preset, String &r_error);
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index 1249f2219f..f56eda4694 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -121,6 +121,75 @@ uint8_t FileAccessAndroid::get_8() const {
return byte;
}
+uint16_t FileAccessAndroid::get_16() const {
+ if (pos >= len) {
+ eof = true;
+ return 0;
+ }
+
+ uint16_t bytes = 0;
+ int r = AAsset_read(asset, &bytes, 2);
+
+ if (r >= 0) {
+ pos += r;
+ if (pos >= len) {
+ eof = true;
+ }
+ }
+
+ if (big_endian) {
+ bytes = BSWAP16(bytes);
+ }
+
+ return bytes;
+}
+
+uint32_t FileAccessAndroid::get_32() const {
+ if (pos >= len) {
+ eof = true;
+ return 0;
+ }
+
+ uint32_t bytes = 0;
+ int r = AAsset_read(asset, &bytes, 4);
+
+ if (r >= 0) {
+ pos += r;
+ if (pos >= len) {
+ eof = true;
+ }
+ }
+
+ if (big_endian) {
+ bytes = BSWAP32(bytes);
+ }
+
+ return bytes;
+}
+
+uint64_t FileAccessAndroid::get_64() const {
+ if (pos >= len) {
+ eof = true;
+ return 0;
+ }
+
+ uint64_t bytes = 0;
+ int r = AAsset_read(asset, &bytes, 8);
+
+ if (r >= 0) {
+ pos += r;
+ if (pos >= len) {
+ eof = true;
+ }
+ }
+
+ if (big_endian) {
+ bytes = BSWAP64(bytes);
+ }
+
+ return bytes;
+}
+
uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
@@ -151,6 +220,18 @@ void FileAccessAndroid::store_8(uint8_t p_dest) {
ERR_FAIL();
}
+void FileAccessAndroid::store_16(uint16_t p_dest) {
+ ERR_FAIL();
+}
+
+void FileAccessAndroid::store_32(uint32_t p_dest) {
+ ERR_FAIL();
+}
+
+void FileAccessAndroid::store_64(uint64_t p_dest) {
+ ERR_FAIL();
+}
+
bool FileAccessAndroid::file_exists(const String &p_path) {
String path = fix_path(p_path).simplify_path();
if (path.begins_with("/")) {
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index 3aa4ca98fc..ec613b6687 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -66,12 +66,18 @@ public:
virtual bool eof_reached() const override; // reading passed EOF
virtual uint8_t get_8() const override; // get a byte
+ virtual uint16_t get_16() const override;
+ virtual uint32_t get_32() const override;
+ virtual uint64_t get_64() const override;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; // get last error
virtual void flush() override;
virtual void store_8(uint8_t p_dest) override; // store a byte
+ virtual void store_16(uint16_t p_dest) override;
+ virtual void store_32(uint32_t p_dest) override;
+ virtual void store_64(uint64_t p_dest) override;
virtual bool file_exists(const String &p_path) override; // return true if a file exists
diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp
index beea73fd61..46d9728632 100644
--- a/platform/android/file_access_filesystem_jandroid.cpp
+++ b/platform/android/file_access_filesystem_jandroid.cpp
@@ -181,6 +181,36 @@ uint8_t FileAccessFilesystemJAndroid::get_8() const {
return byte;
}
+uint16_t FileAccessFilesystemJAndroid::get_16() const {
+ ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
+ uint16_t bytes = 0;
+ get_buffer(reinterpret_cast<uint8_t *>(&bytes), 2);
+ if (big_endian) {
+ bytes = BSWAP16(bytes);
+ }
+ return bytes;
+}
+
+uint32_t FileAccessFilesystemJAndroid::get_32() const {
+ ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
+ uint32_t bytes = 0;
+ get_buffer(reinterpret_cast<uint8_t *>(&bytes), 4);
+ if (big_endian) {
+ bytes = BSWAP32(bytes);
+ }
+ return bytes;
+}
+
+uint64_t FileAccessFilesystemJAndroid::get_64() const {
+ ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
+ uint64_t bytes = 0;
+ get_buffer(reinterpret_cast<uint8_t *>(&bytes), 8);
+ if (big_endian) {
+ bytes = BSWAP64(bytes);
+ }
+ return bytes;
+}
+
String FileAccessFilesystemJAndroid::get_line() const {
ERR_FAIL_COND_V_MSG(!is_open(), String(), "File must be opened before use.");
@@ -250,6 +280,27 @@ void FileAccessFilesystemJAndroid::store_8(uint8_t p_dest) {
store_buffer(&p_dest, 1);
}
+void FileAccessFilesystemJAndroid::store_16(uint16_t p_dest) {
+ if (big_endian) {
+ p_dest = BSWAP16(p_dest);
+ }
+ store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 2);
+}
+
+void FileAccessFilesystemJAndroid::store_32(uint32_t p_dest) {
+ if (big_endian) {
+ p_dest = BSWAP32(p_dest);
+ }
+ store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 4);
+}
+
+void FileAccessFilesystemJAndroid::store_64(uint64_t p_dest) {
+ if (big_endian) {
+ p_dest = BSWAP64(p_dest);
+ }
+ store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 8);
+}
+
void FileAccessFilesystemJAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
if (_file_write) {
ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h
index 0c3f8d7259..f33aa64ebe 100644
--- a/platform/android/file_access_filesystem_jandroid.h
+++ b/platform/android/file_access_filesystem_jandroid.h
@@ -77,6 +77,9 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
virtual uint8_t get_8() const override; ///< get a byte
+ virtual uint16_t get_16() const override;
+ virtual uint32_t get_32() const override;
+ virtual uint64_t get_64() const override;
virtual String get_line() const override; ///< get a line
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
@@ -84,6 +87,9 @@ public:
virtual void flush() override;
virtual void store_8(uint8_t p_dest) override; ///< store a byte
+ virtual void store_16(uint16_t p_dest) override;
+ virtual void store_32(uint32_t p_dest) override;
+ virtual void store_64(uint64_t p_dest) override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index 079f629b12..4abc6548bf 100644
--- a/platform/android/java/app/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
- package="com.godot.game"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="auto" >
diff --git a/platform/android/java/app/assetPacks/installTime/build.gradle b/platform/android/java/app/assetPacks/installTime/build.gradle
index b06faac374..46fa046ed4 100644
--- a/platform/android/java/app/assetPacks/installTime/build.gradle
+++ b/platform/android/java/app/assetPacks/installTime/build.gradle
@@ -1,4 +1,6 @@
-apply plugin: 'com.android.asset-pack'
+plugins {
+ id 'com.android.asset-pack'
+}
assetPack {
packName = "installTime" // Directory name for the asset pack
diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle
index 01b148aeef..f084c60209 100644
--- a/platform/android/java/app/build.gradle
+++ b/platform/android/java/app/build.gradle
@@ -1,17 +1,4 @@
// Gradle build config for Godot Engine's Android port.
-buildscript {
- apply from: 'config.gradle'
-
- repositories {
- google()
- mavenCentral()
- }
- dependencies {
- classpath libraries.androidGradlePlugin
- classpath libraries.kotlinGradlePlugin
- }
-}
-
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
@@ -23,6 +10,8 @@ allprojects {
repositories {
google()
mavenCentral()
+ gradlePluginPortal()
+ maven { url "https://plugins.gradle.org/m2/" }
// Godot user plugins custom maven repos
String[] mavenRepos = getGodotPluginsMavenRepos()
@@ -42,8 +31,7 @@ configurations {
}
dependencies {
- implementation libraries.kotlinStdLib
- implementation libraries.androidxFragment
+ implementation "androidx.fragment:fragment:$versions.fragmentVersion"
if (rootProject.findProject(":lib")) {
implementation project(":lib")
@@ -88,6 +76,8 @@ android {
assetPacks = [":assetPacks:installTime"]
+ namespace = 'com.godot.game'
+
defaultConfig {
// The default ignore pattern for the 'assets' directory includes hidden files and directories which are used by Godot projects.
aaptOptions {
@@ -241,3 +231,26 @@ task copyAndRenameReleaseAab(type: Copy) {
into getExportPath()
rename "build-release.aab", getExportFilename()
}
+
+/**
+ * Used to validate the version of the Java SDK used for the Godot gradle builds.
+ */
+task validateJavaVersion {
+ if (JavaVersion.current() != versions.javaVersion) {
+ throw new GradleException("Invalid Java version ${JavaVersion.current()}. Version ${versions.javaVersion} is the required Java version for Godot gradle builds.")
+ }
+}
+
+/*
+When they're scheduled to run, the copy*AARToAppModule tasks generate dependencies for the 'app'
+module, so we're ensuring the ':app:preBuild' task is set to run after those tasks.
+ */
+if (rootProject.tasks.findByPath("copyDebugAARToAppModule") != null) {
+ preBuild.mustRunAfter(rootProject.tasks.named("copyDebugAARToAppModule"))
+}
+if (rootProject.tasks.findByPath("copyDevAARToAppModule") != null) {
+ preBuild.mustRunAfter(rootProject.tasks.named("copyDevAARToAppModule"))
+}
+if (rootProject.tasks.findByPath("copyReleaseAARToAppModule") != null) {
+ preBuild.mustRunAfter(rootProject.tasks.named("copyReleaseAARToAppModule"))
+}
diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle
index a91e7bc7ce..7224765f28 100644
--- a/platform/android/java/app/config.gradle
+++ b/platform/android/java/app/config.gradle
@@ -1,27 +1,20 @@
ext.versions = [
- androidGradlePlugin: '7.2.1',
- compileSdk : 33,
+ androidGradlePlugin: '8.2.0',
+ compileSdk : 34,
// Also update 'platform/android/export/export_plugin.cpp#OPENGL_MIN_SDK_VERSION'
minSdk : 21,
// Also update 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION'
- targetSdk : 33,
- buildTools : '33.0.2',
- kotlinVersion : '1.7.0',
- fragmentVersion : '1.3.6',
- nexusPublishVersion: '1.1.0',
- javaVersion : 17,
+ targetSdk : 34,
+ buildTools : '34.0.0',
+ kotlinVersion : '1.9.20',
+ fragmentVersion : '1.6.2',
+ nexusPublishVersion: '1.3.0',
+ javaVersion : JavaVersion.VERSION_17,
// Also update 'platform/android/detect.py#get_ndk_version()' when this is updated.
ndkVersion : '23.2.8568313'
]
-ext.libraries = [
- androidGradlePlugin: "com.android.tools.build:gradle:$versions.androidGradlePlugin",
- kotlinGradlePlugin : "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlinVersion",
- kotlinStdLib : "org.jetbrains.kotlin:kotlin-stdlib:$versions.kotlinVersion",
- androidxFragment : "androidx.fragment:fragment:$versions.fragmentVersion",
-]
-
ext.getExportPackageName = { ->
// Retrieve the app id from the project property set by the Godot build command.
String appId = project.hasProperty("export_package_name") ? project.property("export_package_name") : ""
diff --git a/platform/android/java/app/settings.gradle b/platform/android/java/app/settings.gradle
index b4524a3f60..dcac44e393 100644
--- a/platform/android/java/app/settings.gradle
+++ b/platform/android/java/app/settings.gradle
@@ -7,8 +7,10 @@ pluginManagement {
id 'org.jetbrains.kotlin.android' version versions.kotlinVersion
}
repositories {
- gradlePluginPortal()
google()
+ mavenCentral()
+ gradlePluginPortal()
+ maven { url "https://plugins.gradle.org/m2/" }
}
}
diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle
index f94454e2a7..a8cabc7045 100644
--- a/platform/android/java/build.gradle
+++ b/platform/android/java/build.gradle
@@ -1,18 +1,3 @@
-buildscript {
- apply from: 'app/config.gradle'
-
- repositories {
- google()
- mavenCentral()
- maven { url "https://plugins.gradle.org/m2/" }
- }
- dependencies {
- classpath libraries.androidGradlePlugin
- classpath libraries.kotlinGradlePlugin
- classpath 'io.github.gradle-nexus:publish-plugin:1.3.0'
- }
-}
-
plugins {
id 'io.github.gradle-nexus.publish-plugin'
}
@@ -31,6 +16,8 @@ allprojects {
repositories {
google()
mavenCentral()
+ gradlePluginPortal()
+ maven { url "https://plugins.gradle.org/m2/" }
}
}
@@ -303,7 +290,7 @@ task generateGodotTemplates {
*/
task generateDevTemplate {
// add parameter to set symbols to true
- gradle.startParameter.projectProperties += [doNotStrip: true]
+ gradle.startParameter.projectProperties += [doNotStrip: "true"]
gradle.startParameter.excludedTaskNames += templateExcludedBuildTask()
dependsOn = templateBuildTasks()
diff --git a/platform/android/java/editor/build.gradle b/platform/android/java/editor/build.gradle
index 38034aa47c..0f7ffeecae 100644
--- a/platform/android/java/editor/build.gradle
+++ b/platform/android/java/editor/build.gradle
@@ -2,14 +2,14 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
+ id 'base'
}
dependencies {
- implementation libraries.kotlinStdLib
- implementation libraries.androidxFragment
+ implementation "androidx.fragment:fragment:$versions.fragmentVersion"
implementation project(":lib")
- implementation "androidx.window:window:1.0.0"
+ implementation "androidx.window:window:1.2.0"
}
ext {
@@ -81,6 +81,8 @@ android {
buildToolsVersion versions.buildTools
ndkVersion versions.ndkVersion
+ namespace = "org.godotengine.editor"
+
defaultConfig {
// The 'applicationId' suffix allows to install Godot 3.x(v3) and 4.x(v4) on the same device
applicationId "org.godotengine.editor.v4"
@@ -90,7 +92,10 @@ android {
targetSdkVersion versions.targetSdk
missingDimensionStrategy 'products', 'editor'
- setProperty("archivesBaseName", "android_editor")
+ }
+
+ base {
+ archivesName = "android_editor"
}
compileOptions {
@@ -111,6 +116,10 @@ android {
}
}
+ buildFeatures {
+ buildConfig = true
+ }
+
buildTypes {
dev {
initWith debug
diff --git a/platform/android/java/editor/src/main/AndroidManifest.xml b/platform/android/java/editor/src/main/AndroidManifest.xml
index 1405b6c737..78dcddac0e 100644
--- a/platform/android/java/editor/src/main/AndroidManifest.xml
+++ b/platform/android/java/editor/src/main/AndroidManifest.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
- package="org.godotengine.editor"
android:installLocation="auto">
<supports-screens
diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
index 0d7017ae71..caf64bc933 100644
--- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
+++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
@@ -91,6 +91,10 @@ open class GodotEditor : GodotActivity() {
private val commandLineParams = ArrayList<String>()
override fun onCreate(savedInstanceState: Bundle?) {
+ // We exclude certain permissions from the set we request at startup, as they'll be
+ // requested on demand based on use-cases.
+ PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO))
+
val params = intent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS)
Log.d(TAG, "Received parameters ${params.contentToString()}")
updateCommandLineParams(params)
diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.properties b/platform/android/java/gradle/wrapper/gradle-wrapper.properties
index aa991fceae..471fefaf90 100644
--- a/platform/android/java/gradle/wrapper/gradle-wrapper.properties
+++ b/platform/android/java/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,6 @@
+#Wed Jan 17 12:08:26 PST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml
index f03a1dd47a..8240843876 100644
--- a/platform/android/java/lib/AndroidManifest.xml
+++ b/platform/android/java/lib/AndroidManifest.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.godotengine.godot"
android:versionCode="1"
android:versionName="1.0">
diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle
index 4340250ad3..61ae0cd58a 100644
--- a/platform/android/java/lib/build.gradle
+++ b/platform/android/java/lib/build.gradle
@@ -10,8 +10,7 @@ ext {
apply from: "../scripts/publish-module.gradle"
dependencies {
- implementation libraries.kotlinStdLib
- implementation libraries.androidxFragment
+ implementation "androidx.fragment:fragment:$versions.fragmentVersion"
}
def pathToRootDir = "../../../../"
@@ -39,6 +38,11 @@ android {
jvmTarget = versions.javaVersion
}
+ buildFeatures {
+ aidl = true
+ buildConfig = true
+ }
+
buildTypes {
dev {
initWith debug
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
index 217e7a2b60..da86e67c7d 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
@@ -484,6 +484,14 @@ class Godot(private val context: Context) : SensorEventListener {
return containerLayout
}
+ fun onStart(host: GodotHost) {
+ if (host != primaryHost) {
+ return
+ }
+
+ renderView!!.onActivityStarted()
+ }
+
fun onResume(host: GodotHost) {
if (host != primaryHost) {
return
@@ -528,6 +536,14 @@ class Godot(private val context: Context) : SensorEventListener {
}
}
+ fun onStop(host: GodotHost) {
+ if (host != primaryHost) {
+ return
+ }
+
+ renderView!!.onActivityStopped()
+ }
+
fun onDestroy(primaryHost: GodotHost) {
if (this.primaryHost != primaryHost) {
return
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt b/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt
index a60f6e997e..e01c5481d5 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt
@@ -30,7 +30,6 @@
package org.godotengine.godot
-import android.Manifest
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
@@ -65,10 +64,6 @@ abstract class GodotActivity : FragmentActivity(), GodotHost {
private set
override fun onCreate(savedInstanceState: Bundle?) {
- // We exclude certain permissions from the set we request at startup, as they'll be
- // requested on demand based on use-cases.
- PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO))
-
super.onCreate(savedInstanceState)
setContentView(R.layout.godot_app_layout)
@@ -156,7 +151,8 @@ abstract class GodotActivity : FragmentActivity(), GodotHost {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
godotFragment?.onRequestPermissionsResult(requestCode, permissions, grantResults)
- if (requestCode == PermissionsUtil.REQUEST_ALL_PERMISSION_REQ_CODE) {
+ // Logging the result of permission requests
+ if (requestCode == PermissionsUtil.REQUEST_ALL_PERMISSION_REQ_CODE || requestCode == PermissionsUtil.REQUEST_SINGLE_PERMISSION_REQ_CODE) {
Log.d(TAG, "Received permissions request result..")
for (i in permissions.indices) {
val permissionGranted = grantResults[i] == PackageManager.PERMISSION_GRANTED
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java b/platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java
index f1c029e7a1..643c9a658e 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java
@@ -271,6 +271,32 @@ public class GodotFragment extends Fragment implements IDownloaderClient, GodotH
}
@Override
+ public void onStop() {
+ super.onStop();
+ if (!godot.isInitialized()) {
+ if (null != mDownloaderClientStub) {
+ mDownloaderClientStub.disconnect(getActivity());
+ }
+ return;
+ }
+
+ godot.onStop(this);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (!godot.isInitialized()) {
+ if (null != mDownloaderClientStub) {
+ mDownloaderClientStub.connect(getActivity());
+ }
+ return;
+ }
+
+ godot.onStart(this);
+ }
+
+ @Override
public void onResume() {
super.onResume();
if (!godot.isInitialized()) {
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
index 52350c12a6..81043ce782 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
@@ -114,12 +114,30 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
@Override
public void onActivityPaused() {
- onPause();
+ queueEvent(() -> {
+ GodotLib.focusout();
+ // Pause the renderer
+ godotRenderer.onActivityPaused();
+ });
+ }
+
+ @Override
+ public void onActivityStopped() {
+ pauseGLThread();
}
@Override
public void onActivityResumed() {
- onResume();
+ queueEvent(() -> {
+ // Resume the renderer
+ godotRenderer.onActivityResumed();
+ GodotLib.focusin();
+ });
+ }
+
+ @Override
+ public void onActivityStarted() {
+ resumeGLThread();
}
@Override
@@ -283,26 +301,4 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
/* Set the renderer responsible for frame rendering */
setRenderer(godotRenderer);
}
-
- @Override
- public void onResume() {
- super.onResume();
-
- queueEvent(() -> {
- // Resume the renderer
- godotRenderer.onActivityResumed();
- GodotLib.focusin();
- });
- }
-
- @Override
- public void onPause() {
- super.onPause();
-
- queueEvent(() -> {
- GodotLib.focusout();
- // Pause the renderer
- godotRenderer.onActivityPaused();
- });
- }
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
index edcd9c4d1f..4b51bd778d 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
@@ -178,12 +178,10 @@ public class GodotIO {
}
public int[] getDisplaySafeArea() {
- DisplayMetrics metrics = activity.getResources().getDisplayMetrics();
- Display display = activity.getWindowManager().getDefaultDisplay();
- Point size = new Point();
- display.getRealSize(size);
+ Rect rect = new Rect();
+ activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
- int[] result = { 0, 0, size.x, size.y };
+ int[] result = { rect.left, rect.top, rect.right, rect.bottom };
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets();
DisplayCutout cutout = insets.getDisplayCutout();
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
index ebf3a6b2fb..5b2f9f57c7 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
@@ -47,8 +47,13 @@ public interface GodotRenderView {
void queueOnRenderThread(Runnable event);
void onActivityPaused();
+
+ void onActivityStopped();
+
void onActivityResumed();
+ void onActivityStarted();
+
void onBackPressed();
GodotInputHandler getInputHandler();
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
index 48708152be..a1ee9bd6b4 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
@@ -92,12 +92,30 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
@Override
public void onActivityPaused() {
- onPause();
+ queueOnVkThread(() -> {
+ GodotLib.focusout();
+ // Pause the renderer
+ mRenderer.onVkPause();
+ });
+ }
+
+ @Override
+ public void onActivityStopped() {
+ pauseRenderThread();
+ }
+
+ @Override
+ public void onActivityStarted() {
+ resumeRenderThread();
}
@Override
public void onActivityResumed() {
- onResume();
+ queueOnVkThread(() -> {
+ // Resume the renderer
+ mRenderer.onVkResume();
+ GodotLib.focusin();
+ });
}
@Override
@@ -211,26 +229,4 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
}
return super.onResolvePointerIcon(me, pointerIndex);
}
-
- @Override
- public void onResume() {
- super.onResume();
-
- queueOnVkThread(() -> {
- // Resume the renderer
- mRenderer.onVkResume();
- GodotLib.focusin();
- });
- }
-
- @Override
- public void onPause() {
- super.onPause();
-
- queueOnVkThread(() -> {
- GodotLib.focusout();
- // Pause the renderer
- mRenderer.onVkPause();
- });
- }
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java b/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java
index 56397bb2c2..ef97aaeab9 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java
@@ -122,8 +122,8 @@ import javax.microedition.khronos.opengles.GL10;
* <p>
* <h3>Activity Life-cycle</h3>
* A GLSurfaceView must be notified when to pause and resume rendering. GLSurfaceView clients
- * are required to call {@link #onPause()} when the activity stops and
- * {@link #onResume()} when the activity starts. These calls allow GLSurfaceView to
+ * are required to call {@link #pauseGLThread()} when the activity stops and
+ * {@link #resumeGLThread()} when the activity starts. These calls allow GLSurfaceView to
* pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate
* the OpenGL display.
* <p>
@@ -339,8 +339,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
* setRenderer is called:
* <ul>
* <li>{@link #getRenderMode()}
- * <li>{@link #onPause()}
- * <li>{@link #onResume()}
+ * <li>{@link #pauseGLThread()}
+ * <li>{@link #resumeGLThread()}
* <li>{@link #queueEvent(Runnable)}
* <li>{@link #requestRender()}
* <li>{@link #setRenderMode(int)}
@@ -568,6 +568,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
}
+ // -- GODOT start --
/**
* Pause the rendering thread, optionally tearing down the EGL context
* depending upon the value of {@link #setPreserveEGLContextOnPause(boolean)}.
@@ -578,22 +579,23 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
*
* Must not be called before a renderer has been set.
*/
- public void onPause() {
+ protected final void pauseGLThread() {
mGLThread.onPause();
}
/**
* Resumes the rendering thread, re-creating the OpenGL context if necessary. It
- * is the counterpart to {@link #onPause()}.
+ * is the counterpart to {@link #pauseGLThread()}.
*
* This method should typically be called in
* {@link android.app.Activity#onStart Activity.onStart}.
*
* Must not be called before a renderer has been set.
*/
- public void onResume() {
+ protected final void resumeGLThread() {
mGLThread.onResume();
}
+ // -- GODOT end --
/**
* Queue a runnable to be run on the GL rendering thread. This can be used
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt
index e26c9d39c2..89fbb9f580 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt
@@ -210,21 +210,23 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi
}
override fun onScroll(
- originEvent: MotionEvent,
+ originEvent: MotionEvent?,
terminusEvent: MotionEvent,
distanceX: Float,
distanceY: Float
): Boolean {
if (scaleInProgress) {
if (dragInProgress) {
- // Cancel the drag
- GodotInputHandler.handleMotionEvent(
- originEvent.source,
- MotionEvent.ACTION_CANCEL,
- originEvent.buttonState,
- originEvent.x,
- originEvent.y
- )
+ if (originEvent != null) {
+ // Cancel the drag
+ GodotInputHandler.handleMotionEvent(
+ originEvent.source,
+ MotionEvent.ACTION_CANCEL,
+ originEvent.buttonState,
+ originEvent.x,
+ originEvent.y
+ )
+ }
dragInProgress = false
}
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
index 9a82204467..737b4ac20b 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
@@ -56,9 +56,9 @@ import java.util.Set;
public final class PermissionsUtil {
private static final String TAG = PermissionsUtil.class.getSimpleName();
- static final int REQUEST_RECORD_AUDIO_PERMISSION = 1;
- static final int REQUEST_CAMERA_PERMISSION = 2;
- static final int REQUEST_VIBRATE_PERMISSION = 3;
+ public static final int REQUEST_RECORD_AUDIO_PERMISSION = 1;
+ public static final int REQUEST_CAMERA_PERMISSION = 2;
+ public static final int REQUEST_VIBRATE_PERMISSION = 3;
public static final int REQUEST_ALL_PERMISSION_REQ_CODE = 1001;
public static final int REQUEST_SINGLE_PERMISSION_REQ_CODE = 1002;
public static final int REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE = 2002;
@@ -70,7 +70,7 @@ public final class PermissionsUtil {
* Request a dangerous permission. name must be specified in <a href="https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/res/AndroidManifest.xml">this</a>
* @param permissionName the name of the requested permission.
* @param activity the caller activity for this method.
- * @return true/false. "true" if permission was granted otherwise returns "false".
+ * @return true/false. "true" if permission is already granted, "false" if a permission request was dispatched.
*/
public static boolean requestPermission(String permissionName, Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
@@ -124,7 +124,7 @@ public final class PermissionsUtil {
/**
* Request dangerous permissions which are defined in the Android manifest file from the user.
* @param activity the caller activity for this method.
- * @return true/false. "true" if all permissions were granted otherwise returns "false".
+ * @return true/false. "true" if all permissions were already granted, returns "false" if permissions requests were dispatched.
*/
public static boolean requestManifestPermissions(Activity activity) {
return requestManifestPermissions(activity, null);
@@ -134,7 +134,7 @@ public final class PermissionsUtil {
* Request dangerous permissions which are defined in the Android manifest file from the user.
* @param activity the caller activity for this method.
* @param excludes Set of permissions to exclude from the request
- * @return true/false. "true" if all permissions were granted otherwise returns "false".
+ * @return true/false. "true" if all permissions were already granted, returns "false" if permissions requests were dispatched.
*/
public static boolean requestManifestPermissions(Activity activity, @Nullable Set<String> excludes) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
@@ -235,7 +235,7 @@ public final class PermissionsUtil {
/**
* Check if the given permission is in the AndroidManifest.xml file.
* @param context the caller context for this method.
- * @param permission the permession to look for in the manifest file.
+ * @param permission the permission to look for in the manifest file.
* @return "true" if the permission is in the manifest file of the activity, "false" otherwise.
*/
public static boolean hasManifestPermission(Context context, String permission) {
diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
index 3828004198..791b425444 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
@@ -99,7 +99,7 @@ open internal class VkSurfaceView(context: Context) : SurfaceView(context), Surf
*
* Must not be called before a [VkRenderer] has been set.
*/
- open fun onResume() {
+ protected fun resumeRenderThread() {
vkThread.onResume()
}
@@ -108,7 +108,7 @@ open internal class VkSurfaceView(context: Context) : SurfaceView(context), Surf
*
* Must not be called before a [VkRenderer] has been set.
*/
- open fun onPause() {
+ protected fun pauseRenderThread() {
vkThread.onPause()
}
diff --git a/platform/android/java/nativeSrcsConfigs/AndroidManifest.xml b/platform/android/java/nativeSrcsConfigs/AndroidManifest.xml
index dc180375d5..8072ee00db 100644
--- a/platform/android/java/nativeSrcsConfigs/AndroidManifest.xml
+++ b/platform/android/java/nativeSrcsConfigs/AndroidManifest.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
-<manifest package="org.godotengine.godot" />
+<manifest />
diff --git a/platform/android/java/nativeSrcsConfigs/build.gradle b/platform/android/java/nativeSrcsConfigs/build.gradle
index 5e810ae1ba..a728241181 100644
--- a/platform/android/java/nativeSrcsConfigs/build.gradle
+++ b/platform/android/java/nativeSrcsConfigs/build.gradle
@@ -9,6 +9,8 @@ android {
buildToolsVersion versions.buildTools
ndkVersion versions.ndkVersion
+ namespace = "org.godotengine.godot"
+
defaultConfig {
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
diff --git a/platform/android/java/settings.gradle b/platform/android/java/settings.gradle
index 466ffebf22..3137e74244 100644
--- a/platform/android/java/settings.gradle
+++ b/platform/android/java/settings.gradle
@@ -5,12 +5,15 @@ pluginManagement {
plugins {
id 'com.android.application' version versions.androidGradlePlugin
id 'com.android.library' version versions.androidGradlePlugin
+ id 'com.android.asset-pack' version versions.androidGradlePlugin
id 'org.jetbrains.kotlin.android' version versions.kotlinVersion
id 'io.github.gradle-nexus.publish-plugin' version versions.nexusPublishVersion
}
repositories {
- gradlePluginPortal()
google()
+ mavenCentral()
+ gradlePluginPortal()
+ maven { url "https://plugins.gradle.org/m2/" }
}
}
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 50075ed3f5..08e792cc04 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -484,7 +484,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *
env->DeleteLocalRef(jobj);
}
- MessageQueue::get_singleton()->push_callp(obj, str_method, argptrs, count);
+ Callable(obj, str_method).call_deferredp(argptrs, count);
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jclass clazz, jstring p_permission, jboolean p_result) {
diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp
index 4e401e633e..3c950bb1b1 100644
--- a/platform/android/java_godot_wrapper.cpp
+++ b/platform/android/java_godot_wrapper.cpp
@@ -334,7 +334,7 @@ void GodotJavaWrapper::vibrate(int p_duration_ms) {
}
}
-int GodotJavaWrapper::create_new_godot_instance(List<String> args) {
+int GodotJavaWrapper::create_new_godot_instance(const List<String> &args) {
if (_create_new_godot_instance) {
JNIEnv *env = get_jni_env();
ERR_FAIL_NULL_V(env, 0);
diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h
index 52043c6027..93998021a9 100644
--- a/platform/android/java_godot_wrapper.h
+++ b/platform/android/java_godot_wrapper.h
@@ -104,7 +104,7 @@ public:
void init_input_devices();
void vibrate(int p_duration_ms);
String get_input_fallback_mapping();
- int create_new_godot_instance(List<String> args);
+ int create_new_godot_instance(const List<String> &args);
void begin_benchmark_measure(const String &p_context, const String &p_label);
void end_benchmark_measure(const String &p_context, const String &p_label);
void dump_benchmark(const String &benchmark_file);