diff options
Diffstat (limited to 'platform/android')
28 files changed, 254 insertions, 487 deletions
diff --git a/platform/android/SCsub b/platform/android/SCsub index 7e9dac926c..56fbd2f7e4 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -9,7 +9,6 @@ android_files = [ "dir_access_jandroid.cpp", "thread_jandroid.cpp", "net_socket_android.cpp", - "audio_driver_jandroid.cpp", "java_godot_lib_jni.cpp", "java_class_wrapper.cpp", "java_godot_wrapper.cpp", diff --git a/platform/android/api/java_class_wrapper.h b/platform/android/api/java_class_wrapper.h index d6c7a1abe5..ff7bf43573 100644 --- a/platform/android/api/java_class_wrapper.h +++ b/platform/android/api/java_class_wrapper.h @@ -31,7 +31,7 @@ #ifndef JAVA_CLASS_WRAPPER_H #define JAVA_CLASS_WRAPPER_H -#include "core/object/reference.h" +#include "core/object/ref_counted.h" #ifdef ANDROID_ENABLED #include <android/log.h> @@ -42,8 +42,8 @@ class JavaObject; #endif -class JavaClass : public Reference { - GDCLASS(JavaClass, Reference); +class JavaClass : public RefCounted { + GDCLASS(JavaClass, RefCounted); #ifdef ANDROID_ENABLED enum ArgumentType{ @@ -184,8 +184,8 @@ public: JavaClass(); }; -class JavaObject : public Reference { - GDCLASS(JavaObject, Reference); +class JavaObject : public RefCounted { + GDCLASS(JavaObject, RefCounted); #ifdef ANDROID_ENABLED Ref<JavaClass> base_class; diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp deleted file mode 100644 index 3a2ccac481..0000000000 --- a/platform/android/audio_driver_jandroid.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/*************************************************************************/ -/* audio_driver_jandroid.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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. */ -/*************************************************************************/ - -#include "audio_driver_jandroid.h" - -#include "core/config/project_settings.h" -#include "core/os/os.h" -#include "thread_jandroid.h" - -AudioDriverAndroid *AudioDriverAndroid::s_ad = nullptr; - -jobject AudioDriverAndroid::io; -jmethodID AudioDriverAndroid::_init_audio; -jmethodID AudioDriverAndroid::_write_buffer; -jmethodID AudioDriverAndroid::_quit; -jmethodID AudioDriverAndroid::_pause; -bool AudioDriverAndroid::active = false; -jclass AudioDriverAndroid::cls; -int AudioDriverAndroid::audioBufferFrames = 0; -int AudioDriverAndroid::mix_rate = 44100; -bool AudioDriverAndroid::quit = false; -jobject AudioDriverAndroid::audioBuffer = nullptr; -void *AudioDriverAndroid::audioBufferPinned = nullptr; -Mutex AudioDriverAndroid::mutex; -int32_t *AudioDriverAndroid::audioBuffer32 = nullptr; - -const char *AudioDriverAndroid::get_name() const { - return "Android"; -} - -Error AudioDriverAndroid::init() { - /* - // TODO: pass in/return a (Java) device ID, also whether we're opening for input or output - this->spec.samples = Android_JNI_OpenAudioDevice(this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples); - SDL_CalculateAudioSpec(&this->spec); - - if (this->spec.samples == 0) { - // Init failed? - SDL_SetError("Java-side initialization failed!"); - return 0; - } -*/ - - //Android_JNI_SetupThread(); - - // __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device"); - - JNIEnv *env = get_jni_env(); - int mix_rate = GLOBAL_GET("audio/driver/mix_rate"); - - int latency = GLOBAL_GET("audio/driver/output_latency"); - unsigned int buffer_size = next_power_of_2(latency * mix_rate / 1000); - print_verbose("Audio buffer size: " + itos(buffer_size)); - - audioBuffer = env->CallObjectMethod(io, _init_audio, mix_rate, buffer_size); - - ERR_FAIL_COND_V(audioBuffer == nullptr, ERR_INVALID_PARAMETER); - - audioBuffer = env->NewGlobalRef(audioBuffer); - - jboolean isCopy = JNI_FALSE; - audioBufferPinned = env->GetShortArrayElements((jshortArray)audioBuffer, &isCopy); - audioBufferFrames = env->GetArrayLength((jshortArray)audioBuffer); - audioBuffer32 = memnew_arr(int32_t, audioBufferFrames); - - return OK; -} - -void AudioDriverAndroid::start() { - active = true; -} - -void AudioDriverAndroid::setup(jobject p_io) { - JNIEnv *env = get_jni_env(); - io = p_io; - - jclass c = env->GetObjectClass(io); - cls = (jclass)env->NewGlobalRef(c); - - _init_audio = env->GetMethodID(cls, "audioInit", "(II)Ljava/lang/Object;"); - _write_buffer = env->GetMethodID(cls, "audioWriteShortBuffer", "([S)V"); - _quit = env->GetMethodID(cls, "audioQuit", "()V"); - _pause = env->GetMethodID(cls, "audioPause", "(Z)V"); -} - -void AudioDriverAndroid::thread_func(JNIEnv *env) { - jclass cls = env->FindClass("org/godotengine/godot/Godot"); - if (cls) { - cls = (jclass)env->NewGlobalRef(cls); - } - jfieldID fid = env->GetStaticFieldID(cls, "io", "Lorg/godotengine/godot/GodotIO;"); - jobject ob = env->GetStaticObjectField(cls, fid); - jobject gob = env->NewGlobalRef(ob); - jclass c = env->GetObjectClass(gob); - jclass lcls = (jclass)env->NewGlobalRef(c); - _write_buffer = env->GetMethodID(lcls, "audioWriteShortBuffer", "([S)V"); - - while (!quit) { - int16_t *ptr = (int16_t *)audioBufferPinned; - int fc = audioBufferFrames; - - if (!s_ad->active || mutex.try_lock() != OK) { - for (int i = 0; i < fc; i++) { - ptr[i] = 0; - } - - } else { - s_ad->audio_server_process(fc / 2, audioBuffer32); - - mutex.unlock(); - - for (int i = 0; i < fc; i++) { - ptr[i] = audioBuffer32[i] >> 16; - } - } - env->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)ptr, JNI_COMMIT); - env->CallVoidMethod(gob, _write_buffer, (jshortArray)audioBuffer); - } -} - -int AudioDriverAndroid::get_mix_rate() const { - return mix_rate; -} - -AudioDriver::SpeakerMode AudioDriverAndroid::get_speaker_mode() const { - return SPEAKER_MODE_STEREO; -} - -void AudioDriverAndroid::lock() { - mutex.lock(); -} - -void AudioDriverAndroid::unlock() { - mutex.unlock(); -} - -void AudioDriverAndroid::finish() { - JNIEnv *env = get_jni_env(); - env->CallVoidMethod(io, _quit); - - if (audioBuffer) { - env->DeleteGlobalRef(audioBuffer); - audioBuffer = nullptr; - audioBufferPinned = nullptr; - } - - active = false; -} - -void AudioDriverAndroid::set_pause(bool p_pause) { - JNIEnv *env = get_jni_env(); - env->CallVoidMethod(io, _pause, p_pause); -} - -AudioDriverAndroid::AudioDriverAndroid() { - s_ad = this; - active = false; -} diff --git a/platform/android/audio_driver_jandroid.h b/platform/android/audio_driver_jandroid.h deleted file mode 100644 index 9007fd2f81..0000000000 --- a/platform/android/audio_driver_jandroid.h +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************/ -/* audio_driver_jandroid.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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. */ -/*************************************************************************/ - -#ifndef AUDIO_DRIVER_ANDROID_H -#define AUDIO_DRIVER_ANDROID_H - -#include "servers/audio_server.h" - -#include "java_godot_lib_jni.h" - -class AudioDriverAndroid : public AudioDriver { - static Mutex mutex; - static AudioDriverAndroid *s_ad; - static jobject io; - static jmethodID _init_audio; - static jmethodID _write_buffer; - static jmethodID _quit; - static jmethodID _pause; - static bool active; - static bool quit; - - static jclass cls; - - static jobject audioBuffer; - static void *audioBufferPinned; - static int32_t *audioBuffer32; - static int audioBufferFrames; - static int mix_rate; - -public: - void set_singleton(); - - virtual const char *get_name() const; - - virtual Error init(); - virtual void start(); - virtual int get_mix_rate() const; - virtual SpeakerMode get_speaker_mode() const; - virtual void lock(); - virtual void unlock(); - virtual void finish(); - - virtual void set_pause(bool p_pause); - - static void setup(jobject p_io); - static void thread_func(JNIEnv *env); - - AudioDriverAndroid(); -}; - -#endif // AUDIO_DRIVER_ANDROID_H diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h index 7b9cbeea47..cdf98187ed 100644 --- a/platform/android/dir_access_jandroid.h +++ b/platform/android/dir_access_jandroid.h @@ -31,7 +31,7 @@ #ifndef DIR_ACCESS_JANDROID_H #define DIR_ACCESS_JANDROID_H -#include "core/os/dir_access.h" +#include "core/io/dir_access.h" #include "java_godot_lib_jni.h" #include <stdio.h> diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index ff61eeaee1..66a2013c4e 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -410,8 +410,6 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis keep_screen_on = GLOBAL_GET("display/window/energy_saving/keep_screen_on"); - buttons_state = 0; - #if defined(OPENGL_ENABLED) if (rendering_driver == "opengl") { bool gl_initialization_error = false; @@ -484,16 +482,16 @@ DisplayServerAndroid::~DisplayServerAndroid() { void DisplayServerAndroid::process_joy_event(DisplayServerAndroid::JoypadEvent p_event) { switch (p_event.type) { case JOY_EVENT_BUTTON: - Input::get_singleton()->joy_button(p_event.device, p_event.index, p_event.pressed); + Input::get_singleton()->joy_button(p_event.device, (JoyButton)p_event.index, p_event.pressed); break; case JOY_EVENT_AXIS: Input::JoyAxisValue value; value.min = -1; value.value = p_event.value; - Input::get_singleton()->joy_axis(p_event.device, p_event.index, value); + Input::get_singleton()->joy_axis(p_event.device, (JoyAxis)p_event.index, value); break; case JOY_EVENT_HAT: - Input::get_singleton()->joy_hat(p_event.device, p_event.hat); + Input::get_singleton()->joy_hat(p_event.device, (HatMask)p_event.hat); break; default: return; @@ -528,7 +526,7 @@ void DisplayServerAndroid::process_key_event(int p_keycode, int p_scancode, int } Ref<InputEventKey> ev; - ev.instance(); + ev.instantiate(); int val = unicode; int keycode = android_get_keysym(p_keycode); int phy_keycode = android_get_keysym(p_scancode); @@ -575,7 +573,7 @@ void DisplayServerAndroid::process_touch(int p_event, int p_pointer, const Vecto //end all if exist for (int i = 0; i < touch.size(); i++) { Ref<InputEventScreenTouch> ev; - ev.instance(); + ev.instantiate(); ev->set_index(touch[i].id); ev->set_pressed(false); ev->set_position(touch[i].pos); @@ -592,7 +590,7 @@ void DisplayServerAndroid::process_touch(int p_event, int p_pointer, const Vecto //send touch for (int i = 0; i < touch.size(); i++) { Ref<InputEventScreenTouch> ev; - ev.instance(); + ev.instantiate(); ev->set_index(touch[i].id); ev->set_pressed(true); ev->set_position(touch[i].pos); @@ -618,7 +616,7 @@ void DisplayServerAndroid::process_touch(int p_event, int p_pointer, const Vecto continue; //no move unncesearily Ref<InputEventScreenDrag> ev; - ev.instance(); + ev.instantiate(); ev->set_index(touch[i].id); ev->set_position(p_points[idx].pos); ev->set_relative(p_points[idx].pos - touch[i].pos); @@ -633,7 +631,7 @@ void DisplayServerAndroid::process_touch(int p_event, int p_pointer, const Vecto //end all if exist for (int i = 0; i < touch.size(); i++) { Ref<InputEventScreenTouch> ev; - ev.instance(); + ev.instantiate(); ev->set_index(touch[i].id); ev->set_pressed(false); ev->set_position(touch[i].pos); @@ -649,7 +647,7 @@ void DisplayServerAndroid::process_touch(int p_event, int p_pointer, const Vecto touch.push_back(tp); Ref<InputEventScreenTouch> ev; - ev.instance(); + ev.instantiate(); ev->set_index(tp.id); ev->set_pressed(true); @@ -664,7 +662,7 @@ void DisplayServerAndroid::process_touch(int p_event, int p_pointer, const Vecto for (int i = 0; i < touch.size(); i++) { if (touch[i].id == p_pointer) { Ref<InputEventScreenTouch> ev; - ev.instance(); + ev.instantiate(); ev->set_index(touch[i].id); ev->set_pressed(false); ev->set_position(touch[i].pos); @@ -685,7 +683,7 @@ void DisplayServerAndroid::process_hover(int p_type, Point2 p_pos) { case AMOTION_EVENT_ACTION_HOVER_ENTER: // hover enter case AMOTION_EVENT_ACTION_HOVER_EXIT: { // hover exit Ref<InputEventMouseMotion> ev; - ev.instance(); + ev.instantiate(); _set_key_modifier_state(ev); ev->set_position(p_pos); ev->set_global_position(p_pos); @@ -697,12 +695,12 @@ void DisplayServerAndroid::process_hover(int p_type, Point2 p_pos) { } void DisplayServerAndroid::process_mouse_event(int input_device, int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor, float event_horizontal_factor) { - int event_buttons_mask = _android_button_mask_to_godot_button_mask(event_android_buttons_mask); + MouseButton event_buttons_mask = _android_button_mask_to_godot_button_mask(event_android_buttons_mask); switch (event_action) { case AMOTION_EVENT_ACTION_BUTTON_PRESS: case AMOTION_EVENT_ACTION_BUTTON_RELEASE: { Ref<InputEventMouseButton> ev; - ev.instance(); + ev.instantiate(); _set_key_modifier_state(ev); if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE) { ev->set_position(event_pos); @@ -712,7 +710,7 @@ void DisplayServerAndroid::process_mouse_event(int input_device, int event_actio ev->set_global_position(hover_prev_pos); } ev->set_pressed(event_action == AMOTION_EVENT_ACTION_BUTTON_PRESS); - int changed_button_mask = buttons_state ^ event_buttons_mask; + MouseButton changed_button_mask = MouseButton(buttons_state ^ event_buttons_mask); buttons_state = event_buttons_mask; @@ -723,7 +721,7 @@ void DisplayServerAndroid::process_mouse_event(int input_device, int event_actio case AMOTION_EVENT_ACTION_MOVE: { Ref<InputEventMouseMotion> ev; - ev.instance(); + ev.instantiate(); _set_key_modifier_state(ev); if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE) { ev->set_position(event_pos); @@ -740,7 +738,7 @@ void DisplayServerAndroid::process_mouse_event(int input_device, int event_actio } break; case AMOTION_EVENT_ACTION_SCROLL: { Ref<InputEventMouseButton> ev; - ev.instance(); + ev.instantiate(); if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE) { ev->set_position(event_pos); ev->set_global_position(event_pos); @@ -765,11 +763,11 @@ void DisplayServerAndroid::process_mouse_event(int input_device, int event_actio } } -void DisplayServerAndroid::_wheel_button_click(int event_buttons_mask, const Ref<InputEventMouseButton> &ev, int wheel_button, float factor) { +void DisplayServerAndroid::_wheel_button_click(MouseButton event_buttons_mask, const Ref<InputEventMouseButton> &ev, MouseButton wheel_button, float factor) { Ref<InputEventMouseButton> evd = ev->duplicate(); _set_key_modifier_state(evd); evd->set_button_index(wheel_button); - evd->set_button_mask(event_buttons_mask ^ (1 << (wheel_button - 1))); + evd->set_button_mask(MouseButton(event_buttons_mask ^ (1 << (wheel_button - 1)))); evd->set_factor(factor); Input::get_singleton()->accumulate_input_event(evd); Ref<InputEventMouseButton> evdd = evd->duplicate(); @@ -779,9 +777,9 @@ void DisplayServerAndroid::_wheel_button_click(int event_buttons_mask, const Ref } void DisplayServerAndroid::process_double_tap(int event_android_button_mask, Point2 p_pos) { - int event_button_mask = _android_button_mask_to_godot_button_mask(event_android_button_mask); + MouseButton event_button_mask = _android_button_mask_to_godot_button_mask(event_android_button_mask); Ref<InputEventMouseButton> ev; - ev.instance(); + ev.instantiate(); _set_key_modifier_state(ev); ev->set_position(p_pos); ev->set_global_position(p_pos); @@ -792,7 +790,7 @@ void DisplayServerAndroid::process_double_tap(int event_android_button_mask, Poi Input::get_singleton()->accumulate_input_event(ev); } -int DisplayServerAndroid::_button_index_from_mask(int button_mask) { +MouseButton DisplayServerAndroid::_button_index_from_mask(MouseButton button_mask) { switch (button_mask) { case MOUSE_BUTTON_MASK_LEFT: return MOUSE_BUTTON_LEFT; @@ -805,13 +803,13 @@ int DisplayServerAndroid::_button_index_from_mask(int button_mask) { case MOUSE_BUTTON_MASK_XBUTTON2: return MOUSE_BUTTON_XBUTTON2; default: - return 0; + return MOUSE_BUTTON_NONE; } } void DisplayServerAndroid::process_scroll(Point2 p_pos) { Ref<InputEventPanGesture> ev; - ev.instance(); + ev.instantiate(); _set_key_modifier_state(ev); ev->set_position(p_pos); ev->set_delta(p_pos - scroll_prev_pos); @@ -863,12 +861,12 @@ Point2i DisplayServerAndroid::mouse_get_position() const { return hover_prev_pos; } -int DisplayServerAndroid::mouse_get_button_state() const { +MouseButton DisplayServerAndroid::mouse_get_button_state() const { return buttons_state; } -int DisplayServerAndroid::_android_button_mask_to_godot_button_mask(int android_button_mask) { - int godot_button_mask = 0; +MouseButton DisplayServerAndroid::_android_button_mask_to_godot_button_mask(int android_button_mask) { + MouseButton godot_button_mask = MOUSE_BUTTON_NONE; if (android_button_mask & AMOTION_EVENT_BUTTON_PRIMARY) { godot_button_mask |= MOUSE_BUTTON_MASK_LEFT; } diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 1379baf154..a39271d524 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -68,7 +68,7 @@ private: bool control_mem = false; bool meta_mem = false; - int buttons_state; + MouseButton buttons_state = MOUSE_BUTTON_NONE; // https://developer.android.com/reference/android/view/PointerIcon // mapping between Godot's cursor shape to Android's' @@ -81,7 +81,7 @@ private: 1004, //CURSOR_BUSY 1021, //CURSOR_DRAG 1021, //CURSOR_CAN_DRO - 1000, //CURSOR_FORBIDD (no corresponding icon in Android's icon so fallback to default) + 1000, //CURSOR_FORBIDD (no corresponding icon in Android's icon so fallback to default) 1015, //CURSOR_VSIZE 1014, //CURSOR_HSIZE 1017, //CURSOR_BDIAGSI @@ -120,11 +120,11 @@ private: void _set_key_modifier_state(Ref<InputEventWithModifiers> ev); - static int _button_index_from_mask(int button_mask); + static MouseButton _button_index_from_mask(MouseButton button_mask); - static int _android_button_mask_to_godot_button_mask(int android_button_mask); + static MouseButton _android_button_mask_to_godot_button_mask(int android_button_mask); - void _wheel_button_click(int event_buttons_mask, const Ref<InputEventMouseButton> &ev, int wheel_button, float factor); + void _wheel_button_click(MouseButton event_buttons_mask, const Ref<InputEventMouseButton> &ev, MouseButton wheel_button, float factor); public: static DisplayServerAndroid *get_singleton(); @@ -219,7 +219,7 @@ public: void notify_surface_changed(int p_width, int p_height); virtual Point2i mouse_get_position() const; - virtual int mouse_get_button_state() const; + virtual MouseButton mouse_get_button_state() const; DisplayServerAndroid(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); ~DisplayServerAndroid(); diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index c45828e194..733f91c929 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -31,11 +31,12 @@ #include "export.h" #include "core/config/project_settings.h" +#include "core/io/dir_access.h" +#include "core/io/file_access.h" #include "core/io/image_loader.h" +#include "core/io/json.h" #include "core/io/marshalls.h" #include "core/io/zip_io.h" -#include "core/os/dir_access.h" -#include "core/os/file_access.h" #include "core/os/os.h" #include "core/templates/safe_refcount.h" #include "core/version.h" @@ -206,6 +207,7 @@ static const char *LEGACY_BUILD_SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi-v static const char *SPLASH_BG_COLOR_PATH = "res/drawable-nodpi/splash_bg_color.png"; static const char *LEGACY_BUILD_SPLASH_BG_COLOR_PATH = "res/drawable-nodpi-v4/splash_bg_color.png"; static const char *SPLASH_CONFIG_PATH = "res://android/build/res/drawable/splash_drawable.xml"; +static const char *GDNATIVE_LIBS_PATH = "res://android/build/libs/gdnativelibs.json"; const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> @@ -277,6 +279,11 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { EditorProgress *ep = nullptr; }; + struct CustomExportData { + bool debug; + Vector<String> libs; + }; + Vector<PluginConfigAndroid> plugins; String last_plugin_names; uint64_t last_custom_build_time = 0; @@ -609,9 +616,9 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { zip_fileinfo zipfi; zipfi.tmz_date.tm_hour = time.hour; zipfi.tmz_date.tm_mday = date.day; - zipfi.tmz_date.tm_min = time.min; + zipfi.tmz_date.tm_min = time.minute; zipfi.tmz_date.tm_mon = date.month - 1; // tm_mon is zero indexed - zipfi.tmz_date.tm_sec = time.sec; + zipfi.tmz_date.tm_sec = time.second; zipfi.tmz_date.tm_year = date.year; zipfi.dosDate = 0; zipfi.external_fa = 0; @@ -757,6 +764,33 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { return OK; } + static Error copy_gradle_so(void *p_userdata, const SharedObject &p_so) { + ERR_FAIL_COND_V_MSG(!p_so.path.get_file().begins_with("lib"), FAILED, + "Android .so file names must start with \"lib\", but got: " + p_so.path); + Vector<String> abis = get_abis(); + CustomExportData *export_data = (CustomExportData *)p_userdata; + bool exported = false; + for (int i = 0; i < p_so.tags.size(); ++i) { + int abi_index = abis.find(p_so.tags[i]); + if (abi_index != -1) { + exported = true; + String base = "res://android/build/libs"; + String type = export_data->debug ? "debug" : "release"; + String abi = abis[abi_index]; + String filename = p_so.path.get_file(); + String dst_path = base.plus_file(type).plus_file(abi).plus_file(filename); + Vector<uint8_t> data = FileAccess::get_file_as_array(p_so.path); + print_verbose("Copying .so file from " + p_so.path + " to " + dst_path); + Error err = store_file_at_path(dst_path, data); + ERR_FAIL_COND_V_MSG(err, err, "Failed to copy .so file from " + p_so.path + " to " + dst_path); + export_data->libs.push_back(dst_path); + } + } + ERR_FAIL_COND_V_MSG(!exported, FAILED, + "Cannot determine ABI for library \"" + p_so.path + "\". One of the supported ABIs must be used as a tag: " + String(" ").join(abis)); + return OK; + } + void _get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions) { const char **aperms = android_perms; while (*aperms) { @@ -1461,7 +1495,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { String project_splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); if (!project_splash_path.is_empty()) { - splash_image.instance(); + splash_image.instantiate(); print_verbose("Loading splash image: " + project_splash_path); const Error err = ImageLoader::load_image(project_splash_path, splash_image); if (err) { @@ -1501,7 +1535,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } print_verbose("Creating splash background color image."); - splash_bg_color_image.instance(); + splash_bg_color_image.instantiate(); splash_bg_color_image->create(splash_image->get_width(), splash_image->get_height(), false, splash_image->get_format()); splash_bg_color_image->fill(bg_color); @@ -1512,9 +1546,9 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { void load_icon_refs(const Ref<EditorExportPreset> &p_preset, Ref<Image> &icon, Ref<Image> &foreground, Ref<Image> &background) { String project_icon_path = ProjectSettings::get_singleton()->get("application/config/icon"); - icon.instance(); - foreground.instance(); - background.instance(); + icon.instantiate(); + foreground.instantiate(); + background.instantiate(); // Regular icon: user selection -> project icon -> default. String path = static_cast<String>(p_preset->get(launcher_icon_option)).strip_edges(); @@ -1849,7 +1883,7 @@ public: err = OS::get_singleton()->execute(adb, args, &output, &rv, true); print_verbose(output); if (err || rv != 0) { - EditorNode::add_io_error("Could not install to device."); + EditorNode::add_io_error("Could not install to device: " + output); CLEANUP_AND_RETURN(ERR_CANT_CREATE); } @@ -2380,6 +2414,28 @@ public: } } + void _remove_copied_libs() { + print_verbose("Removing previously installed libraries..."); + Error error; + String libs_json = FileAccess::get_file_as_string(GDNATIVE_LIBS_PATH, &error); + if (error || libs_json.is_empty()) { + print_verbose("No previously installed libraries found"); + return; + } + + JSON json; + error = json.parse(libs_json); + ERR_FAIL_COND_MSG(error, "Error parsing \"" + libs_json + "\" on line " + itos(json.get_error_line()) + ": " + json.get_error_message()); + + Vector<String> libs = json.get_data(); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + for (int i = 0; i < libs.size(); i++) { + print_verbose("Removing previously installed library " + libs[i]); + da->remove(libs[i]); + } + da->remove(GDNATIVE_LIBS_PATH); + } + String join_list(List<String> parts, const String &separator) const { String ret; for (int i = 0; i < parts.size(); ++i) { @@ -2491,13 +2547,22 @@ public: //stores all the project files inside the Gradle project directory. Also includes all ABIs _clear_assets_directory(); + _remove_copied_libs(); if (!apk_expansion) { print_verbose("Exporting project files.."); - err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, nullptr, ignore_so_file); + CustomExportData user_data; + user_data.debug = p_debug; + err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so); if (err != OK) { EditorNode::add_io_error("Could not export project files to gradle project\n"); return err; } + if (user_data.libs.size() > 0) { + FileAccessRef fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE); + JSON json; + fa->store_string(json.stringify(user_data.libs, "\t")); + fa->close(); + } } else { print_verbose("Saving apk expansion file.."); err = save_apk_expansion_file(p_preset, p_path); @@ -2568,19 +2633,35 @@ public: // Sensitive additions must be done below the logging statement. print_verbose("Build Android project using gradle command: " + String("\n") + build_command + " " + join_list(cmdline, String(" "))); - if (should_sign && !p_debug) { - // Pass the release keystore info as well - String release_keystore = p_preset->get("keystore/release"); - String release_username = p_preset->get("keystore/release_user"); - String release_password = p_preset->get("keystore/release_password"); - if (!FileAccess::exists(release_keystore)) { - EditorNode::add_io_error("Could not find keystore, unable to export."); - return ERR_FILE_CANT_OPEN; - } + if (should_sign) { + if (p_debug) { + String debug_keystore = p_preset->get("keystore/debug"); + String debug_password = p_preset->get("keystore/debug_password"); + String debug_user = p_preset->get("keystore/debug_user"); + + if (debug_keystore.is_empty()) { + debug_keystore = EditorSettings::get_singleton()->get("export/android/debug_keystore"); + debug_password = EditorSettings::get_singleton()->get("export/android/debug_keystore_pass"); + debug_user = EditorSettings::get_singleton()->get("export/android/debug_keystore_user"); + } - cmdline.push_back("-Prelease_keystore_file=" + release_keystore); // argument to specify the release keystore file. - cmdline.push_back("-Prelease_keystore_alias=" + release_username); // argument to specify the release keystore alias. - cmdline.push_back("-Prelease_keystore_password=" + release_password); // argument to specity the release keystore password. + cmdline.push_back("-Pdebug_keystore_file=" + debug_keystore); // argument to specify the debug keystore file. + cmdline.push_back("-Pdebug_keystore_alias=" + debug_user); // argument to specify the debug keystore alias. + cmdline.push_back("-Pdebug_keystore_password=" + debug_password); // argument to specify the debug keystore password. + } else { + // Pass the release keystore info as well + String release_keystore = p_preset->get("keystore/release"); + String release_username = p_preset->get("keystore/release_user"); + String release_password = p_preset->get("keystore/release_password"); + if (!FileAccess::exists(release_keystore)) { + EditorNode::add_io_error("Could not find keystore, unable to export."); + return ERR_FILE_CANT_OPEN; + } + + cmdline.push_back("-Prelease_keystore_file=" + release_keystore); // argument to specify the release keystore file. + cmdline.push_back("-Prelease_keystore_alias=" + release_username); // argument to specify the release keystore alias. + cmdline.push_back("-Prelease_keystore_password=" + release_password); // argument to specify the release keystore password. + } } int result = EditorNode::get_singleton()->execute_and_show_output(TTR("Building Android Project (gradle)"), build_command, cmdline); @@ -2941,11 +3022,11 @@ public: EditorExportPlatformAndroid() { Ref<Image> img = memnew(Image(_android_logo)); - logo.instance(); + logo.instantiate(); logo->create_from_image(img); img = Ref<Image>(memnew(Image(_android_run_icon))); - run_icon.instance(); + run_icon.instantiate(); run_icon->create_from_image(img); devices_changed.set(); diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index 0bb94dcc97..17f0e9f154 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -31,9 +31,9 @@ #ifndef GODOT_GRADLE_EXPORT_UTIL_H #define GODOT_GRADLE_EXPORT_UTIL_H +#include "core/io/dir_access.h" +#include "core/io/file_access.h" #include "core/io/zip_io.h" -#include "core/os/dir_access.h" -#include "core/os/file_access.h" #include "core/os/os.h" #include "editor/editor_export.h" @@ -96,14 +96,6 @@ Error create_directory(const String &p_dir) { return OK; } -// Implementation of EditorExportSaveSharedObject. -// This method will only be called as an input to export_project_files. -// This method lets the .so files for all ABIs to be copied -// into the gradle project from the .AAR file -Error ignore_so_file(void *p_userdata, const SharedObject &p_so) { - return OK; -} - // Writes p_data into a file at p_path, creating directories if necessary. // Note: this will overwrite the file at p_path if it already exists. Error store_file_at_path(const String &p_path, const Vector<uint8_t> &p_data) { diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h index 8890e0f645..bb4ce36947 100644 --- a/platform/android/file_access_android.h +++ b/platform/android/file_access_android.h @@ -31,7 +31,7 @@ #ifndef FILE_ACCESS_ANDROID_H #define FILE_ACCESS_ANDROID_H -#include "core/os/file_access.h" +#include "core/io/file_access.h" #include <android/asset_manager.h> #include <android/log.h> #include <stdio.h> diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle index 1b1fb47bd8..18e07c3762 100644 --- a/platform/android/java/app/build.gradle +++ b/platform/android/java/app/build.gradle @@ -6,7 +6,7 @@ buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { classpath libraries.androidGradlePlugin @@ -18,9 +18,8 @@ apply plugin: 'com.android.application' allprojects { repositories { - mavenCentral() google() - jcenter() + mavenCentral() // Godot user plugins custom maven repos String[] mavenRepos = getGodotPluginsMavenRepos() @@ -113,6 +112,15 @@ android { } signingConfigs { + debug { + if (hasCustomDebugKeystore()) { + storeFile new File(getDebugKeystoreFile()) + storePassword getDebugKeystorePassword() + keyAlias getDebugKeyAlias() + keyPassword getDebugKeystorePassword() + } + } + release { File keystoreFile = new File(getReleaseKeystoreFile()) if (keystoreFile.isFile()) { diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle index b278d15bdf..81fc87b7ef 100644 --- a/platform/android/java/app/config.gradle +++ b/platform/android/java/app/config.gradle @@ -1,11 +1,11 @@ ext.versions = [ - androidGradlePlugin: '4.0.1', + androidGradlePlugin: '4.2.1', compileSdk : 29, minSdk : 18, targetSdk : 29, buildTools : '30.0.3', supportCoreUtils : '1.0.0', - kotlinVersion : '1.4.10', + kotlinVersion : '1.5.10', v4Support : '1.0.0', javaVersion : 1.8, ndkVersion : '21.4.7075529' // Also update 'platform/android/detect.py#get_project_ndk_version()' when this is updated. @@ -191,6 +191,35 @@ ext.getGodotPluginsLocalBinaries = { -> return binDeps } +ext.getDebugKeystoreFile = { -> + String keystoreFile = project.hasProperty("debug_keystore_file") ? project.property("debug_keystore_file") : "" + if (keystoreFile == null || keystoreFile.isEmpty()) { + keystoreFile = "." + } + return keystoreFile +} + +ext.hasCustomDebugKeystore = { -> + File keystoreFile = new File(getDebugKeystoreFile()) + return keystoreFile.isFile() +} + +ext.getDebugKeystorePassword = { -> + String keystorePassword = project.hasProperty("debug_keystore_password") ? project.property("debug_keystore_password") : "" + if (keystorePassword == null || keystorePassword.isEmpty()) { + keystorePassword = "android" + } + return keystorePassword +} + +ext.getDebugKeyAlias = { -> + String keyAlias = project.hasProperty("debug_keystore_alias") ? project.property("debug_keystore_alias") : "" + if (keyAlias == null || keyAlias.isEmpty()) { + keyAlias = "androiddebugkey" + } + return keyAlias +} + ext.getReleaseKeystoreFile = { -> String keystoreFile = project.hasProperty("release_keystore_file") ? project.property("release_keystore_file") : "" if (keystoreFile == null || keystoreFile.isEmpty()) { diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle index a7fe500be2..ee24a46d9f 100644 --- a/platform/android/java/build.gradle +++ b/platform/android/java/build.gradle @@ -5,7 +5,7 @@ buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { classpath libraries.androidGradlePlugin @@ -16,7 +16,6 @@ buildscript { allprojects { repositories { google() - jcenter() mavenCentral() } } @@ -118,8 +117,8 @@ task zipCustomBuild(type: Zip) { } from(fileTree(dir: 'app', excludes: ['**/build/**', '**/.gradle/**', '**/*.iml']), fileTree(dir: '.', includes: ['gradle.properties', 'gradlew', 'gradlew.bat', 'gradle/**'])) include '**/*' - archiveName 'android_source.zip' - destinationDir(file(binDir)) + archiveFileName = 'android_source.zip' + destinationDirectory = file(binDir) } def templateExcludedBuildTask() { diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.properties b/platform/android/java/gradle/wrapper/gradle-wrapper.properties index a7d8a0f310..74c5636f8a 100644 --- a/platform/android/java/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/java/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Sep 02 02:44:30 PDT 2019 +#Wed Jun 23 23:42:22 PDT 2021 distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip +zipStoreBase=GRADLE_USER_HOME diff --git a/platform/android/java/gradlew.bat b/platform/android/java/gradlew.bat index f9553162f1..11cc30edb0 100644 --- a/platform/android/java/gradlew.bat +++ b/platform/android/java/gradlew.bat @@ -1,7 +1,7 @@ @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem Gradle startup script for Windows @rem @rem ########################################################################## @@ -75,7 +75,7 @@ if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd diff --git a/platform/android/java/lib/res/values/strings.xml b/platform/android/java/lib/res/values/strings.xml index 590b066d8a..010006b81e 100644 --- a/platform/android/java/lib/res/values/strings.xml +++ b/platform/android/java/lib/res/values/strings.xml @@ -6,7 +6,7 @@ <string name="text_button_resume_cellular">Resume download</string> <string name="text_button_wifi_settings">Wi-Fi settings</string> <string name="text_verifying_download">Verifying Download</string> - <string name="text_validation_complete">XAPK File Validation Complete. Select OK to exit.</string> + <string name="text_validation_complete">XAPK File Validation Complete. Select OK to exit.</string> <string name="text_validation_failed">XAPK File Validation Failed.</string> <string name="text_button_pause">Pause Download</string> <string name="text_button_resume">Resume Download</string> 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 c7c7c1b40c..12a8bdb90b 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -328,95 +328,6 @@ public class GodotIO { } ///////////////////////// - // AUDIO - ///////////////////////// - - private Object buf; - private Thread mAudioThread; - private AudioTrack mAudioTrack; - - public Object audioInit(int sampleRate, int desiredFrames) { - int channelConfig = AudioFormat.CHANNEL_OUT_STEREO; - int audioFormat = AudioFormat.ENCODING_PCM_16BIT; - int frameSize = 4; - - System.out.printf("audioInit: initializing audio:\n"); - - //Log.v("Godot", "Godot audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer"); - - // Let the user pick a larger buffer if they really want -- but ye - // gods they probably shouldn't, the minimums are horrifyingly high - // latency already - desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize); - - mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, - channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM); - - audioStartThread(); - - //Log.v("Godot", "Godot audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer"); - - buf = new short[desiredFrames * 2]; - return buf; - } - - public void audioStartThread() { - mAudioThread = new Thread(new Runnable() { - public void run() { - mAudioTrack.play(); - GodotLib.audio(); - } - }); - - // I'd take REALTIME if I could get it! - mAudioThread.setPriority(Thread.MAX_PRIORITY); - mAudioThread.start(); - } - - public void audioWriteShortBuffer(short[] buffer) { - for (int i = 0; i < buffer.length;) { - int result = mAudioTrack.write(buffer, i, buffer.length - i); - if (result > 0) { - i += result; - } else if (result == 0) { - try { - Thread.sleep(1); - } catch (InterruptedException e) { - // Nom nom - } - } else { - Log.w("Godot", "Godot audio: error return from write(short)"); - return; - } - } - } - - public void audioQuit() { - if (mAudioThread != null) { - try { - mAudioThread.join(); - } catch (Exception e) { - Log.v("Godot", "Problem stopping audio thread: " + e); - } - mAudioThread = null; - - //Log.v("Godot", "Finished waiting for audio thread"); - } - - if (mAudioTrack != null) { - mAudioTrack.stop(); - mAudioTrack = null; - } - } - - public void audioPause(boolean p_pause) { - if (p_pause) - mAudioTrack.pause(); - else - mAudioTrack.play(); - } - - ///////////////////////// // MISCELLANEOUS OS IO ///////////////////////// @@ -452,6 +363,10 @@ public class GodotIO { return activity.getFilesDir().getAbsolutePath(); } + public String getExternalDataDir() { + return activity.getExternalFilesDir(null).getAbsolutePath(); + } + public String getLocale() { return Locale.getDefault().toString(); } 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 534a50e9ed..8108118388 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java @@ -175,11 +175,6 @@ public class GodotLib { public static native void focusout(); /** - * Invoked when the audio thread is started. - */ - public static native void audio(); - - /** * Used to access Godot global properties. * @param p_key Property key * @return String value of the property diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt index f0e37d80b8..b01dc2653a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt @@ -115,7 +115,7 @@ open internal class VkSurfaceView(context: Context) : SurfaceView(context), Surf /** * Tear down the rendering thread. * - * Must not be called before a [VkRenderer] has been set. + * Must not be called before a [VkRenderer] has been set. */ fun onDestroy() { vkThread.blockingExit() diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index f49b0e843a..ed6b5c3e14 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -102,7 +102,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, if (p_args[i]->get_type() != Variant::OBJECT) arg_expected = Variant::OBJECT; else { - Ref<Reference> ref = *p_args[i]; + Ref<RefCounted> ref = *p_args[i]; if (!ref.is_null()) { if (Object::cast_to<JavaObject>(ref.ptr())) { Ref<JavaObject> jo = ref; @@ -488,7 +488,7 @@ Variant JavaClass::call(const StringName &p_method, const Variant **p_args, int return ret; } - return Reference::call(p_method, p_args, p_argcount, r_error); + return RefCounted::call(p_method, p_args, p_argcount, r_error); } JavaClass::JavaClass() { diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp index ec3b6f8ac0..5e99135498 100644 --- a/platform/android/java_godot_io_wrapper.cpp +++ b/platform/android/java_godot_io_wrapper.cpp @@ -49,6 +49,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc _open_URI = p_env->GetMethodID(cls, "openURI", "(Ljava/lang/String;)I"); _get_data_dir = p_env->GetMethodID(cls, "getDataDir", "()Ljava/lang/String;"); + _get_external_data_dir = p_env->GetMethodID(cls, "getExternalDataDir", "()Ljava/lang/String;"); _get_locale = p_env->GetMethodID(cls, "getLocale", "()Ljava/lang/String;"); _get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;"); _get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I"); @@ -92,6 +93,17 @@ String GodotIOJavaWrapper::get_user_data_dir() { } } +String GodotIOJavaWrapper::get_external_data_dir() { + if (_get_external_data_dir) { + JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, String()); + jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_external_data_dir); + return jstring_to_string(s, env); + } else { + return String(); + } +} + String GodotIOJavaWrapper::get_locale() { if (_get_locale) { JNIEnv *env = get_jni_env(); diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h index 394e97effa..e4c0a4b2c7 100644 --- a/platform/android/java_godot_io_wrapper.h +++ b/platform/android/java_godot_io_wrapper.h @@ -47,6 +47,7 @@ private: jmethodID _open_URI = 0; jmethodID _get_data_dir = 0; + jmethodID _get_external_data_dir = 0; jmethodID _get_locale = 0; jmethodID _get_model = 0; jmethodID _get_screen_DPI = 0; @@ -66,6 +67,7 @@ public: Error open_uri(const String &p_uri); String get_user_data_dir(); + String get_external_data_dir(); String get_locale(); String get_model(); int get_screen_dpi(); diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index c7ff6cb2c0..4c66789a83 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -36,7 +36,6 @@ #include "android/asset_manager_jni.h" #include "api/java_class_wrapper.h" #include "api/jni_singleton.h" -#include "audio_driver_jandroid.h" #include "core/config/engine.h" #include "core/config/project_settings.h" #include "core/input/input.h" @@ -94,7 +93,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en FileAccessAndroid::asset_manager = AAssetManager_fromJava(env, amgr); DirAccessJAndroid::setup(godot_io_java->get_instance()); - AudioDriverAndroid::setup(godot_io_java->get_instance()); NetSocketAndroid::setup(godot_java->get_member_object("netUtils", "Lorg/godotengine/godot/utils/GodotNetUtils;", env)); os_android = new OS_Android(godot_java, godot_io_java, p_use_apk_expansion); @@ -326,15 +324,15 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, j int hat = 0; if (p_hat_x != 0) { if (p_hat_x < 0) - hat |= Input::HAT_MASK_LEFT; + hat |= HatMask::HAT_MASK_LEFT; else - hat |= Input::HAT_MASK_RIGHT; + hat |= HatMask::HAT_MASK_RIGHT; } if (p_hat_y != 0) { if (p_hat_y < 0) - hat |= Input::HAT_MASK_UP; + hat |= HatMask::HAT_MASK_UP; else - hat |= Input::HAT_MASK_DOWN; + hat |= HatMask::HAT_MASK_DOWN; } jevent.hat = hat; @@ -385,11 +383,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv *env, os_android->main_loop_focusout(); } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jclass clazz) { - setup_android_thread(); - AudioDriverAndroid::thread_func(env); -} - JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv *env, jclass clazz, jstring path) { String js = jstring_to_string(path, env); diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index a3e2933185..63e9e6d8e5 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -56,7 +56,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jclass clazz, jint p_device, jint p_axis, jfloat p_value); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jclass clazz, jint p_device, jint p_hat_x, jint p_hat_y); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jclass clazz, jint p_device, jboolean p_connected, jstring p_name); -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jclass clazz); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gravity(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnetometer(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 422814dd50..222976d948 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -45,6 +45,23 @@ #include "java_godot_io_wrapper.h" #include "java_godot_wrapper.h" +String _remove_symlink(const String &dir) { + // Workaround for Android 6.0+ using a symlink. + // Save the current directory. + char current_dir_name[2048]; + getcwd(current_dir_name, 2048); + // Change directory to the external data directory. + chdir(dir.utf8().get_data()); + // Get the actual directory without the potential symlink. + char dir_name_wihout_symlink[2048]; + getcwd(dir_name_wihout_symlink, 2048); + // Convert back to a String. + String dir_without_symlink(dir_name_wihout_symlink); + // Restore original current directory. + chdir(current_dir_name); + return dir_without_symlink; +} + class AndroidLogger : public Logger { public: virtual void logv(const char *p_format, va_list p_list, bool p_err) { @@ -199,26 +216,18 @@ String OS_Android::get_user_data_dir() const { String data_dir = godot_io_java->get_user_data_dir(); if (data_dir != "") { - //store current dir - char real_current_dir_name[2048]; - getcwd(real_current_dir_name, 2048); - - //go to data dir - chdir(data_dir.utf8().get_data()); - - //get actual data dir, so we resolve potential symlink (Android 6.0+ seems to use symlink) - char data_current_dir_name[2048]; - getcwd(data_current_dir_name, 2048); - - //cache by parsing utf8 - data_dir_cache.parse_utf8(data_current_dir_name); - - //restore original dir so we don't mess things up - chdir(real_current_dir_name); - + data_dir_cache = _remove_symlink(data_dir); return data_dir_cache; } + return "."; +} +String OS_Android::get_external_data_dir() const { + String data_dir = godot_io_java->get_external_data_dir(); + if (data_dir != "") { + data_dir = _remove_symlink(data_dir); + return data_dir; + } return "."; } diff --git a/platform/android/os_android.h b/platform/android/os_android.h index dd14b69cf9..1e89e9211d 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -31,7 +31,6 @@ #ifndef OS_ANDROID_H #define OS_ANDROID_H -#include "audio_driver_jandroid.h" #include "audio_driver_opensl.h" #include "core/os/main_loop.h" #include "drivers/unix/os_unix.h" @@ -59,7 +58,6 @@ private: mutable String data_dir_cache; - //AudioDriverAndroid audio_driver_android; AudioDriverOpenSL audio_driver_android; MainLoop *main_loop; @@ -111,6 +109,7 @@ public: virtual Error shell_open(String p_uri) override; virtual String get_user_data_dir() const override; + virtual String get_external_data_dir() const override; virtual String get_resource_dir() const override; virtual String get_locale() const override; virtual String get_model_name() const override; diff --git a/platform/android/plugin/godot_plugin_config.h b/platform/android/plugin/godot_plugin_config.h index 173ac115a2..6b708548ae 100644 --- a/platform/android/plugin/godot_plugin_config.h +++ b/platform/android/plugin/godot_plugin_config.h @@ -37,8 +37,8 @@ /* The `config` section and fields are required and defined as follow: -- **name**: name of the plugin -- **binary_type**: can be either `local` or `remote`. The type affects the **binary** field +- **name**: name of the plugin. +- **binary_type**: can be either `local` or `remote`. The type affects the **binary** field. - **binary**: - if **binary_type** is `local`, then this should be the filename of the plugin `aar` file in the `res://android/plugins` directory (e.g: `MyPlugin.aar`). - if **binary_type** is `remote`, then this should be a declaration for a remote gradle binary (e.g: "org.godot.example:my-plugin:0.0.0"). @@ -102,7 +102,7 @@ struct PluginConfigAndroid { static inline String resolve_local_dependency_path(String plugin_config_dir, String dependency_path) { String absolute_path; if (!dependency_path.is_empty()) { - if (dependency_path.is_abs_path()) { + if (dependency_path.is_absolute_path()) { absolute_path = ProjectSettings::get_singleton()->globalize_path(dependency_path); } else { absolute_path = plugin_config_dir.plus_file(dependency_path); diff --git a/platform/android/plugin/godot_plugin_jni.cpp b/platform/android/plugin/godot_plugin_jni.cpp index ba3e9fa20f..cf0c02e2bf 100644 --- a/platform/android/plugin/godot_plugin_jni.cpp +++ b/platform/android/plugin/godot_plugin_jni.cpp @@ -43,7 +43,7 @@ extern "C" { JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jclass clazz, jstring name, jobject obj) { String singname = jstring_to_string(name, env); - JNISingleton *s = (JNISingleton *)ClassDB::instance("JNISingleton"); + JNISingleton *s = (JNISingleton *)ClassDB::instantiate("JNISingleton"); s->set_instance(env->NewGlobalRef(obj)); jni_singletons[singname] = s; |