diff options
Diffstat (limited to 'platform/android')
63 files changed, 741 insertions, 830 deletions
diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp index 10f23b320b..81802298d9 100644 --- a/platform/android/android_input_handler.cpp +++ b/platform/android/android_input_handler.cpp @@ -381,13 +381,3 @@ MouseButton AndroidInputHandler::_android_button_mask_to_godot_button_mask(int a return godot_button_mask; } - -void AndroidInputHandler::process_scroll(Point2 p_pos) { - Ref<InputEventPanGesture> ev; - ev.instantiate(); - _set_key_modifier_state(ev); - ev->set_position(p_pos); - ev->set_delta(p_pos - scroll_prev_pos); - Input::get_singleton()->parse_input_event(ev); - scroll_prev_pos = p_pos; -} diff --git a/platform/android/android_input_handler.h b/platform/android/android_input_handler.h index 2b237c4006..1397ca59e4 100644 --- a/platform/android/android_input_handler.h +++ b/platform/android/android_input_handler.h @@ -69,7 +69,6 @@ private: Vector<TouchPos> touch; Point2 hover_prev_pos; // needed to calculate the relative position on hover events - Point2 scroll_prev_pos; // needed to calculate the relative position on scroll events void _set_key_modifier_state(Ref<InputEventWithModifiers> ev); @@ -83,9 +82,8 @@ public: void process_hover(int p_type, Point2 p_pos); void process_mouse_event(int input_device, int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor = 0, float event_horizontal_factor = 0); void process_double_tap(int event_android_button_mask, Point2 p_pos); - void process_scroll(Point2 p_pos); void process_joy_event(JoypadEvent p_event); void process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed); }; -#endif +#endif // ANDROID_INPUT_HANDLER_H diff --git a/platform/android/api/java_class_wrapper.h b/platform/android/api/java_class_wrapper.h index 96b7b48e48..ac8d6585d3 100644 --- a/platform/android/api/java_class_wrapper.h +++ b/platform/android/api/java_class_wrapper.h @@ -63,7 +63,7 @@ class JavaClass : public RefCounted { ARG_TYPE_MASK = (1 << 16) - 1 }; - Map<StringName, Variant> constant_map; + RBMap<StringName, Variant> constant_map; struct MethodInfo { bool _static = false; @@ -174,7 +174,7 @@ class JavaClass : public RefCounted { bool _call_method(JavaObject *p_instance, const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error, Variant &ret); friend class JavaClassWrapper; - Map<StringName, List<MethodInfo>> methods; + HashMap<StringName, List<MethodInfo>> methods; jclass _class; #endif @@ -207,7 +207,7 @@ class JavaClassWrapper : public Object { GDCLASS(JavaClassWrapper, Object); #ifdef ANDROID_ENABLED - Map<String, Ref<JavaClass>> class_cache; + RBMap<String, Ref<JavaClass>> class_cache; friend class JavaClass; jclass activityClass; jmethodID findClass; diff --git a/platform/android/api/jni_singleton.h b/platform/android/api/jni_singleton.h index 74ca10e5e2..690fddae21 100644 --- a/platform/android/api/jni_singleton.h +++ b/platform/android/api/jni_singleton.h @@ -48,13 +48,13 @@ class JNISingleton : public Object { }; jobject instance; - Map<StringName, MethodData> method_map; + RBMap<StringName, MethodData> method_map; #endif public: virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override { #ifdef ANDROID_ENABLED - Map<StringName, MethodData>::Element *E = method_map.find(p_method); + RBMap<StringName, MethodData>::Element *E = method_map.find(p_method); // Check the method we're looking for is in the JNISingleton map and that // the arguments match. @@ -73,7 +73,7 @@ public: return Object::callp(p_method, p_args, p_argcount, r_error); } - ERR_FAIL_COND_V(!instance, Variant()); + ERR_FAIL_NULL_V(instance, Variant()); r_error.error = Callable::CallError::CALL_OK; diff --git a/platform/android/audio_driver_opensl.cpp b/platform/android/audio_driver_opensl.cpp index dcaa586e3b..6b22a0ffa1 100644 --- a/platform/android/audio_driver_opensl.cpp +++ b/platform/android/audio_driver_opensl.cpp @@ -80,8 +80,6 @@ void AudioDriverOpenSL::_buffer_callbacks( ad->_buffer_callback(queueItf); } -AudioDriverOpenSL *AudioDriverOpenSL::s_ad = nullptr; - const char *AudioDriverOpenSL::get_name() const { return "Android"; } @@ -133,8 +131,6 @@ void AudioDriverOpenSL::start() { ERR_FAIL_COND(res != SL_RESULT_SUCCESS); SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, BUFFER_COUNT }; - //bufferQueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE; - //bufferQueue.numBuffers = BUFFER_COUNT; /* Four buffers in our buffer queue */ /* Setup the format of the content in the buffer queue */ pcm.formatType = SL_DATAFORMAT_PCM; pcm.numChannels = 2; @@ -155,13 +151,8 @@ void AudioDriverOpenSL::start() { locator_outputmix.outputMix = OutputMix; audioSink.pLocator = (void *)&locator_outputmix; audioSink.pFormat = nullptr; - /* Initialize the context for Buffer queue callbacks */ - //cntxt.pDataBase = (void*)&pcmData; - //cntxt.pData = cntxt.pDataBase; - //cntxt.size = sizeof(pcmData); /* Create the music player */ - { const SLInterfaceID ids[2] = { SL_IID_BUFFERQUEUE, SL_IID_EFFECTSEND }; const SLboolean req[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE }; @@ -341,5 +332,4 @@ void AudioDriverOpenSL::set_pause(bool p_pause) { } AudioDriverOpenSL::AudioDriverOpenSL() { - s_ad = this; } diff --git a/platform/android/audio_driver_opensl.h b/platform/android/audio_driver_opensl.h index eea1fc227f..7b09438858 100644 --- a/platform/android/audio_driver_opensl.h +++ b/platform/android/audio_driver_opensl.h @@ -105,4 +105,4 @@ public: AudioDriverOpenSL(); }; -#endif // AUDIO_DRIVER_ANDROID_H +#endif // AUDIO_DRIVER_OPENSL_H diff --git a/platform/android/detect.py b/platform/android/detect.py index 0099ac7e0d..47cfade765 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -1,7 +1,7 @@ import os import sys import platform -from distutils.version import LooseVersion +import subprocess def is_active(): @@ -13,41 +13,35 @@ def get_name(): def can_build(): - return ("ANDROID_SDK_ROOT" in os.environ) or ("ANDROID_HOME" in os.environ) - - -def get_platform(platform): - return int(platform.split("-")[1]) + return os.path.exists(get_env_android_sdk_root()) def get_opts(): from SCons.Variables import BoolVariable, EnumVariable return [ - ("ANDROID_NDK_ROOT", "Path to the Android NDK", get_android_ndk_root()), - ("ANDROID_SDK_ROOT", "Path to the Android SDK", get_android_sdk_root()), + ("ANDROID_SDK_ROOT", "Path to the Android SDK", get_env_android_sdk_root()), ("ndk_platform", 'Target platform (android-<api>, e.g. "android-24")', "android-24"), EnumVariable("android_arch", "Target architecture", "arm64v8", ("armv7", "arm64v8", "x86", "x86_64")), ] # Return the ANDROID_SDK_ROOT environment variable. -# While ANDROID_HOME has been deprecated, it's used as a fallback for backward -# compatibility purposes. -def get_android_sdk_root(): - if "ANDROID_SDK_ROOT" in os.environ: - return os.environ.get("ANDROID_SDK_ROOT", 0) - else: - return os.environ.get("ANDROID_HOME", 0) +def get_env_android_sdk_root(): + return os.environ.get("ANDROID_SDK_ROOT", -1) -# Return the ANDROID_NDK_ROOT environment variable. -# We generate one for this build using the ANDROID_SDK_ROOT env -# variable and the project ndk version. -# If the env variable is already defined, we override it with -# our own to match what the project expects. -def get_android_ndk_root(): - return get_android_sdk_root() + "/ndk/" + get_project_ndk_version() +def get_min_sdk_version(platform): + return int(platform.split("-")[1]) + + +def get_android_ndk_root(env): + return env["ANDROID_SDK_ROOT"] + "/ndk/" + get_ndk_version() + + +# This is kept in sync with the value in 'platform/android/java/app/config.gradle'. +def get_ndk_version(): + return "23.2.8568313" def get_flags(): @@ -56,133 +50,70 @@ def get_flags(): ] -def create(env): - tools = env["TOOLS"] - if "mingw" in tools: - tools.remove("mingw") - if "applelink" in tools: - tools.remove("applelink") - env.Tool("gcc") - return env.Clone(tools=tools) - - -# Check if ANDROID_NDK_ROOT is valid. -# If not, install the ndk using ANDROID_SDK_ROOT and sdkmanager. +# Check if Android NDK version is installed +# If not, install it. def install_ndk_if_needed(env): print("Checking for Android NDK...") - env_ndk_version = get_env_ndk_version(env["ANDROID_NDK_ROOT"]) - if env_ndk_version is None: - # Reinstall the ndk and update ANDROID_NDK_ROOT. - print("Installing Android NDK...") - if env["ANDROID_SDK_ROOT"] is None: - raise Exception("Invalid ANDROID_SDK_ROOT environment variable.") - - import subprocess - + sdk_root = env["ANDROID_SDK_ROOT"] + if not os.path.exists(get_android_ndk_root(env)): extension = ".bat" if os.name == "nt" else "" - sdkmanager_path = env["ANDROID_SDK_ROOT"] + "/cmdline-tools/latest/bin/sdkmanager" + extension - ndk_download_args = "ndk;" + get_project_ndk_version() - subprocess.check_call([sdkmanager_path, ndk_download_args]) - - env["ANDROID_NDK_ROOT"] = env["ANDROID_SDK_ROOT"] + "/ndk/" + get_project_ndk_version() - print("ANDROID_NDK_ROOT: " + env["ANDROID_NDK_ROOT"]) + sdkmanager = sdk_root + "/cmdline-tools/latest/bin/sdkmanager" + extension + if os.path.exists(sdkmanager): + # Install the Android NDK + print("Installing Android NDK...") + ndk_download_args = "ndk;" + get_ndk_version() + subprocess.check_call([sdkmanager, ndk_download_args]) + else: + print("Cannot find " + sdkmanager) + print( + "Please ensure ANDROID_SDK_ROOT is correct and cmdline-tools are installed, or install NDK version " + + get_ndk_version() + + " manually." + ) + sys.exit() + env["ANDROID_NDK_ROOT"] = get_android_ndk_root(env) def configure(env): install_ndk_if_needed(env) - - # Workaround for MinGW. See: - # https://www.scons.org/wiki/LongCmdLinesOnWin32 - if os.name == "nt": - - import subprocess - - def mySubProcess(cmdline, env): - # print("SPAWNED : " + cmdline) - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW - proc = subprocess.Popen( - cmdline, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - startupinfo=startupinfo, - shell=False, - env=env, - ) - data, err = proc.communicate() - rv = proc.wait() - if rv: - print("=====") - print(err) - print("=====") - return rv - - def mySpawn(sh, escape, cmd, args, env): - - newargs = " ".join(args[1:]) - cmdline = cmd + " " + newargs - - rv = 0 - if len(cmdline) > 32000 and cmd.endswith("ar"): - cmdline = cmd + " " + args[1] + " " + args[2] + " " - for i in range(3, len(args)): - rv = mySubProcess(cmdline + args[i], env) - if rv: - break - else: - rv = mySubProcess(cmdline, env) - - return rv - - env["SPAWN"] = mySpawn + ndk_root = env["ANDROID_NDK_ROOT"] # Architecture if env["android_arch"] not in ["armv7", "arm64v8", "x86", "x86_64"]: - env["android_arch"] = "armv7" + env["android_arch"] = "arm64v8" print("Building for Android, platform " + env["ndk_platform"] + " (" + env["android_arch"] + ")") - can_vectorize = True - if env["android_arch"] == "x86": - env["ARCH"] = "arch-x86" - env.extra_suffix = ".x86" + env.extra_suffix - target_subpath = "x86-4.9" - abi_subpath = "i686-linux-android" - arch_subpath = "x86" - env["x86_libtheora_opt_gcc"] = True - elif env["android_arch"] == "x86_64": - if get_platform(env["ndk_platform"]) < 21: + if get_min_sdk_version(env["ndk_platform"]) < 21: + if env["android_arch"] == "x86_64" or env["android_arch"] == "arm64v8": print( - "WARNING: android_arch=x86_64 is not supported by ndk_platform lower than android-21; setting" - " ndk_platform=android-21" + "WARNING: android_arch=" + + env["android_arch"] + + " is not supported by ndk_platform lower than android-21; setting ndk_platform=android-21" ) env["ndk_platform"] = "android-21" - env["ARCH"] = "arch-x86_64" - env.extra_suffix = ".x86_64" + env.extra_suffix - target_subpath = "x86_64-4.9" - abi_subpath = "x86_64-linux-android" - arch_subpath = "x86_64" - env["x86_libtheora_opt_gcc"] = True - elif env["android_arch"] == "armv7": - env["ARCH"] = "arch-arm" - target_subpath = "arm-linux-androideabi-4.9" - abi_subpath = "arm-linux-androideabi" - arch_subpath = "armeabi-v7a" + + if env["android_arch"] == "armv7": + target_triple = "armv7a-linux-androideabi" + bin_utils = "arm-linux-androideabi" env.extra_suffix = ".armv7" + env.extra_suffix elif env["android_arch"] == "arm64v8": - if get_platform(env["ndk_platform"]) < 21: - print( - "WARNING: android_arch=arm64v8 is not supported by ndk_platform lower than android-21; setting" - " ndk_platform=android-21" - ) - env["ndk_platform"] = "android-21" - env["ARCH"] = "arch-arm64" - target_subpath = "aarch64-linux-android-4.9" - abi_subpath = "aarch64-linux-android" - arch_subpath = "arm64-v8a" + target_triple = "aarch64-linux-android" + bin_utils = target_triple env.extra_suffix = ".armv8" + env.extra_suffix + elif env["android_arch"] == "x86": + target_triple = "i686-linux-android" + bin_utils = target_triple + env.extra_suffix = ".x86" + env.extra_suffix + elif env["android_arch"] == "x86_64": + target_triple = "x86_64-linux-android" + bin_utils = target_triple + env.extra_suffix = ".x86_64" + env.extra_suffix + + target_option = ["-target", target_triple + str(get_min_sdk_version(env["ndk_platform"]))] + env.Append(CCFLAGS=target_option) + env.Append(LINKFLAGS=target_option) # Build type @@ -191,15 +122,11 @@ def configure(env): # `-O2` is more friendly to debuggers than `-O3`, leading to better crash backtraces # when using `target=release_debug`. opt = "-O3" if env["target"] == "release" else "-O2" - env.Append(LINKFLAGS=[opt]) env.Append(CCFLAGS=[opt, "-fomit-frame-pointer"]) elif env["optimize"] == "size": # optimize for size - env.Append(CCFLAGS=["-Os"]) - env.Append(LINKFLAGS=["-Os"]) - + env.Append(CCFLAGS=["-Oz"]) env.Append(CPPDEFINES=["NDEBUG"]) - if can_vectorize: - env.Append(CCFLAGS=["-ftree-vectorize"]) + env.Append(CCFLAGS=["-ftree-vectorize"]) elif env["target"] == "debug": env.Append(LINKFLAGS=["-O0"]) env.Append(CCFLAGS=["-O0", "-g", "-fno-limit-debug-info"]) @@ -211,7 +138,6 @@ def configure(env): env["SHLIBSUFFIX"] = ".so" if env["PLATFORM"] == "win32": - env.Tool("gcc") env.use_windows_spawn_fix() if sys.platform.startswith("linux"): @@ -224,32 +150,15 @@ def configure(env): else: host_subpath = "windows" - compiler_path = env["ANDROID_NDK_ROOT"] + "/toolchains/llvm/prebuilt/" + host_subpath + "/bin" - gcc_toolchain_path = env["ANDROID_NDK_ROOT"] + "/toolchains/" + target_subpath + "/prebuilt/" + host_subpath - tools_path = gcc_toolchain_path + "/" + abi_subpath + "/bin" - - # For Clang to find NDK tools in preference of those system-wide - env.PrependENVPath("PATH", tools_path) - - ccache_path = os.environ.get("CCACHE") - if ccache_path is None: - env["CC"] = compiler_path + "/clang" - env["CXX"] = compiler_path + "/clang++" - else: - # there aren't any ccache wrappers available for Android, - # to enable caching we need to prepend the path to the ccache binary - env["CC"] = ccache_path + " " + compiler_path + "/clang" - env["CXX"] = ccache_path + " " + compiler_path + "/clang++" - env["AR"] = tools_path + "/ar" - env["RANLIB"] = tools_path + "/ranlib" - env["AS"] = tools_path + "/as" + toolchain_path = ndk_root + "/toolchains/llvm/prebuilt/" + host_subpath + compiler_path = toolchain_path + "/bin" + bin_utils_path = toolchain_path + "/" + bin_utils + "/bin" - common_opts = ["-gcc-toolchain", gcc_toolchain_path] - - # Compile flags - - env.Append(CPPFLAGS=["-isystem", env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++/include"]) - env.Append(CPPFLAGS=["-isystem", env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++abi/include"]) + env["CC"] = compiler_path + "/clang" + env["CXX"] = compiler_path + "/clang++" + env["AR"] = compiler_path + "/llvm-ar" + env["RANLIB"] = compiler_path + "/llvm-ranlib" + env["AS"] = bin_utils_path + "/as" # Disable exceptions and rtti on non-tools (template) builds if env["tools"]: @@ -261,100 +170,31 @@ def configure(env): # Don't use dynamic_cast, necessary with no-rtti. env.Append(CPPDEFINES=["NO_SAFE_CAST"]) - lib_sysroot = env["ANDROID_NDK_ROOT"] + "/platforms/" + env["ndk_platform"] + "/" + env["ARCH"] - - # Using NDK unified headers (NDK r15+) - sysroot = env["ANDROID_NDK_ROOT"] + "/sysroot" - env.Append(CPPFLAGS=["--sysroot=" + sysroot]) - env.Append(CPPFLAGS=["-isystem", sysroot + "/usr/include/" + abi_subpath]) - env.Append(CPPFLAGS=["-isystem", env["ANDROID_NDK_ROOT"] + "/sources/android/support/include"]) - # For unified headers this define has to be set manually - env.Append(CPPDEFINES=[("__ANDROID_API__", str(get_platform(env["ndk_platform"])))]) - env.Append( CCFLAGS=( - "-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden" - " -fno-strict-aliasing".split() + "-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing".split() ) ) env.Append(CPPDEFINES=["NO_STATVFS", "GLES_ENABLED"]) - if get_platform(env["ndk_platform"]) >= 24: + if get_min_sdk_version(env["ndk_platform"]) >= 24: env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)]) if env["android_arch"] == "x86": - target_opts = ["-target", "i686-none-linux-android"] - # The NDK adds this if targeting API < 21, so we can drop it when Godot targets it at least + # The NDK adds this if targeting API < 24, so we can drop it when Godot targets it at least env.Append(CCFLAGS=["-mstackrealign"]) - - elif env["android_arch"] == "x86_64": - target_opts = ["-target", "x86_64-none-linux-android"] - elif env["android_arch"] == "armv7": - target_opts = ["-target", "armv7-none-linux-androideabi"] env.Append(CCFLAGS="-march=armv7-a -mfloat-abi=softfp".split()) env.Append(CPPDEFINES=["__ARM_ARCH_7__", "__ARM_ARCH_7A__"]) - # Enable ARM NEON instructions to compile more optimized code. - env.Append(CCFLAGS=["-mfpu=neon"]) env.Append(CPPDEFINES=["__ARM_NEON__"]) - elif env["android_arch"] == "arm64v8": - target_opts = ["-target", "aarch64-none-linux-android"] env.Append(CCFLAGS=["-mfix-cortex-a53-835769"]) env.Append(CPPDEFINES=["__ARM_ARCH_8A__"]) - env.Append(CCFLAGS=target_opts) - env.Append(CCFLAGS=common_opts) - # Link flags - ndk_version = get_env_ndk_version(env["ANDROID_NDK_ROOT"]) - if ndk_version != None and LooseVersion(ndk_version) >= LooseVersion("17.1.4828580"): - env.Append(LINKFLAGS=["-Wl,--exclude-libs,libgcc.a", "-Wl,--exclude-libs,libatomic.a", "-nostdlib++"]) - else: - env.Append( - LINKFLAGS=[ - env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++/libs/" + arch_subpath + "/libandroid_support.a" - ] - ) - env.Append(LINKFLAGS=["-shared", "--sysroot=" + lib_sysroot, "-Wl,--warn-shared-textrel"]) - env.Append(LIBPATH=[env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++/libs/" + arch_subpath + "/"]) - env.Append( - LINKFLAGS=[env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++/libs/" + arch_subpath + "/libc++_shared.so"] - ) - - if env["android_arch"] == "armv7": - env.Append(LINKFLAGS="-Wl,--fix-cortex-a8".split()) - env.Append(LINKFLAGS="-Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now".split()) - env.Append(LINKFLAGS="-Wl,-soname,libgodot_android.so -Wl,--gc-sections".split()) - - env.Append(LINKFLAGS=target_opts) - env.Append(LINKFLAGS=common_opts) - - env.Append( - LIBPATH=[ - env["ANDROID_NDK_ROOT"] - + "/toolchains/" - + target_subpath - + "/prebuilt/" - + host_subpath - + "/lib/gcc/" - + abi_subpath - + "/4.9.x" - ] - ) - env.Append( - LIBPATH=[ - env["ANDROID_NDK_ROOT"] - + "/toolchains/" - + target_subpath - + "/prebuilt/" - + host_subpath - + "/" - + abi_subpath - + "/lib" - ] - ) + env.Append(LINKFLAGS="-Wl,--gc-sections -Wl,--no-undefined -Wl,-z,now".split()) + env.Append(LINKFLAGS="-Wl,-soname,libgodot_android.so") env.Prepend(CPPPATH=["#platform/android"]) env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED", "NO_FCNTL"]) @@ -364,25 +204,3 @@ def configure(env): env.Append(CPPDEFINES=["VULKAN_ENABLED"]) if not env["use_volk"]: env.Append(LIBS=["vulkan"]) - - -# Return the project NDK version. -# This is kept in sync with the value in 'platform/android/java/app/config.gradle'. -def get_project_ndk_version(): - return "21.4.7075529" - - -# Return NDK version string in source.properties (adapted from the Chromium project). -def get_env_ndk_version(path): - if path is None: - return None - prop_file_path = os.path.join(path, "source.properties") - try: - with open(prop_file_path) as prop_file: - for line in prop_file: - key_value = list(map(lambda x: x.strip(), line.split("="))) - if key_value[0] == "Pkg.Revision": - return key_value[1] - except Exception: - print("Could not read source prop file '%s'" % prop_file_path) - return None diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp index e2b1c757d6..5b9eee8117 100644 --- a/platform/android/dir_access_jandroid.cpp +++ b/platform/android/dir_access_jandroid.cpp @@ -55,7 +55,6 @@ Error DirAccessJAndroid::list_dir_begin() { if (res <= 0) { return ERR_CANT_OPEN; } - id = res; return OK; @@ -69,7 +68,6 @@ String DirAccessJAndroid::get_next() { if (!str) { return ""; } - String ret = jstring_to_string((jstring)str, env); env->DeleteLocalRef((jobject)str); return ret; @@ -89,7 +87,6 @@ void DirAccessJAndroid::list_dir_end() { if (id == 0) { return; } - JNIEnv *env = get_jni_env(); env->CallVoidMethod(io, _dir_close, id); id = 0; @@ -228,12 +225,9 @@ void DirAccessJAndroid::setup(jobject p_io) { _dir_next = env->GetMethodID(cls, "dir_next", "(I)Ljava/lang/String;"); _dir_close = env->GetMethodID(cls, "dir_close", "(I)V"); _dir_is_dir = env->GetMethodID(cls, "dir_is_dir", "(I)Z"); - - //(*env)->CallVoidMethod(env,obj,aMethodID, myvar); } DirAccessJAndroid::DirAccessJAndroid() { - id = 0; } DirAccessJAndroid::~DirAccessJAndroid() { diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h index 3d3c9f9223..0e1b12cb58 100644 --- a/platform/android/dir_access_jandroid.h +++ b/platform/android/dir_access_jandroid.h @@ -36,8 +36,6 @@ #include <stdio.h> class DirAccessJAndroid : public DirAccess { - //AAssetDir* aad; - static jobject io; static jclass cls; @@ -46,7 +44,7 @@ class DirAccessJAndroid : public DirAccess { static jmethodID _dir_close; static jmethodID _dir_is_dir; - int id; + int id = 0; String current_dir; String current; diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index d414ea5824..3be220d110 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -105,7 +105,7 @@ void DisplayServerAndroid::tts_stop() { void DisplayServerAndroid::clipboard_set(const String &p_text) { GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); - ERR_FAIL_COND(!godot_java); + ERR_FAIL_NULL(godot_java); if (godot_java->has_set_clipboard()) { godot_java->set_clipboard(p_text); @@ -116,7 +116,7 @@ void DisplayServerAndroid::clipboard_set(const String &p_text) { String DisplayServerAndroid::clipboard_get() const { GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); - ERR_FAIL_COND_V(!godot_java, String()); + ERR_FAIL_NULL_V(godot_java, String()); if (godot_java->has_get_clipboard()) { return godot_java->get_clipboard(); @@ -127,7 +127,7 @@ String DisplayServerAndroid::clipboard_get() const { bool DisplayServerAndroid::clipboard_has() const { GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); - ERR_FAIL_COND_V(!godot_java, false); + ERR_FAIL_NULL_V(godot_java, false); if (godot_java->has_has_clipboard()) { return godot_java->has_clipboard(); @@ -150,7 +150,7 @@ Rect2i DisplayServerAndroid::get_display_safe_area() const { void DisplayServerAndroid::screen_set_keep_on(bool p_enable) { GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); - ERR_FAIL_COND(!godot_java); + ERR_FAIL_NULL(godot_java); godot_java->set_keep_screen_on(p_enable); keep_screen_on = p_enable; @@ -162,14 +162,14 @@ bool DisplayServerAndroid::screen_is_kept_on() const { void DisplayServerAndroid::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) { GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); - ERR_FAIL_COND(!godot_io_java); + ERR_FAIL_NULL(godot_io_java); godot_io_java->set_screen_orientation(p_orientation); } DisplayServer::ScreenOrientation DisplayServerAndroid::screen_get_orientation(int p_screen) const { GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); - ERR_FAIL_COND_V(!godot_io_java, SCREEN_LANDSCAPE); + ERR_FAIL_NULL_V(godot_io_java, SCREEN_LANDSCAPE); const int orientation = godot_io_java->get_screen_orientation(); ERR_FAIL_INDEX_V_MSG(orientation, 7, SCREEN_LANDSCAPE, "Unrecognized screen orientation"); @@ -195,14 +195,14 @@ Rect2i DisplayServerAndroid::screen_get_usable_rect(int p_screen) const { int DisplayServerAndroid::screen_get_dpi(int p_screen) const { GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); - ERR_FAIL_COND_V(!godot_io_java, 0); + ERR_FAIL_NULL_V(godot_io_java, 0); return godot_io_java->get_screen_dpi(); } float DisplayServerAndroid::screen_get_scale(int p_screen) const { GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); - ERR_FAIL_COND_V(!godot_io_java, 1.0f); + ERR_FAIL_NULL_V(godot_io_java, 1.0f); return godot_io_java->get_scaled_density(); } @@ -223,7 +223,7 @@ bool DisplayServerAndroid::screen_is_touchscreen(int p_screen) const { void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) { GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); - ERR_FAIL_COND(!godot_io_java); + ERR_FAIL_NULL(godot_io_java); if (godot_io_java->has_vk()) { godot_io_java->show_vk(p_existing_text, p_multiline, p_max_length, p_cursor_start, p_cursor_end); @@ -234,7 +234,7 @@ void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, void DisplayServerAndroid::virtual_keyboard_hide() { GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); - ERR_FAIL_COND(!godot_io_java); + ERR_FAIL_NULL(godot_io_java); if (godot_io_java->has_vk()) { godot_io_java->hide_vk(); @@ -245,7 +245,7 @@ void DisplayServerAndroid::virtual_keyboard_hide() { int DisplayServerAndroid::virtual_keyboard_get_height() const { GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); - ERR_FAIL_COND_V(!godot_io_java, 0); + ERR_FAIL_NULL_V(godot_io_java, 0); return godot_io_java->get_vk_height(); } @@ -456,9 +456,9 @@ void DisplayServerAndroid::reset_window() { #if defined(VULKAN_ENABLED) if (rendering_driver == "vulkan") { ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window(); - ERR_FAIL_COND(!native_window); + ERR_FAIL_NULL(native_window); - ERR_FAIL_COND(!context_vulkan); + ERR_FAIL_NULL(context_vulkan); VSyncMode last_vsync_mode = context_vulkan->get_vsync_mode(MAIN_WINDOW_ID); context_vulkan->window_destroy(MAIN_WINDOW_ID); @@ -519,7 +519,7 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis if (rendering_driver == "vulkan") { ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window(); - ERR_FAIL_COND(!native_window); + ERR_FAIL_NULL(native_window); context_vulkan = memnew(VulkanContextAndroid); if (context_vulkan->initialize() != OK) { diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index aa4b394965..560f188b82 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -36,11 +36,6 @@ #include "editor/editor_settings.h" void register_android_exporter() { - String exe_ext; - if (OS::get_singleton()->get_name() == "Windows") { - exe_ext = "*.exe"; - } - EDITOR_DEF("export/android/android_sdk_path", ""); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/android_sdk_path", PROPERTY_HINT_GLOBAL_DIR)); EDITOR_DEF("export/android/debug_keystore", ""); diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 5aef64943b..b40c1f5090 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -207,9 +207,9 @@ static const char *SPLASH_CONFIG_PATH = "res://android/build/res/drawable/splash static const char *GDNATIVE_LIBS_PATH = "res://android/build/libs/gdnativelibs.json"; static const int icon_densities_count = 6; -static const char *launcher_icon_option = "launcher_icons/main_192x192"; -static const char *launcher_adaptive_icon_foreground_option = "launcher_icons/adaptive_foreground_432x432"; -static const char *launcher_adaptive_icon_background_option = "launcher_icons/adaptive_background_432x432"; +static const char *launcher_icon_option = PNAME("launcher_icons/main_192x192"); +static const char *launcher_adaptive_icon_foreground_option = PNAME("launcher_icons/adaptive_foreground_432x432"); +static const char *launcher_adaptive_icon_background_option = PNAME("launcher_icons/adaptive_background_432x432"); static const LauncherIcon launcher_icons[icon_densities_count] = { { "res/mipmap-xxxhdpi-v4/icon.png", 192 }, @@ -245,7 +245,7 @@ static const char *APK_ASSETS_DIRECTORY = "res://android/build/assets"; static const char *AAB_ASSETS_DIRECTORY = "res://android/build/assetPacks/installTime/src/main/assets"; 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 = 30; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk' +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) { @@ -409,7 +409,7 @@ void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) { List<String> args; args.push_back("kill-server"); OS::get_singleton()->execute(adb, args); - }; + } } String EditorExportPlatformAndroid::get_project_name(const String &p_name) const { @@ -522,8 +522,8 @@ bool EditorExportPlatformAndroid::is_package_name_valid(const String &p_package, bool EditorExportPlatformAndroid::_should_compress_asset(const String &p_path, const Vector<uint8_t> &p_data) { /* - * By not compressing files with little or not benefit in doing so, - * a performance gain is expected attime. Moreover, if the APK is + * By not compressing files with little or no benefit in doing so, + * a performance gain is expected at runtime. Moreover, if the APK is * zip-aligned, assets stored as they are can be efficiently read by * Android by memory-mapping them. */ @@ -807,7 +807,6 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref<EditorExportPres } manifest_text += _get_xr_features_tag(p_preset); - manifest_text += _get_instrumentation_tag(p_preset); manifest_text += _get_application_tag(p_preset, _has_storage_permission(perms)); manifest_text += "</manifest>\n"; String manifest_path = vformat("res://android/build/src/%s/AndroidManifest.xml", (p_debug ? "debug" : "release")); @@ -834,11 +833,9 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p uint32_t ofs = 8; uint32_t string_count = 0; - //uint32_t styles_count = 0; uint32_t string_flags = 0; uint32_t string_data_offset = 0; - //uint32_t styles_offset = 0; uint32_t string_table_begins = 0; uint32_t string_table_ends = 0; Vector<uint8_t> stable_extra; @@ -879,10 +876,8 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p int iofs = ofs + 8; string_count = decode_uint32(&p_manifest[iofs]); - // iofs + 4 is `styles_count`. string_flags = decode_uint32(&p_manifest[iofs + 8]); string_data_offset = decode_uint32(&p_manifest[iofs + 12]); - // iofs + 16 is `styles_offset`. uint32_t st_offset = iofs + 20; string_table.resize(string_count); @@ -969,10 +964,6 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p encode_uint32(retain_data_on_uninstall, &p_manifest.write[iofs + 16]); } - if (tname == "instrumentation" && attrname == "targetPackage") { - string_table.write[attr_value] = get_package_name(package_name); - } - if (tname == "activity" && attrname == "screenOrientation") { encode_uint32(screen_orientation, &p_manifest.write[iofs + 16]); } @@ -1697,7 +1688,7 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio Vector<PluginConfigAndroid> plugins_configs = get_plugins(); for (int i = 0; i < plugins_configs.size(); i++) { print_verbose("Found Android plugin " + plugins_configs[i].name); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + plugins_configs[i].name), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("plugins"), plugins_configs[i].name)), false)); } plugins_changed.clear(); @@ -1707,7 +1698,7 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio // All Android devices supporting Vulkan run 64-bit Android, // so there is usually no point in exporting for 32-bit Android. const bool is_default = abi == "arm64-v8a"; - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "architectures/" + abi), is_default)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("architectures"), abi)), is_default)); } r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"), "")); @@ -1758,7 +1749,7 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio const char **perms = android_perms; while (*perms) { - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "permissions/" + String(*perms).to_lower()), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("permissions"), String(*perms).to_lower())), false)); perms++; } } @@ -1827,7 +1818,7 @@ Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset, String can_export_error; bool can_export_missing_templates; if (!can_export(p_preset, can_export_error, can_export_missing_templates)) { - EditorNode::add_io_error(can_export_error); + add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), can_export_error); return ERR_UNCONFIGURED; } @@ -1855,7 +1846,8 @@ Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset, { \ DirAccess::remove_file_or_error(tmp_export_path); \ return m_err; \ - } + } \ + ((void)0) // Export to temporary APK before sending to device. Error err = export_project_helper(p_preset, true, tmp_export_path, EXPORT_FORMAT_APK, true, p_debug_flags); @@ -1905,7 +1897,7 @@ Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset, err = OS::get_singleton()->execute(adb, args, &output, &rv, true); print_verbose(output); if (err || rv != 0) { - EditorNode::add_io_error(vformat(TTR("Could not install to device: %s"), output)); + add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), vformat(TTR("Could not install to device: %s"), output)); CLEANUP_AND_RETURN(ERR_CANT_CREATE); } @@ -1983,7 +1975,7 @@ Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset, err = OS::get_singleton()->execute(adb, args, &output, &rv, true); print_verbose(output); if (err || rv != 0) { - EditorNode::add_io_error(TTR("Could not execute on device.")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), TTR("Could not execute on device.")); CLEANUP_AND_RETURN(ERR_CANT_CREATE); } @@ -2038,7 +2030,7 @@ String EditorExportPlatformAndroid::get_apksigner_path() { da->list_dir_end(); if (apksigner_path.is_empty()) { - EditorNode::get_singleton()->show_warning(TTR("Unable to find the 'apksigner' tool.")); + print_error("Unable to find the 'apksigner' tool."); } return apksigner_path; @@ -2343,7 +2335,7 @@ Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_pre String apksigner = get_apksigner_path(); print_verbose("Starting signing of the " + export_label + " binary using " + apksigner); if (!FileAccess::exists(apksigner)) { - EditorNode::add_io_error(vformat(TTR("'apksigner' could not be found.\nPlease check the command is available in the Android SDK build-tools directory.\nThe resulting %s is unsigned."), export_label)); + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("'apksigner' could not be found. Please check that the command is available in the Android SDK build-tools directory. The resulting %s is unsigned."), export_label)); return OK; } @@ -2376,7 +2368,7 @@ Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_pre } if (!FileAccess::exists(keystore)) { - EditorNode::add_io_error(TTR("Could not find keystore, unable to export.")); + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not find keystore, unable to export.")); return ERR_FILE_CANT_OPEN; } @@ -2397,10 +2389,14 @@ Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_pre } int retval; output.clear(); - OS::get_singleton()->execute(apksigner, args, &output, &retval, true); + Error err = OS::get_singleton()->execute(apksigner, args, &output, &retval, true); + if (err != OK) { + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start apksigner executable.")); + return err; + } print_verbose(output); if (retval) { - EditorNode::add_io_error(vformat(TTR("'apksigner' returned with error #%d"), retval)); + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("'apksigner' returned with error #%d"), retval)); return ERR_CANT_CREATE; } @@ -2417,10 +2413,14 @@ Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_pre } output.clear(); - OS::get_singleton()->execute(apksigner, args, &output, &retval, true); + err = OS::get_singleton()->execute(apksigner, args, &output, &retval, true); + if (err != OK) { + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start apksigner executable.")); + return err; + } print_verbose(output); if (retval) { - EditorNode::add_io_error(vformat(TTR("'apksigner' verification of %s failed."), export_label)); + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("'apksigner' verification of %s failed."), export_label)); return ERR_CANT_CREATE; } @@ -2528,22 +2528,21 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP if (export_format == EXPORT_FORMAT_AAB) { if (!p_path.ends_with(".aab")) { - EditorNode::get_singleton()->show_warning(TTR("Invalid filename! Android App Bundle requires the *.aab extension.")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Invalid filename! Android App Bundle requires the *.aab extension.")); return ERR_UNCONFIGURED; } if (apk_expansion) { - EditorNode::get_singleton()->show_warning(TTR("APK Expansion not compatible with Android App Bundle.")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("APK Expansion not compatible with Android App Bundle.")); return ERR_UNCONFIGURED; } } if (export_format == EXPORT_FORMAT_APK && !p_path.ends_with(".apk")) { - EditorNode::get_singleton()->show_warning( - TTR("Invalid filename! Android APK requires the *.apk extension.")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Invalid filename! Android APK requires the *.apk extension.")); return ERR_UNCONFIGURED; } if (export_format > EXPORT_FORMAT_AAB || export_format < EXPORT_FORMAT_APK) { - EditorNode::add_io_error(TTR("Unsupported export format!\n")); - return ERR_UNCONFIGURED; //TODO: is this the right error? + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Unsupported export format!")); + return ERR_UNCONFIGURED; } if (use_custom_build) { @@ -2553,13 +2552,13 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP print_verbose("Checking build version.."); Ref<FileAccess> f = FileAccess::open("res://android/.build_version", FileAccess::READ); if (f.is_null()) { - EditorNode::get_singleton()->show_warning(TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu.")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu.")); return ERR_UNCONFIGURED; } String version = f->get_line().strip_edges(); print_verbose("- build version: " + version); if (version != VERSION_FULL_CONFIG) { - EditorNode::get_singleton()->show_warning(vformat(TTR("Android build version mismatch:\n Template installed: %s\n Godot Version: %s\nPlease reinstall Android build template from 'Project' menu."), version, VERSION_FULL_CONFIG)); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Android build version mismatch: Template installed: %s, Godot version: %s. Please reinstall Android build template from 'Project' menu."), version, VERSION_FULL_CONFIG)); return ERR_UNCONFIGURED; } } @@ -2572,7 +2571,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP String project_name = get_project_name(p_preset->get("package/name")); err = _create_project_name_strings_files(p_preset, project_name); //project name localization. if (err != OK) { - EditorNode::add_io_error(TTR("Unable to overwrite res://android/build/res/*.xml files with project name")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Unable to overwrite res://android/build/res/*.xml files with project name.")); } // Copies the project icon files into the appropriate Gradle project directory. _copy_icons_to_gradle_project(p_preset, processed_splash_config_xml, splash_image, splash_bg_color_image, main_image, foreground, background); @@ -2589,7 +2588,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP user_data.debug = p_debug; err = export_project_files(p_preset, p_debug, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so); if (err != OK) { - EditorNode::add_io_error(TTR("Could not export project files to gradle project\n")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not export project files to gradle project.")); return err; } if (user_data.libs.size() > 0) { @@ -2601,7 +2600,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP print_verbose("Saving apk expansion file.."); err = save_apk_expansion_file(p_preset, p_debug, p_path); if (err != OK) { - EditorNode::add_io_error(TTR("Could not write expansion package file!")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not write expansion package file!")); return err; } } @@ -2686,7 +2685,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP debug_keystore = OS::get_singleton()->get_resource_dir().plus_file(debug_keystore).simplify_path(); } if (!FileAccess::exists(debug_keystore)) { - EditorNode::add_io_error(TTR("Could not find keystore, unable to export.")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Could not find keystore, unable to export.")); return ERR_FILE_CANT_OPEN; } @@ -2702,7 +2701,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP release_keystore = OS::get_singleton()->get_resource_dir().plus_file(release_keystore).simplify_path(); } if (!FileAccess::exists(release_keystore)) { - EditorNode::add_io_error(TTR("Could not find keystore, unable to export.")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Could not find keystore, unable to export.")); return ERR_FILE_CANT_OPEN; } @@ -2714,7 +2713,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP int result = EditorNode::get_singleton()->execute_and_show_output(TTR("Building Android Project (gradle)"), build_command, cmdline); if (result != 0) { - EditorNode::get_singleton()->show_warning(TTR("Building of Android project failed, check output for the error.\nAlternatively visit docs.godotengine.org for Android build documentation.")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Building of Android project failed, check output for the error. Alternatively visit docs.godotengine.org for Android build documentation.")); return ERR_CANT_CREATE; } @@ -2744,7 +2743,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP print_verbose("Copying Android binary using gradle command: " + String("\n") + build_command + " " + join_list(copy_args, String(" "))); int copy_result = EditorNode::get_singleton()->execute_and_show_output(TTR("Moving output"), build_command, copy_args); if (copy_result != 0) { - EditorNode::get_singleton()->show_warning(TTR("Unable to copy and rename export file, check gradle project directory for outputs.")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Unable to copy and rename export file, check gradle project directory for outputs.")); return ERR_CANT_CREATE; } @@ -2766,7 +2765,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP src_apk = find_export_template("android_release.apk"); } if (src_apk.is_empty()) { - EditorNode::add_io_error(vformat(TTR("Package not found: %s"), src_apk)); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Package not found: \"%s\"."), src_apk)); return ERR_FILE_NOT_FOUND; } } @@ -2784,7 +2783,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP unzFile pkg = unzOpen2(src_apk.utf8().get_data(), &io); if (!pkg) { - EditorNode::add_io_error(vformat(TTR("Could not find template APK to export:\n%s"), src_apk)); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not find template APK to export: \"%s\"."), src_apk)); return ERR_FILE_NOT_FOUND; } @@ -2799,7 +2798,8 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP { \ DirAccess::remove_file_or_error(tmp_unaligned_path); \ return m_err; \ - } + } \ + ((void)0) zipFile unaligned_apk = zipOpen2(tmp_unaligned_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io2); @@ -2914,7 +2914,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP if (!invalid_abis.is_empty()) { String unsupported_arch = String(", ").join(invalid_abis); - EditorNode::add_io_error(vformat(TTR("Missing libraries in the export template for the selected architectures: %s.\nPlease build a template with all required libraries, or uncheck the missing architectures in the export preset."), unsupported_arch)); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Missing libraries in the export template for the selected architectures: %s. Please build a template with all required libraries, or uncheck the missing architectures in the export preset."), unsupported_arch)); CLEANUP_AND_RETURN(ERR_FILE_NOT_FOUND); } @@ -2932,7 +2932,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP if (apk_expansion) { err = save_apk_expansion_file(p_preset, p_debug, p_path); if (err != OK) { - EditorNode::add_io_error(TTR("Could not write expansion package file!")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not write expansion package file!")); return err; } } else { @@ -2945,7 +2945,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP if (err != OK) { unzClose(pkg); - EditorNode::add_io_error(TTR("Could not export project files")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not export project files."))); CLEANUP_AND_RETURN(ERR_SKIP); } @@ -2981,7 +2981,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP unzFile tmp_unaligned = unzOpen2(tmp_unaligned_path.utf8().get_data(), &io); if (!tmp_unaligned) { - EditorNode::add_io_error(TTR("Could not unzip temporary unaligned APK.")); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not unzip temporary unaligned APK."))); CLEANUP_AND_RETURN(ERR_FILE_NOT_FOUND); } @@ -3067,7 +3067,7 @@ void EditorExportPlatformAndroid::get_platform_features(List<String> *r_features r_features->push_back("android"); } -void EditorExportPlatformAndroid::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) { +void EditorExportPlatformAndroid::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) { } EditorExportPlatformAndroid::EditorExportPlatformAndroid() { diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h index 0f267cf13a..eeb5aae0f1 100644 --- a/platform/android/export/export_plugin.h +++ b/platform/android/export/export_plugin.h @@ -28,6 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef ANDROID_EXPORT_PLUGIN_H +#define ANDROID_EXPORT_PLUGIN_H + #include "godot_plugin_config.h" #include "core/io/zip_io.h" @@ -228,9 +231,11 @@ public: virtual void get_platform_features(List<String> *r_features) override; - virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override; + virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override; EditorExportPlatformAndroid(); ~EditorExportPlatformAndroid(); }; + +#endif // ANDROID_EXPORT_PLUGIN_H diff --git a/platform/android/export/godot_plugin_config.cpp b/platform/android/export/godot_plugin_config.cpp index 1210c09666..3daf6e44cd 100644 --- a/platform/android/export/godot_plugin_config.cpp +++ b/platform/android/export/godot_plugin_config.cpp @@ -71,7 +71,6 @@ PluginConfigAndroid PluginConfigAndroid::resolve_prebuilt_plugin(PluginConfigAnd Vector<PluginConfigAndroid> PluginConfigAndroid::get_prebuilt_plugins(String plugins_base_dir) { Vector<PluginConfigAndroid> prebuilt_plugins; - // prebuilt_plugins.push_back(resolve_prebuilt_plugin(MY_PREBUILT_PLUGIN, plugins_base_dir)); return prebuilt_plugins; } diff --git a/platform/android/export/godot_plugin_config.h b/platform/android/export/godot_plugin_config.h index 51cb4dea47..5188f615d4 100644 --- a/platform/android/export/godot_plugin_config.h +++ b/platform/android/export/godot_plugin_config.h @@ -103,4 +103,4 @@ struct PluginConfigAndroid { static String get_plugins_names(Vector<PluginConfigAndroid> plugins_configs); }; -#endif // GODOT_PLUGIN_CONFIG_H +#endif // ANDROID_GODOT_PLUGIN_CONFIG_H diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp index d9574a1a52..9a470edfdd 100644 --- a/platform/android/export/gradle_export_util.cpp +++ b/platform/android/export/gradle_export_util.cpp @@ -232,19 +232,6 @@ String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset) { return manifest_xr_features; } -String _get_instrumentation_tag(const Ref<EditorExportPreset> &p_preset) { - String package_name = p_preset->get("package/unique_name"); - String manifest_instrumentation_text = vformat( - " <instrumentation\n" - " tools:node=\"replace\"\n" - " android:name=\".GodotInstrumentation\"\n" - " android:icon=\"@mipmap/icon\"\n" - " android:label=\"@string/godot_project_name_string\"\n" - " android:targetPackage=\"%s\" />\n", - package_name); - return manifest_instrumentation_text; -} - String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) { int xr_mode_index = (int)(p_preset->get("xr_features/xr_mode")); bool uses_xr = xr_mode_index == XR_MODE_OPENXR; diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index 30a7f04729..109852bdfc 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -102,10 +102,8 @@ String _get_screen_sizes_tag(const Ref<EditorExportPreset> &p_preset); String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset); -String _get_instrumentation_tag(const Ref<EditorExportPreset> &p_preset); - String _get_activity_tag(const Ref<EditorExportPreset> &p_preset); String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_storage_permission); -#endif //GODOT_GRADLE_EXPORT_UTIL_H +#endif // GODOT_GRADLE_EXPORT_UTIL_H diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp index d7ba31e3c9..4bb8a13bb6 100644 --- a/platform/android/file_access_android.cpp +++ b/platform/android/file_access_android.cpp @@ -49,11 +49,11 @@ Error FileAccessAndroid::_open(const String &p_path, int p_mode_flags) { } ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, ERR_UNAVAILABLE); //can't write on android.. - a = AAssetManager_open(asset_manager, path.utf8().get_data(), AASSET_MODE_STREAMING); - if (!a) { + asset = AAssetManager_open(asset_manager, path.utf8().get_data(), AASSET_MODE_STREAMING); + if (!asset) { return ERR_CANT_OPEN; } - len = AAsset_getLength(a); + len = AAsset_getLength(asset); pos = 0; eof = false; @@ -61,21 +61,21 @@ Error FileAccessAndroid::_open(const String &p_path, int p_mode_flags) { } void FileAccessAndroid::_close() { - if (!a) { + if (!asset) { return; } - AAsset_close(a); - a = nullptr; + AAsset_close(asset); + asset = nullptr; } bool FileAccessAndroid::is_open() const { - return a != nullptr; + return asset != nullptr; } void FileAccessAndroid::seek(uint64_t p_position) { - ERR_FAIL_COND(!a); + ERR_FAIL_NULL(asset); - AAsset_seek(a, p_position, SEEK_SET); + AAsset_seek(asset, p_position, SEEK_SET); pos = p_position; if (pos > len) { pos = len; @@ -86,8 +86,8 @@ void FileAccessAndroid::seek(uint64_t p_position) { } void FileAccessAndroid::seek_end(int64_t p_position) { - ERR_FAIL_COND(!a); - AAsset_seek(a, p_position, SEEK_END); + ERR_FAIL_NULL(asset); + AAsset_seek(asset, p_position, SEEK_END); pos = len + p_position; } @@ -110,7 +110,7 @@ uint8_t FileAccessAndroid::get_8() const { } uint8_t byte; - AAsset_read(a, &byte, 1); + AAsset_read(asset, &byte, 1); pos++; return byte; } @@ -118,7 +118,7 @@ uint8_t FileAccessAndroid::get_8() const { uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); - int r = AAsset_read(a, p_dst, p_length); + int r = AAsset_read(asset, p_dst, p_length); if (pos + p_length > len) { eof = true; diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h index 33b692da20..c16f74ac43 100644 --- a/platform/android/file_access_android.h +++ b/platform/android/file_access_android.h @@ -35,11 +35,10 @@ #include <android/asset_manager.h> #include <android/log.h> #include <stdio.h> -//#include <android_native_app_glue.h> class FileAccessAndroid : public FileAccess { static Ref<FileAccess> create_android(); - mutable AAsset *a = nullptr; + mutable AAsset *asset = nullptr; mutable uint64_t len = 0; mutable uint64_t pos = 0; mutable bool eof = false; @@ -49,32 +48,30 @@ class FileAccessAndroid : public FileAccess { public: static AAssetManager *asset_manager; - virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual bool is_open() const; ///< true when file is open + virtual Error _open(const String &p_path, int p_mode_flags); // open a file + virtual bool is_open() const; // true when file is open - virtual void seek(uint64_t p_position); ///< seek to a given position - virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual uint64_t get_position() const; ///< get position in the file - virtual uint64_t get_length() const; ///< get size of the file + virtual void seek(uint64_t p_position); // seek to a given position + virtual void seek_end(int64_t p_position = 0); // seek from the end of file + virtual uint64_t get_position() const; // get position in the file + virtual uint64_t get_length() const; // get size of the file - virtual bool eof_reached() const; ///< reading passed EOF + virtual bool eof_reached() const; // reading passed EOF - virtual uint8_t get_8() const; ///< get a byte + virtual uint8_t get_8() const; // get a byte virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; - virtual Error get_error() const; ///< get last error + virtual Error get_error() const; // get last error virtual void flush(); - virtual void store_8(uint8_t p_dest); ///< store a byte + virtual void store_8(uint8_t p_dest); // store a byte - virtual bool file_exists(const String &p_path); ///< return true if a file exists + virtual bool file_exists(const String &p_path); // return true if a file exists virtual uint64_t _get_modified_time(const String &p_file) { return 0; } virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; } virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; } - //static void make_default(); - ~FileAccessAndroid(); }; diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml index c98e8f1d55..2d4c4763a2 100644 --- a/platform/android/java/app/AndroidManifest.xml +++ b/platform/android/java/app/AndroidManifest.xml @@ -59,6 +59,7 @@ android:theme="@style/GodotAppSplashTheme" android:launchMode="singleTask" android:excludeFromRecents="false" + android:exported="true" android:screenOrientation="landscape" android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode" android:resizeableActivity="false" diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle index b6303d1bc9..63b10e62b1 100644 --- a/platform/android/java/app/build.gradle +++ b/platform/android/java/app/build.gradle @@ -1,6 +1,4 @@ // Gradle build config for Godot Engine's Android port. -apply from: 'config.gradle' - buildscript { apply from: 'config.gradle' @@ -14,7 +12,12 @@ buildscript { } } -apply plugin: 'com.android.application' +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' +} + +apply from: 'config.gradle' allprojects { repositories { @@ -79,6 +82,10 @@ android { targetCompatibility versions.javaVersion } + kotlinOptions { + jvmTarget = versions.javaVersion + } + assetPacks = [":assetPacks:installTime"] defaultConfig { diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle index 1b2976e715..3daf628e63 100644 --- a/platform/android/java/app/config.gradle +++ b/platform/android/java/app/config.gradle @@ -1,20 +1,21 @@ ext.versions = [ androidGradlePlugin: '7.0.3', - compileSdk : 30, + compileSdk : 31, minSdk : 19, // Also update 'platform/android/java/lib/AndroidManifest.xml#minSdkVersion' & 'platform/android/export/export_plugin.cpp#DEFAULT_MIN_SDK_VERSION' - targetSdk : 30, // Also update 'platform/android/java/lib/AndroidManifest.xml#targetSdkVersion' & 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION' + targetSdk : 31, // Also update 'platform/android/java/lib/AndroidManifest.xml#targetSdkVersion' & 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION' buildTools : '30.0.3', - kotlinVersion : '1.6.10', + kotlinVersion : '1.6.21', fragmentVersion : '1.3.6', + nexusPublishVersion: '1.1.0', javaVersion : 11, - ndkVersion : '21.4.7075529' // Also update 'platform/android/detect.py#get_project_ndk_version()' when this is updated. + ndkVersion : '23.2.8568313' // Also update 'platform/android/detect.py#get_ndk_version()' when this is updated. ] 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-jdk7:$versions.kotlinVersion", + kotlinStdLib : "org.jetbrains.kotlin:kotlin-stdlib:$versions.kotlinVersion", androidxFragment : "androidx.fragment:fragment:$versions.fragmentVersion", ] diff --git a/platform/android/java/app/res/values/themes.xml b/platform/android/java/app/res/values/themes.xml index 99f723f5ba..d64b50ca45 100644 --- a/platform/android/java/app/res/values/themes.xml +++ b/platform/android/java/app/res/values/themes.xml @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <style name="GodotAppMainTheme" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen"/> + <style name="GodotAppMainTheme" parent="@android:style/Theme.Black.NoTitleBar"/> - <style name="GodotAppSplashTheme" parent="@style/GodotAppMainTheme"> + <style name="GodotAppSplashTheme" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen"> <item name="android:windowBackground">@drawable/splash_drawable</item> <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item> </style> diff --git a/platform/android/java/app/settings.gradle b/platform/android/java/app/settings.gradle index e38d7b2ba6..ba53aefe7f 100644 --- a/platform/android/java/app/settings.gradle +++ b/platform/android/java/app/settings.gradle @@ -1,2 +1,15 @@ // This is the root directory of the Godot custom build. +pluginManagement { + apply from: 'config.gradle' + + plugins { + id 'com.android.application' version versions.androidGradlePlugin + id 'org.jetbrains.kotlin.android' version versions.kotlinVersion + } + repositories { + gradlePluginPortal() + google() + } +} + include ':assetPacks:installTime' diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle index e16ca65df5..da30bd3a95 100644 --- a/platform/android/java/build.gradle +++ b/platform/android/java/build.gradle @@ -1,7 +1,3 @@ -apply plugin: 'io.github.gradle-nexus.publish-plugin' -apply from: 'app/config.gradle' -apply from: 'scripts/publish-root.gradle' - buildscript { apply from: 'app/config.gradle' @@ -17,6 +13,13 @@ buildscript { } } +plugins { + id 'io.github.gradle-nexus.publish-plugin' +} + +apply from: 'app/config.gradle' +apply from: 'scripts/publish-root.gradle' + allprojects { repositories { google() diff --git a/platform/android/java/editor/build.gradle b/platform/android/java/editor/build.gradle index 3312f61ad3..dd167c3880 100644 --- a/platform/android/java/editor/build.gradle +++ b/platform/android/java/editor/build.gradle @@ -1,10 +1,15 @@ // Gradle build config for Godot Engine's Android port. -apply plugin: 'com.android.application' +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' +} dependencies { implementation libraries.kotlinStdLib implementation libraries.androidxFragment implementation project(":lib") + + implementation "androidx.window:window:1.0.0" } android { @@ -29,6 +34,10 @@ android { targetCompatibility versions.javaVersion } + kotlinOptions { + jvmTarget = versions.javaVersion + } + 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 bae075d929..93cbb47400 100644 --- a/platform/android/java/editor/src/main/AndroidManifest.xml +++ b/platform/android/java/editor/src/main/AndroidManifest.xml @@ -34,6 +34,9 @@ android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" android:process=":GodotProjectManager"> + <layout android:defaultHeight="@dimen/editor_default_window_height" + android:defaultWidth="@dimen/editor_default_window_width" /> + <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> @@ -46,7 +49,10 @@ android:process=":GodotEditor" android:launchMode="singleTask" android:screenOrientation="userLandscape" + android:exported="false" android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"> + <layout android:defaultHeight="@dimen/editor_default_window_height" + android:defaultWidth="@dimen/editor_default_window_width" /> </activity> <activity @@ -55,8 +61,11 @@ android:label="@string/godot_project_name_string" android:process=":GodotGame" android:launchMode="singleTask" + android:exported="false" android:screenOrientation="userLandscape" android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"> + <layout android:defaultHeight="@dimen/editor_default_window_height" + android:defaultWidth="@dimen/editor_default_window_width" /> </activity> </application> diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.java b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.java deleted file mode 100644 index 8a6bf88267..0000000000 --- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.java +++ /dev/null @@ -1,124 +0,0 @@ -/*************************************************************************/ -/* GodotEditor.java */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -package org.godotengine.editor; - -import org.godotengine.godot.FullScreenGodotApp; -import org.godotengine.godot.utils.PermissionsUtil; - -import android.content.Intent; -import android.os.Bundle; -import android.os.Debug; - -import androidx.annotation.Nullable; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Base class for the Godot Android Editor activities. - * - * This provides the basic templates for the activities making up this application. - * Each derived activity runs in its own process, which enable up to have several instances of - * the Godot engine up and running at the same time. - * - * It also plays the role of the primary editor window. - */ -public class GodotEditor extends FullScreenGodotApp { - private static final boolean WAIT_FOR_DEBUGGER = false; - private static final String COMMAND_LINE_PARAMS = "command_line_params"; - - private static final String EDITOR_ARG = "--editor"; - private static final String PROJECT_MANAGER_ARG = "--project-manager"; - - private final List<String> commandLineParams = new ArrayList<>(); - - @Override - public void onCreate(Bundle savedInstanceState) { - PermissionsUtil.requestManifestPermissions(this); - - String[] params = getIntent().getStringArrayExtra(COMMAND_LINE_PARAMS); - updateCommandLineParams(params); - - if (BuildConfig.BUILD_TYPE.equals("debug") && WAIT_FOR_DEBUGGER) { - Debug.waitForDebugger(); - } - super.onCreate(savedInstanceState); - } - - private void updateCommandLineParams(@Nullable String[] args) { - // Update the list of command line params with the new args - commandLineParams.clear(); - if (args != null && args.length > 0) { - commandLineParams.addAll(Arrays.asList(args)); - } - } - - @Override - public List<String> getCommandLine() { - return commandLineParams; - } - - @Override - public void onNewGodotInstanceRequested(String[] args) { - // Parse the arguments to figure out which activity to start. - Class<?> targetClass = GodotGame.class; - for (String arg : args) { - if (EDITOR_ARG.equals(arg)) { - targetClass = GodotEditor.class; - break; - } - - if (PROJECT_MANAGER_ARG.equals(arg)) { - targetClass = GodotProjectManager.class; - break; - } - } - - // Launch a new activity - Intent newInstance = new Intent(this, targetClass).putExtra(COMMAND_LINE_PARAMS, args); - startActivity(newInstance); - } - - @Override - public void setRequestedOrientation(int requestedOrientation) { - if (!overrideOrientationRequest()) { - super.setRequestedOrientation(requestedOrientation); - } - } - - /** - * The Godot Android Editor sets its own orientation via its AndroidManifest - */ - protected boolean overrideOrientationRequest() { - return true; - } -} 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 new file mode 100644 index 0000000000..a1ade722e8 --- /dev/null +++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt @@ -0,0 +1,146 @@ +/*************************************************************************/ +/* GodotEditor.kt */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +package org.godotengine.editor + +import android.content.Intent +import android.os.Build +import android.os.Bundle +import android.os.Debug +import androidx.window.layout.WindowMetricsCalculator +import org.godotengine.godot.FullScreenGodotApp +import org.godotengine.godot.utils.PermissionsUtil +import java.util.* +import kotlin.math.min + +/** + * Base class for the Godot Android Editor activities. + * + * This provides the basic templates for the activities making up this application. + * Each derived activity runs in its own process, which enable up to have several instances of + * the Godot engine up and running at the same time. + * + * It also plays the role of the primary editor window. + */ +open class GodotEditor : FullScreenGodotApp() { + + companion object { + private const val WAIT_FOR_DEBUGGER = false + + private const val COMMAND_LINE_PARAMS = "command_line_params" + + private const val EDITOR_ARG = "--editor" + private const val PROJECT_MANAGER_ARG = "--project-manager" + } + + private val commandLineParams = ArrayList<String>() + + override fun onCreate(savedInstanceState: Bundle?) { + PermissionsUtil.requestManifestPermissions(this) + + val params = intent.getStringArrayExtra(COMMAND_LINE_PARAMS) + updateCommandLineParams(params) + + if (BuildConfig.BUILD_TYPE == "debug" && WAIT_FOR_DEBUGGER) { + Debug.waitForDebugger() + } + + super.onCreate(savedInstanceState) + } + + private fun updateCommandLineParams(args: Array<String>?) { + // Update the list of command line params with the new args + commandLineParams.clear() + if (args != null && args.isNotEmpty()) { + commandLineParams.addAll(listOf(*args)) + } + } + + override fun getCommandLine() = commandLineParams + + override fun onNewGodotInstanceRequested(args: Array<String>) { + // Parse the arguments to figure out which activity to start. + var targetClass: Class<*> = GodotGame::class.java + + // Whether we should launch the new godot instance in an adjacent window + // https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_LAUNCH_ADJACENT + var launchAdjacent = + Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && (isInMultiWindowMode || isLargeScreen) + + for (arg in args) { + if (EDITOR_ARG == arg) { + targetClass = GodotEditor::class.java + launchAdjacent = false + break + } + + if (PROJECT_MANAGER_ARG == arg) { + targetClass = GodotProjectManager::class.java + launchAdjacent = false + break + } + } + + // Launch a new activity + val newInstance = Intent(this, targetClass) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .putExtra(COMMAND_LINE_PARAMS, args) + if (launchAdjacent) { + newInstance.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT) + } + startActivity(newInstance) + } + + // Get the screen's density scale + protected val isLargeScreen: Boolean + // Get the minimum window size // Correspond to the EXPANDED window size class. + get() { + val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this) + + // Get the screen's density scale + val scale = resources.displayMetrics.density + + // Get the minimum window size + val minSize = min(metrics.bounds.width(), metrics.bounds.height()).toFloat() + val minSizeDp = minSize / scale + return minSizeDp >= 840f // Correspond to the EXPANDED window size class. + } + + override fun setRequestedOrientation(requestedOrientation: Int) { + if (!overrideOrientationRequest()) { + super.setRequestedOrientation(requestedOrientation) + } + } + + /** + * The Godot Android Editor sets its own orientation via its AndroidManifest + */ + protected open fun overrideOrientationRequest() = true +} diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.java b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt index 12766775a8..783095f93a 100644 --- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.java +++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt @@ -1,5 +1,5 @@ /*************************************************************************/ -/* GodotGame.java */ +/* GodotGame.kt */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -package org.godotengine.editor; +package org.godotengine.editor /** * Drives the 'run project' window of the Godot Editor. */ -public class GodotGame extends GodotEditor { - protected boolean overrideOrientationRequest() { - return false; - } +class GodotGame : GodotEditor() { + override fun overrideOrientationRequest() = false } diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotProjectManager.java b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotProjectManager.kt index d30f66bb8c..bcf4659603 100644 --- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotProjectManager.java +++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotProjectManager.kt @@ -1,5 +1,5 @@ /*************************************************************************/ -/* GodotProjectManager.java */ +/* GodotProjectManager.kt */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,14 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -package org.godotengine.editor; +package org.godotengine.editor /** * Launcher activity for the Godot Android Editor. * * It presents the user with the project manager interface. * Upon selection of a project, this activity (via its parent logic) starts the - * {@link GodotEditor} activity. + * [GodotEditor] activity. */ -public class GodotProjectManager extends GodotEditor { -} +class GodotProjectManager : GodotEditor() diff --git a/platform/android/java/editor/src/main/res/values/dimens.xml b/platform/android/java/editor/src/main/res/values/dimens.xml new file mode 100644 index 0000000000..03fb6184d2 --- /dev/null +++ b/platform/android/java/editor/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <dimen name="editor_default_window_height">600dp</dimen> + <dimen name="editor_default_window_width">800dp</dimen> +</resources> diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml index 2de62271c4..228d8d45fa 100644 --- a/platform/android/java/lib/AndroidManifest.xml +++ b/platform/android/java/lib/AndroidManifest.xml @@ -5,7 +5,7 @@ android:versionName="1.0"> <!-- Should match the mindSdk and targetSdk values in platform/android/java/app/config.gradle --> - <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="30" /> + <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" /> <application> @@ -16,12 +16,13 @@ <service android:name=".GodotDownloaderService" /> - </application> + <activity + android:name=".utils.ProcessPhoenix" + android:theme="@android:style/Theme.Translucent.NoTitleBar" + android:process=":phoenix" + android:exported="false" + /> - <instrumentation - android:icon="@mipmap/icon" - android:label="@string/godot_project_name_string" - android:name="org.godotengine.godot.GodotInstrumentation" - android:targetPackage="org.godotengine.godot" /> + </application> </manifest> diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle index c806de1ded..6b82326a27 100644 --- a/platform/android/java/lib/build.gradle +++ b/platform/android/java/lib/build.gradle @@ -1,5 +1,7 @@ -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' +plugins { + id 'com.android.library' + id 'org.jetbrains.kotlin.android' +} ext { PUBLISH_VERSION = getGodotPublishVersion() @@ -34,6 +36,10 @@ android { targetCompatibility versions.javaVersion } + kotlinOptions { + jvmTarget = versions.javaVersion + } + buildTypes { dev { initWith debug diff --git a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java index fb1604f6af..f21f88db0a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java +++ b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java @@ -30,7 +30,8 @@ package org.godotengine.godot; -import android.content.ComponentName; +import org.godotengine.godot.utils.ProcessPhoenix; + import android.content.Intent; import android.os.Bundle; import android.util.Log; @@ -71,6 +72,7 @@ public abstract class FullScreenGodotApp extends FragmentActivity implements God @Override public void onDestroy() { + Log.v(TAG, "Destroying Godot app..."); super.onDestroy(); onGodotForceQuit(godotFragment); } @@ -78,27 +80,21 @@ public abstract class FullScreenGodotApp extends FragmentActivity implements God @Override public final void onGodotForceQuit(Godot instance) { if (instance == godotFragment) { - System.exit(0); + Log.v(TAG, "Force quitting Godot instance"); + ProcessPhoenix.forceQuit(this); } } @Override public final void onGodotRestartRequested(Godot instance) { if (instance == godotFragment) { - // HACK: - // - // Currently it's very hard to properly deinitialize Godot on Android to restart the game + // It's very hard to properly de-initialize Godot on Android to restart the game // from scratch. Therefore, we need to kill the whole app process and relaunch it. // // Restarting only the activity, wouldn't be enough unless it did proper cleanup (including // releasing and reloading native libs or resetting their state somehow and clearing statics). - // - // Using instrumentation is a way of making the whole app process restart, because Android - // will kill any process of the same package which was already running. - // - Bundle args = new Bundle(); - args.putParcelable("intent", getIntent()); - startInstrumentation(new ComponentName(this, GodotInstrumentation.class), null, args); + Log.v(TAG, "Restarting Godot instance..."); + ProcessPhoenix.triggerRebirth(this); } } 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 377881be85..cafae94d62 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -463,13 +463,9 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC tts = new GodotTTS(activity); mSensorManager = (SensorManager)activity.getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); mGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY); - mSensorManager.registerListener(this, mGravity, SensorManager.SENSOR_DELAY_GAME); mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); - mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME); mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); - mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME); GodotLib.initialize(activity, this, activity.getAssets(), use_apk_expansion); 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 b69d25dd8b..a8e3669ac6 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -224,12 +224,30 @@ public class GodotIO { } public int getScreenDPI() { - DisplayMetrics metrics = activity.getResources().getDisplayMetrics(); - return (int)(metrics.density * 160f); + return activity.getResources().getDisplayMetrics().densityDpi; } + /** + * Returns bucketized density values. + */ public float getScaledDensity() { - return activity.getResources().getDisplayMetrics().scaledDensity; + int densityDpi = activity.getResources().getDisplayMetrics().densityDpi; + float selectedScaledDensity; + if (densityDpi >= DisplayMetrics.DENSITY_XXXHIGH) { + selectedScaledDensity = 4.0f; + } else if (densityDpi >= DisplayMetrics.DENSITY_XXHIGH) { + selectedScaledDensity = 3.0f; + } else if (densityDpi >= DisplayMetrics.DENSITY_XHIGH) { + selectedScaledDensity = 2.0f; + } else if (densityDpi >= DisplayMetrics.DENSITY_HIGH) { + selectedScaledDensity = 1.5f; + } else if (densityDpi >= DisplayMetrics.DENSITY_MEDIUM) { + selectedScaledDensity = 1.0f; + } else { + selectedScaledDensity = 0.75f; + } + Log.d(TAG, "Selected scaled density: " + selectedScaledDensity); + return selectedScaledDensity; } public double getScreenRefreshRate(double fallback) { diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotInstrumentation.java b/platform/android/java/lib/src/org/godotengine/godot/GodotInstrumentation.java deleted file mode 100644 index 44f0a3eb3e..0000000000 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotInstrumentation.java +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************/ -/* GodotInstrumentation.java */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -package org.godotengine.godot; - -import android.app.Instrumentation; -import android.content.Intent; -import android.os.Bundle; - -public class GodotInstrumentation extends Instrumentation { - private Intent intent; - - @Override - public void onCreate(Bundle arguments) { - intent = arguments.getParcelable("intent"); - start(); - } - - @Override - public void onStart() { - startActivitySync(intent); - } -} diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java index 1f8f8c82a6..3182ab0666 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java @@ -114,11 +114,6 @@ public class GodotLib { public static native void doubleTap(int buttonMask, int x, int y); /** - * Forward scroll events from the main thread to the GL thread. - */ - public static native void scroll(int x, int y); - - /** * Forward accelerometer sensor events from the main thread to the GL thread. * @see android.hardware.SensorEventListener#onSensorChanged(SensorEvent) */ diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java index ac13cad23e..778efa914a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java @@ -80,15 +80,6 @@ public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener } @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - //Log.i("GodotGesture", "onScroll"); - final int x = Math.round(distanceX); - final int y = Math.round(distanceY); - GodotLib.scroll(x, y); - return true; - } - - @Override public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { //Log.i("GodotGesture", "onFling"); return true; diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java index 8694bb91e1..ccfb865b1a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java @@ -186,6 +186,9 @@ public class GodotInputHandler implements InputManager.InputDeviceListener { if (mJoystickIds.indexOfKey(deviceId) >= 0) { final int godotJoyId = mJoystickIds.get(deviceId); Joystick joystick = mJoysticksDevices.get(deviceId); + if (joystick == null) { + return true; + } for (int i = 0; i < joystick.axes.size(); i++) { final int axis = joystick.axes.get(i); diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/ProcessPhoenix.java b/platform/android/java/lib/src/org/godotengine/godot/utils/ProcessPhoenix.java new file mode 100644 index 0000000000..2cc37b627a --- /dev/null +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/ProcessPhoenix.java @@ -0,0 +1,141 @@ +// clang-format off + +/* Third-party library. + * Upstream: https://github.com/JakeWharton/ProcessPhoenix + * Commit: 12cb27c2cc9c3fc555e97f2db89e571667de82c4 + */ + +/* + * Copyright (C) 2014 Jake Wharton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.godotengine.godot.utils; + +import android.app.Activity; +import android.app.ActivityManager; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Process; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; + +/** + * Process Phoenix facilitates restarting your application process. This should only be used for + * things like fundamental state changes in your debug builds (e.g., changing from staging to + * production). + * <p> + * Trigger process recreation by calling {@link #triggerRebirth} with a {@link Context} instance. + */ +public final class ProcessPhoenix extends Activity { + private static final String KEY_RESTART_INTENTS = "phoenix_restart_intents"; + private static final String KEY_MAIN_PROCESS_PID = "phoenix_main_process_pid"; + + /** + * Call to restart the application process using the {@linkplain Intent#CATEGORY_DEFAULT default} + * activity as an intent. + * <p> + * Behavior of the current process after invoking this method is undefined. + */ + public static void triggerRebirth(Context context) { + triggerRebirth(context, getRestartIntent(context)); + } + + /** + * Call to restart the application process using the specified intents. + * <p> + * Behavior of the current process after invoking this method is undefined. + */ + public static void triggerRebirth(Context context, Intent... nextIntents) { + if (nextIntents.length < 1) { + throw new IllegalArgumentException("intents cannot be empty"); + } + // create a new task for the first activity. + nextIntents[0].addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK); + + Intent intent = new Intent(context, ProcessPhoenix.class); + intent.addFlags(FLAG_ACTIVITY_NEW_TASK); // In case we are called with non-Activity context. + intent.putParcelableArrayListExtra(KEY_RESTART_INTENTS, new ArrayList<>(Arrays.asList(nextIntents))); + intent.putExtra(KEY_MAIN_PROCESS_PID, Process.myPid()); + context.startActivity(intent); + } + + // -- GODOT start -- + /** + * Finish the activity and kill its process + */ + public static void forceQuit(Activity activity) { + forceQuit(activity, Process.myPid()); + } + + /** + * Finish the activity and kill its process + * @param activity + * @param pid + */ + public static void forceQuit(Activity activity, int pid) { + Process.killProcess(pid); // Kill original main process + activity.finish(); + Runtime.getRuntime().exit(0); // Kill kill kill! + } + + // -- GODOT end -- + + private static Intent getRestartIntent(Context context) { + String packageName = context.getPackageName(); + Intent defaultIntent = context.getPackageManager().getLaunchIntentForPackage(packageName); + if (defaultIntent != null) { + return defaultIntent; + } + + throw new IllegalStateException("Unable to determine default activity for " + + packageName + + ". Does an activity specify the DEFAULT category in its intent filter?"); + } + + @Override protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // -- GODOT start -- + ArrayList<Intent> intents = getIntent().getParcelableArrayListExtra(KEY_RESTART_INTENTS); + startActivities(intents.toArray(new Intent[intents.size()])); + forceQuit(this, getIntent().getIntExtra(KEY_MAIN_PROCESS_PID, -1)); + // -- GODOT end -- + } + + /** + * Checks if the current process is a temporary Phoenix Process. + * This can be used to avoid initialisation of unused resources or to prevent running code that + * is not multi-process ready. + * + * @return true if the current process is a temporary Phoenix Process + */ + public static boolean isPhoenixProcess(Context context) { + int currentPid = Process.myPid(); + ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + List<ActivityManager.RunningAppProcessInfo> runningProcesses = manager.getRunningAppProcesses(); + if (runningProcesses != null) { + for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) { + if (processInfo.pid == currentPid && processInfo.processName.endsWith(":phoenix")) { + return true; + } + } + } + return false; + } +} diff --git a/platform/android/java/nativeSrcsConfigs/build.gradle b/platform/android/java/nativeSrcsConfigs/build.gradle index 0cb769b539..5e810ae1ba 100644 --- a/platform/android/java/nativeSrcsConfigs/build.gradle +++ b/platform/android/java/nativeSrcsConfigs/build.gradle @@ -1,6 +1,7 @@ // Non functional android library used to provide Android Studio editor support to the project. plugins { id 'com.android.library' + id 'org.jetbrains.kotlin.android' } android { @@ -18,6 +19,10 @@ android { targetCompatibility versions.javaVersion } + kotlinOptions { + jvmTarget = versions.javaVersion + } + packagingOptions { exclude 'META-INF/LICENSE' exclude 'META-INF/NOTICE' diff --git a/platform/android/java/settings.gradle b/platform/android/java/settings.gradle index 56e1b6fd3a..466ffebf22 100644 --- a/platform/android/java/settings.gradle +++ b/platform/android/java/settings.gradle @@ -1,4 +1,19 @@ // Configure the root project. +pluginManagement { + apply from: 'app/config.gradle' + + plugins { + id 'com.android.application' version versions.androidGradlePlugin + id 'com.android.library' version versions.androidGradlePlugin + id 'org.jetbrains.kotlin.android' version versions.kotlinVersion + id 'io.github.gradle-nexus.publish-plugin' version versions.nexusPublishVersion + } + repositories { + gradlePluginPortal() + google() + } +} + rootProject.name = "Godot" include ':app' diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index 1805807f90..349ae704f9 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -34,16 +34,16 @@ #include "thread_jandroid.h" bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error, Variant &ret) { - Map<StringName, List<MethodInfo>>::Element *M = methods.find(p_method); + HashMap<StringName, List<MethodInfo>>::Iterator M = methods.find(p_method); if (!M) { return false; } JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); + ERR_FAIL_NULL_V(env, false); MethodInfo *method = nullptr; - for (MethodInfo &E : M->get()) { + for (MethodInfo &E : M->value) { if (!p_instance && !E._static) { r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; continue; @@ -971,14 +971,14 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) { } JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, Ref<JavaClass>()); + ERR_FAIL_NULL_V(env, Ref<JavaClass>()); jclass bclass = env->FindClass(p_class.utf8().get_data()); - ERR_FAIL_COND_V(!bclass, Ref<JavaClass>()); + ERR_FAIL_NULL_V(bclass, Ref<JavaClass>()); jobjectArray methods = (jobjectArray)env->CallObjectMethod(bclass, getDeclaredMethods); - ERR_FAIL_COND_V(!methods, Ref<JavaClass>()); + ERR_FAIL_NULL_V(methods, Ref<JavaClass>()); Ref<JavaClass> java_class = memnew(JavaClass); @@ -1061,7 +1061,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) { if (E->get().param_types.size() != mi.param_types.size()) { continue; } - bool valid = true; + bool this_valid = true; for (int j = 0; j < E->get().param_types.size(); j++) { Variant::Type _new; float new_l; @@ -1070,14 +1070,14 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) { JavaClass::_convert_to_variant_type(E->get().param_types[j], existing, existing_l); JavaClass::_convert_to_variant_type(mi.param_types[j], _new, new_l); if (_new != existing) { - valid = false; + this_valid = false; break; } new_likeliness += new_l; existing_likeliness = existing_l; } - if (!valid) { + if (!this_valid) { continue; } @@ -1155,10 +1155,10 @@ JavaClassWrapper::JavaClassWrapper(jobject p_activity) { singleton = this; JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); + ERR_FAIL_NULL(env); - jclass activityClass = env->FindClass("android/app/Activity"); - jmethodID getClassLoader = env->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;"); + jclass activity = env->FindClass("android/app/Activity"); + jmethodID getClassLoader = env->GetMethodID(activity, "getClassLoader", "()Ljava/lang/ClassLoader;"); classLoader = env->CallObjectMethod(p_activity, getClassLoader); classLoader = (jclass)env->NewGlobalRef(classLoader); jclass classLoaderClass = env->FindClass("java/lang/ClassLoader"); @@ -1168,18 +1168,18 @@ JavaClassWrapper::JavaClassWrapper(jobject p_activity) { getDeclaredMethods = env->GetMethodID(bclass, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;"); getFields = env->GetMethodID(bclass, "getFields", "()[Ljava/lang/reflect/Field;"); Class_getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;"); - // + bclass = env->FindClass("java/lang/reflect/Method"); getParameterTypes = env->GetMethodID(bclass, "getParameterTypes", "()[Ljava/lang/Class;"); getReturnType = env->GetMethodID(bclass, "getReturnType", "()Ljava/lang/Class;"); getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;"); getModifiers = env->GetMethodID(bclass, "getModifiers", "()I"); - /// + bclass = env->FindClass("java/lang/reflect/Field"); Field_getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;"); Field_getModifiers = env->GetMethodID(bclass, "getModifiers", "()I"); Field_get = env->GetMethodID(bclass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); - // each + bclass = env->FindClass("java/lang/Boolean"); Boolean_booleanValue = env->GetMethodID(bclass, "booleanValue", "()Z"); diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp index 7ae3a65105..b71c6ef1e6 100644 --- a/platform/android/java_godot_io_wrapper.cpp +++ b/platform/android/java_godot_io_wrapper.cpp @@ -80,7 +80,7 @@ jobject GodotIOJavaWrapper::get_instance() { Error GodotIOJavaWrapper::open_uri(const String &p_uri) { if (_open_URI) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ERR_UNAVAILABLE); + ERR_FAIL_NULL_V(env, ERR_UNAVAILABLE); jstring jStr = env->NewStringUTF(p_uri.utf8().get_data()); return env->CallIntMethod(godot_io_instance, _open_URI, jStr) ? ERR_CANT_OPEN : OK; } else { @@ -91,7 +91,7 @@ Error GodotIOJavaWrapper::open_uri(const String &p_uri) { String GodotIOJavaWrapper::get_cache_dir() { if (_get_cache_dir) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, String()); + ERR_FAIL_NULL_V(env, String()); jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_cache_dir); return jstring_to_string(s, env); } else { @@ -102,7 +102,7 @@ String GodotIOJavaWrapper::get_cache_dir() { String GodotIOJavaWrapper::get_user_data_dir() { if (_get_data_dir) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, String()); + ERR_FAIL_NULL_V(env, String()); jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_data_dir); return jstring_to_string(s, env); } else { @@ -113,7 +113,7 @@ String GodotIOJavaWrapper::get_user_data_dir() { String GodotIOJavaWrapper::get_locale() { if (_get_locale) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, String()); + ERR_FAIL_NULL_V(env, String()); jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_locale); return jstring_to_string(s, env); } else { @@ -124,7 +124,7 @@ String GodotIOJavaWrapper::get_locale() { String GodotIOJavaWrapper::get_model() { if (_get_model) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, String()); + ERR_FAIL_NULL_V(env, String()); jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_model); return jstring_to_string(s, env); } else { @@ -135,7 +135,7 @@ String GodotIOJavaWrapper::get_model() { int GodotIOJavaWrapper::get_screen_dpi() { if (_get_screen_DPI) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 160); + ERR_FAIL_NULL_V(env, 160); return env->CallIntMethod(godot_io_instance, _get_screen_DPI); } else { return 160; @@ -145,7 +145,7 @@ int GodotIOJavaWrapper::get_screen_dpi() { float GodotIOJavaWrapper::get_scaled_density() { if (_get_scaled_density) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 1.0f); + ERR_FAIL_NULL_V(env, 1.0f); return env->CallFloatMethod(godot_io_instance, _get_scaled_density); } else { return 1.0f; @@ -202,7 +202,7 @@ Rect2i GodotIOJavaWrapper::get_display_safe_area() { String GodotIOJavaWrapper::get_unique_id() { if (_get_unique_id) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, String()); + ERR_FAIL_NULL_V(env, String()); jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_unique_id); return jstring_to_string(s, env); } else { @@ -211,13 +211,13 @@ String GodotIOJavaWrapper::get_unique_id() { } bool GodotIOJavaWrapper::has_vk() { - return (_show_keyboard != 0) && (_hide_keyboard != 0); + return (_show_keyboard != nullptr) && (_hide_keyboard != nullptr); } void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { if (_show_keyboard) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); + ERR_FAIL_NULL(env); jstring jStr = env->NewStringUTF(p_existing.utf8().get_data()); env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end); } @@ -226,7 +226,7 @@ void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int void GodotIOJavaWrapper::hide_vk() { if (_hide_keyboard) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); + ERR_FAIL_NULL(env); env->CallVoidMethod(godot_io_instance, _hide_keyboard); } } @@ -234,7 +234,7 @@ void GodotIOJavaWrapper::hide_vk() { void GodotIOJavaWrapper::set_screen_orientation(int p_orient) { if (_set_screen_orientation) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); + ERR_FAIL_NULL(env); env->CallVoidMethod(godot_io_instance, _set_screen_orientation, p_orient); } } @@ -242,7 +242,7 @@ void GodotIOJavaWrapper::set_screen_orientation(int p_orient) { int GodotIOJavaWrapper::get_screen_orientation() { if (_get_screen_orientation) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); + ERR_FAIL_NULL_V(env, 0); return env->CallIntMethod(godot_io_instance, _get_screen_orientation); } else { return 0; @@ -252,7 +252,7 @@ int GodotIOJavaWrapper::get_screen_orientation() { String GodotIOJavaWrapper::get_system_dir(int p_dir, bool p_shared_storage) { if (_get_system_dir) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, String(".")); + ERR_FAIL_NULL_V(env, String(".")); jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_system_dir, p_dir, p_shared_storage); return jstring_to_string(s, env); } else { diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h index 02c57130ab..aec7d1db97 100644 --- a/platform/android/java_godot_io_wrapper.h +++ b/platform/android/java_godot_io_wrapper.h @@ -91,4 +91,4 @@ public: String get_system_dir(int p_dir, bool p_shared_storage); }; -#endif /* !JAVA_GODOT_IO_WRAPPER_H */ +#endif // JAVA_GODOT_IO_WRAPPER_H diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 8ad72b499e..6e716c34a6 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -62,7 +62,6 @@ static AndroidInputHandler *input_handler = nullptr; static GodotJavaWrapper *godot_java = nullptr; static GodotIOJavaWrapper *godot_io_java = nullptr; -static bool initialized = false; static SafeNumeric<int> step; // Shared between UI and render threads static Size2 new_size; @@ -80,8 +79,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHei } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject godot_instance, jobject p_asset_manager, jboolean p_use_apk_expansion) { - initialized = true; - JavaVM *jvm; env->GetJavaVM(&jvm); @@ -101,9 +98,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en os_android = new OS_Android(godot_java, godot_io_java, p_use_apk_expansion); - char wd[500]; - getcwd(wd, 500); - godot_java->on_video_init(env); } @@ -144,7 +138,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc for (int i = 0; i < cmdlen; i++) { jstring string = (jstring)env->GetObjectArrayElement(p_cmdline, i); - const char *rawString = env->GetStringUTFChars(string, 0); + const char *rawString = env->GetStringUTFChars(string, nullptr); cmdline[i] = rawString; j_cmdline[i] = string; @@ -163,6 +157,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc memfree(cmdline); } + // Note: --help and --version return ERR_HELP, but this should be translated to 0 if exit codes are propagated. if (err != OK) { return; // should exit instead and print the error } @@ -312,15 +307,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubleTap(JNIEnv *env } // Called on the UI thread -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jclass clazz, jint p_x, jint p_y) { - if (step.get() <= 0) { - return; - } - - input_handler->process_scroll(Point2(p_x, p_y)); -} - -// Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jclass clazz, jint p_device, jint p_button, jboolean p_pressed) { if (step.get() <= 0) { return; @@ -436,7 +422,7 @@ JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv * JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *env, jclass clazz, jlong ID, jstring method, jobjectArray params) { Object *obj = ObjectDB::get_instance(ObjectID(ID)); - ERR_FAIL_COND(!obj); + ERR_FAIL_NULL(obj); int res = env->PushLocalFrame(16); ERR_FAIL_COND(res != 0); @@ -447,27 +433,26 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *en Variant *vlist = (Variant *)alloca(sizeof(Variant) * count); Variant **vptr = (Variant **)alloca(sizeof(Variant *) * count); for (int i = 0; i < count; i++) { - jobject obj = env->GetObjectArrayElement(params, i); + jobject jobj = env->GetObjectArrayElement(params, i); Variant v; - if (obj) { - v = _jobject_to_variant(env, obj); + if (jobj) { + v = _jobject_to_variant(env, jobj); } memnew_placement(&vlist[i], Variant); vlist[i] = v; vptr[i] = &vlist[i]; - env->DeleteLocalRef(obj); + env->DeleteLocalRef(jobj); } Callable::CallError err; obj->callp(str_method, (const Variant **)vptr, count, err); - // something env->PopLocalFrame(nullptr); } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *env, jclass clazz, jlong ID, jstring method, jobjectArray params) { Object *obj = ObjectDB::get_instance(ObjectID(ID)); - ERR_FAIL_COND(!obj); + ERR_FAIL_NULL(obj); int res = env->PushLocalFrame(16); ERR_FAIL_COND(res != 0); @@ -480,16 +465,16 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv * const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * count); for (int i = 0; i < count; i++) { - jobject obj = env->GetObjectArrayElement(params, i); - if (obj) { - args[i] = _jobject_to_variant(env, obj); + jobject jobj = env->GetObjectArrayElement(params, i); + if (jobj) { + args[i] = _jobject_to_variant(env, jobj); } - env->DeleteLocalRef(obj); + env->DeleteLocalRef(jobj); argptrs[i] = &args[i]; } MessageQueue::get_singleton()->push_callp(obj, str_method, (const Variant **)argptrs, count); - // something + env->PopLocalFrame(nullptr); } diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index 4f2195942c..aa8d67cf46 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -51,7 +51,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3FI(JNIEn JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3FIFF(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray positions, jint buttons_mask, jfloat vertical_factor, jfloat horizontal_factor); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jclass clazz, jint p_type, jfloat p_x, jfloat p_y); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubleTap(JNIEnv *env, jclass clazz, jint p_button_mask, jint p_x, jint p_y); -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jclass clazz, jint p_x, jint p_y); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jclass clazz, jint p_keycode, jint p_scancode, jint p_unicode_char, jboolean p_pressed); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jclass clazz, jint p_device, jint p_button, jboolean p_pressed); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jclass clazz, jint p_device, jint p_axis, jfloat p_value); @@ -72,4 +71,4 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNI JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz); } -#endif /* !JAVA_GODOT_LIB_JNI_H */ +#endif // JAVA_GODOT_LIB_JNI_H diff --git a/platform/android/java_godot_view_wrapper.cpp b/platform/android/java_godot_view_wrapper.cpp index 5605d834fa..0153ba96fc 100644 --- a/platform/android/java_godot_view_wrapper.cpp +++ b/platform/android/java_godot_view_wrapper.cpp @@ -34,7 +34,7 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); + ERR_FAIL_NULL(env); _godot_view = env->NewGlobalRef(godot_view); @@ -48,27 +48,27 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) { } void GodotJavaViewWrapper::request_pointer_capture() { - if (_request_pointer_capture != 0) { + if (_request_pointer_capture != nullptr) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); + ERR_FAIL_NULL(env); env->CallVoidMethod(_godot_view, _request_pointer_capture); } } void GodotJavaViewWrapper::release_pointer_capture() { - if (_request_pointer_capture != 0) { + if (_request_pointer_capture != nullptr) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); + ERR_FAIL_NULL(env); env->CallVoidMethod(_godot_view, _release_pointer_capture); } } void GodotJavaViewWrapper::set_pointer_icon(int pointer_type) { - if (_set_pointer_icon != 0) { + if (_set_pointer_icon != nullptr) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); + ERR_FAIL_NULL(env); env->CallVoidMethod(_godot_view, _set_pointer_icon, pointer_type); } @@ -76,7 +76,7 @@ void GodotJavaViewWrapper::set_pointer_icon(int pointer_type) { GodotJavaViewWrapper::~GodotJavaViewWrapper() { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); + ERR_FAIL_NULL(env); env->DeleteGlobalRef(_godot_view); env->DeleteGlobalRef(_cls); diff --git a/platform/android/java_godot_view_wrapper.h b/platform/android/java_godot_view_wrapper.h index 6e02c26ae2..b1f258bbb5 100644 --- a/platform/android/java_godot_view_wrapper.h +++ b/platform/android/java_godot_view_wrapper.h @@ -57,4 +57,4 @@ public: ~GodotJavaViewWrapper(); }; -#endif //GODOT_JAVA_GODOT_VIEW_WRAPPER_H +#endif // GODOT_JAVA_GODOT_VIEW_WRAPPER_H diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp index 2c8378e685..e3456fe4e4 100644 --- a/platform/android/java_godot_wrapper.cpp +++ b/platform/android/java_godot_wrapper.cpp @@ -96,9 +96,7 @@ jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_cl if (p_env == nullptr) { p_env = get_jni_env(); } - - ERR_FAIL_COND_V(p_env == nullptr, nullptr); - + ERR_FAIL_NULL_V(p_env, nullptr); jfieldID fid = p_env->GetStaticFieldID(godot_class, p_name, p_class); return p_env->GetStaticObjectField(godot_class, fid); } else { @@ -109,8 +107,7 @@ jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_cl jobject GodotJavaWrapper::get_class_loader() { if (_get_class_loader) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, nullptr); - + ERR_FAIL_NULL_V(env, nullptr); return env->CallObjectMethod(activity, _get_class_loader); } else { return nullptr; @@ -122,8 +119,7 @@ GodotJavaViewWrapper *GodotJavaWrapper::get_godot_view() { return _godot_view; } JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, nullptr); - + ERR_FAIL_NULL_V(env, nullptr); jmethodID godot_view_getter = env->GetMethodID(godot_class, "getRenderView", "()Lorg/godotengine/godot/GodotRenderView;"); _godot_view = new GodotJavaViewWrapper(env->CallObjectMethod(godot_instance, godot_view_getter)); return _godot_view; @@ -134,8 +130,7 @@ void GodotJavaWrapper::on_video_init(JNIEnv *p_env) { if (p_env == nullptr) { p_env = get_jni_env(); } - ERR_FAIL_COND(p_env == nullptr); - + ERR_FAIL_NULL(p_env); p_env->CallVoidMethod(godot_instance, _on_video_init); } } @@ -154,7 +149,7 @@ void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) { if (p_env == nullptr) { p_env = get_jni_env(); } - ERR_FAIL_COND(p_env == nullptr); + ERR_FAIL_NULL(p_env); p_env->CallVoidMethod(godot_instance, _on_godot_main_loop_started); } } @@ -164,8 +159,7 @@ void GodotJavaWrapper::restart(JNIEnv *p_env) { if (p_env == nullptr) { p_env = get_jni_env(); } - ERR_FAIL_COND(p_env == nullptr); - + ERR_FAIL_NULL(p_env); p_env->CallVoidMethod(godot_instance, _restart); } } @@ -175,8 +169,7 @@ void GodotJavaWrapper::force_quit(JNIEnv *p_env) { if (p_env == nullptr) { p_env = get_jni_env(); } - ERR_FAIL_COND(p_env == nullptr); - + ERR_FAIL_NULL(p_env); p_env->CallVoidMethod(godot_instance, _finish); } } @@ -184,8 +177,7 @@ void GodotJavaWrapper::force_quit(JNIEnv *p_env) { void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) { if (_set_keep_screen_on) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - + ERR_FAIL_NULL(env); env->CallVoidMethod(godot_instance, _set_keep_screen_on, p_enabled); } } @@ -193,8 +185,7 @@ void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) { void GodotJavaWrapper::alert(const String &p_message, const String &p_title) { if (_alert) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - + ERR_FAIL_NULL(env); jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data()); jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data()); env->CallVoidMethod(godot_instance, _alert, jStrMessage, jStrTitle); @@ -203,24 +194,21 @@ void GodotJavaWrapper::alert(const String &p_message, const String &p_title) { int GodotJavaWrapper::get_gles_version_code() { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - + ERR_FAIL_NULL_V(env, 0); if (_get_GLES_version_code) { return env->CallIntMethod(godot_instance, _get_GLES_version_code); } - return 0; } bool GodotJavaWrapper::has_get_clipboard() { - return _get_clipboard != 0; + return _get_clipboard != nullptr; } String GodotJavaWrapper::get_clipboard() { if (_get_clipboard) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, String()); - + ERR_FAIL_NULL_V(env, String()); jstring s = (jstring)env->CallObjectMethod(godot_instance, _get_clipboard); return jstring_to_string(s, env); } else { @@ -231,8 +219,7 @@ String GodotJavaWrapper::get_clipboard() { String GodotJavaWrapper::get_input_fallback_mapping() { if (_get_input_fallback_mapping) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, String()); - + ERR_FAIL_NULL_V(env, String()); jstring fallback_mapping = (jstring)env->CallObjectMethod(godot_instance, _get_input_fallback_mapping); return jstring_to_string(fallback_mapping, env); } else { @@ -241,28 +228,26 @@ String GodotJavaWrapper::get_input_fallback_mapping() { } bool GodotJavaWrapper::has_set_clipboard() { - return _set_clipboard != 0; + return _set_clipboard != nullptr; } void GodotJavaWrapper::set_clipboard(const String &p_text) { if (_set_clipboard) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - + ERR_FAIL_NULL(env); jstring jStr = env->NewStringUTF(p_text.utf8().get_data()); env->CallVoidMethod(godot_instance, _set_clipboard, jStr); } } bool GodotJavaWrapper::has_has_clipboard() { - return _has_clipboard != 0; + return _has_clipboard != nullptr; } bool GodotJavaWrapper::has_clipboard() { if (_has_clipboard) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - + ERR_FAIL_NULL_V(env, false); return env->CallBooleanMethod(godot_instance, _has_clipboard); } else { return false; @@ -272,8 +257,7 @@ bool GodotJavaWrapper::has_clipboard() { bool GodotJavaWrapper::request_permission(const String &p_name) { if (_request_permission) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - + ERR_FAIL_NULL_V(env, false); jstring jStrName = env->NewStringUTF(p_name.utf8().get_data()); return env->CallBooleanMethod(godot_instance, _request_permission, jStrName); } else { @@ -284,8 +268,7 @@ bool GodotJavaWrapper::request_permission(const String &p_name) { bool GodotJavaWrapper::request_permissions() { if (_request_permissions) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - + ERR_FAIL_NULL_V(env, false); return env->CallBooleanMethod(godot_instance, _request_permissions); } else { return false; @@ -296,14 +279,12 @@ Vector<String> GodotJavaWrapper::get_granted_permissions() const { Vector<String> permissions_list; if (_get_granted_permissions) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, permissions_list); - + ERR_FAIL_NULL_V(env, permissions_list); jobject permissions_object = env->CallObjectMethod(godot_instance, _get_granted_permissions); jobjectArray *arr = reinterpret_cast<jobjectArray *>(&permissions_object); - int i = 0; jsize len = env->GetArrayLength(*arr); - for (i = 0; i < len; i++) { + for (int i = 0; i < len; i++) { jstring jstr = (jstring)env->GetObjectArrayElement(*arr, i); String str = jstring_to_string(jstr, env); permissions_list.push_back(str); @@ -316,8 +297,7 @@ Vector<String> GodotJavaWrapper::get_granted_permissions() const { void GodotJavaWrapper::init_input_devices() { if (_init_input_devices) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - + ERR_FAIL_NULL(env); env->CallVoidMethod(godot_instance, _init_input_devices); } } @@ -325,8 +305,7 @@ void GodotJavaWrapper::init_input_devices() { jobject GodotJavaWrapper::get_surface() { if (_get_surface) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, nullptr); - + ERR_FAIL_NULL_V(env, nullptr); return env->CallObjectMethod(godot_instance, _get_surface); } else { return nullptr; @@ -336,8 +315,7 @@ jobject GodotJavaWrapper::get_surface() { bool GodotJavaWrapper::is_activity_resumed() { if (_is_activity_resumed) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - + ERR_FAIL_NULL_V(env, false); return env->CallBooleanMethod(godot_instance, _is_activity_resumed); } else { return false; @@ -347,8 +325,7 @@ bool GodotJavaWrapper::is_activity_resumed() { void GodotJavaWrapper::vibrate(int p_duration_ms) { if (_vibrate) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - + ERR_FAIL_NULL(env); env->CallVoidMethod(godot_instance, _vibrate, p_duration_ms); } } @@ -356,8 +333,7 @@ void GodotJavaWrapper::vibrate(int p_duration_ms) { void GodotJavaWrapper::create_new_godot_instance(List<String> args) { if (_create_new_godot_instance) { JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - + ERR_FAIL_NULL(env); jobjectArray jargs = env->NewObjectArray(args.size(), env->FindClass("java/lang/String"), env->NewStringUTF("")); for (int i = 0; i < args.size(); i++) { env->SetObjectArrayElement(jargs, i, env->NewStringUTF(args[i].utf8().get_data())); diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h index f04fda7c3d..bbf7c0ae33 100644 --- a/platform/android/java_godot_wrapper.h +++ b/platform/android/java_godot_wrapper.h @@ -51,27 +51,27 @@ private: GodotJavaViewWrapper *_godot_view = nullptr; - jmethodID _on_video_init = 0; - jmethodID _restart = 0; - jmethodID _finish = 0; - jmethodID _set_keep_screen_on = 0; - jmethodID _alert = 0; - jmethodID _get_GLES_version_code = 0; - jmethodID _get_clipboard = 0; - jmethodID _set_clipboard = 0; - jmethodID _has_clipboard = 0; - jmethodID _request_permission = 0; - jmethodID _request_permissions = 0; - jmethodID _get_granted_permissions = 0; - jmethodID _init_input_devices = 0; - jmethodID _get_surface = 0; - jmethodID _is_activity_resumed = 0; - jmethodID _vibrate = 0; - jmethodID _get_input_fallback_mapping = 0; - jmethodID _on_godot_setup_completed = 0; - jmethodID _on_godot_main_loop_started = 0; - jmethodID _get_class_loader = 0; - jmethodID _create_new_godot_instance = 0; + jmethodID _on_video_init = nullptr; + jmethodID _restart = nullptr; + jmethodID _finish = nullptr; + jmethodID _set_keep_screen_on = nullptr; + jmethodID _alert = nullptr; + jmethodID _get_GLES_version_code = nullptr; + jmethodID _get_clipboard = nullptr; + jmethodID _set_clipboard = nullptr; + jmethodID _has_clipboard = nullptr; + jmethodID _request_permission = nullptr; + jmethodID _request_permissions = nullptr; + jmethodID _get_granted_permissions = nullptr; + jmethodID _init_input_devices = nullptr; + jmethodID _get_surface = nullptr; + jmethodID _is_activity_resumed = nullptr; + jmethodID _vibrate = nullptr; + jmethodID _get_input_fallback_mapping = nullptr; + jmethodID _on_godot_setup_completed = nullptr; + jmethodID _on_godot_main_loop_started = nullptr; + jmethodID _get_class_loader = nullptr; + jmethodID _create_new_godot_instance = nullptr; public: GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_godot_instance); @@ -108,4 +108,4 @@ public: void create_new_godot_instance(List<String> args); }; -#endif /* !JAVA_GODOT_WRAPPER_H */ +#endif // JAVA_GODOT_WRAPPER_H diff --git a/platform/android/jni_utils.cpp b/platform/android/jni_utils.cpp index e2573d10f8..193ef61264 100644 --- a/platform/android/jni_utils.cpp +++ b/platform/android/jni_utils.cpp @@ -123,10 +123,10 @@ jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_a for (int j = 0; j < keys.size(); j++) { Variant var = dict[keys[j]]; - jvalret v = _variant_to_jvalue(env, var.get_type(), &var, true); - env->SetObjectArrayElement(jvalues, j, v.val.l); - if (v.obj) { - env->DeleteLocalRef(v.obj); + jvalret valret = _variant_to_jvalue(env, var.get_type(), &var, true); + env->SetObjectArrayElement(jvalues, j, valret.val.l); + if (valret.obj) { + env->DeleteLocalRef(valret.obj); } } @@ -186,7 +186,7 @@ String _get_class_name(JNIEnv *env, jclass cls, bool *array) { if (array) { jmethodID isArray = env->GetMethodID(cclass, "isArray", "()Z"); jboolean isarr = env->CallBooleanMethod(cls, isArray); - (*array) = isarr ? true : false; + (*array) = isarr != 0; } String name = jstring_to_string(clsName, env); env->DeleteLocalRef(clsName); diff --git a/platform/android/net_socket_android.cpp b/platform/android/net_socket_android.cpp index a65e7c6724..225a1132fe 100644 --- a/platform/android/net_socket_android.cpp +++ b/platform/android/net_socket_android.cpp @@ -32,10 +32,10 @@ #include "thread_jandroid.h" -jobject NetSocketAndroid::net_utils = 0; -jclass NetSocketAndroid::cls = 0; -jmethodID NetSocketAndroid::_multicast_lock_acquire = 0; -jmethodID NetSocketAndroid::_multicast_lock_release = 0; +jobject NetSocketAndroid::net_utils = nullptr; +jclass NetSocketAndroid::cls = nullptr; +jmethodID NetSocketAndroid::_multicast_lock_acquire = nullptr; +jmethodID NetSocketAndroid::_multicast_lock_release = nullptr; void NetSocketAndroid::setup(jobject p_net_utils) { JNIEnv *env = get_jni_env(); diff --git a/platform/android/net_socket_android.h b/platform/android/net_socket_android.h index 3e919497ea..97a611cb04 100644 --- a/platform/android/net_socket_android.h +++ b/platform/android/net_socket_android.h @@ -74,4 +74,4 @@ public: ~NetSocketAndroid(); }; -#endif +#endif // NET_SOCKET_ANDROID_H diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 25daf1ca90..6674428de8 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -76,9 +76,7 @@ public: }; void OS_Android::alert(const String &p_alert, const String &p_title) { - GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); - ERR_FAIL_COND(!godot_java); - + ERR_FAIL_NULL(godot_java); godot_java->alert(p_alert, p_title); } @@ -106,7 +104,6 @@ void OS_Android::initialize_core() { DirAccess::make_default<DirAccessJAndroid>(DirAccess::ACCESS_RESOURCES); } #endif - DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA); DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM); @@ -164,7 +161,7 @@ Vector<String> OS_Android::get_granted_permissions() const { Error OS_Android::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) { p_library_handle = dlopen(p_path.utf8().get_data(), RTLD_NOW); - ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + dlerror() + "."); + ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + dlerror() + "."); if (r_resolved_path != nullptr) { *r_resolved_path = p_path; @@ -313,7 +310,7 @@ Size2i OS_Android::get_display_size() const { void OS_Android::set_opengl_extensions(const char *p_gl_extensions) { #if defined(GLES3_ENABLED) - ERR_FAIL_COND(!p_gl_extensions); + ERR_FAIL_NULL(p_gl_extensions); gl_extensions = p_gl_extensions; #endif } diff --git a/platform/android/os_android.h b/platform/android/os_android.h index f86c5b5212..3f607eac48 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -135,4 +135,4 @@ public: ~OS_Android(); }; -#endif +#endif // OS_ANDROID_H diff --git a/platform/android/plugin/godot_plugin_jni.cpp b/platform/android/plugin/godot_plugin_jni.cpp index 158512803a..7a39e2003d 100644 --- a/platform/android/plugin/godot_plugin_jni.cpp +++ b/platform/android/plugin/godot_plugin_jni.cpp @@ -123,7 +123,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitS variant_params[i] = _jobject_to_variant(env, j_param); args[i] = &variant_params[i]; env->DeleteLocalRef(j_param); - }; + } singleton->emit_signalp(StringName(signal_name), args, count); } diff --git a/platform/android/string_android.h b/platform/android/string_android.h index 2afaa86fec..79c71b5d04 100644 --- a/platform/android/string_android.h +++ b/platform/android/string_android.h @@ -30,6 +30,7 @@ #ifndef STRING_ANDROID_H #define STRING_ANDROID_H + #include "core/string/ustring.h" #include "thread_jandroid.h" #include <jni.h> diff --git a/platform/android/thread_jandroid.h b/platform/android/thread_jandroid.h index 2073423f8d..3b000517fd 100644 --- a/platform/android/thread_jandroid.h +++ b/platform/android/thread_jandroid.h @@ -38,4 +38,4 @@ void init_thread_jandroid(JavaVM *p_jvm, JNIEnv *p_env); void setup_android_thread(); JNIEnv *get_jni_env(); -#endif +#endif // THREAD_JANDROID_H diff --git a/platform/android/tts_android.cpp b/platform/android/tts_android.cpp index 528878f14e..27ba8da448 100644 --- a/platform/android/tts_android.cpp +++ b/platform/android/tts_android.cpp @@ -35,18 +35,18 @@ #include "string_android.h" #include "thread_jandroid.h" -jobject TTS_Android::tts = 0; -jclass TTS_Android::cls = 0; +jobject TTS_Android::tts = nullptr; +jclass TTS_Android::cls = nullptr; -jmethodID TTS_Android::_is_speaking = 0; -jmethodID TTS_Android::_is_paused = 0; -jmethodID TTS_Android::_get_voices = 0; -jmethodID TTS_Android::_speak = 0; -jmethodID TTS_Android::_pause_speaking = 0; -jmethodID TTS_Android::_resume_speaking = 0; -jmethodID TTS_Android::_stop_speaking = 0; +jmethodID TTS_Android::_is_speaking = nullptr; +jmethodID TTS_Android::_is_paused = nullptr; +jmethodID TTS_Android::_get_voices = nullptr; +jmethodID TTS_Android::_speak = nullptr; +jmethodID TTS_Android::_pause_speaking = nullptr; +jmethodID TTS_Android::_resume_speaking = nullptr; +jmethodID TTS_Android::_stop_speaking = nullptr; -Map<int, Char16String> TTS_Android::ids; +HashMap<int, Char16String> TTS_Android::ids; void TTS_Android::setup(jobject p_tts) { JNIEnv *env = get_jni_env(); @@ -175,8 +175,8 @@ void TTS_Android::resume() { } void TTS_Android::stop() { - for (Map<int, Char16String>::Element *E = ids.front(); E; E = E->next()) { - DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, E->key()); + for (const KeyValue<int, Char16String> &E : ids) { + DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, E.key); } ids.clear(); diff --git a/platform/android/tts_android.h b/platform/android/tts_android.h index efeed94856..bc0cdb8d55 100644 --- a/platform/android/tts_android.h +++ b/platform/android/tts_android.h @@ -49,7 +49,7 @@ class TTS_Android { static jmethodID _resume_speaking; static jmethodID _stop_speaking; - static Map<int, Char16String> ids; + static HashMap<int, Char16String> ids; public: static void setup(jobject p_tts); |