diff options
Diffstat (limited to 'platform/android')
12 files changed, 207 insertions, 39 deletions
diff --git a/platform/android/api/java_class_wrapper.h b/platform/android/api/java_class_wrapper.h index 4718de29ad..64da049407 100644 --- a/platform/android/api/java_class_wrapper.h +++ b/platform/android/api/java_class_wrapper.h @@ -47,7 +47,6 @@ class JavaClass : public Reference { #ifdef ANDROID_ENABLED enum ArgumentType{ - ARG_TYPE_VOID, ARG_TYPE_BOOLEAN, ARG_TYPE_BYTE, diff --git a/platform/android/audio_driver_opensl.h b/platform/android/audio_driver_opensl.h index 9858a40822..b30711705b 100644 --- a/platform/android/audio_driver_opensl.h +++ b/platform/android/audio_driver_opensl.h @@ -42,7 +42,6 @@ class AudioDriverOpenSL : public AudioDriver { Mutex mutex; enum { - BUFFER_COUNT = 2 }; diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 5007b3f570..53b43ae0e8 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -29,7 +29,6 @@ /*************************************************************************/ #include "export.h" -#include "gradle_export_util.h" #include "core/config/project_settings.h" #include "core/io/image_loader.h" @@ -827,7 +826,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { int version_code = p_preset->get("version/code"); String package_name = p_preset->get("package/unique_name"); - int orientation = p_preset->get("screen/orientation"); + const int screen_orientation = _get_android_orientation_value(_get_screen_orientation()); bool screen_support_small = p_preset->get("screen/support_small"); bool screen_support_normal = p_preset->get("screen/support_normal"); @@ -937,7 +936,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } if (tname == "activity" && attrname == "screenOrientation") { - encode_uint32(orientation == 0 ? 0 : 1, &p_manifest.write[iofs + 16]); + encode_uint32(screen_orientation, &p_manifest.write[iofs + 16]); } if (tname == "supports-screens") { @@ -1636,7 +1635,6 @@ public: r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name [default if blank]"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/signed"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/immersive_mode"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "screen/orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait"), 0)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_small"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_normal"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_large"), true)); @@ -1645,10 +1643,10 @@ public: r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_icon_option, PROPERTY_HINT_FILE, "*.png"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_foreground_option, PROPERTY_HINT_FILE, "*.png"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_background_option, PROPERTY_HINT_FILE, "*.png"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_user"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release", PROPERTY_HINT_GLOBAL_FILE, "*.keystore"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_user"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_password"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "apk_expansion/enable"), false)); @@ -1968,9 +1966,21 @@ public: valid = false; } else { Error errn; + // Check for the platform-tools directory. DirAccessRef da = DirAccess::open(sdk_path.plus_file("platform-tools"), &errn); if (errn != OK) { - err += TTR("Invalid Android SDK path for custom build in Editor Settings.") + "\n"; + err += TTR("Invalid Android SDK path for custom build in Editor Settings."); + err += TTR("Missing 'platform-tools' directory!"); + err += "\n"; + valid = false; + } + + // Check for the build-tools directory. + DirAccessRef build_tools_da = DirAccess::open(sdk_path.plus_file("build-tools"), &errn); + if (errn != OK) { + err += TTR("Invalid Android SDK path for custom build in Editor Settings."); + err += TTR("Missing 'build-tools' directory!"); + err += "\n"; valid = false; } } @@ -2159,14 +2169,16 @@ public: } } - Error sign_apk(const Ref<EditorExportPreset> &p_preset, bool p_debug, String apk_path, EditorProgress ep) { + Error sign_apk(const Ref<EditorExportPreset> &p_preset, bool p_debug, String export_path, EditorProgress ep) { + int export_format = int(p_preset->get("custom_template/export_format")); + String export_label = export_format == 1 ? "AAB" : "APK"; 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"); String jarsigner = EditorSettings::get_singleton()->get("export/android/jarsigner"); if (!FileAccess::exists(jarsigner)) { - EditorNode::add_io_error("'jarsigner' could not be found.\nPlease supply a path in the Editor Settings.\nThe resulting APK is unsigned."); + EditorNode::add_io_error("'jarsigner' could not be found.\nPlease supply a path in the Editor Settings.\nThe resulting " + export_label + " is unsigned."); return OK; } @@ -2184,7 +2196,7 @@ public: user = EditorSettings::get_singleton()->get("export/android/debug_keystore_user"); } - if (ep.step("Signing debug APK...", 103)) { + if (ep.step("Signing debug " + export_label + "...", 103)) { return ERR_SKIP; } @@ -2193,7 +2205,7 @@ public: password = release_password; user = release_username; - if (ep.step("Signing release APK...", 103)) { + if (ep.step("Signing release " + export_label + "...", 103)) { return ERR_SKIP; } } @@ -2218,7 +2230,7 @@ public: args.push_back(keystore); args.push_back("-storepass"); args.push_back(password); - args.push_back(apk_path); + args.push_back(export_path); args.push_back(user); int retval; OS::get_singleton()->execute(jarsigner, args, true, NULL, NULL, &retval); @@ -2227,7 +2239,7 @@ public: return ERR_CANT_CREATE; } - if (ep.step("Verifying APK...", 104)) { + if (ep.step("Verifying " + export_label + "...", 104)) { return ERR_SKIP; } @@ -2235,17 +2247,78 @@ public: args.push_back("-verify"); args.push_back("-keystore"); args.push_back(keystore); - args.push_back(apk_path); + args.push_back(export_path); args.push_back("-verbose"); OS::get_singleton()->execute(jarsigner, args, true, NULL, NULL, &retval); if (retval) { - EditorNode::add_io_error("'jarsigner' verification of APK failed. Make sure to use a jarsigner from OpenJDK 8."); + EditorNode::add_io_error("'jarsigner' verification of " + export_label + " failed. Make sure to use a jarsigner from OpenJDK 8."); return ERR_CANT_CREATE; } return OK; } + void _clear_assets_directory() { + DirAccessRef da_res = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (da_res->dir_exists("res://android/build/assets")) { + DirAccessRef da_assets = DirAccess::open("res://android/build/assets"); + da_assets->erase_contents_recursive(); + da_res->remove("res://android/build/assets"); + } + } + + Error _zip_align_project(const String &sdk_path, const String &unaligned_file_path, const String &aligned_file_path) { + // Look for the zipalign tool. + String zipalign_command; + Error errn; + String build_tools_dir = sdk_path.plus_file("build-tools"); + DirAccessRef da = DirAccess::open(build_tools_dir, &errn); + if (errn != OK) { + return errn; + } + + // There are additional versions directories we need to go through. + da->list_dir_begin(); + String sub_dir = da->get_next(); + while (!sub_dir.empty()) { + if (!sub_dir.begins_with(".") && da->current_is_dir()) { + // Check if the tool is here. + String tool_path = build_tools_dir.plus_file(sub_dir).plus_file("zipalign"); + if (FileAccess::exists(tool_path)) { + zipalign_command = tool_path; + break; + } + } + sub_dir = da->get_next(); + } + da->list_dir_end(); + + if (zipalign_command.empty()) { + EditorNode::get_singleton()->show_warning(TTR("Unable to find the zipalign tool.")); + return ERR_CANT_CREATE; + } + + List<String> zipalign_args; + zipalign_args.push_back("-f"); + zipalign_args.push_back("-v"); + zipalign_args.push_back("4"); + zipalign_args.push_back(unaligned_file_path); // source file + zipalign_args.push_back(aligned_file_path); // destination file + + int result = EditorNode::get_singleton()->execute_and_show_output(TTR("Aligning APK..."), zipalign_command, zipalign_args); + if (result != 0) { + EditorNode::get_singleton()->show_warning(TTR("Unable to complete APK alignment.")); + return ERR_CANT_CREATE; + } + + // Delete the unaligned path. + errn = da->remove(unaligned_file_path); + if (errn != OK) { + EditorNode::get_singleton()->show_warning(TTR("Unable to delete unaligned APK.")); + } + return OK; + } + virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override { ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); @@ -2325,13 +2398,8 @@ public: _write_tmp_manifest(p_preset, p_give_internet, p_debug); //stores all the project files inside the Gradle project directory. Also includes all ABIs + _clear_assets_directory(); if (!apk_expansion) { - DirAccess *da_res = DirAccess::create(DirAccess::ACCESS_RESOURCES); - if (da_res->dir_exists("res://android/build/assets")) { - DirAccess *da_assets = DirAccess::open("res://android/build/assets"); - da_assets->erase_contents_recursive(); - da_res->remove("res://android/build/assets"); - } err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, NULL, ignore_so_file); if (err != OK) { EditorNode::add_io_error("Could not export project files to gradle project\n"); @@ -2419,7 +2487,16 @@ public: copy_args.push_back(build_path); // start directory. String export_filename = p_path.get_file(); + if (export_format == 0) { + // By default, generated apk are not aligned. + export_filename += ".unaligned"; + } String export_path = p_path.get_base_dir(); + if (export_path.is_rel_path()) { + export_path = OS::get_singleton()->get_resource_dir().plus_file(export_path); + } + export_path = ProjectSettings::get_singleton()->globalize_path(export_path).simplify_path(); + String export_file_path = export_path.plus_file(export_filename); copy_args.push_back("-Pexport_path=file:" + export_path); copy_args.push_back("-Pexport_filename=" + export_filename); @@ -2430,11 +2507,20 @@ public: return ERR_CANT_CREATE; } if (_signed) { - err = sign_apk(p_preset, p_debug, p_path, ep); + err = sign_apk(p_preset, p_debug, export_file_path, ep); + if (err != OK) { + return err; + } + } + + if (export_format == 0) { + // Perform zip alignment + err = _zip_align_project(sdk_path, export_file_path, export_path.plus_file(p_path.get_file())); if (err != OK) { return err; } } + return OK; } // This is the start of the Legacy build system @@ -2781,7 +2867,7 @@ void register_android_exporter() { EDITOR_DEF("export/android/jarsigner", ""); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/jarsigner", PROPERTY_HINT_GLOBAL_FILE, exe_ext)); EDITOR_DEF("export/android/debug_keystore", ""); - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore", PROPERTY_HINT_GLOBAL_FILE, "*.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"); EDITOR_DEF("export/android/force_system_user", false); diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index 95f870bc35..3bc3651712 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -44,6 +44,67 @@ const String godot_project_name_xml_string = R"(<?xml version="1.0" encoding="ut </resources> )"; +DisplayServer::ScreenOrientation _get_screen_orientation() { + String orientation_settings = ProjectSettings::get_singleton()->get("display/window/handheld/orientation"); + DisplayServer::ScreenOrientation screen_orientation; + if (orientation_settings == "portrait") + screen_orientation = DisplayServer::SCREEN_PORTRAIT; + else if (orientation_settings == "reverse_landscape") + screen_orientation = DisplayServer::SCREEN_REVERSE_LANDSCAPE; + else if (orientation_settings == "reverse_portrait") + screen_orientation = DisplayServer::SCREEN_REVERSE_PORTRAIT; + else if (orientation_settings == "sensor_landscape") + screen_orientation = DisplayServer::SCREEN_SENSOR_LANDSCAPE; + else if (orientation_settings == "sensor_portrait") + screen_orientation = DisplayServer::SCREEN_SENSOR_PORTRAIT; + else if (orientation_settings == "sensor") + screen_orientation = DisplayServer::SCREEN_SENSOR; + else + screen_orientation = DisplayServer::SCREEN_LANDSCAPE; + + return screen_orientation; +} + +int _get_android_orientation_value(DisplayServer::ScreenOrientation screen_orientation) { + switch (screen_orientation) { + case DisplayServer::SCREEN_PORTRAIT: + return 1; + case DisplayServer::SCREEN_REVERSE_LANDSCAPE: + return 8; + case DisplayServer::SCREEN_REVERSE_PORTRAIT: + return 9; + case DisplayServer::SCREEN_SENSOR_LANDSCAPE: + return 11; + case DisplayServer::SCREEN_SENSOR_PORTRAIT: + return 12; + case DisplayServer::SCREEN_SENSOR: + return 13; + case DisplayServer::SCREEN_LANDSCAPE: + default: + return 0; + } +} + +String _get_android_orientation_label(DisplayServer::ScreenOrientation screen_orientation) { + switch (screen_orientation) { + case DisplayServer::SCREEN_PORTRAIT: + return "portrait"; + case DisplayServer::SCREEN_REVERSE_LANDSCAPE: + return "reverseLandscape"; + case DisplayServer::SCREEN_REVERSE_PORTRAIT: + return "reversePortrait"; + case DisplayServer::SCREEN_SENSOR_LANDSCAPE: + return "userLandscape"; + case DisplayServer::SCREEN_SENSOR_PORTRAIT: + return "userPortrait"; + case DisplayServer::SCREEN_SENSOR: + return "fullUser"; + case DisplayServer::SCREEN_LANDSCAPE: + default: + return "landscape"; + } +} + // Utility method used to create a directory. Error create_directory(const String &p_dir) { if (!DirAccess::exists(p_dir)) { @@ -209,7 +270,7 @@ String _get_plugins_tag(const String &plugins_names) { String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) { bool uses_xr = (int)(p_preset->get("xr_features/xr_mode")) == 1; - String orientation = (int)(p_preset->get("screen/orientation")) == 1 ? "portrait" : "landscape"; + String orientation = _get_android_orientation_label(_get_screen_orientation()); String manifest_activity_text = vformat( " <activity android:name=\"com.godot.game.GodotApp\" " "tools:replace=\"android:screenOrientation\" " diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp index 11faeff3e8..2446ca2829 100644 --- a/platform/android/file_access_android.cpp +++ b/platform/android/file_access_android.cpp @@ -34,7 +34,6 @@ AAssetManager *FileAccessAndroid::asset_manager = nullptr; /*void FileAccessAndroid::make_default() { - create_func=create_android; }*/ diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle index 821a4dc584..73c136ed0e 100644 --- a/platform/android/java/build.gradle +++ b/platform/android/java/build.gradle @@ -22,8 +22,6 @@ allprojects { } ext { - sconsExt = org.gradle.internal.os.OperatingSystem.current().isWindows() ? ".bat" : "" - supportedAbis = ["armv7", "arm64v8", "x86", "x86_64"] supportedTargets = ["release", "debug"] diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle index e3c5a02203..89ce3d15e6 100644 --- a/platform/android/java/lib/build.gradle +++ b/platform/android/java/lib/build.gradle @@ -64,10 +64,42 @@ android { throw new GradleException("Invalid default abi: " + defaultAbi) } + // Find scons' executable path + File sconsExecutableFile = null + def sconsName = "scons" + def sconsExts = (org.gradle.internal.os.OperatingSystem.current().isWindows() + ? [".bat", ".exe"] + : [""]) + logger.lifecycle("Looking for $sconsName executable path") + for (ext in sconsExts) { + String sconsNameExt = sconsName + ext + logger.lifecycle("Checking $sconsNameExt") + + sconsExecutableFile = org.gradle.internal.os.OperatingSystem.current().findInPath(sconsNameExt) + if (sconsExecutableFile != null) { + // We're done! + break + } + + // Check all the options in path + List<File> allOptions = org.gradle.internal.os.OperatingSystem.current().findAllInPath(sconsNameExt) + if (!allOptions.isEmpty()) { + // Pick the first option and we're done! + sconsExecutableFile = allOptions.get(0) + break + } + } + + if (sconsExecutableFile == null) { + throw new GradleException("Unable to find executable path for the '$sconsName' command.") + } else { + logger.lifecycle("Found executable path for $sconsName: ${sconsExecutableFile.absolutePath}") + } + // Creating gradle task to generate the native libraries for the default abi. def taskName = getSconsTaskName(buildType) tasks.create(name: taskName, type: Exec) { - executable "scons" + sconsExt + executable sconsExecutableFile.absolutePath args "--directory=${pathToRootDir}", "platform=android", "target=${releaseTarget}", "android_arch=${defaultAbi}", "-j" + Runtime.runtime.availableProcessors() } diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index 6cf340c418..3bbe35091c 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -760,9 +760,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC /* @Override public boolean dispatchKeyEvent(KeyEvent event) { - if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) { - System.out.printf("** BACK REQUEST!\n"); GodotLib.quit(); 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 874fd88848..894009e30f 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -515,13 +515,13 @@ public class GodotIO { activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); } break; case SCREEN_SENSOR_LANDSCAPE: { - activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE); } break; case SCREEN_SENSOR_PORTRAIT: { - activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT); } break; case SCREEN_SENSOR: { - activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } break; } } diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt index 7fa8e3b4e5..f93cf0fa38 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt @@ -52,7 +52,6 @@ import org.godotengine.godot.plugin.GodotPluginRegistry * @see [VkSurfaceView.startRenderer] */ internal class VkRenderer { - private val pluginRegistry: GodotPluginRegistry = GodotPluginRegistry.getPluginRegistry() /** 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 6b0e12b21a..e5c7a39bfb 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 @@ -50,7 +50,6 @@ import android.view.SurfaceView * </ul> */ open internal class VkSurfaceView(context: Context) : SurfaceView(context), SurfaceHolder.Callback { - companion object { fun checkState(expression: Boolean, errorMessage: Any) { check(expression) { errorMessage.toString() } diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt index 7557c8aa22..fb02e3a69f 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt @@ -41,7 +41,6 @@ import kotlin.concurrent.withLock * The implementation is modeled after [android.opengl.GLSurfaceView]'s GLThread. */ internal class VkThread(private val vkSurfaceView: VkSurfaceView, private val vkRenderer: VkRenderer) : Thread(TAG) { - companion object { private val TAG = VkThread::class.java.simpleName } @@ -226,5 +225,4 @@ internal class VkThread(private val vkSurfaceView: VkSurfaceView, private val vk threadExiting() } } - } |