diff --git a/platform/android/README.md b/platform/android/README.md deleted file mode 100644 index 343e588..0000000 --- a/platform/android/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Android platform port - -This folder contains the Java and C++ (JNI) code for the Android platform port, -using [Gradle](https://gradle.org/) as a build system. - -## Artwork license - -[`logo.png`](logo.png) and [`run_icon.png`](run_icon.png) are licensed under -[Creative Commons Attribution 3.0 Unported](https://developer.android.com/distribute/marketing-tools/brand-guidelines#android_robot) -per the Android logo usage guidelines: - -> The Android robot is reproduced or modified from work created and shared by -> Google and used according to terms described in the Creative Commons 3.0 -> Attribution License. diff --git a/platform/android/SCsub b/platform/android/SCsub deleted file mode 100644 index 79ee1e8..0000000 --- a/platform/android/SCsub +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python - -Import("env") - -android_files = [ - "os_android.cpp", - "android_input_handler.cpp", - "file_access_android.cpp", - "file_access_filesystem_jandroid.cpp", - "audio_driver_opensl.cpp", - "dir_access_jandroid.cpp", - "thread_jandroid.cpp", - "net_socket_android.cpp", - "java_pandemonium_lib_jni.cpp", - "java_class_wrapper.cpp", - "java_pandemonium_wrapper.cpp", - "java_pandemonium_io_wrapper.cpp", - "java_pandemonium_view_wrapper.cpp", - "jni_utils.cpp", - "android_keys_utils.cpp", - "plugin/pandemonium_plugin_jni.cpp", -] - -env_android = env.Clone() - -android_objects = [] -for x in android_files: - android_objects.append(env_android.SharedObject(x)) - -env_thirdparty = env_android.Clone() -env_thirdparty.disable_warnings() -thirdparty_obj = env_thirdparty.SharedObject("#thirdparty/misc/ifaddrs-android.cc") -android_objects.append(thirdparty_obj) - -lib = env_android.add_shared_library("#bin/libpandemonium", [android_objects], SHLIBSUFFIX=env["SHLIBSUFFIX"]) - -# Needed to force rebuilding the platform files when the thirdparty code is updated. -env.Depends(lib, thirdparty_obj) - -lib_arch_dir = "" -if env["android_arch"] == "armv7": - lib_arch_dir = "armeabi-v7a" -elif env["android_arch"] == "arm64v8": - lib_arch_dir = "arm64-v8a" -elif env["android_arch"] == "x86": - lib_arch_dir = "x86" -elif env["android_arch"] == "x86_64": - lib_arch_dir = "x86_64" -else: - print("WARN: Architecture not suitable for embedding into APK; keeping .so at \\bin") - -if lib_arch_dir != "": - if env["target"] == "release": - lib_type_dir = "release" - elif env["target"] == "release_debug": - lib_type_dir = "debug" - else: # debug - lib_type_dir = "dev" - - lib_tools_dir = "" - - out_dir = "#platform/android/java/lib/libs/" + lib_tools_dir + lib_type_dir + "/" + lib_arch_dir - env_android.Command( - out_dir + "/libpandemonium_android.so", "#bin/libpandemonium" + env["SHLIBSUFFIX"], Move("$TARGET", "$SOURCE") - ) - - stl_lib_path = ( - str(env["ANDROID_NDK_ROOT"]) + "/sources/cxx-stl/llvm-libc++/libs/" + lib_arch_dir + "/libc++_shared.so" - ) - env_android.Command(out_dir + "/libc++_shared.so", stl_lib_path, Copy("$TARGET", "$SOURCE")) diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp deleted file mode 100644 index 22c88bb..0000000 --- a/platform/android/android_input_handler.cpp +++ /dev/null @@ -1,419 +0,0 @@ -/*************************************************************************/ -/* android_input_handler.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "android_input_handler.h" - -#include "android_keys_utils.h" - -#include "core/os/os.h" - -void AndroidInputHandler::process_joy_event(const JoypadEvent &p_event) { - switch (p_event.type) { - case JOY_EVENT_BUTTON: - input->joy_button(p_event.device, p_event.index, p_event.pressed); - break; - case JOY_EVENT_AXIS: - input->joy_axis(p_event.device, p_event.index, p_event.value); - break; - case JOY_EVENT_HAT: - input->joy_hat(p_event.device, p_event.hat); - break; - default: - return; - } -} - -void AndroidInputHandler::_set_key_modifier_state(Ref ev) const { - ev->set_shift(shift_mem); - ev->set_alt(alt_mem); - ev->set_metakey(meta_mem); - ev->set_control(control_mem); -} - -void AndroidInputHandler::process_key_event(int p_scancode, int p_physical_scancode, int p_unicode, bool p_pressed) { - Ref ev; - ev.instance(); - - unsigned int physical_scancode = pandemonium_code_from_android_code(p_physical_scancode); - unsigned int scancode = physical_scancode; - if (p_scancode != 0) { - scancode = pandemonium_code_from_unicode(p_scancode); - } - - switch (physical_scancode) { - case KEY_SHIFT: { - shift_mem = p_pressed; - } break; - case KEY_ALT: { - alt_mem = p_pressed; - } break; - case KEY_CONTROL: { - control_mem = p_pressed; - } break; - case KEY_META: { - meta_mem = p_pressed; - } break; - default: - break; - } - - ev->set_scancode(scancode); - ev->set_physical_scancode(physical_scancode); - ev->set_unicode(p_unicode); - ev->set_pressed(p_pressed); - - _set_key_modifier_state(ev); - - if (p_physical_scancode == AKEYCODE_BACK) { - if (MainLoop *main_loop = OS::get_singleton()->get_main_loop()) { - main_loop->call_deferred("notification", MainLoop::NOTIFICATION_WM_GO_BACK_REQUEST); - } - } - - input->parse_input_event(ev); -} - -void AndroidInputHandler::_cancel_all_touch() { - _parse_all_touch(false, true); - touch.clear(); -} - -void AndroidInputHandler::_parse_all_touch(bool p_pressed, bool p_canceled, bool p_double_tap) { - if (touch.size()) { - //end all if exist - for (int i = 0; i < touch.size(); i++) { - Ref ev; - ev.instance(); - ev->set_index(touch[i].id); - ev->set_pressed(p_pressed); - ev->set_canceled(p_canceled); - ev->set_position(touch[i].pos); - ev->set_double_tap(p_double_tap); - input->parse_input_event(ev); - } - } -} - -void AndroidInputHandler::_release_all_touch() { - _parse_all_touch(false); - touch.clear(); -} - -void AndroidInputHandler::process_touch_event(int p_event, int p_pointer, const Vector &p_points, bool p_double_tap) { - switch (p_event) { - case AMOTION_EVENT_ACTION_DOWN: { //gesture begin - // Release any remaining touches or mouse event - _release_mouse_event_info(); - _release_all_touch(); - - touch.resize(p_points.size()); - for (int i = 0; i < p_points.size(); i++) { - touch.write[i].id = p_points[i].id; - touch.write[i].pos = p_points[i].pos; - } - - //send touch - _parse_all_touch(true, false, p_double_tap); - - } break; - case AMOTION_EVENT_ACTION_MOVE: { //motion - if (touch.size() != p_points.size()) { - return; - } - - for (int i = 0; i < touch.size(); i++) { - int idx = -1; - for (int j = 0; j < p_points.size(); j++) { - if (touch[i].id == p_points[j].id) { - idx = j; - break; - } - } - - ERR_CONTINUE(idx == -1); - - if (touch[i].pos == p_points[idx].pos) - continue; //no move unncesearily - - Ref ev; - ev.instance(); - ev->set_index(touch[i].id); - ev->set_position(p_points[idx].pos); - ev->set_relative(p_points[idx].pos - touch[i].pos); - input->parse_input_event(ev); - touch.write[i].pos = p_points[idx].pos; - } - - } break; - case AMOTION_EVENT_ACTION_CANCEL: { - _cancel_all_touch(); - } break; - case AMOTION_EVENT_ACTION_UP: { //release - _release_all_touch(); - } break; - case AMOTION_EVENT_ACTION_POINTER_DOWN: { // add touch - for (int i = 0; i < p_points.size(); i++) { - if (p_points[i].id == p_pointer) { - TouchPos tp = p_points[i]; - touch.push_back(tp); - - Ref ev; - ev.instance(); - - ev->set_index(tp.id); - ev->set_pressed(true); - ev->set_position(tp.pos); - input->parse_input_event(ev); - - break; - } - } - } break; - case AMOTION_EVENT_ACTION_POINTER_UP: { // remove touch - for (int i = 0; i < touch.size(); i++) { - if (touch[i].id == p_pointer) { - Ref ev; - ev.instance(); - ev->set_index(touch[i].id); - ev->set_pressed(false); - ev->set_position(touch[i].pos); - input->parse_input_event(ev); - touch.remove(i); - - break; - } - } - } break; - } -} - -void AndroidInputHandler::_cancel_mouse_event_info(bool p_source_mouse_relative) { - buttons_state = 0; - _parse_mouse_event_info(0, false, true, false, p_source_mouse_relative); - mouse_event_info.valid = false; -} - -void AndroidInputHandler::_parse_mouse_event_info(int buttons_mask, bool p_pressed, bool p_canceled, bool p_double_click, bool p_source_mouse_relative) { - if (!mouse_event_info.valid) { - return; - } - - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - - if (p_source_mouse_relative) { - ev->set_position(hover_prev_pos); - ev->set_global_position(hover_prev_pos); - } else { - ev->set_position(mouse_event_info.pos); - ev->set_global_position(mouse_event_info.pos); - hover_prev_pos = mouse_event_info.pos; - } - - ev->set_pressed(p_pressed); - ev->set_canceled(p_canceled); - int changed_button_mask = buttons_state ^ buttons_mask; - - buttons_state = buttons_mask; - - ev->set_button_index(_button_index_from_mask(changed_button_mask)); - ev->set_button_mask(buttons_mask); - ev->set_doubleclick(p_double_click); - input->parse_input_event(ev); -} - -void AndroidInputHandler::_release_mouse_event_info(bool p_source_mouse_relative) { - _parse_mouse_event_info(0, false, false, false, p_source_mouse_relative); - mouse_event_info.valid = false; -} - -void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_android_buttons_mask, Point2 p_event_pos, Vector2 p_delta, bool p_double_click, bool p_source_mouse_relative) { - int event_buttons_mask = _android_button_mask_to_pandemonium_button_mask(p_event_android_buttons_mask); - switch (p_event_action) { - case AMOTION_EVENT_ACTION_HOVER_MOVE: // hover move - case AMOTION_EVENT_ACTION_HOVER_ENTER: // hover enter - case AMOTION_EVENT_ACTION_HOVER_EXIT: { // hover exit - // https://developer.android.com/reference/android/view/MotionEvent.html#ACTION_HOVER_ENTER - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - ev->set_position(p_event_pos); - ev->set_global_position(p_event_pos); - ev->set_relative(p_event_pos - hover_prev_pos); - input->parse_input_event(ev); - hover_prev_pos = p_event_pos; - } break; - case AMOTION_EVENT_ACTION_DOWN: - case AMOTION_EVENT_ACTION_BUTTON_PRESS: { - // Release any remaining touches or mouse event - _release_mouse_event_info(); - _release_all_touch(); - - mouse_event_info.valid = true; - mouse_event_info.pos = p_event_pos; - _parse_mouse_event_info(event_buttons_mask, true, false, p_double_click, p_source_mouse_relative); - } break; - - case AMOTION_EVENT_ACTION_CANCEL: { - _cancel_mouse_event_info(p_source_mouse_relative); - } break; - - case AMOTION_EVENT_ACTION_UP: - case AMOTION_EVENT_ACTION_BUTTON_RELEASE: { - _release_mouse_event_info(p_source_mouse_relative); - } break; - - case AMOTION_EVENT_ACTION_MOVE: { - if (!mouse_event_info.valid) { - return; - } - - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - - if (p_source_mouse_relative) { - ev->set_position(hover_prev_pos); - ev->set_global_position(hover_prev_pos); - ev->set_relative(p_event_pos); - } else { - ev->set_position(p_event_pos); - ev->set_global_position(p_event_pos); - ev->set_relative(p_event_pos - hover_prev_pos); - mouse_event_info.pos = p_event_pos; - hover_prev_pos = p_event_pos; - } - - ev->set_button_mask(event_buttons_mask); - input->parse_input_event(ev); - } break; - - case AMOTION_EVENT_ACTION_SCROLL: { - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - - if (p_source_mouse_relative) { - ev->set_position(hover_prev_pos); - ev->set_global_position(hover_prev_pos); - } else { - ev->set_position(p_event_pos); - ev->set_global_position(p_event_pos); - } - - ev->set_pressed(true); - buttons_state = event_buttons_mask; - if (p_delta.y > 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_UP, p_delta.y); - } else if (p_delta.y < 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_DOWN, -p_delta.y); - } - - if (p_delta.x > 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_RIGHT, p_delta.x); - } else if (p_delta.x < 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_LEFT, -p_delta.x); - } - } break; - } -} - -void AndroidInputHandler::_wheel_button_click(int event_buttons_mask, const Ref &ev, int wheel_button, float factor) { - Ref evd = ev->duplicate(); - evd->set_button_index(wheel_button); - evd->set_button_mask(event_buttons_mask ^ (1 << (wheel_button - 1))); - evd->set_factor(factor); - input->parse_input_event(evd); - Ref evdd = evd->duplicate(); - evdd->set_pressed(false); - evdd->set_button_mask(event_buttons_mask); - input->parse_input_event(evdd); -} - -void AndroidInputHandler::process_magnify(Point2 p_pos, float p_factor) { - Ref magnify_event; - magnify_event.instance(); - _set_key_modifier_state(magnify_event); - magnify_event->set_position(p_pos); - magnify_event->set_factor(p_factor); - input->parse_input_event(magnify_event); -} - -void AndroidInputHandler::process_pan(Point2 p_pos, Vector2 p_delta) { - Ref pan_event; - pan_event.instance(); - _set_key_modifier_state(pan_event); - pan_event->set_position(p_pos); - pan_event->set_delta(p_delta); - input->parse_input_event(pan_event); -} - -int AndroidInputHandler::_button_index_from_mask(int button_mask) { - switch (button_mask) { - case BUTTON_MASK_LEFT: - return BUTTON_LEFT; - case BUTTON_MASK_RIGHT: - return BUTTON_RIGHT; - case BUTTON_MASK_MIDDLE: - return BUTTON_MIDDLE; - case BUTTON_MASK_XBUTTON1: - return BUTTON_XBUTTON1; - case BUTTON_MASK_XBUTTON2: - return BUTTON_XBUTTON2; - default: - return 0; - } -} - -int AndroidInputHandler::_android_button_mask_to_pandemonium_button_mask(int android_button_mask) { - int pandemonium_button_mask = 0; - if (android_button_mask & AMOTION_EVENT_BUTTON_PRIMARY) { - pandemonium_button_mask |= BUTTON_MASK_LEFT; - } - if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) { - pandemonium_button_mask |= BUTTON_MASK_RIGHT; - } - if (android_button_mask & AMOTION_EVENT_BUTTON_TERTIARY) { - pandemonium_button_mask |= BUTTON_MASK_MIDDLE; - } - if (android_button_mask & AMOTION_EVENT_BUTTON_BACK) { - pandemonium_button_mask |= BUTTON_MASK_XBUTTON1; - } - if (android_button_mask & AMOTION_EVENT_BUTTON_FORWARD) { - pandemonium_button_mask |= BUTTON_MASK_XBUTTON2; - } - - return pandemonium_button_mask; -} - -void AndroidInputHandler::joy_connection_changed(int p_device, bool p_connected, String p_name) { - input->joy_connection_changed(p_device, p_connected, p_name, ""); -} diff --git a/platform/android/android_input_handler.h b/platform/android/android_input_handler.h deleted file mode 100644 index 39f94ae..0000000 --- a/platform/android/android_input_handler.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef ANDROID_INPUT_HANDLER_H -#define ANDROID_INPUT_HANDLER_H -/*************************************************************************/ -/* android_input_handler.h */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "main/input_default.h" - -// This class encapsulates all the handling of input events that come from the Android UI thread. -// Remarks: -// - It's not thread-safe by itself, so its functions must only be called on a single thread, which is the Android UI thread. -// - Its functions must only call thread-safe methods. -class AndroidInputHandler { -public: - struct TouchPos { - int id; - Point2 pos; - }; - - struct MouseEventInfo { - bool valid = false; - Point2 pos; - }; - - enum { - JOY_EVENT_BUTTON = 0, - JOY_EVENT_AXIS = 1, - JOY_EVENT_HAT = 2 - }; - - struct JoypadEvent { - int device; - int type; - int index; - bool pressed; - float value; - int hat; - }; - -private: - Vector touch; - MouseEventInfo mouse_event_info; - Point2 hover_prev_pos; // needed to calculate the relative position on hover events - - bool alt_mem = false; - bool shift_mem = false; - bool control_mem = false; - bool meta_mem = false; - - int buttons_state = 0; - - InputDefault *input = static_cast(InputDefault::get_singleton()); - - void _set_key_modifier_state(Ref ev) const; - - static int _button_index_from_mask(int button_mask); - - static int _android_button_mask_to_pandemonium_button_mask(int android_button_mask); - - void _wheel_button_click(int event_buttons_mask, const Ref &ev, int wheel_button, float factor); - - void _parse_mouse_event_info(int buttons_mask, bool p_pressed, bool p_canceled, bool p_double_click, bool p_source_mouse_relative); - - void _release_mouse_event_info(bool p_source_mouse_relative = false); - - void _cancel_mouse_event_info(bool p_source_mouse_relative = false); - - void _parse_all_touch(bool p_pressed, bool p_canceled = false, bool p_double_tap = false); - - void _release_all_touch(); - - void _cancel_all_touch(); - -public: - void process_joy_event(const JoypadEvent &p_event); - void process_key_event(int p_scancode, int p_physical_scancode, int p_unicode, bool p_pressed); - void process_mouse_event(int p_event_action, int p_event_android_buttons_mask, Point2 p_event_pos, Vector2 p_delta, bool p_double_click, bool p_source_mouse_relative); - void process_touch_event(int p_event, int p_pointer, const Vector &p_points, bool p_double_tap); - void process_magnify(Point2 p_pos, float p_factor); - void process_pan(Point2 p_pos, Vector2 p_delta); - void joy_connection_changed(int p_device, bool p_connected, String p_name); -}; - -#endif diff --git a/platform/android/android_keys_utils.cpp b/platform/android/android_keys_utils.cpp deleted file mode 100644 index 45d2742..0000000 --- a/platform/android/android_keys_utils.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/*************************************************************************/ -/* android_keys_utils.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "android_keys_utils.h" - -unsigned int pandemonium_code_from_android_code(unsigned int p_code) { - for (int i = 0; android_pandemonium_code_pairs[i].android_code != AKEYCODE_MAX; i++) { - if (android_pandemonium_code_pairs[i].android_code == p_code) { - return android_pandemonium_code_pairs[i].pandemonium_code; - } - } - - return KEY_UNKNOWN; -} - -unsigned int pandemonium_code_from_unicode(unsigned int p_code) { - unsigned int code = p_code; - if (code > 0xFF) { - return KEY_UNKNOWN; - } - // Known control codes. - if (code == '\b') { // 0x08 - return KEY_BACKSPACE; - } - if (code == '\t') { // 0x09 - return KEY_TAB; - } - if (code == '\n') { // 0x0A - return KEY_ENTER; - } - if (code == 0x1B) { - return KEY_ESCAPE; - } - if (code == 0x7F) { - return KEY_DELETE; - } - // Unknown control codes. - if (code <= 0x1F || (code >= 0x80 && code <= 0x9F)) { - return KEY_UNKNOWN; - } - // Convert to uppercase. - if (code >= 'a' && code <= 'z') { // 0x61 - 0x7A - code -= ('a' - 'A'); - } - if (code >= u'à' && code <= u'ö') { // 0xE0 - 0xF6 - code -= (u'à' - u'À'); // 0xE0 - 0xC0 - } - if (code >= u'ø' && code <= u'þ') { // 0xF8 - 0xFF - code -= (u'ø' - u'Ø'); // 0xF8 - 0xD8 - } - return code; -} diff --git a/platform/android/android_keys_utils.h b/platform/android/android_keys_utils.h deleted file mode 100644 index 5baf4ab..0000000 --- a/platform/android/android_keys_utils.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef ANDROID_KEYS_UTILS_H -#define ANDROID_KEYS_UTILS_H -/*************************************************************************/ -/* android_keys_utils.h */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include -#include - -#define AKEYCODE_MAX 0xFFFF - -struct AndroidPandemoniumCodePair { - unsigned int android_code = 0; - unsigned int pandemonium_code = 0; -}; - -static AndroidPandemoniumCodePair android_pandemonium_code_pairs[] = { - { AKEYCODE_UNKNOWN, KEY_UNKNOWN }, // (0) Unknown key code. - { AKEYCODE_BACK, KEY_BACK }, // (4) Back key. - { AKEYCODE_0, KEY_0 }, // (7) '0' key. - { AKEYCODE_1, KEY_1 }, // (8) '1' key. - { AKEYCODE_2, KEY_2 }, // (9) '2' key. - { AKEYCODE_3, KEY_3 }, // (10) '3' key. - { AKEYCODE_4, KEY_4 }, // (11) '4' key. - { AKEYCODE_5, KEY_5 }, // (12) '5' key. - { AKEYCODE_6, KEY_6 }, // (13) '6' key. - { AKEYCODE_7, KEY_7 }, // (14) '7' key. - { AKEYCODE_8, KEY_8 }, // (15) '8' key. - { AKEYCODE_9, KEY_9 }, // (16) '9' key. - { AKEYCODE_STAR, KEY_ASTERISK }, // (17) '*' key. - { AKEYCODE_POUND, KEY_NUMBERSIGN }, // (18) '#' key. - { AKEYCODE_DPAD_UP, KEY_UP }, // (19) Directional Pad Up key. - { AKEYCODE_DPAD_DOWN, KEY_DOWN }, // (20) Directional Pad Down key. - { AKEYCODE_DPAD_LEFT, KEY_LEFT }, // (21) Directional Pad Left key. - { AKEYCODE_DPAD_RIGHT, KEY_RIGHT }, // (22) Directional Pad Right key. - { AKEYCODE_DPAD_CENTER, KEY_ENTER }, // (23) Directional Pad Center key. - { AKEYCODE_VOLUME_UP, KEY_VOLUMEUP }, // (24) Volume Up key. - { AKEYCODE_VOLUME_DOWN, KEY_VOLUMEDOWN }, // (25) Volume Down key. - { AKEYCODE_POWER, KEY_STANDBY }, // (26) Power key. - { AKEYCODE_CLEAR, KEY_CLEAR }, // (28) Clear key. - { AKEYCODE_A, KEY_A }, // (29) 'A' key. - { AKEYCODE_B, KEY_B }, // (30) 'B' key. - { AKEYCODE_C, KEY_C }, // (31) 'C' key. - { AKEYCODE_D, KEY_D }, // (32) 'D' key. - { AKEYCODE_E, KEY_E }, // (33) 'E' key. - { AKEYCODE_F, KEY_F }, // (34) 'F' key. - { AKEYCODE_G, KEY_G }, // (35) 'G' key. - { AKEYCODE_H, KEY_H }, // (36) 'H' key. - { AKEYCODE_I, KEY_I }, // (37) 'I' key. - { AKEYCODE_J, KEY_J }, // (38) 'J' key. - { AKEYCODE_K, KEY_K }, // (39) 'K' key. - { AKEYCODE_L, KEY_L }, // (40) 'L' key. - { AKEYCODE_M, KEY_M }, // (41) 'M' key. - { AKEYCODE_N, KEY_N }, // (42) 'N' key. - { AKEYCODE_O, KEY_O }, // (43) 'O' key. - { AKEYCODE_P, KEY_P }, // (44) 'P' key. - { AKEYCODE_Q, KEY_Q }, // (45) 'Q' key. - { AKEYCODE_R, KEY_R }, // (46) 'R' key. - { AKEYCODE_S, KEY_S }, // (47) 'S' key. - { AKEYCODE_T, KEY_T }, // (48) 'T' key. - { AKEYCODE_U, KEY_U }, // (49) 'U' key. - { AKEYCODE_V, KEY_V }, // (50) 'V' key. - { AKEYCODE_W, KEY_W }, // (51) 'W' key. - { AKEYCODE_X, KEY_X }, // (52) 'X' key. - { AKEYCODE_Y, KEY_Y }, // (53) 'Y' key. - { AKEYCODE_Z, KEY_Z }, // (54) 'Z' key. - { AKEYCODE_COMMA, KEY_COMMA }, // (55) ',’ key. - { AKEYCODE_PERIOD, KEY_PERIOD }, // (56) '.' key. - { AKEYCODE_ALT_LEFT, KEY_ALT }, // (57) Left Alt modifier key. - { AKEYCODE_ALT_RIGHT, KEY_ALT }, // (58) Right Alt modifier key. - { AKEYCODE_SHIFT_LEFT, KEY_SHIFT }, // (59) Left Shift modifier key. - { AKEYCODE_SHIFT_RIGHT, KEY_SHIFT }, // (60) Right Shift modifier key. - { AKEYCODE_TAB, KEY_TAB }, // (61) Tab key. - { AKEYCODE_SPACE, KEY_SPACE }, // (62) Space key. - { AKEYCODE_ENVELOPE, KEY_LAUNCHMAIL }, // (65) Envelope special function key. - { AKEYCODE_ENTER, KEY_ENTER }, // (66) Enter key. - { AKEYCODE_DEL, KEY_BACKSPACE }, // (67) Backspace key. - { AKEYCODE_GRAVE, KEY_QUOTELEFT }, // (68) '`' (backtick) key. - { AKEYCODE_MINUS, KEY_MINUS }, // (69) '-'. - { AKEYCODE_EQUALS, KEY_EQUAL }, // (70) '=' key. - { AKEYCODE_LEFT_BRACKET, KEY_BRACKETLEFT }, // (71) '[' key. - { AKEYCODE_RIGHT_BRACKET, KEY_BRACKETRIGHT }, // (72) ']' key. - { AKEYCODE_BACKSLASH, KEY_BACKSLASH }, // (73) '\' key. - { AKEYCODE_SEMICOLON, KEY_SEMICOLON }, // (74) ';' key. - { AKEYCODE_APOSTROPHE, KEY_APOSTROPHE }, // (75) ''' (apostrophe) key. - { AKEYCODE_SLASH, KEY_SLASH }, // (76) '/' key. - { AKEYCODE_AT, KEY_AT }, // (77) '@' key. - { AKEYCODE_PLUS, KEY_PLUS }, // (81) '+' key. - { AKEYCODE_MENU, KEY_MENU }, // (82) Menu key. - { AKEYCODE_SEARCH, KEY_SEARCH }, // (84) Search key. - { AKEYCODE_MEDIA_STOP, KEY_MEDIASTOP }, // (86) Stop media key. - { AKEYCODE_MEDIA_NEXT, KEY_MEDIANEXT }, // (87) Play Next media key. - { AKEYCODE_MEDIA_PREVIOUS, KEY_MEDIAPREVIOUS }, // (88) Play Previous media key. - { AKEYCODE_PAGE_UP, KEY_PAGEUP }, // (92) Page Up key. - { AKEYCODE_PAGE_DOWN, KEY_PAGEDOWN }, // (93) Page Down key. - { AKEYCODE_ESCAPE, KEY_ESCAPE }, // (111) Escape key. - { AKEYCODE_FORWARD_DEL, KEY_DELETE }, // (112) Forward Delete key. - { AKEYCODE_CTRL_LEFT, KEY_CONTROL }, // (113) Left Control modifier key. - { AKEYCODE_CTRL_RIGHT, KEY_CONTROL }, // (114) Right Control modifier key. - { AKEYCODE_CAPS_LOCK, KEY_CAPSLOCK }, // (115) Caps Lock key. - { AKEYCODE_SCROLL_LOCK, KEY_SCROLLLOCK }, // (116) Scroll Lock key. - { AKEYCODE_META_LEFT, KEY_META }, // (117) Left Meta modifier key. - { AKEYCODE_META_RIGHT, KEY_META }, // (118) Right Meta modifier key. - { AKEYCODE_SYSRQ, KEY_PRINT }, // (120) System Request / Print Screen key. - { AKEYCODE_BREAK, KEY_PAUSE }, // (121) Break / Pause key. - { AKEYCODE_MOVE_HOME, KEY_HOME }, // (122) Home Movement key. - { AKEYCODE_MOVE_END, KEY_END }, // (123) End Movement key. - { AKEYCODE_INSERT, KEY_INSERT }, // (124) Insert key. - { AKEYCODE_FORWARD, KEY_FORWARD }, // (125) Forward key. - { AKEYCODE_MEDIA_PLAY, KEY_MEDIAPLAY }, // (126) Play media key. - { AKEYCODE_MEDIA_RECORD, KEY_MEDIARECORD }, // (130) Record media key. - { AKEYCODE_F1, KEY_F1 }, // (131) F1 key. - { AKEYCODE_F2, KEY_F2 }, // (132) F2 key. - { AKEYCODE_F3, KEY_F3 }, // (133) F3 key. - { AKEYCODE_F4, KEY_F4 }, // (134) F4 key. - { AKEYCODE_F5, KEY_F5 }, // (135) F5 key. - { AKEYCODE_F6, KEY_F6 }, // (136) F6 key. - { AKEYCODE_F7, KEY_F7 }, // (137) F7 key. - { AKEYCODE_F8, KEY_F8 }, // (138) F8 key. - { AKEYCODE_F9, KEY_F9 }, // (139) F9 key. - { AKEYCODE_F10, KEY_F10 }, // (140) F10 key. - { AKEYCODE_F11, KEY_F11 }, // (141) F11 key. - { AKEYCODE_F12, KEY_F12 }, // (142) F12 key. - { AKEYCODE_NUM_LOCK, KEY_NUMLOCK }, // (143) Num Lock key. - { AKEYCODE_NUMPAD_0, KEY_KP_0 }, // (144) Numeric keypad '0' key. - { AKEYCODE_NUMPAD_1, KEY_KP_1 }, // (145) Numeric keypad '1' key. - { AKEYCODE_NUMPAD_2, KEY_KP_2 }, // (146) Numeric keypad '2' key. - { AKEYCODE_NUMPAD_3, KEY_KP_3 }, // (147) Numeric keypad '3' key. - { AKEYCODE_NUMPAD_4, KEY_KP_4 }, // (148) Numeric keypad '4' key. - { AKEYCODE_NUMPAD_5, KEY_KP_5 }, // (149) Numeric keypad '5' key. - { AKEYCODE_NUMPAD_6, KEY_KP_6 }, // (150) Numeric keypad '6' key. - { AKEYCODE_NUMPAD_7, KEY_KP_7 }, // (151) Numeric keypad '7' key. - { AKEYCODE_NUMPAD_8, KEY_KP_8 }, // (152) Numeric keypad '8' key. - { AKEYCODE_NUMPAD_9, KEY_KP_9 }, // (153) Numeric keypad '9' key. - { AKEYCODE_NUMPAD_DIVIDE, KEY_KP_DIVIDE }, // (154) Numeric keypad '/' key (for division). - { AKEYCODE_NUMPAD_MULTIPLY, KEY_KP_MULTIPLY }, // (155) Numeric keypad '*' key (for multiplication). - { AKEYCODE_NUMPAD_SUBTRACT, KEY_KP_SUBTRACT }, // (156) Numeric keypad '-' key (for subtraction). - { AKEYCODE_NUMPAD_ADD, KEY_KP_ADD }, // (157) Numeric keypad '+' key (for addition). - { AKEYCODE_NUMPAD_DOT, KEY_KP_PERIOD }, // (158) Numeric keypad '.' key (for decimals or digit grouping). - { AKEYCODE_NUMPAD_ENTER, KEY_KP_ENTER }, // (160) Numeric keypad Enter key. - { AKEYCODE_VOLUME_MUTE, KEY_VOLUMEMUTE }, // (164) Volume Mute key. - { AKEYCODE_YEN, KEY_YEN }, // (216) Japanese Yen key. - { AKEYCODE_HELP, KEY_HELP }, // (259) Help key. - { AKEYCODE_REFRESH, KEY_REFRESH }, // (285) Refresh key. - { AKEYCODE_MAX, KEY_UNKNOWN } -}; - -unsigned int pandemonium_code_from_android_code(unsigned int p_code); -unsigned int pandemonium_code_from_unicode(unsigned int p_code); - -#endif // ANDROID_KEYS_UTILS_H diff --git a/platform/android/api/api.cpp b/platform/android/api/api.cpp deleted file mode 100644 index d66c908..0000000 --- a/platform/android/api/api.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/*************************************************************************/ -/* api.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "api.h" - -#include "core/config/engine.h" -#include "java_class_wrapper.h" -#include "jni_singleton.h" - -#if !defined(ANDROID_ENABLED) -static JavaClassWrapper *java_class_wrapper = nullptr; -#endif - -void register_android_api() { -#if !defined(ANDROID_ENABLED) - // On Android platforms, the `java_class_wrapper` instantiation and the - // `JNISingleton` registration occurs in - // `platform/android/java_pandemonium_lib_jni.cpp#Java_org_pandemoniumengine_pandemonium_PandemoniumLib_setup` - java_class_wrapper = memnew(JavaClassWrapper); // Dummy - ClassDB::register_class(); -#endif - - ClassDB::register_class(); - ClassDB::register_class(); - Engine::get_singleton()->add_singleton(Engine::Singleton("JavaClassWrapper", JavaClassWrapper::get_singleton())); -} - -void unregister_android_api() { -#if !defined(ANDROID_ENABLED) - memdelete(java_class_wrapper); -#endif -} - -void JavaClassWrapper::_bind_methods() { - ClassDB::bind_method(D_METHOD("wrap", "name"), &JavaClassWrapper::wrap); -} - -#if !defined(ANDROID_ENABLED) - -Variant JavaClass::call(const StringName &, const Variant **, int, Variant::CallError &) { - return Variant(); -} - -JavaClass::JavaClass() { -} - -Variant JavaObject::call(const StringName &, const Variant **, int, Variant::CallError &) { - return Variant(); -} - -JavaClassWrapper *JavaClassWrapper::singleton = nullptr; - -Ref JavaClassWrapper::wrap(const String &) { - return Ref(); -} - -JavaClassWrapper::JavaClassWrapper() { - singleton = this; -} - -#endif diff --git a/platform/android/api/api.h b/platform/android/api/api.h deleted file mode 100644 index 9e0c331..0000000 --- a/platform/android/api/api.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef ANDROID_API_H -#define ANDROID_API_H -/*************************************************************************/ -/* api.h */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -void register_android_api(); -void unregister_android_api(); - -#endif // ANDROID_API_H diff --git a/platform/android/api/java_class_wrapper.h b/platform/android/api/java_class_wrapper.h deleted file mode 100644 index e7baff4..0000000 --- a/platform/android/api/java_class_wrapper.h +++ /dev/null @@ -1,254 +0,0 @@ -#ifndef JAVA_CLASS_WRAPPER_H -#define JAVA_CLASS_WRAPPER_H -/*************************************************************************/ -/* java_class_wrapper.h */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "core/object/reference.h" - -#ifdef ANDROID_ENABLED -#include -#include -#endif - -#ifdef ANDROID_ENABLED -class JavaObject; -#endif - -class JavaClass : public Reference { - GDCLASS(JavaClass, Reference); - -#ifdef ANDROID_ENABLED - enum ArgumentType{ - - ARG_TYPE_VOID, - ARG_TYPE_BOOLEAN, - ARG_TYPE_BYTE, - ARG_TYPE_CHAR, - ARG_TYPE_SHORT, - ARG_TYPE_INT, - ARG_TYPE_LONG, - ARG_TYPE_FLOAT, - ARG_TYPE_DOUBLE, - ARG_TYPE_STRING, //special case - ARG_TYPE_CLASS, - ARG_ARRAY_BIT = 1 << 16, - ARG_NUMBER_CLASS_BIT = 1 << 17, - ARG_TYPE_MASK = (1 << 16) - 1 - }; - - RBMap constant_map; - - struct MethodInfo { - bool _static; - Vector param_types; - Vector param_sigs; - uint32_t return_type; - jmethodID method; - }; - - _FORCE_INLINE_ static void _convert_to_variant_type(int p_sig, Variant::Type &r_type, float &likelihood) { - likelihood = 1.0; - r_type = Variant::NIL; - - switch (p_sig) { - case ARG_TYPE_VOID: - r_type = Variant::NIL; - break; - case ARG_TYPE_BOOLEAN | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_BOOLEAN: - r_type = Variant::BOOL; - break; - case ARG_TYPE_BYTE | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_BYTE: - r_type = Variant::INT; - likelihood = 0.1; - break; - case ARG_TYPE_CHAR | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_CHAR: - r_type = Variant::INT; - likelihood = 0.2; - break; - case ARG_TYPE_SHORT | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_SHORT: - r_type = Variant::INT; - likelihood = 0.3; - break; - case ARG_TYPE_INT | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_INT: - r_type = Variant::INT; - likelihood = 1.0; - break; - case ARG_TYPE_LONG | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_LONG: - r_type = Variant::INT; - likelihood = 0.5; - break; - case ARG_TYPE_FLOAT | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_FLOAT: - r_type = Variant::REAL; - likelihood = 1.0; - break; - case ARG_TYPE_DOUBLE | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_DOUBLE: - r_type = Variant::REAL; - likelihood = 0.5; - break; - case ARG_TYPE_STRING: - r_type = Variant::STRING; - break; - case ARG_TYPE_CLASS: - r_type = Variant::OBJECT; - break; - case ARG_ARRAY_BIT | ARG_TYPE_VOID: - r_type = Variant::NIL; - break; - case ARG_ARRAY_BIT | ARG_TYPE_BOOLEAN: - r_type = Variant::ARRAY; - break; - case ARG_ARRAY_BIT | ARG_TYPE_BYTE: - r_type = Variant::POOL_BYTE_ARRAY; - likelihood = 1.0; - break; - case ARG_ARRAY_BIT | ARG_TYPE_CHAR: - r_type = Variant::POOL_BYTE_ARRAY; - likelihood = 0.5; - break; - case ARG_ARRAY_BIT | ARG_TYPE_SHORT: - r_type = Variant::POOL_INT_ARRAY; - likelihood = 0.3; - break; - case ARG_ARRAY_BIT | ARG_TYPE_INT: - r_type = Variant::POOL_INT_ARRAY; - likelihood = 1.0; - break; - case ARG_ARRAY_BIT | ARG_TYPE_LONG: - r_type = Variant::POOL_INT_ARRAY; - likelihood = 0.5; - break; - case ARG_ARRAY_BIT | ARG_TYPE_FLOAT: - r_type = Variant::POOL_REAL_ARRAY; - likelihood = 1.0; - break; - case ARG_ARRAY_BIT | ARG_TYPE_DOUBLE: - r_type = Variant::POOL_REAL_ARRAY; - likelihood = 0.5; - break; - case ARG_ARRAY_BIT | ARG_TYPE_STRING: - r_type = Variant::POOL_STRING_ARRAY; - break; - case ARG_ARRAY_BIT | ARG_TYPE_CLASS: - r_type = Variant::ARRAY; - break; - } - } - - _FORCE_INLINE_ static bool _convert_object_to_variant(JNIEnv *env, jobject obj, Variant &var, uint32_t p_sig); - - bool _call_method(JavaObject *p_instance, const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error, Variant &ret); - - friend class JavaClassWrapper; - RBMap> methods; - jclass _class; -#endif - -public: - virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); - - JavaClass(); -}; - -class JavaObject : public Reference { - GDCLASS(JavaObject, Reference); - -#ifdef ANDROID_ENABLED - Ref base_class; - friend class JavaClass; - - jobject instance; -#endif - -public: - virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); - -#ifdef ANDROID_ENABLED - JavaObject(const Ref &p_base, jobject *p_instance); - ~JavaObject(); -#endif -}; - -class JavaClassWrapper : public Object { - GDCLASS(JavaClassWrapper, Object); - -#ifdef ANDROID_ENABLED - RBMap> class_cache; - friend class JavaClass; - jclass activityClass; - jmethodID findClass; - jmethodID getDeclaredMethods; - jmethodID getFields; - jmethodID getParameterTypes; - jmethodID getReturnType; - jmethodID getModifiers; - jmethodID getName; - jmethodID Class_getName; - jmethodID Field_getName; - jmethodID Field_getModifiers; - jmethodID Field_get; - jmethodID Boolean_booleanValue; - jmethodID Byte_byteValue; - jmethodID Character_characterValue; - jmethodID Short_shortValue; - jmethodID Integer_integerValue; - jmethodID Long_longValue; - jmethodID Float_floatValue; - jmethodID Double_doubleValue; - jobject classLoader; - - bool _get_type_sig(JNIEnv *env, jobject obj, uint32_t &sig, String &strsig); -#endif - - static JavaClassWrapper *singleton; - -protected: - static void _bind_methods(); - -public: - static JavaClassWrapper *get_singleton() { return singleton; } - - Ref wrap(const String &p_class); - -#ifdef ANDROID_ENABLED - JavaClassWrapper(jobject p_activity = NULL); -#else - JavaClassWrapper(); -#endif -}; - -#endif // JAVA_CLASS_WRAPPER_H diff --git a/platform/android/api/jni_singleton.h b/platform/android/api/jni_singleton.h deleted file mode 100644 index 9971d37..0000000 --- a/platform/android/api/jni_singleton.h +++ /dev/null @@ -1,221 +0,0 @@ -#ifndef JNI_SINGLETON_H -#define JNI_SINGLETON_H -/*************************************************************************/ -/* jni_singleton.h */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include -#include -#ifdef ANDROID_ENABLED -#include -#endif - -class JNISingleton : public Object { - GDCLASS(JNISingleton, Object); - -#ifdef ANDROID_ENABLED - struct MethodData { - jmethodID method; - Variant::Type ret_type; - Vector argtypes; - }; - - jobject instance; - RBMap method_map; -#endif - -public: - virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { -#ifdef ANDROID_ENABLED - RBMap::Element *E = method_map.find(p_method); - - // Check the method we're looking for is in the JNISingleton map and that - // the arguments match. - bool call_error = !E || E->get().argtypes.size() != p_argcount; - if (!call_error) { - for (int i = 0; i < p_argcount; i++) { - if (!Variant::can_convert(p_args[i]->get_type(), E->get().argtypes[i])) { - call_error = true; - break; - } - } - } - - if (call_error) { - // The method is not in this map, defaulting to the regular instance calls. - return Object::call(p_method, p_args, p_argcount, r_error); - } - - ERR_FAIL_COND_V(!instance, Variant()); - - r_error.error = Variant::CallError::CALL_OK; - - jvalue *v = NULL; - - if (p_argcount) { - v = (jvalue *)alloca(sizeof(jvalue) * p_argcount); - } - - JNIEnv *env = get_jni_env(); - - int res = env->PushLocalFrame(16); - - ERR_FAIL_COND_V(res != 0, Variant()); - - List to_erase; - for (int i = 0; i < p_argcount; i++) { - jvalret vr = _variant_to_jvalue(env, E->get().argtypes[i], p_args[i]); - v[i] = vr.val; - if (vr.obj) - to_erase.push_back(vr.obj); - } - - Variant ret; - - switch (E->get().ret_type) { - case Variant::NIL: { - env->CallVoidMethodA(instance, E->get().method, v); - } break; - case Variant::BOOL: { - ret = env->CallBooleanMethodA(instance, E->get().method, v) == JNI_TRUE; - } break; - case Variant::INT: { - ret = env->CallIntMethodA(instance, E->get().method, v); - } break; - case Variant::REAL: { - ret = env->CallFloatMethodA(instance, E->get().method, v); - } break; - case Variant::STRING: { - jobject o = env->CallObjectMethodA(instance, E->get().method, v); - ret = jstring_to_string((jstring)o, env); - env->DeleteLocalRef(o); - } break; - case Variant::POOL_STRING_ARRAY: { - jobjectArray arr = (jobjectArray)env->CallObjectMethodA(instance, E->get().method, v); - - ret = _jobject_to_variant(env, arr); - - env->DeleteLocalRef(arr); - } break; - case Variant::POOL_INT_ARRAY: { - jintArray arr = (jintArray)env->CallObjectMethodA(instance, E->get().method, v); - - int fCount = env->GetArrayLength(arr); - PoolVector sarr; - sarr.resize(fCount); - - PoolVector::Write w = sarr.write(); - env->GetIntArrayRegion(arr, 0, fCount, w.ptr()); - w.release(); - ret = sarr; - env->DeleteLocalRef(arr); - } break; - case Variant::POOL_REAL_ARRAY: { - jfloatArray arr = (jfloatArray)env->CallObjectMethodA(instance, E->get().method, v); - - int fCount = env->GetArrayLength(arr); - PoolVector sarr; - sarr.resize(fCount); - - PoolVector::Write w = sarr.write(); - env->GetFloatArrayRegion(arr, 0, fCount, w.ptr()); - w.release(); - ret = sarr; - env->DeleteLocalRef(arr); - } break; - - case Variant::DICTIONARY: { - jobject obj = env->CallObjectMethodA(instance, E->get().method, v); - ret = _jobject_to_variant(env, obj); - env->DeleteLocalRef(obj); - - } break; - default: { - env->PopLocalFrame(NULL); - ERR_FAIL_V(Variant()); - } break; - } - - while (to_erase.size()) { - env->DeleteLocalRef(to_erase.front()->get()); - to_erase.pop_front(); - } - - env->PopLocalFrame(NULL); - - return ret; -#else // ANDROID_ENABLED - - // Defaulting to the regular instance calls. - return Object::call(p_method, p_args, p_argcount, r_error); -#endif - } - -#ifdef ANDROID_ENABLED - jobject get_instance() const { - return instance; - } - - void set_instance(jobject p_instance) { - instance = p_instance; - } - - void add_method(const StringName &p_name, jmethodID p_method, const Vector &p_args, Variant::Type p_ret_type) { - MethodData md; - md.method = p_method; - md.argtypes = p_args; - md.ret_type = p_ret_type; - method_map[p_name] = md; - } - - void add_signal(const StringName &p_name, const Vector &p_args) { - if (p_args.size() == 0) - ADD_SIGNAL(MethodInfo(p_name)); - else if (p_args.size() == 1) - ADD_SIGNAL(MethodInfo(p_name, PropertyInfo(p_args[0], "arg1"))); - else if (p_args.size() == 2) - ADD_SIGNAL(MethodInfo(p_name, PropertyInfo(p_args[0], "arg1"), PropertyInfo(p_args[1], "arg2"))); - else if (p_args.size() == 3) - ADD_SIGNAL(MethodInfo(p_name, PropertyInfo(p_args[0], "arg1"), PropertyInfo(p_args[1], "arg2"), PropertyInfo(p_args[2], "arg3"))); - else if (p_args.size() == 4) - ADD_SIGNAL(MethodInfo(p_name, PropertyInfo(p_args[0], "arg1"), PropertyInfo(p_args[1], "arg2"), PropertyInfo(p_args[2], "arg3"), PropertyInfo(p_args[3], "arg4"))); - else if (p_args.size() == 5) - ADD_SIGNAL(MethodInfo(p_name, PropertyInfo(p_args[0], "arg1"), PropertyInfo(p_args[1], "arg2"), PropertyInfo(p_args[2], "arg3"), PropertyInfo(p_args[3], "arg4"), PropertyInfo(p_args[4], "arg5"))); - } - -#endif - - JNISingleton() { -#ifdef ANDROID_ENABLED - instance = NULL; -#endif - } -}; - -#endif // JNI_SINGLETON_H diff --git a/platform/android/audio_driver_opensl.cpp b/platform/android/audio_driver_opensl.cpp deleted file mode 100644 index 5bf310c..0000000 --- a/platform/android/audio_driver_opensl.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/*************************************************************************/ -/* audio_driver_opensl.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "audio_driver_opensl.h" - -#include - -#define MAX_NUMBER_INTERFACES 3 -#define MAX_NUMBER_OUTPUT_DEVICES 6 - -/* Structure for passing information to callback function */ - -void AudioDriverOpenSL::_buffer_callback( - SLAndroidSimpleBufferQueueItf queueItf) { - bool mix = true; - - if (pause) { - mix = false; - } else { - mix = mutex.try_lock() == OK; - } - - if (mix) { - audio_server_process(buffer_size, mixdown_buffer); - } else { - int32_t *src_buff = mixdown_buffer; - for (unsigned int i = 0; i < buffer_size * 2; i++) { - src_buff[i] = 0; - } - } - - if (mix) - mutex.unlock(); - - const int32_t *src_buff = mixdown_buffer; - - int16_t *ptr = (int16_t *)buffers[last_free]; - last_free = (last_free + 1) % BUFFER_COUNT; - - for (unsigned int i = 0; i < buffer_size * 2; i++) { - ptr[i] = src_buff[i] >> 16; - } - - (*queueItf)->Enqueue(queueItf, ptr, 4 * buffer_size); -} - -void AudioDriverOpenSL::_buffer_callbacks( - SLAndroidSimpleBufferQueueItf queueItf, - void *pContext) { - AudioDriverOpenSL *ad = (AudioDriverOpenSL *)pContext; - - ad->_buffer_callback(queueItf); -} - -AudioDriverOpenSL *AudioDriverOpenSL::s_ad = NULL; - -const char *AudioDriverOpenSL::get_name() const { - return "Android"; -} - -Error AudioDriverOpenSL::init() { - SLresult res; - SLEngineOption EngineOption[] = { - { (SLuint32)SL_ENGINEOPTION_THREADSAFE, (SLuint32)SL_BOOLEAN_TRUE } - }; - res = slCreateEngine(&sl, 1, EngineOption, 0, NULL, NULL); - ERR_FAIL_COND_V_MSG(res != SL_RESULT_SUCCESS, ERR_INVALID_PARAMETER, "Could not initialize OpenSL."); - - res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); - ERR_FAIL_COND_V_MSG(res != SL_RESULT_SUCCESS, ERR_INVALID_PARAMETER, "Could not realize OpenSL."); - - return OK; -} - -void AudioDriverOpenSL::start() { - active = false; - - SLresult res; - - buffer_size = 1024; - - for (int i = 0; i < BUFFER_COUNT; i++) { - buffers[i] = memnew_arr(int16_t, buffer_size * 2); - memset(buffers[i], 0, buffer_size * 4); - } - - mixdown_buffer = memnew_arr(int32_t, buffer_size * 2); - - /* Callback context for the buffer queue callback function */ - - /* Get the SL Engine Interface which is implicit */ - res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void *)&EngineItf); - - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - - { - const SLInterfaceID ids[1] = { SL_IID_ENVIRONMENTALREVERB }; - const SLboolean req[1] = { SL_BOOLEAN_FALSE }; - res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, 0, ids, req); - } - - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - // Realizing the Output Mix object in synchronous mode. - res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE); - 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; - pcm.samplesPerSec = SL_SAMPLINGRATE_44_1; - pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; - pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16; - pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; -#ifdef BIG_ENDIAN_ENABLED - pcm.endianness = SL_BYTEORDER_BIGENDIAN; -#else - pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; -#endif - audioSource.pFormat = (void *)&pcm; - audioSource.pLocator = (void *)&loc_bufq; - - /* Setup the data sink structure */ - locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; - locator_outputmix.outputMix = OutputMix; - audioSink.pLocator = (void *)&locator_outputmix; - audioSink.pFormat = NULL; - /* 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 }; - - res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 1, ids, req); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - } - /* Realizing the player in synchronous mode. */ - res = (*player)->Realize(player, SL_BOOLEAN_FALSE); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - /* Get seek and play interfaces */ - res = (*player)->GetInterface(player, SL_IID_PLAY, (void *)&playItf); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - res = (*player)->GetInterface(player, SL_IID_BUFFERQUEUE, - (void *)&bufferQueueItf); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - /* Setup to receive buffer queue event callbacks */ - res = (*bufferQueueItf)->RegisterCallback(bufferQueueItf, _buffer_callbacks, this); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - - last_free = 0; - - //fill up buffers - for (int i = 0; i < BUFFER_COUNT; i++) { - /* Enqueue a few buffers to get the ball rolling */ - res = (*bufferQueueItf)->Enqueue(bufferQueueItf, buffers[i], 4 * buffer_size); /* Size given in */ - } - - res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - - active = true; -} - -void AudioDriverOpenSL::_record_buffer_callback(SLAndroidSimpleBufferQueueItf queueItf) { - for (int i = 0; i < rec_buffer.size(); i++) { - int32_t sample = rec_buffer[i] << 16; - input_buffer_write(sample); - input_buffer_write(sample); // call twice to convert to Stereo - } - - SLresult res = (*recordBufferQueueItf)->Enqueue(recordBufferQueueItf, rec_buffer.ptrw(), rec_buffer.size() * sizeof(int16_t)); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); -} - -void AudioDriverOpenSL::_record_buffer_callbacks(SLAndroidSimpleBufferQueueItf queueItf, void *pContext) { - AudioDriverOpenSL *ad = (AudioDriverOpenSL *)pContext; - - ad->_record_buffer_callback(queueItf); -} - -Error AudioDriverOpenSL::capture_init_device() { - SLDataLocator_IODevice loc_dev = { - SL_DATALOCATOR_IODEVICE, - SL_IODEVICE_AUDIOINPUT, - SL_DEFAULTDEVICEID_AUDIOINPUT, - NULL - }; - SLDataSource recSource = { &loc_dev, NULL }; - - SLDataLocator_AndroidSimpleBufferQueue loc_bq = { - SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, - 2 - }; - SLDataFormat_PCM format_pcm = { - SL_DATAFORMAT_PCM, - 1, - SL_SAMPLINGRATE_44_1, - SL_PCMSAMPLEFORMAT_FIXED_16, - SL_PCMSAMPLEFORMAT_FIXED_16, - SL_SPEAKER_FRONT_CENTER, - SL_BYTEORDER_LITTLEENDIAN - }; - SLDataSink recSnk = { &loc_bq, &format_pcm }; - - const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION }; - const SLboolean req[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE }; - - SLresult res = (*EngineItf)->CreateAudioRecorder(EngineItf, &recorder, &recSource, &recSnk, 2, ids, req); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recorder)->Realize(recorder, SL_BOOLEAN_FALSE); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recorder)->GetInterface(recorder, SL_IID_RECORD, (void *)&recordItf); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recorder)->GetInterface(recorder, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, (void *)&recordBufferQueueItf); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recordBufferQueueItf)->RegisterCallback(recordBufferQueueItf, _record_buffer_callbacks, this); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - SLuint32 state; - res = (*recordItf)->GetRecordState(recordItf, &state); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - if (state != SL_RECORDSTATE_STOPPED) { - res = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recordBufferQueueItf)->Clear(recordBufferQueueItf); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - } - - const int rec_buffer_frames = 2048; - rec_buffer.resize(rec_buffer_frames); - input_buffer_init(rec_buffer_frames); - - res = (*recordBufferQueueItf)->Enqueue(recordBufferQueueItf, rec_buffer.ptrw(), rec_buffer.size() * sizeof(int16_t)); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_RECORDING); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - return OK; -} - -Error AudioDriverOpenSL::capture_start() { - if (OS::get_singleton()->request_permission("RECORD_AUDIO")) { - return capture_init_device(); - } - - WARN_PRINT("Unable to start audio capture - No RECORD_AUDIO permission"); - return ERR_UNAUTHORIZED; -} - -Error AudioDriverOpenSL::capture_stop() { - SLuint32 state; - SLresult res = (*recordItf)->GetRecordState(recordItf, &state); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - if (state != SL_RECORDSTATE_STOPPED) { - res = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recordBufferQueueItf)->Clear(recordBufferQueueItf); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - } - - return OK; -} - -int AudioDriverOpenSL::get_mix_rate() const { - return 44100; // hardcoded for Android, as selected by SL_SAMPLINGRATE_44_1 -} - -AudioDriver::SpeakerMode AudioDriverOpenSL::get_speaker_mode() const { - return SPEAKER_MODE_STEREO; -} - -void AudioDriverOpenSL::lock() { - if (active) - mutex.lock(); -} - -void AudioDriverOpenSL::unlock() { - if (active) - mutex.unlock(); -} - -void AudioDriverOpenSL::finish() { - (*sl)->Destroy(sl); -} - -void AudioDriverOpenSL::set_pause(bool p_pause) { - pause = p_pause; - - if (active) { - if (pause) { - (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED); - } else { - (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); - } - } -} - -AudioDriverOpenSL::AudioDriverOpenSL() { - s_ad = this; - pause = false; - active = false; -} diff --git a/platform/android/audio_driver_opensl.h b/platform/android/audio_driver_opensl.h deleted file mode 100644 index e257cd0..0000000 --- a/platform/android/audio_driver_opensl.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef AUDIO_DRIVER_OPENSL_H -#define AUDIO_DRIVER_OPENSL_H -/*************************************************************************/ -/* audio_driver_opensl.h */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "core/os/mutex.h" -#include "servers/audio_server.h" - -#include -#include - -class AudioDriverOpenSL : public AudioDriver { - bool active; - Mutex mutex; - - enum { - - BUFFER_COUNT = 2 - }; - - bool pause; - - uint32_t buffer_size; - int16_t *buffers[BUFFER_COUNT]; - int32_t *mixdown_buffer; - int last_free; - - Vector rec_buffer; - - SLPlayItf playItf; - SLRecordItf recordItf; - SLObjectItf sl; - SLEngineItf EngineItf; - SLObjectItf OutputMix; - SLObjectItf player; - SLObjectItf recorder; - SLAndroidSimpleBufferQueueItf bufferQueueItf; - SLAndroidSimpleBufferQueueItf recordBufferQueueItf; - SLDataSource audioSource; - SLDataFormat_PCM pcm; - SLDataSink audioSink; - SLDataLocator_OutputMix locator_outputmix; - - static AudioDriverOpenSL *s_ad; - - void _buffer_callback( - SLAndroidSimpleBufferQueueItf queueItf); - - static void _buffer_callbacks( - SLAndroidSimpleBufferQueueItf queueItf, - void *pContext); - - void _record_buffer_callback( - SLAndroidSimpleBufferQueueItf queueItf); - - static void _record_buffer_callbacks( - SLAndroidSimpleBufferQueueItf queueItf, - void *pContext); - - virtual Error capture_init_device(); - -public: - 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); - - virtual Error capture_start(); - virtual Error capture_stop(); - - AudioDriverOpenSL(); -}; - -#endif // AUDIO_DRIVER_ANDROID_H diff --git a/platform/android/detect.py b/platform/android/detect.py deleted file mode 100644 index 973da36..0000000 --- a/platform/android/detect.py +++ /dev/null @@ -1,197 +0,0 @@ -import os -import sys -import platform -import subprocess - -def is_active(): - return True - -def get_name(): - return "Android" - -def can_build(): - return os.path.exists(get_env_android_sdk_root()) - -def get_opts(): - from SCons.Variables import BoolVariable, EnumVariable - - return [ - ("ANDROID_SDK_ROOT", "Path to the Android SDK", get_env_android_sdk_root()), - ("ndk_platform", 'Target platform (android-, e.g. "android-19")', "android-19"), - EnumVariable("android_arch", "Target architecture", "armv7", ("armv7", "arm64v8", "x86", "x86_64")), - BoolVariable("android_neon", "Enable NEON support (armv7 only)", True), - ] - -# Return the ANDROID_SDK_ROOT environment variable. -def get_env_android_sdk_root(): - return os.environ.get("ANDROID_SDK_ROOT", -1) - -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(): - return [ - ("tools", False), - ] - -# Check if Android NDK version is installed -# If not, install it. -def install_ndk_if_needed(env): - print("Checking for Android NDK...") - sdk_root = env["ANDROID_SDK_ROOT"] - if not os.path.exists(get_android_ndk_root(env)): - extension = ".bat" if os.name == "nt" else "" - - 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) - ndk_root = env["ANDROID_NDK_ROOT"] - - # Architecture - - if env["android_arch"] not in ["armv7", "arm64v8", "x86", "x86_64"]: - env["android_arch"] = "arm64v8" - - neon_text = "" - if env["android_arch"] == "armv7" and env["android_neon"]: - neon_text = " (with NEON)" - print("Building for Android (" + env["android_arch"] + ")" + neon_text) - - if get_min_sdk_version(env["ndk_platform"]) < 21: - if env["android_arch"] == "x86_64" or env["android_arch"] == "arm64v8": - print( - "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" - - if env["android_arch"] == "armv7": - target_triple = "armv7a-linux-androideabi" - if env["android_neon"]: - env.extra_suffix = ".armv7.neon" + env.extra_suffix - else: - env.extra_suffix = ".armv7" + env.extra_suffix - elif env["android_arch"] == "arm64v8": - target_triple = "aarch64-linux-android" - env.extra_suffix = ".armv8" + env.extra_suffix - elif env["android_arch"] == "x86": - target_triple = "i686-linux-android" - env.extra_suffix = ".x86" + env.extra_suffix - elif env["android_arch"] == "x86_64": - target_triple = "x86_64-linux-android" - env.extra_suffix = ".x86_64" + env.extra_suffix - - target_option = ["-target", target_triple + str(get_min_sdk_version(env["ndk_platform"]))] - env.Append(ASFLAGS=[target_option, "-c"]) - env.Append(CCFLAGS=target_option) - env.Append(LINKFLAGS=target_option) - - # Build type - - if env["target"].startswith("release"): - if env["optimize"] == "speed": # optimize for speed (default) - # `-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(CCFLAGS=[opt]) - elif env["optimize"] == "size": # optimize for size - env.Append(CCFLAGS=["-Oz"]) - elif env["target"] == "debug": - env.Append(LINKFLAGS=["-O0"]) - env.Append(CCFLAGS=["-O0", "-g"]) - - # LTO - - if env["lto"] == "auto": # LTO benefits for Android (size, performance) haven't been clearly established yet. - env["lto"] = "none" - - if env["lto"] != "none": - if env["lto"] == "thin": - env.Append(CCFLAGS=["-flto=thin"]) - env.Append(LINKFLAGS=["-flto=thin"]) - else: - env.Append(CCFLAGS=["-flto"]) - env.Append(LINKFLAGS=["-flto"]) - - # Compiler configuration - - env["SHLIBSUFFIX"] = ".so" - - if env["PLATFORM"] == "win32": - env.use_windows_spawn_fix() - - if sys.platform.startswith("linux"): - host_subpath = "linux-x86_64" - elif sys.platform.startswith("darwin"): - host_subpath = "darwin-x86_64" - elif sys.platform.startswith("win"): - if platform.machine().endswith("64"): - host_subpath = "windows-x86_64" - else: - host_subpath = "windows" - - toolchain_path = ndk_root + "/toolchains/llvm/prebuilt/" + host_subpath - compiler_path = toolchain_path + "/bin" - - env["CC"] = compiler_path + "/clang" - env["CXX"] = compiler_path + "/clang++" - env["AR"] = compiler_path + "/llvm-ar" - env["RANLIB"] = compiler_path + "/llvm-ranlib" - env["AS"] = compiler_path + "/clang" - - env.Append( - CCFLAGS="-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing".split() - ) - env.Append(CPPDEFINES=["NO_STATVFS", "GLES_ENABLED"]) - - if get_min_sdk_version(env["ndk_platform"]) >= 24: - env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)]) - - env["neon_enabled"] = False - if env["android_arch"] == "x86": - env.Append(CCFLAGS=["-mstackrealign"]) - elif env["android_arch"] == "armv7": - env.Append(CCFLAGS="-march=armv7-a -mfloat-abi=softfp".split()) - env.Append(CPPDEFINES=["__ARM_ARCH_7__", "__ARM_ARCH_7A__"]) - if env["android_neon"]: - env["neon_enabled"] = True - env.Append(CPPDEFINES=["__ARM_NEON__"]) - else: - env.Append(CCFLAGS=["-mfpu=vfpv3-d16"]) - elif env["android_arch"] == "arm64v8": - env.Append(CCFLAGS=["-mfix-cortex-a53-835769"]) - env.Append(CPPDEFINES=["__ARM_ARCH_8A__"]) - - # Link flags - 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"]) - env.Append(LIBS=["OpenSLES", "EGL", "GLESv3", "GLESv2", "android", "log", "z", "dl"]) - - diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp deleted file mode 100644 index 78ad9c7..0000000 --- a/platform/android/dir_access_jandroid.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/*************************************************************************/ -/* dir_access_jandroid.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "dir_access_jandroid.h" -#include "core/string/print_string.h" -#include "file_access_android.h" -#include "string_android.h" -#include "thread_jandroid.h" - -jobject DirAccessJAndroid::dir_access_handler = nullptr; -jclass DirAccessJAndroid::cls = NULL; -jmethodID DirAccessJAndroid::_dir_open = NULL; -jmethodID DirAccessJAndroid::_dir_next = NULL; -jmethodID DirAccessJAndroid::_dir_close = NULL; -jmethodID DirAccessJAndroid::_dir_is_dir = NULL; -jmethodID DirAccessJAndroid::_dir_exists = nullptr; -jmethodID DirAccessJAndroid::_file_exists = nullptr; -jmethodID DirAccessJAndroid::_get_drive_count = nullptr; -jmethodID DirAccessJAndroid::_get_drive = nullptr; -jmethodID DirAccessJAndroid::_make_dir = nullptr; -jmethodID DirAccessJAndroid::_get_space_left = nullptr; -jmethodID DirAccessJAndroid::_rename = nullptr; -jmethodID DirAccessJAndroid::_remove = nullptr; -jmethodID DirAccessJAndroid::_current_is_hidden = nullptr; - -Error DirAccessJAndroid::list_dir_begin() { - list_dir_end(); - - int res = dir_open(current_dir); - if (res <= 0) { - return ERR_CANT_OPEN; - } - - id = res; - - return OK; -} - -String DirAccessJAndroid::get_next() { - ERR_FAIL_COND_V(id == 0, ""); - - if (_dir_next) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ""); - jstring str = (jstring)env->CallObjectMethod(dir_access_handler, _dir_next, get_access_type(), id); - - if (!str) { - return ""; - } - - String ret = jstring_to_string((jstring)str, env); - env->DeleteLocalRef((jobject)str); - return ret; - } else { - return ""; - } -} - -bool DirAccessJAndroid::current_is_dir() const { - if (_dir_is_dir) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - return env->CallBooleanMethod(dir_access_handler, _dir_is_dir, get_access_type(), id); - } else { - return false; - } -} - -bool DirAccessJAndroid::current_is_hidden() const { - if (_current_is_hidden) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - return env->CallBooleanMethod(dir_access_handler, _current_is_hidden, get_access_type(), id); - } - return false; -} - -void DirAccessJAndroid::list_dir_end() { - if (id == 0) - return; - - dir_close(id); - id = 0; -} - -int DirAccessJAndroid::get_drive_count() { - if (_get_drive_count) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - return env->CallIntMethod(dir_access_handler, _get_drive_count, get_access_type()); - } else { - return 0; - } -} - -String DirAccessJAndroid::get_drive(int p_drive) { - if (_get_drive) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ""); - jstring j_drive = (jstring)env->CallObjectMethod(dir_access_handler, _get_drive, get_access_type(), p_drive); - - if (!j_drive) { - return ""; - } - - String drive = jstring_to_string(j_drive, env); - env->DeleteLocalRef(j_drive); - return drive; - } else { - return ""; - } -} - -String DirAccessJAndroid::_get_root_string() const { - if (get_access_type() == ACCESS_FILESYSTEM) { - return "/"; - } - return DirAccessUnix::_get_root_string(); -} - -String DirAccessJAndroid::get_current_dir() { - String base = _get_root_path(); - String bd = current_dir; - if (!base.empty()) { - bd = current_dir.replace_first(base, ""); - } - - String root_string = _get_root_string(); - if (bd.begins_with(root_string)) { - return bd; - } else if (bd.begins_with("/")) { - return root_string + bd.substr(1, bd.length()); - } else { - return root_string + bd; - } -} - -Error DirAccessJAndroid::change_dir(String p_dir) { - String new_dir = get_absolute_path(p_dir); - if (new_dir == current_dir) { - return OK; - } - - if (!dir_exists(new_dir)) { - return ERR_INVALID_PARAMETER; - } - - current_dir = new_dir; - - return OK; -} - -String DirAccessJAndroid::get_absolute_path(String p_path) { - if (current_dir != "" && p_path == current_dir) { - return current_dir; - } - - if (p_path.is_rel_path()) { - p_path = get_current_dir().plus_file(p_path); - } - - p_path = fix_path(p_path); - p_path = p_path.simplify_path(); - return p_path; -} - -bool DirAccessJAndroid::file_exists(String p_file) { - if (_file_exists) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - - String path = get_absolute_path(p_file); - jstring j_path = env->NewStringUTF(path.utf8().get_data()); - bool result = env->CallBooleanMethod(dir_access_handler, _file_exists, get_access_type(), j_path); - env->DeleteLocalRef(j_path); - return result; - } else { - return false; - } -} - -bool DirAccessJAndroid::dir_exists(String p_dir) { - if (_dir_exists) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - - String path = get_absolute_path(p_dir); - jstring j_path = env->NewStringUTF(path.utf8().get_data()); - bool result = env->CallBooleanMethod(dir_access_handler, _dir_exists, get_access_type(), j_path); - env->DeleteLocalRef(j_path); - return result; - } else { - return false; - } -} - -Error DirAccessJAndroid::make_dir_recursive(String p_dir) { - // Check if the directory exists already - if (dir_exists(p_dir)) { - return ERR_ALREADY_EXISTS; - } - - if (_make_dir) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED); - - String path = get_absolute_path(p_dir); - jstring j_dir = env->NewStringUTF(path.utf8().get_data()); - bool result = env->CallBooleanMethod(dir_access_handler, _make_dir, get_access_type(), j_dir); - env->DeleteLocalRef(j_dir); - if (result) { - return OK; - } else { - return FAILED; - } - } else { - return ERR_UNCONFIGURED; - } -} - -Error DirAccessJAndroid::make_dir(String p_dir) { - return make_dir_recursive(p_dir); -} - -Error DirAccessJAndroid::rename(String p_from, String p_to) { - if (_rename) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED); - - String from_path = get_absolute_path(p_from); - jstring j_from = env->NewStringUTF(from_path.utf8().get_data()); - - String to_path = get_absolute_path(p_to); - jstring j_to = env->NewStringUTF(to_path.utf8().get_data()); - - bool result = env->CallBooleanMethod(dir_access_handler, _rename, get_access_type(), j_from, j_to); - env->DeleteLocalRef(j_from); - env->DeleteLocalRef(j_to); - if (result) { - return OK; - } else { - return FAILED; - } - } else { - return ERR_UNCONFIGURED; - } -} - -Error DirAccessJAndroid::remove(String p_name) { - if (_remove) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED); - - String path = get_absolute_path(p_name); - jstring j_name = env->NewStringUTF(path.utf8().get_data()); - bool result = env->CallBooleanMethod(dir_access_handler, _remove, get_access_type(), j_name); - env->DeleteLocalRef(j_name); - if (result) { - return OK; - } else { - return FAILED; - } - } else { - return ERR_UNCONFIGURED; - } -} - -uint64_t DirAccessJAndroid::get_space_left() { - if (_get_space_left) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - return env->CallLongMethod(dir_access_handler, _get_space_left, get_access_type()); - } else { - return 0; - } -} - -void DirAccessJAndroid::setup(jobject p_dir_access_handler) { - JNIEnv *env = get_jni_env(); - dir_access_handler = env->NewGlobalRef(p_dir_access_handler); - - jclass c = env->GetObjectClass(dir_access_handler); - cls = (jclass)env->NewGlobalRef(c); - - _dir_open = env->GetMethodID(cls, "dirOpen", "(ILjava/lang/String;)I"); - _dir_next = env->GetMethodID(cls, "dirNext", "(II)Ljava/lang/String;"); - _dir_close = env->GetMethodID(cls, "dirClose", "(II)V"); - _dir_is_dir = env->GetMethodID(cls, "dirIsDir", "(II)Z"); - _dir_exists = env->GetMethodID(cls, "dirExists", "(ILjava/lang/String;)Z"); - _file_exists = env->GetMethodID(cls, "fileExists", "(ILjava/lang/String;)Z"); - _get_drive_count = env->GetMethodID(cls, "getDriveCount", "(I)I"); - _get_drive = env->GetMethodID(cls, "getDrive", "(II)Ljava/lang/String;"); - _make_dir = env->GetMethodID(cls, "makeDir", "(ILjava/lang/String;)Z"); - _get_space_left = env->GetMethodID(cls, "getSpaceLeft", "(I)J"); - _rename = env->GetMethodID(cls, "rename", "(ILjava/lang/String;Ljava/lang/String;)Z"); - _remove = env->GetMethodID(cls, "remove", "(ILjava/lang/String;)Z"); - _current_is_hidden = env->GetMethodID(cls, "isCurrentHidden", "(II)Z"); -} - -DirAccessJAndroid::DirAccessJAndroid() { - id = 0; -} - -DirAccessJAndroid::~DirAccessJAndroid() { - list_dir_end(); -} - -int DirAccessJAndroid::dir_open(String p_path) { - if (_dir_open) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - - String path = get_absolute_path(p_path); - jstring js = env->NewStringUTF(path.utf8().get_data()); - int dirId = env->CallIntMethod(dir_access_handler, _dir_open, get_access_type(), js); - env->DeleteLocalRef(js); - return dirId; - } else { - return 0; - } -} - -void DirAccessJAndroid::dir_close(int p_id) { - if (_dir_close) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - env->CallVoidMethod(dir_access_handler, _dir_close, get_access_type(), p_id); - } -} diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h deleted file mode 100644 index ee8560f..0000000 --- a/platform/android/dir_access_jandroid.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef DIR_ACCESS_JANDROID_H -#define DIR_ACCESS_JANDROID_H -/*************************************************************************/ -/* dir_access_jandroid.h */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "core/os/dir_access.h" -#include "drivers/unix/dir_access_unix.h" -#include "java_pandemonium_lib_jni.h" -#include - -/// Android implementation of the DirAccess interface used to provide access to -/// ACCESS_FILESYSTEM and ACCESS_RESOURCES directory resources. -/// The implementation use jni in order to comply with Android filesystem -/// access restriction. -class DirAccessJAndroid : public DirAccessUnix { - static jobject dir_access_handler; - - static jclass cls; - - static jmethodID _dir_open; - static jmethodID _dir_next; - static jmethodID _dir_close; - static jmethodID _dir_is_dir; - - static jmethodID _dir_exists; - static jmethodID _file_exists; - static jmethodID _get_drive_count; - static jmethodID _get_drive; - static jmethodID _make_dir; - static jmethodID _get_space_left; - static jmethodID _rename; - static jmethodID _remove; - static jmethodID _current_is_hidden; - -public: - virtual Error list_dir_begin(); ///< This starts dir listing - virtual String get_next(); - virtual bool current_is_dir() const; - virtual bool current_is_hidden() const; - virtual void list_dir_end(); ///< - - virtual int get_drive_count(); - virtual String get_drive(int p_drive); - - virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success - virtual String get_current_dir(); ///< return current dir location - - virtual bool file_exists(String p_file); - virtual bool dir_exists(String p_dir); - - virtual Error make_dir(String p_dir); - virtual Error make_dir_recursive(String p_dir); - - virtual Error rename(String p_from, String p_to); - virtual Error remove(String p_name); - - virtual bool is_link(String p_file) { return false; } - virtual String read_link(String p_file) { return p_file; } - virtual Error create_link(String p_source, String p_target) { return FAILED; } - - virtual uint64_t get_space_left(); - - static void setup(jobject p_dir_access_handler); - - DirAccessJAndroid(); - ~DirAccessJAndroid(); - -protected: - String _get_root_string() const; - -private: - int id; - - int dir_open(String p_path); - void dir_close(int p_id); - String get_absolute_path(String p_path); -}; - -#endif // DIR_ACCESS_JANDROID_H diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp deleted file mode 100644 index df1b491..0000000 --- a/platform/android/export/export.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/*************************************************************************/ -/* export.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "export.h" - -#include "export_plugin.h" - -#include "editor/editor_settings.h" - -void register_android_exporter() { -#ifndef ANDROID_ENABLED - 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", ""); - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks")); - EDITOR_DEF("export/android/debug_keystore_user", "androiddebugkey"); - EDITOR_DEF("export/android/debug_keystore_pass", "android"); - EDITOR_DEF("export/android/force_system_user", false); - - EDITOR_DEF("export/android/shutdown_adb_on_exit", true); -#endif - - Ref exporter = Ref(memnew(EditorExportPlatformAndroid)); - EditorExport::get_singleton()->add_export_platform(exporter); -} diff --git a/platform/android/export/export.h b/platform/android/export/export.h deleted file mode 100644 index 82ce40f..0000000 --- a/platform/android/export/export.h +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************/ -/* export.h */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#ifndef ANDROID_EXPORT_H -#define ANDROID_EXPORT_H - -void register_android_exporter(); - -#endif // ANDROID_EXPORT_H diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp deleted file mode 100644 index 8182e6f..0000000 --- a/platform/android/export/export_plugin.cpp +++ /dev/null @@ -1,3338 +0,0 @@ -/*************************************************************************/ -/* export_plugin.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "export_plugin.h" - -static const char *android_perms[] = { - "ACCESS_CHECKIN_PROPERTIES", - "ACCESS_COARSE_LOCATION", - "ACCESS_FINE_LOCATION", - "ACCESS_LOCATION_EXTRA_COMMANDS", - "ACCESS_MOCK_LOCATION", - "ACCESS_NETWORK_STATE", - "ACCESS_SURFACE_FLINGER", - "ACCESS_WIFI_STATE", - "ACCOUNT_MANAGER", - "ADD_VOICEMAIL", - "AUTHENTICATE_ACCOUNTS", - "BATTERY_STATS", - "BIND_ACCESSIBILITY_SERVICE", - "BIND_APPWIDGET", - "BIND_DEVICE_ADMIN", - "BIND_INPUT_METHOD", - "BIND_NFC_SERVICE", - "BIND_NOTIFICATION_LISTENER_SERVICE", - "BIND_PRINT_SERVICE", - "BIND_REMOTEVIEWS", - "BIND_TEXT_SERVICE", - "BIND_VPN_SERVICE", - "BIND_WALLPAPER", - "BLUETOOTH", - "BLUETOOTH_ADMIN", - "BLUETOOTH_PRIVILEGED", - "BRICK", - "BROADCAST_PACKAGE_REMOVED", - "BROADCAST_SMS", - "BROADCAST_STICKY", - "BROADCAST_WAP_PUSH", - "CALL_PHONE", - "CALL_PRIVILEGED", - "CAMERA", - "CAPTURE_AUDIO_OUTPUT", - "CAPTURE_SECURE_VIDEO_OUTPUT", - "CAPTURE_VIDEO_OUTPUT", - "CHANGE_COMPONENT_ENABLED_STATE", - "CHANGE_CONFIGURATION", - "CHANGE_NETWORK_STATE", - "CHANGE_WIFI_MULTICAST_STATE", - "CHANGE_WIFI_STATE", - "CLEAR_APP_CACHE", - "CLEAR_APP_USER_DATA", - "CONTROL_LOCATION_UPDATES", - "DELETE_CACHE_FILES", - "DELETE_PACKAGES", - "DEVICE_POWER", - "DIAGNOSTIC", - "DISABLE_KEYGUARD", - "DUMP", - "EXPAND_STATUS_BAR", - "FACTORY_TEST", - "FLASHLIGHT", - "FORCE_BACK", - "GET_ACCOUNTS", - "GET_PACKAGE_SIZE", - "GET_TASKS", - "GET_TOP_ACTIVITY_INFO", - "GLOBAL_SEARCH", - "HARDWARE_TEST", - "INJECT_EVENTS", - "INSTALL_LOCATION_PROVIDER", - "INSTALL_PACKAGES", - "INSTALL_SHORTCUT", - "INTERNAL_SYSTEM_WINDOW", - "INTERNET", - "KILL_BACKGROUND_PROCESSES", - "LOCATION_HARDWARE", - "MANAGE_ACCOUNTS", - "MANAGE_APP_TOKENS", - "MANAGE_DOCUMENTS", - "MANAGE_EXTERNAL_STORAGE", - "MASTER_CLEAR", - "MEDIA_CONTENT_CONTROL", - "MODIFY_AUDIO_SETTINGS", - "MODIFY_PHONE_STATE", - "MOUNT_FORMAT_FILESYSTEMS", - "MOUNT_UNMOUNT_FILESYSTEMS", - "NFC", - "PERSISTENT_ACTIVITY", - "PROCESS_OUTGOING_CALLS", - "READ_CALENDAR", - "READ_CALL_LOG", - "READ_CONTACTS", - "READ_EXTERNAL_STORAGE", - "READ_FRAME_BUFFER", - "READ_HISTORY_BOOKMARKS", - "READ_INPUT_STATE", - "READ_LOGS", - "READ_PHONE_STATE", - "READ_PROFILE", - "READ_SMS", - "READ_SOCIAL_STREAM", - "READ_SYNC_SETTINGS", - "READ_SYNC_STATS", - "READ_USER_DICTIONARY", - "REBOOT", - "RECEIVE_BOOT_COMPLETED", - "RECEIVE_MMS", - "RECEIVE_SMS", - "RECEIVE_WAP_PUSH", - "RECORD_AUDIO", - "REORDER_TASKS", - "RESTART_PACKAGES", - "SEND_RESPOND_VIA_MESSAGE", - "SEND_SMS", - "SET_ACTIVITY_WATCHER", - "SET_ALARM", - "SET_ALWAYS_FINISH", - "SET_ANIMATION_SCALE", - "SET_DEBUG_APP", - "SET_ORIENTATION", - "SET_POINTER_SPEED", - "SET_PREFERRED_APPLICATIONS", - "SET_PROCESS_LIMIT", - "SET_TIME", - "SET_TIME_ZONE", - "SET_WALLPAPER", - "SET_WALLPAPER_HINTS", - "SIGNAL_PERSISTENT_PROCESSES", - "STATUS_BAR", - "SUBSCRIBED_FEEDS_READ", - "SUBSCRIBED_FEEDS_WRITE", - "SYSTEM_ALERT_WINDOW", - "TRANSMIT_IR", - "UNINSTALL_SHORTCUT", - "UPDATE_DEVICE_STATS", - "USE_CREDENTIALS", - "USE_SIP", - "VIBRATE", - "WAKE_LOCK", - "WRITE_APN_SETTINGS", - "WRITE_CALENDAR", - "WRITE_CALL_LOG", - "WRITE_CONTACTS", - "WRITE_EXTERNAL_STORAGE", - "WRITE_GSERVICES", - "WRITE_HISTORY_BOOKMARKS", - "WRITE_PROFILE", - "WRITE_SECURE_SETTINGS", - "WRITE_SETTINGS", - "WRITE_SMS", - "WRITE_SOCIAL_STREAM", - "WRITE_SYNC_SETTINGS", - "WRITE_USER_DICTIONARY", - nullptr -}; - -static const char *SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi/splash.png"; -static const char *LEGACY_BUILD_SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi-v4/splash.png"; -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"; - -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 LauncherIcon launcher_icons[icon_densities_count] = { - { "res/mipmap-xxxhdpi-v4/icon.png", 192 }, - { "res/mipmap-xxhdpi-v4/icon.png", 144 }, - { "res/mipmap-xhdpi-v4/icon.png", 96 }, - { "res/mipmap-hdpi-v4/icon.png", 72 }, - { "res/mipmap-mdpi-v4/icon.png", 48 }, - { "res/mipmap/icon.png", 192 } -}; - -static const LauncherIcon launcher_adaptive_icon_foregrounds[icon_densities_count] = { - { "res/mipmap-xxxhdpi-v4/icon_foreground.png", 432 }, - { "res/mipmap-xxhdpi-v4/icon_foreground.png", 324 }, - { "res/mipmap-xhdpi-v4/icon_foreground.png", 216 }, - { "res/mipmap-hdpi-v4/icon_foreground.png", 162 }, - { "res/mipmap-mdpi-v4/icon_foreground.png", 108 }, - { "res/mipmap/icon_foreground.png", 432 } -}; - -static const LauncherIcon launcher_adaptive_icon_backgrounds[icon_densities_count] = { - { "res/mipmap-xxxhdpi-v4/icon_background.png", 432 }, - { "res/mipmap-xxhdpi-v4/icon_background.png", 324 }, - { "res/mipmap-xhdpi-v4/icon_background.png", 216 }, - { "res/mipmap-hdpi-v4/icon_background.png", 162 }, - { "res/mipmap-mdpi-v4/icon_background.png", 108 }, - { "res/mipmap/icon_background.png", 432 } -}; - -static const int EXPORT_FORMAT_APK = 0; -static const int EXPORT_FORMAT_AAB = 1; - -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 = 33; // 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); - -#ifndef ANDROID_ENABLED -void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) { - EditorExportPlatformAndroid *ea = (EditorExportPlatformAndroid *)ud; - - while (!ea->quit_request.is_set()) { - // Check for plugins updates - { - // Nothing to do if we already know the plugins have changed. - if (!ea->plugins_changed.is_set()) { - Vector loaded_plugins = get_plugins(); - - ea->plugins_lock.lock(); - - if (ea->plugins.size() != loaded_plugins.size()) { - ea->plugins_changed.set(); - } else { - for (int i = 0; i < ea->plugins.size(); i++) { - if (ea->plugins[i].name != loaded_plugins[i].name) { - ea->plugins_changed.set(); - break; - } - } - } - - if (ea->plugins_changed.is_set()) { - ea->plugins = loaded_plugins; - } - - ea->plugins_lock.unlock(); - } - } - - // Check for devices updates - String adb = get_adb_path(); - if (FileAccess::exists(adb)) { - String devices; - List args; - args.push_back("devices"); - int ec; - OS::get_singleton()->execute(adb, args, true, nullptr, &devices, &ec); - - Vector ds = devices.split("\n"); - Vector ldevices; - for (int i = 1; i < ds.size(); i++) { - String d = ds[i]; - int dpos = d.find("device"); - if (dpos == -1) { - continue; - } - d = d.substr(0, dpos).strip_edges(); - ldevices.push_back(d); - } - - ea->device_lock.lock(); - - bool different = false; - - if (ea->devices.size() != ldevices.size()) { - different = true; - } else { - for (int i = 0; i < ea->devices.size(); i++) { - if (ea->devices[i].id != ldevices[i]) { - different = true; - break; - } - } - } - - if (different) { - Vector ndevices; - - for (int i = 0; i < ldevices.size(); i++) { - Device d; - d.id = ldevices[i]; - for (int j = 0; j < ea->devices.size(); j++) { - if (ea->devices[j].id == ldevices[i]) { - d.description = ea->devices[j].description; - d.name = ea->devices[j].name; - d.api_level = ea->devices[j].api_level; - } - } - - if (d.description == "") { - //in the oven, request! - args.clear(); - args.push_back("-s"); - args.push_back(d.id); - args.push_back("shell"); - args.push_back("getprop"); - int ec2; - String dp; - - OS::get_singleton()->execute(adb, args, true, nullptr, &dp, &ec2); - - Vector props = dp.split("\n"); - String vendor; - String device; - d.description = "Device ID: " + d.id + "\n"; - d.api_level = 0; - for (int j = 0; j < props.size(); j++) { - // got information by `shell cat /system/build.prop` before and its format is "property=value" - // it's now changed to use `shell getporp` because of permission issue with Android 8.0 and above - // its format is "[property]: [value]" so changed it as like build.prop - String p = props[j]; - p = p.replace("]: ", "="); - p = p.replace("[", ""); - p = p.replace("]", ""); - - if (p.begins_with("ro.product.model=")) { - device = p.get_slice("=", 1).strip_edges(); - } else if (p.begins_with("ro.product.brand=")) { - vendor = p.get_slice("=", 1).strip_edges().capitalize(); - } else if (p.begins_with("ro.build.display.id=")) { - d.description += "Build: " + p.get_slice("=", 1).strip_edges() + "\n"; - } else if (p.begins_with("ro.build.version.release=")) { - d.description += "Release: " + p.get_slice("=", 1).strip_edges() + "\n"; - } else if (p.begins_with("ro.build.version.sdk=")) { - d.api_level = p.get_slice("=", 1).to_int(); - } else if (p.begins_with("ro.product.cpu.abi=")) { - d.description += "CPU: " + p.get_slice("=", 1).strip_edges() + "\n"; - } else if (p.begins_with("ro.product.manufacturer=")) { - d.description += "Manufacturer: " + p.get_slice("=", 1).strip_edges() + "\n"; - } else if (p.begins_with("ro.board.platform=")) { - d.description += "Chipset: " + p.get_slice("=", 1).strip_edges() + "\n"; - } else if (p.begins_with("ro.opengles.version=")) { - uint32_t opengl = p.get_slice("=", 1).to_int(); - d.description += "OpenGL: " + itos(opengl >> 16) + "." + itos((opengl >> 8) & 0xFF) + "." + itos((opengl)&0xFF) + "\n"; - } - } - - d.name = vendor + " " + device; - if (device == String()) { - continue; - } - } - - ndevices.push_back(d); - } - - ea->devices = ndevices; - ea->devices_changed.set(); - } - - ea->device_lock.unlock(); - } - - uint64_t sleep = 300'000; - uint64_t wait = 3'000'000; - uint64_t time = OS::get_singleton()->get_ticks_usec(); - while (OS::get_singleton()->get_ticks_usec() - time < wait) { - OS::get_singleton()->delay_usec(sleep); - if (ea->quit_request.is_set()) { - break; - } - } - } - - if (EditorSettings::get_singleton()->get("export/android/shutdown_adb_on_exit")) { - String adb = get_adb_path(); - if (!FileAccess::exists(adb)) { - return; //adb not configured - } - - List args; - args.push_back("kill-server"); - OS::get_singleton()->execute(adb, args, true); - } -} -#endif - -String EditorExportPlatformAndroid::get_project_name(const String &p_name) const { - String aname; - if (p_name != "") { - aname = p_name; - } else { - aname = ProjectSettings::get_singleton()->get("application/config/name"); - } - - if (aname == "") { - aname = VERSION_NAME; - } - - return aname; -} - -String EditorExportPlatformAndroid::get_package_name(const String &p_package) const { - String pname = p_package; - String basename = ProjectSettings::get_singleton()->get("application/config/name"); - basename = basename.to_lower(); - - String name; - bool first = true; - for (int i = 0; i < basename.length(); i++) { - CharType c = basename[i]; - if (c >= '0' && c <= '9' && first) { - continue; - } - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) { - name += String::chr(c); - first = false; - } - } - if (name == "") { - name = "noname"; - } - - pname = pname.replace("$genname", name); - - return pname; -} - -String EditorExportPlatformAndroid::get_assets_directory(const Ref &p_preset, int p_export_format) const { - return p_export_format == EXPORT_FORMAT_AAB ? AAB_ASSETS_DIRECTORY : APK_ASSETS_DIRECTORY; -} - -bool EditorExportPlatformAndroid::is_package_name_valid(const String &p_package, String *r_error) const { - String pname = p_package; - - if (pname.length() == 0) { - if (r_error) { - *r_error = TTR("Package name is missing."); - } - return false; - } - - int segments = 0; - bool first = true; - for (int i = 0; i < pname.length(); i++) { - CharType c = pname[i]; - if (first && c == '.') { - if (r_error) { - *r_error = TTR("Package segments must be of non-zero length."); - } - return false; - } - if (c == '.') { - segments++; - first = true; - continue; - } - if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_')) { - if (r_error) { - *r_error = vformat(TTR("The character '%s' is not allowed in Android application package names."), String::chr(c)); - } - return false; - } - if (first && (c >= '0' && c <= '9')) { - if (r_error) { - *r_error = TTR("A digit cannot be the first character in a package segment."); - } - return false; - } - if (first && c == '_') { - if (r_error) { - *r_error = vformat(TTR("The character '%s' cannot be the first character in a package segment."), String::chr(c)); - } - return false; - } - first = false; - } - - if (segments == 0) { - if (r_error) { - *r_error = TTR("The package must have at least one '.' separator."); - } - return false; - } - - if (first) { - if (r_error) { - *r_error = TTR("Package segments must be of non-zero length."); - } - return false; - } - - return true; -} - -bool EditorExportPlatformAndroid::_should_compress_asset(const String &p_path, const Vector &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 - * zip-aligned, assets stored as they are can be efficiently read by - * Android by memory-mapping them. - */ - - // -- Unconditional uncompress to mimic AAPT plus some other - - static const char *unconditional_compress_ext[] = { - // From https://github.com/android/platform_frameworks_base/blob/master/tools/aapt/Package.cpp - // These formats are already compressed, or don't compress well: - ".jpg", ".jpeg", ".png", ".gif", - ".wav", ".mp2", ".mp3", ".ogg", ".aac", - ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet", - ".rtttl", ".imy", ".xmf", ".mp4", ".m4a", - ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2", - ".amr", ".awb", ".wma", ".wmv", - // Pandemonium-specific: - ".webp", // Same reasoning as .png - ".cfb", // Don't let small config files slow-down startup - ".scn", // Binary scenes are usually already compressed - ".stex", // Streamable textures are usually already compressed - // Trailer for easier processing - nullptr - }; - - for (const char **ext = unconditional_compress_ext; *ext; ++ext) { - if (p_path.to_lower().ends_with(String(*ext))) { - return false; - } - } - - // -- Compressed resource? - - if (p_data.size() >= 4 && p_data[0] == 'R' && p_data[1] == 'S' && p_data[2] == 'C' && p_data[3] == 'C') { - // Already compressed - return false; - } - - // --- TODO: Decide on texture resources according to their image compression setting - - return true; -} - -zip_fileinfo EditorExportPlatformAndroid::get_zip_fileinfo() { - OS::Time time = OS::get_singleton()->get_time(); - OS::Date date = OS::get_singleton()->get_date(); - - 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_mon = date.month - 1; // tm_mon is zero indexed - zipfi.tmz_date.tm_sec = time.sec; - zipfi.tmz_date.tm_year = date.year; - zipfi.dosDate = 0; - zipfi.external_fa = 0; - zipfi.internal_fa = 0; - - return zipfi; -} - -Vector EditorExportPlatformAndroid::get_abis() { - Vector abis; - abis.push_back("armeabi-v7a"); - abis.push_back("arm64-v8a"); - abis.push_back("x86"); - abis.push_back("x86_64"); - return abis; -} - -/// List the gdap files in the directory specified by the p_path parameter. -Vector EditorExportPlatformAndroid::list_gdap_files(const String &p_path) { - Vector dir_files; - DirAccessRef da = DirAccess::open(p_path); - if (da) { - da->list_dir_begin(); - while (true) { - String file = da->get_next(); - if (file == "") { - break; - } - - if (da->current_is_dir() || da->current_is_hidden()) { - continue; - } - - if (file.ends_with(PluginConfigAndroid::PLUGIN_CONFIG_EXT)) { - dir_files.push_back(file); - } - } - da->list_dir_end(); - } - - return dir_files; -} - -Vector EditorExportPlatformAndroid::get_plugins() { - Vector loaded_plugins; - - String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().plus_file("android/plugins"); - - // Add the prebuilt plugins - loaded_plugins.append_array(PluginConfigAndroid::get_prebuilt_plugins(plugins_dir)); - - if (DirAccess::exists(plugins_dir)) { - Vector plugins_filenames = list_gdap_files(plugins_dir); - - if (!plugins_filenames.empty()) { - Ref config_file = memnew(ConfigFile); - for (int i = 0; i < plugins_filenames.size(); i++) { - PluginConfigAndroid config = PluginConfigAndroid::load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i])); - if (config.valid_config) { - loaded_plugins.push_back(config); - } else { - print_error("Invalid plugin config file " + plugins_filenames[i]); - } - } - } - } - - return loaded_plugins; -} - -Vector EditorExportPlatformAndroid::get_enabled_plugins(const Ref &p_presets) { - Vector enabled_plugins; - Vector all_plugins = get_plugins(); - for (int i = 0; i < all_plugins.size(); i++) { - PluginConfigAndroid plugin = all_plugins[i]; - bool enabled = p_presets->get("plugins/" + plugin.name); - if (enabled) { - enabled_plugins.push_back(plugin); - } - } - - return enabled_plugins; -} - -Error EditorExportPlatformAndroid::store_in_apk(APKExportData *ed, const String &p_path, const Vector &p_data, int compression_method) { - zip_fileinfo zipfi = get_zip_fileinfo(); - zipOpenNewFileInZip(ed->apk, - p_path.utf8().get_data(), - &zipfi, - nullptr, - 0, - nullptr, - 0, - nullptr, - compression_method, - Z_DEFAULT_COMPRESSION); - - zipWriteInFileInZip(ed->apk, p_data.ptr(), p_data.size()); - zipCloseFileInZip(ed->apk); - - return OK; -} - -Error EditorExportPlatformAndroid::save_apk_so(void *p_userdata, const SharedObject &p_so) { - if (!p_so.path.get_file().begins_with("lib")) { - String err = "Android .so file names must start with \"lib\", but got: " + p_so.path; - ERR_PRINT(err); - return FAILED; - } - APKExportData *ed = (APKExportData *)p_userdata; - Vector abis = get_abis(); - bool exported = false; - for (int i = 0; i < p_so.tags.size(); ++i) { - // shared objects can be fat (compatible with multiple ABIs) - int abi_index = abis.find(p_so.tags[i]); - if (abi_index != -1) { - exported = true; - String abi = abis[abi_index]; - String dst_path = String("lib").plus_file(abi).plus_file(p_so.path.get_file()); - Vector array = FileAccess::get_file_as_array(p_so.path); - Error store_err = store_in_apk(ed, dst_path, array); - ERR_FAIL_COND_V_MSG(store_err, store_err, "Cannot store in apk file '" + dst_path + "'."); - } - } - if (!exported) { - String abis_string = String(" ").join(abis); - String err = "Cannot determine ABI for library \"" + p_so.path + "\". One of the supported ABIs must be used as a tag: " + abis_string; - ERR_PRINT(err); - return FAILED; - } - return OK; -} - -Error EditorExportPlatformAndroid::save_apk_file(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total) { - APKExportData *ed = (APKExportData *)p_userdata; - String dst_path = p_path.replace_first("res://", "assets/"); - - store_in_apk(ed, dst_path, p_data, _should_compress_asset(p_path, p_data) ? Z_DEFLATED : 0); - return OK; -} - -Error EditorExportPlatformAndroid::ignore_apk_file(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total) { - return OK; -} - -Error EditorExportPlatformAndroid::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 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 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; -} - -bool EditorExportPlatformAndroid::_has_read_write_storage_permission(const Vector &p_permissions) { - return p_permissions.find("android.permission.READ_EXTERNAL_STORAGE") != -1 || p_permissions.find("android.permission.WRITE_EXTERNAL_STORAGE") != -1; -} - -bool EditorExportPlatformAndroid::_has_manage_external_storage_permission(const Vector &p_permissions) { - return p_permissions.find("android.permission.MANAGE_EXTERNAL_STORAGE") != -1; -} - -void EditorExportPlatformAndroid::_get_permissions(const Ref &p_preset, bool p_give_internet, Vector &r_permissions) { - const char **aperms = android_perms; - while (*aperms) { - bool enabled = p_preset->get("permissions/" + String(*aperms).to_lower()); - if (enabled) { - r_permissions.push_back("android.permission." + String(*aperms)); - } - aperms++; - } - PoolStringArray user_perms = p_preset->get("permissions/custom_permissions"); - for (int i = 0; i < user_perms.size(); i++) { - String user_perm = user_perms[i].strip_edges(); - if (!user_perm.empty()) { - r_permissions.push_back(user_perm); - } - } - if (p_give_internet) { - if (r_permissions.find("android.permission.INTERNET") == -1) { - r_permissions.push_back("android.permission.INTERNET"); - } - } -} - -void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref &p_preset, bool p_give_internet, bool p_debug) { - print_verbose("Building temporary manifest.."); - String manifest_text = - "\n" - "\n"; - - manifest_text += _get_screen_sizes_tag(p_preset); - manifest_text += _get_gles_tag(); - - Vector perms; - _get_permissions(p_preset, p_give_internet, perms); - for (int i = 0; i < perms.size(); i++) { - String permission = perms.get(i); - if (permission == "android.permission.WRITE_EXTERNAL_STORAGE" || (permission == "android.permission.READ_EXTERNAL_STORAGE" && _has_manage_external_storage_permission(perms))) { - manifest_text += vformat(" \n", permission); - } else { - manifest_text += vformat(" \n", permission); - } - } - - manifest_text += _get_application_tag(p_preset, _has_read_write_storage_permission(perms)); - manifest_text += "\n"; - String manifest_path = vformat("res://android/build/src/%s/AndroidManifest.xml", (p_debug ? "debug" : "release")); - - print_verbose("Storing manifest into " + manifest_path + ": " + "\n" + manifest_text); - store_string_at_path(manifest_path, manifest_text); -} - -void EditorExportPlatformAndroid::_fix_manifest(const Ref &p_preset, Vector &p_manifest, bool p_give_internet) { - // Leaving the unused types commented because looking these constants up - // again later would be annoying - // const int CHUNK_AXML_FILE = 0x00080003; - // const int CHUNK_RESOURCEIDS = 0x00080180; - const int CHUNK_STRINGS = 0x001C0001; - // const int CHUNK_XML_END_NAMESPACE = 0x00100101; - const int CHUNK_XML_END_TAG = 0x00100103; - // const int CHUNK_XML_START_NAMESPACE = 0x00100100; - const int CHUNK_XML_START_TAG = 0x00100102; - // const int CHUNK_XML_TEXT = 0x00100104; - const int UTF8_FLAG = 0x00000100; - - Vector string_table; - - 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 stable_extra; - - String version_name = p_preset->get("version/name"); - int version_code = p_preset->get("version/code"); - String package_name = p_preset->get("package/unique_name"); - - const int screen_orientation = _get_android_orientation_value( - OS::get_singleton()->get_screen_orientation_from_string(GLOBAL_GET("display/window/handheld/orientation"))); - - bool min_gles3 = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name") == "GLES3" && - !ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2"); - bool screen_support_small = p_preset->get("screen/support_small"); - bool screen_support_normal = p_preset->get("screen/support_normal"); - bool screen_support_large = p_preset->get("screen/support_large"); - bool screen_support_xlarge = p_preset->get("screen/support_xlarge"); - - bool backup_allowed = p_preset->get("user_data_backup/allow"); - bool classify_as_game = p_preset->get("package/classify_as_game"); - bool retain_data_on_uninstall = p_preset->get("package/retain_data_on_uninstall"); - bool exclude_from_recents = p_preset->get("package/exclude_from_recents"); - bool is_resizeable = bool(GLOBAL_GET("display/window/size/resizable")); - - Vector perms; - // Write permissions into the perms variable. - _get_permissions(p_preset, p_give_internet, perms); - bool has_read_write_storage_permission = _has_read_write_storage_permission(perms); - - while (ofs < (uint32_t)p_manifest.size()) { - uint32_t chunk = decode_uint32(&p_manifest[ofs]); - uint32_t size = decode_uint32(&p_manifest[ofs + 4]); - - switch (chunk) { - case CHUNK_STRINGS: { - 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); - uint32_t string_end = 0; - - string_table_begins = st_offset; - - for (uint32_t i = 0; i < string_count; i++) { - uint32_t string_at = decode_uint32(&p_manifest[st_offset + i * 4]); - string_at += st_offset + string_count * 4; - - ERR_FAIL_COND_MSG(string_flags & UTF8_FLAG, "Unimplemented, can't read UTF-8 string table."); - - if (string_flags & UTF8_FLAG) { - } else { - uint32_t len = decode_uint16(&p_manifest[string_at]); - Vector ucstring; - ucstring.resize(len + 1); - for (uint32_t j = 0; j < len; j++) { - uint16_t c = decode_uint16(&p_manifest[string_at + 2 + 2 * j]); - ucstring.write[j] = c; - } - string_end = MAX(string_at + 2 + 2 * len, string_end); - ucstring.write[len] = 0; - string_table.write[i] = ucstring.ptr(); - } - } - - for (uint32_t i = string_end; i < (ofs + size); i++) { - stable_extra.push_back(p_manifest[i]); - } - - string_table_ends = ofs + size; - - } break; - case CHUNK_XML_START_TAG: { - int iofs = ofs + 8; - uint32_t name = decode_uint32(&p_manifest[iofs + 12]); - - String tname = string_table[name]; - uint32_t attrcount = decode_uint32(&p_manifest[iofs + 20]); - iofs += 28; - - for (uint32_t i = 0; i < attrcount; i++) { - uint32_t attr_nspace = decode_uint32(&p_manifest[iofs]); - uint32_t attr_name = decode_uint32(&p_manifest[iofs + 4]); - uint32_t attr_value = decode_uint32(&p_manifest[iofs + 8]); - uint32_t attr_resid = decode_uint32(&p_manifest[iofs + 16]); - - const String value = (attr_value != 0xFFFFFFFF) ? string_table[attr_value] : "Res #" + itos(attr_resid); - String attrname = string_table[attr_name]; - const String nspace = (attr_nspace != 0xFFFFFFFF) ? string_table[attr_nspace] : ""; - - //replace project information - if (tname == "manifest" && attrname == "package") { - string_table.write[attr_value] = get_package_name(package_name); - } - - if (tname == "manifest" && attrname == "versionCode") { - encode_uint32(version_code, &p_manifest.write[iofs + 16]); - } - - if (tname == "manifest" && attrname == "versionName") { - if (attr_value == 0xFFFFFFFF) { - WARN_PRINT("Version name in a resource, should be plain text"); - } else { - string_table.write[attr_value] = version_name; - } - } - - if (tname == "application" && attrname == "requestLegacyExternalStorage") { - encode_uint32(has_read_write_storage_permission ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); - } - - if (tname == "application" && attrname == "allowBackup") { - encode_uint32(backup_allowed, &p_manifest.write[iofs + 16]); - } - - if (tname == "application" && attrname == "isGame") { - encode_uint32(classify_as_game, &p_manifest.write[iofs + 16]); - } - - if (tname == "application" && attrname == "hasFragileUserData") { - encode_uint32(retain_data_on_uninstall, &p_manifest.write[iofs + 16]); - } - - if (tname == "activity" && attrname == "screenOrientation") { - encode_uint32(screen_orientation, &p_manifest.write[iofs + 16]); - } - - if (tname == "activity" && attrname == "excludeFromRecents") { - encode_uint32(exclude_from_recents, &p_manifest.write[iofs + 16]); - } - - if (tname == "activity" && attrname == "resizeableActivity") { - encode_uint32(is_resizeable, &p_manifest.write[iofs + 16]); - } - - if (tname == "provider" && attrname == "authorities") { - string_table.write[attr_value] = get_package_name(package_name) + String(".fileprovider"); - } - - if (tname == "supports-screens") { - if (attrname == "smallScreens") { - encode_uint32(screen_support_small ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); - - } else if (attrname == "normalScreens") { - encode_uint32(screen_support_normal ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); - - } else if (attrname == "largeScreens") { - encode_uint32(screen_support_large ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); - - } else if (attrname == "xlargeScreens") { - encode_uint32(screen_support_xlarge ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); - } - } - - if (tname == "uses-feature" && attrname == "glEsVersion") { - encode_uint32(min_gles3 ? 0x00030000 : 0x00020000, &p_manifest.write[iofs + 16]); - } - - iofs += 20; - } - - } break; - case CHUNK_XML_END_TAG: { - int iofs = ofs + 8; - uint32_t name = decode_uint32(&p_manifest[iofs + 12]); - String tname = string_table[name]; - - if (tname == "uses-feature") { - Vector feature_names; - Vector feature_required_list; - Vector feature_versions; - - if (feature_names.size() > 0) { - ofs += 24; // skip over end tag - - // save manifest ending so we can restore it - Vector manifest_end; - uint32_t manifest_cur_size = p_manifest.size(); - - manifest_end.resize(p_manifest.size() - ofs); - memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size()); - - int32_t attr_name_string = string_table.find("name"); - ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute."); - - int32_t ns_android_string = string_table.find("http://schemas.android.com/apk/res/android"); - if (ns_android_string == -1) { - string_table.push_back("http://schemas.android.com/apk/res/android"); - ns_android_string = string_table.size() - 1; - } - - int32_t attr_uses_feature_string = string_table.find("uses-feature"); - if (attr_uses_feature_string == -1) { - string_table.push_back("uses-feature"); - attr_uses_feature_string = string_table.size() - 1; - } - - int32_t attr_required_string = string_table.find("required"); - if (attr_required_string == -1) { - string_table.push_back("required"); - attr_required_string = string_table.size() - 1; - } - - for (int i = 0; i < feature_names.size(); i++) { - String feature_name = feature_names[i]; - bool feature_required = feature_required_list[i]; - int feature_version = feature_versions[i]; - bool has_version_attribute = feature_version != -1; - - print_line("Adding feature " + feature_name); - - int32_t feature_string = string_table.find(feature_name); - if (feature_string == -1) { - string_table.push_back(feature_name); - feature_string = string_table.size() - 1; - } - - String required_value_string = feature_required ? "true" : "false"; - int32_t required_value = string_table.find(required_value_string); - if (required_value == -1) { - string_table.push_back(required_value_string); - required_value = string_table.size() - 1; - } - - int32_t attr_version_string = -1; - int32_t version_value = -1; - int tag_size; - int attr_count; - if (has_version_attribute) { - attr_version_string = string_table.find("version"); - if (attr_version_string == -1) { - string_table.push_back("version"); - attr_version_string = string_table.size() - 1; - } - - version_value = string_table.find(itos(feature_version)); - if (version_value == -1) { - string_table.push_back(itos(feature_version)); - version_value = string_table.size() - 1; - } - - tag_size = 96; // node and three attrs + end node - attr_count = 3; - } else { - tag_size = 76; // node and two attrs + end node - attr_count = 2; - } - manifest_cur_size += tag_size + 24; - p_manifest.resize(manifest_cur_size); - - // start tag - encode_uint16(0x102, &p_manifest.write[ofs]); // type - encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize - encode_uint32(tag_size, &p_manifest.write[ofs + 4]); // size - encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno - encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment - encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns - encode_uint32(attr_uses_feature_string, &p_manifest.write[ofs + 20]); // name - encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start - encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size - encode_uint16(attr_count, &p_manifest.write[ofs + 28]); // num_attrs - encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index - encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index - encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index - - // android:name attribute - encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns - encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name' - encode_uint32(feature_string, &p_manifest.write[ofs + 44]); // raw_value - encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size - p_manifest.write[ofs + 50] = 0; // typedvalue_always0 - p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string) - encode_uint32(feature_string, &p_manifest.write[ofs + 52]); // typedvalue reference - - // android:required attribute - encode_uint32(ns_android_string, &p_manifest.write[ofs + 56]); // ns - encode_uint32(attr_required_string, &p_manifest.write[ofs + 60]); // 'name' - encode_uint32(required_value, &p_manifest.write[ofs + 64]); // raw_value - encode_uint16(8, &p_manifest.write[ofs + 68]); // typedvalue_size - p_manifest.write[ofs + 70] = 0; // typedvalue_always0 - p_manifest.write[ofs + 71] = 0x03; // typedvalue_type (string) - encode_uint32(required_value, &p_manifest.write[ofs + 72]); // typedvalue reference - - ofs += 76; - - if (has_version_attribute) { - // android:version attribute - encode_uint32(ns_android_string, &p_manifest.write[ofs]); // ns - encode_uint32(attr_version_string, &p_manifest.write[ofs + 4]); // 'name' - encode_uint32(version_value, &p_manifest.write[ofs + 8]); // raw_value - encode_uint16(8, &p_manifest.write[ofs + 12]); // typedvalue_size - p_manifest.write[ofs + 14] = 0; // typedvalue_always0 - p_manifest.write[ofs + 15] = 0x03; // typedvalue_type (string) - encode_uint32(version_value, &p_manifest.write[ofs + 16]); // typedvalue reference - - ofs += 20; - } - - // end tag - encode_uint16(0x103, &p_manifest.write[ofs]); // type - encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize - encode_uint32(24, &p_manifest.write[ofs + 4]); // size - encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno - encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment - encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns - encode_uint32(attr_uses_feature_string, &p_manifest.write[ofs + 20]); // name - - ofs += 24; - } - memcpy(&p_manifest.write[ofs], manifest_end.ptr(), manifest_end.size()); - ofs -= 24; // go back over back end - } - } - if (tname == "manifest") { - // save manifest ending so we can restore it - Vector manifest_end; - uint32_t manifest_cur_size = p_manifest.size(); - - manifest_end.resize(p_manifest.size() - ofs); - memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size()); - - int32_t attr_name_string = string_table.find("name"); - ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute."); - - int32_t ns_android_string = string_table.find("android"); - ERR_FAIL_COND_MSG(ns_android_string == -1, "Template does not have 'android' namespace."); - - int32_t attr_uses_permission_string = string_table.find("uses-permission"); - if (attr_uses_permission_string == -1) { - string_table.push_back("uses-permission"); - attr_uses_permission_string = string_table.size() - 1; - } - - for (int i = 0; i < perms.size(); ++i) { - print_line("Adding permission " + perms[i]); - - manifest_cur_size += 56 + 24; // node + end node - p_manifest.resize(manifest_cur_size); - - // Add permission to the string pool - int32_t perm_string = string_table.find(perms[i]); - if (perm_string == -1) { - string_table.push_back(perms[i]); - perm_string = string_table.size() - 1; - } - - // start tag - encode_uint16(0x102, &p_manifest.write[ofs]); // type - encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize - encode_uint32(56, &p_manifest.write[ofs + 4]); // size - encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno - encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment - encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns - encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name - encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start - encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size - encode_uint16(1, &p_manifest.write[ofs + 28]); // num_attrs - encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index - encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index - encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index - - // attribute - encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns - encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name' - encode_uint32(perm_string, &p_manifest.write[ofs + 44]); // raw_value - encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size - p_manifest.write[ofs + 50] = 0; // typedvalue_always0 - p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string) - encode_uint32(perm_string, &p_manifest.write[ofs + 52]); // typedvalue reference - - ofs += 56; - - // end tag - encode_uint16(0x103, &p_manifest.write[ofs]); // type - encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize - encode_uint32(24, &p_manifest.write[ofs + 4]); // size - encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno - encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment - encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns - encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name - - ofs += 24; - } - - // copy footer back in - memcpy(&p_manifest.write[ofs], manifest_end.ptr(), manifest_end.size()); - } - } break; - } - - ofs += size; - } - - //create new andriodmanifest binary - - Vector ret; - ret.resize(string_table_begins + string_table.size() * 4); - - for (uint32_t i = 0; i < string_table_begins; i++) { - ret.write[i] = p_manifest[i]; - } - - ofs = 0; - for (int i = 0; i < string_table.size(); i++) { - encode_uint32(ofs, &ret.write[string_table_begins + i * 4]); - ofs += string_table[i].length() * 2 + 2 + 2; - } - - ret.resize(ret.size() + ofs); - string_data_offset = ret.size() - ofs; - uint8_t *chars = &ret.write[string_data_offset]; - for (int i = 0; i < string_table.size(); i++) { - String s = string_table[i]; - encode_uint16(s.length(), chars); - chars += 2; - for (int j = 0; j < s.length(); j++) { - encode_uint16(s[j], chars); - chars += 2; - } - encode_uint16(0, chars); - chars += 2; - } - - for (int i = 0; i < stable_extra.size(); i++) { - ret.push_back(stable_extra[i]); - } - - //pad - while (ret.size() % 4) { - ret.push_back(0); - } - - uint32_t new_stable_end = ret.size(); - - uint32_t extra = (p_manifest.size() - string_table_ends); - ret.resize(new_stable_end + extra); - for (uint32_t i = 0; i < extra; i++) { - ret.write[new_stable_end + i] = p_manifest[string_table_ends + i]; - } - - while (ret.size() % 4) { - ret.push_back(0); - } - encode_uint32(ret.size(), &ret.write[4]); //update new file size - - encode_uint32(new_stable_end - 8, &ret.write[12]); //update new string table size - encode_uint32(string_table.size(), &ret.write[16]); //update new number of strings - encode_uint32(string_data_offset - 8, &ret.write[28]); //update new string data offset - - p_manifest = ret; -} - -String EditorExportPlatformAndroid::_parse_string(const uint8_t *p_bytes, bool p_utf8) { - uint32_t offset = 0; - uint32_t len = 0; - - if (p_utf8) { - uint8_t byte = p_bytes[offset]; - if (byte & 0x80) { - offset += 2; - } else { - offset += 1; - } - byte = p_bytes[offset]; - offset++; - if (byte & 0x80) { - len = byte & 0x7F; - len = (len << 8) + p_bytes[offset]; - offset++; - } else { - len = byte; - } - } else { - len = decode_uint16(&p_bytes[offset]); - offset += 2; - if (len & 0x8000) { - len &= 0x7FFF; - len = (len << 16) + decode_uint16(&p_bytes[offset]); - offset += 2; - } - } - - if (p_utf8) { - Vector str8; - str8.resize(len + 1); - for (uint32_t i = 0; i < len; i++) { - str8.write[i] = p_bytes[offset + i]; - } - str8.write[len] = 0; - String str; - str.parse_utf8((const char *)str8.ptr()); - return str; - } else { - String str; - for (uint32_t i = 0; i < len; i++) { - CharType c = decode_uint16(&p_bytes[offset + i * 2]); - if (c == 0) { - break; - } - str += String::chr(c); - } - return str; - } -} - -void EditorExportPlatformAndroid::_fix_resources(const Ref &p_preset, Vector &r_manifest) { - const int UTF8_FLAG = 0x00000100; - - uint32_t string_block_len = decode_uint32(&r_manifest[16]); - uint32_t string_count = decode_uint32(&r_manifest[20]); - uint32_t string_flags = decode_uint32(&r_manifest[28]); - const uint32_t string_table_begins = 40; - - Vector string_table; - - String package_name = p_preset->get("package/name"); - - for (uint32_t i = 0; i < string_count; i++) { - uint32_t offset = decode_uint32(&r_manifest[string_table_begins + i * 4]); - offset += string_table_begins + string_count * 4; - - String str = _parse_string(&r_manifest[offset], string_flags & UTF8_FLAG); - - if (str.begins_with("pandemonium-project-name")) { - if (str == "pandemonium-project-name") { - //project name - str = get_project_name(package_name); - - } else { - String lang = str.substr(str.rfind("-") + 1, str.length()).replace("-", "_"); - String prop = "application/config/name_" + lang; - if (ProjectSettings::get_singleton()->has_setting(prop)) { - str = ProjectSettings::get_singleton()->get(prop); - } else { - str = get_project_name(package_name); - } - } - } - - string_table.push_back(str); - } - - //write a new string table, but use 16 bits - Vector ret; - ret.resize(string_table_begins + string_table.size() * 4); - - for (uint32_t i = 0; i < string_table_begins; i++) { - ret.write[i] = r_manifest[i]; - } - - int ofs = 0; - for (int i = 0; i < string_table.size(); i++) { - encode_uint32(ofs, &ret.write[string_table_begins + i * 4]); - ofs += string_table[i].length() * 2 + 2 + 2; - } - - ret.resize(ret.size() + ofs); - uint8_t *chars = &ret.write[ret.size() - ofs]; - for (int i = 0; i < string_table.size(); i++) { - String s = string_table[i]; - encode_uint16(s.length(), chars); - chars += 2; - for (int j = 0; j < s.length(); j++) { - encode_uint16(s[j], chars); - chars += 2; - } - encode_uint16(0, chars); - chars += 2; - } - - //pad - while (ret.size() % 4) { - ret.push_back(0); - } - - //change flags to not use utf8 - encode_uint32(string_flags & ~0x100, &ret.write[28]); - //change length - encode_uint32(ret.size() - 12, &ret.write[16]); - //append the rest... - int rest_from = 12 + string_block_len; - int rest_to = ret.size(); - int rest_len = (r_manifest.size() - rest_from); - ret.resize(ret.size() + (r_manifest.size() - rest_from)); - for (int i = 0; i < rest_len; i++) { - ret.write[rest_to + i] = r_manifest[rest_from + i]; - } - //finally update the size - encode_uint32(ret.size(), &ret.write[4]); - - r_manifest = ret; -} - -void EditorExportPlatformAndroid::_load_image_data(const Ref &p_splash_image, Vector &p_data) { - PoolVector png_buffer; - Error err = PNGDriverCommon::image_to_png(p_splash_image, png_buffer); - if (err == OK) { - p_data.resize(png_buffer.size()); - memcpy(p_data.ptrw(), png_buffer.read().ptr(), p_data.size()); - } else { - String err_str = String("Failed to convert splash image to png."); - WARN_PRINT(err_str.utf8().get_data()); - } -} - -void EditorExportPlatformAndroid::_process_launcher_icons(const String &p_file_name, const Ref &p_source_image, int dimension, Vector &p_data) { - Ref working_image = p_source_image; - - if (p_source_image->get_width() != dimension || p_source_image->get_height() != dimension) { - working_image = p_source_image->duplicate(); - working_image->resize(dimension, dimension, Image::Interpolation::INTERPOLATE_LANCZOS); - } - - PoolVector png_buffer; - Error err = PNGDriverCommon::image_to_png(working_image, png_buffer); - if (err == OK) { - p_data.resize(png_buffer.size()); - memcpy(p_data.ptrw(), png_buffer.read().ptr(), p_data.size()); - } else { - String err_str = String("Failed to convert resized icon (") + p_file_name + ") to png."; - WARN_PRINT(err_str.utf8().get_data()); - } -} - -String EditorExportPlatformAndroid::load_splash_refs(Ref &splash_image, Ref &splash_bg_color_image) { - bool scale_splash = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize"); - bool apply_filter = ProjectSettings::get_singleton()->get("application/boot_splash/use_filter"); - String project_splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); - - if (!project_splash_path.empty()) { - splash_image.instance(); - print_verbose("Loading splash image: " + project_splash_path); - const Error err = ImageLoader::load_image(project_splash_path, splash_image); - if (err) { - if (OS::get_singleton()->is_stdout_verbose()) { - print_error("- unable to load splash image from " + project_splash_path + " (" + itos(err) + ")"); - } - splash_image.unref(); - } - } - - if (splash_image.is_null()) { - // Use the default - print_verbose("Using default splash image."); - - // Create a 1×1 transparent image. This will effectively hide the splash image. - splash_image.instance(); - splash_image->create(1, 1, false, Image::FORMAT_RGBA8); - splash_image->lock(); - splash_image->set_pixel(0, 0, Color(0, 0, 0, 0)); - splash_image->unlock(); - } - - if (scale_splash) { - Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); - int width, height; - if (screen_size.width > screen_size.height) { - // scale horizontally - height = screen_size.height; - width = splash_image->get_width() * screen_size.height / splash_image->get_height(); - } else { - // scale vertically - width = screen_size.width; - height = splash_image->get_height() * screen_size.width / splash_image->get_width(); - } - splash_image->resize(width, height); - } - - // Setup the splash bg color - bool bg_color_valid; - Color bg_color = ProjectSettings::get_singleton()->get("application/boot_splash/bg_color", &bg_color_valid); - if (!bg_color_valid) { - bg_color = Color(0.14, 0.14, 0.14); - } - - print_verbose("Creating splash background color image."); - splash_bg_color_image.instance(); - 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); - - String processed_splash_config_xml = vformat(SPLASH_CONFIG_XML_CONTENT, bool_to_string(apply_filter)); - return processed_splash_config_xml; -} - -void EditorExportPlatformAndroid::load_icon_refs(const Ref &p_preset, Ref &icon, Ref &foreground, Ref &background) { - String project_icon_path = ProjectSettings::get_singleton()->get("application/config/icon"); - - icon.instance(); - foreground.instance(); - background.instance(); - - // Regular icon: user selection -> project icon -> default. - String path = static_cast(p_preset->get(launcher_icon_option)).strip_edges(); - print_verbose("Loading regular icon from " + path); - if (path.empty() || ImageLoader::load_image(path, icon) != OK) { - print_verbose("- falling back to project icon: " + project_icon_path); - ImageLoader::load_image(project_icon_path, icon); - } - - // Adaptive foreground: user selection -> regular icon (user selection -> project icon -> default). - path = static_cast(p_preset->get(launcher_adaptive_icon_foreground_option)).strip_edges(); - print_verbose("Loading adaptive foreground icon from " + path); - if (path.empty() || ImageLoader::load_image(path, foreground) != OK) { - print_verbose("- falling back to using the regular icon"); - foreground = icon; - } - - // Adaptive background: user selection -> default. - path = static_cast(p_preset->get(launcher_adaptive_icon_background_option)).strip_edges(); - if (!path.empty()) { - print_verbose("Loading adaptive background icon from " + path); - ImageLoader::load_image(path, background); - } -} - -void EditorExportPlatformAndroid::store_image(const LauncherIcon launcher_icon, const Vector &data) { - store_image(launcher_icon.export_path, data); -} - -void EditorExportPlatformAndroid::store_image(const String &export_path, const Vector &data) { - String img_path = export_path.insert(0, "res://android/build/"); - store_file_at_path(img_path, data); -} - -void EditorExportPlatformAndroid::_copy_icons_to_gradle_project(const Ref &p_preset, - const String &processed_splash_config_xml, - const Ref &splash_image, - const Ref &splash_bg_color_image, - const Ref &main_image, - const Ref &foreground, - const Ref &background) { - // Store the splash configuration - if (!processed_splash_config_xml.empty()) { - print_verbose("Storing processed splash configuration: " + String("\n") + processed_splash_config_xml); - store_string_at_path(SPLASH_CONFIG_PATH, processed_splash_config_xml); - } - - // Store the splash image - if (splash_image.is_valid() && !splash_image->empty()) { - print_verbose("Storing splash image in " + String(SPLASH_IMAGE_EXPORT_PATH)); - Vector data; - _load_image_data(splash_image, data); - store_image(SPLASH_IMAGE_EXPORT_PATH, data); - } - - // Store the splash bg color image - if (splash_bg_color_image.is_valid() && !splash_bg_color_image->empty()) { - print_verbose("Storing splash background image in " + String(SPLASH_BG_COLOR_PATH)); - Vector data; - _load_image_data(splash_bg_color_image, data); - store_image(SPLASH_BG_COLOR_PATH, data); - } - - // Prepare images to be resized for the icons. If some image ends up being uninitialized, - // the default image from the export template will be used. - - for (int i = 0; i < icon_densities_count; ++i) { - if (main_image.is_valid() && !main_image->empty()) { - print_verbose("Processing launcher icon for dimension " + itos(launcher_icons[i].dimensions) + " into " + launcher_icons[i].export_path); - Vector data; - _process_launcher_icons(launcher_icons[i].export_path, main_image, launcher_icons[i].dimensions, data); - store_image(launcher_icons[i], data); - } - - if (foreground.is_valid() && !foreground->empty()) { - print_verbose("Processing launcher adaptive icon foreground for dimension " + itos(launcher_adaptive_icon_foregrounds[i].dimensions) + " into " + launcher_adaptive_icon_foregrounds[i].export_path); - Vector data; - _process_launcher_icons(launcher_adaptive_icon_foregrounds[i].export_path, foreground, - launcher_adaptive_icon_foregrounds[i].dimensions, data); - store_image(launcher_adaptive_icon_foregrounds[i], data); - } - - if (background.is_valid() && !background->empty()) { - print_verbose("Processing launcher adaptive icon background for dimension " + itos(launcher_adaptive_icon_backgrounds[i].dimensions) + " into " + launcher_adaptive_icon_backgrounds[i].export_path); - Vector data; - _process_launcher_icons(launcher_adaptive_icon_backgrounds[i].export_path, background, - launcher_adaptive_icon_backgrounds[i].dimensions, data); - store_image(launcher_adaptive_icon_backgrounds[i], data); - } - } -} - -Vector EditorExportPlatformAndroid::get_enabled_abis(const Ref &p_preset) { - Vector abis = get_abis(); - Vector enabled_abis; - for (int i = 0; i < abis.size(); ++i) { - bool is_enabled = p_preset->get("architectures/" + abis[i]); - if (is_enabled) { - enabled_abis.push_back(abis[i]); - } - } - return enabled_abis; -} - -void EditorExportPlatformAndroid::get_preset_features(const Ref &p_preset, List *r_features) { - String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name"); - if (driver == "GLES2") { - r_features->push_back("etc"); - } else if (driver == "GLES3") { - r_features->push_back("etc2"); - if (ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2")) { - r_features->push_back("etc"); - } - } - - Vector abis = get_enabled_abis(p_preset); - for (int i = 0; i < abis.size(); ++i) { - r_features->push_back(abis[i]); - } -} - -void EditorExportPlatformAndroid::get_export_options(List *r_options) { - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_template/use_custom_build"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "custom_template/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK)); - - Vector 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)); - } - plugins_changed.clear(); - - Vector abis = get_abis(); - for (int i = 0; i < abis.size(); ++i) { - String abi = abis[i]; - bool is_default = (abi == "armeabi-v7a" || abi == "arm64-v8a"); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "architectures/" + abi), is_default)); - } - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_user"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_user"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_password"), "")); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "one_click_deploy/clear_previous_install"), false)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name"), "1.0")); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/min_sdk", PROPERTY_HINT_RANGE, SDK_VERSION_RANGE), DEFAULT_MIN_SDK_VERSION)); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/target_sdk", PROPERTY_HINT_RANGE, SDK_VERSION_RANGE), DEFAULT_TARGET_SDK_VERSION)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "net.relintai.pandemonium.$genname")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name [default if blank]"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/signed"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/classify_as_game"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/retain_data_on_uninstall"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/exclude_from_recents"), false)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_icon_option, PROPERTY_HINT_FILE, "*.png"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_foreground_option, PROPERTY_HINT_FILE, "*.png"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_background_option, PROPERTY_HINT_FILE, "*.png"), "")); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "graphics/opengl_debug"), false)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/immersive_mode"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_small"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_normal"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_large"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_xlarge"), true)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data_backup/allow"), false)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "command_line/extra_args"), "")); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "apk_expansion/enable"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "apk_expansion/SALT"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "apk_expansion/public_key", PROPERTY_HINT_MULTILINE_TEXT), "")); - - r_options->push_back(ExportOption(PropertyInfo(Variant::POOL_STRING_ARRAY, "permissions/custom_permissions"), PoolStringArray())); - - const char **perms = android_perms; - while (*perms) { - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "permissions/" + String(*perms).to_lower()), false)); - perms++; - } -} - -String EditorExportPlatformAndroid::get_name() const { - return "Android"; -} - -String EditorExportPlatformAndroid::get_os_name() const { - return "Android"; -} - -Ref EditorExportPlatformAndroid::get_logo() const { - return logo; -} - -bool EditorExportPlatformAndroid::should_update_export_options() { - bool export_options_changed = plugins_changed.is_set(); - if (export_options_changed) { - // don't clear unless we're reporting true, to avoid race - plugins_changed.clear(); - } - return export_options_changed; -} - -bool EditorExportPlatformAndroid::poll_export() { - bool dc = devices_changed.is_set(); - if (dc) { - // don't clear unless we're reporting true, to avoid race - devices_changed.clear(); - } - return dc; -} - -int EditorExportPlatformAndroid::get_options_count() const { - device_lock.lock(); - int dc = devices.size(); - device_lock.unlock(); - - return dc; -} - -String EditorExportPlatformAndroid::get_options_tooltip() const { - return TTR("Select device from the list"); -} - -String EditorExportPlatformAndroid::get_option_label(int p_index) const { - ERR_FAIL_INDEX_V(p_index, devices.size(), ""); - device_lock.lock(); - String s = devices[p_index].name; - device_lock.unlock(); - return s; -} - -String EditorExportPlatformAndroid::get_option_tooltip(int p_index) const { - ERR_FAIL_INDEX_V(p_index, devices.size(), ""); - device_lock.lock(); - String s = devices[p_index].description; - if (devices.size() == 1) { - // Tooltip will be: - // Name - // Description - s = devices[p_index].name + "\n\n" + s; - } - device_lock.unlock(); - return s; -} - -Error EditorExportPlatformAndroid::run(const Ref &p_preset, int p_device, int p_debug_flags) { - ERR_FAIL_INDEX_V(p_device, devices.size(), ERR_INVALID_PARAMETER); - - String can_export_error; - bool can_export_missing_templates; - if (!can_export(p_preset, can_export_error, can_export_missing_templates)) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), can_export_error); - return ERR_UNCONFIGURED; - } - - device_lock.lock(); - - EditorProgress ep("run", vformat(TTR("Running on %s"), devices[p_device].name), 3); - - String adb = get_adb_path(); - - // Export_temp APK. - if (ep.step(TTR("Exporting APK..."), 0)) { - device_lock.unlock(); - return ERR_SKIP; - } - - const bool use_remote = (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) || (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT); - const bool use_reverse = devices[p_device].api_level >= 21; - - if (use_reverse) { - p_debug_flags |= DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST; - } - - String tmp_export_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport." + uitos(OS::get_singleton()->get_unix_time()) + ".apk"); - -#define CLEANUP_AND_RETURN(m_err) \ - { \ - DirAccess::remove_file_or_error(tmp_export_path); \ - device_lock.unlock(); \ - return m_err; \ - } - - // 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); - - if (err != OK) { - CLEANUP_AND_RETURN(err); - } - - List args; - int rv; - String output; - - bool remove_prev = p_preset->get("one_click_deploy/clear_previous_install"); - String version_name = p_preset->get("version/name"); - String package_name = p_preset->get("package/unique_name"); - - if (remove_prev) { - if (ep.step(TTR("Uninstalling..."), 1)) { - CLEANUP_AND_RETURN(ERR_SKIP); - } - - print_line("Uninstalling previous version: " + devices[p_device].name); - - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("uninstall"); - args.push_back(get_package_name(package_name)); - - output.clear(); - err = OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); - print_verbose(output); - } - - print_line("Installing to device (please wait...): " + devices[p_device].name); - if (ep.step(TTR("Installing to device, please wait..."), 2)) { - CLEANUP_AND_RETURN(ERR_SKIP); - } - - args.clear(); - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("install"); - args.push_back("-r"); - args.push_back(tmp_export_path); - - output.clear(); - err = OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); - print_verbose(output); - if (err || rv != 0) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), vformat(TTR("Could not install to device: %s"), output)); - CLEANUP_AND_RETURN(ERR_CANT_CREATE); - } - - if (use_remote) { - if (use_reverse) { - static const char *const msg = "--- Device API >= 21; debugging over USB ---"; - EditorNode::get_singleton()->get_log()->add_message(msg, EditorLog::MSG_TYPE_EDITOR); - print_line(String(msg).to_upper()); - - args.clear(); - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("reverse"); - args.push_back("--remove-all"); - output.clear(); - OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); - print_verbose(output); - - if (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) { - int dbg_port = EditorSettings::get_singleton()->get("network/debug/remote_port"); - args.clear(); - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("reverse"); - args.push_back("tcp:" + itos(dbg_port)); - args.push_back("tcp:" + itos(dbg_port)); - - output.clear(); - OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); - print_verbose(output); - print_line("Reverse result: " + itos(rv)); - } - - if (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT) { - int fs_port = EditorSettings::get_singleton()->get("filesystem/file_server/port"); - - args.clear(); - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("reverse"); - args.push_back("tcp:" + itos(fs_port)); - args.push_back("tcp:" + itos(fs_port)); - - output.clear(); - err = OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); - print_verbose(output); - print_line("Reverse result2: " + itos(rv)); - } - } else { - static const char *const msg = "--- Device API < 21; debugging over Wi-Fi ---"; - EditorNode::get_singleton()->get_log()->add_message(msg, EditorLog::MSG_TYPE_EDITOR); - print_line(String(msg).to_upper()); - } - } - - if (ep.step(TTR("Running on device..."), 3)) { - CLEANUP_AND_RETURN(ERR_SKIP); - } - args.clear(); - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("shell"); - args.push_back("am"); - args.push_back("start"); - if ((bool)EditorSettings::get_singleton()->get("export/android/force_system_user") && devices[p_device].api_level >= 17) { // Multi-user introduced in Android 17 - args.push_back("--user"); - args.push_back("0"); - } - args.push_back("-a"); - args.push_back("android.intent.action.MAIN"); - args.push_back("-n"); - args.push_back(get_package_name(package_name) + "/com.pandemonium.game.PandemoniumApp"); - - output.clear(); - err = OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); - print_verbose(output); - if (err || rv != 0) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), TTR("Could not execute on device.")); - CLEANUP_AND_RETURN(ERR_CANT_CREATE); - } - - CLEANUP_AND_RETURN(OK); -#undef CLEANUP_AND_RETURN -} - -Ref EditorExportPlatformAndroid::get_run_icon() const { - return run_icon; -} - -String EditorExportPlatformAndroid::get_adb_path() { - String exe_ext = ""; - if (OS::get_singleton()->get_name() == "Windows") { - exe_ext = ".exe"; - } - String sdk_path = EditorSettings::get_singleton()->get("export/android/android_sdk_path"); - return sdk_path.plus_file("platform-tools/adb" + exe_ext); -} - -String EditorExportPlatformAndroid::get_apksigner_path() { - String exe_ext = ""; - if (OS::get_singleton()->get_name() == "Windows") { - exe_ext = ".bat"; - } - String apksigner_command_name = "apksigner" + exe_ext; - String sdk_path = EditorSettings::get_singleton()->get("export/android/android_sdk_path"); - String apksigner_path = ""; - - Error errn; - String build_tools_dir = sdk_path.plus_file("build-tools"); - DirAccessRef da = DirAccess::open(build_tools_dir, &errn); - if (errn != OK) { - print_error("Unable to open Android 'build-tools' directory."); - return apksigner_path; - } - - // There are additional versions directories we need to go through. - da->list_dir_begin(); - String sub_dir = da->get_next(); - while (!sub_dir.empty()) { - if (!sub_dir.begins_with(".") && da->current_is_dir()) { - // Check if the tool is here. - String tool_path = build_tools_dir.plus_file(sub_dir).plus_file(apksigner_command_name); - if (FileAccess::exists(tool_path)) { - apksigner_path = tool_path; - break; - } - } - sub_dir = da->get_next(); - } - da->list_dir_end(); - - if (apksigner_path.empty()) { - print_error("Unable to find the 'apksigner' tool."); - } - - return apksigner_path; -} - -bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref &p_preset, String &r_error, bool &r_missing_templates) const { - String err; - bool valid = false; - const bool custom_build_enabled = p_preset->get("custom_template/use_custom_build"); - - // Look for export templates (first official, and if defined custom templates). - - if (!custom_build_enabled) { - String template_err; - bool dvalid = false; - bool rvalid = false; - bool has_export_templates = false; - - if (p_preset->get("custom_template/debug") != "") { - dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); - if (!dvalid) { - template_err += TTR("Custom debug template not found.") + "\n"; - } - } else { - has_export_templates |= exists_export_template("android_debug.apk", &template_err); - } - - if (p_preset->get("custom_template/release") != "") { - rvalid = FileAccess::exists(p_preset->get("custom_template/release")); - if (!rvalid) { - template_err += TTR("Custom release template not found.") + "\n"; - } - } else { - has_export_templates |= exists_export_template("android_release.apk", &template_err); - } - - r_missing_templates = !has_export_templates; - valid = dvalid || rvalid || has_export_templates; - if (!valid) { - err += template_err; - } - } else { - bool installed_android_build_template = FileAccess::exists("res://android/build/build.gradle"); - if (!installed_android_build_template) { - r_missing_templates = !exists_export_template("android_source.zip", &err); - err += TTR("Android build template not installed in the project. Install it from the Project menu.") + "\n"; - } else { - r_missing_templates = false; - } - - valid = installed_android_build_template && !r_missing_templates; - } - - // Validate the rest of the export configuration. - - String dk = p_preset->get("keystore/debug"); - String dk_user = p_preset->get("keystore/debug_user"); - String dk_password = p_preset->get("keystore/debug_password"); - - if ((dk.empty() || dk_user.empty() || dk_password.empty()) && (!dk.empty() || !dk_user.empty() || !dk_password.empty())) { - valid = false; - err += TTR("Either Debug Keystore, Debug User AND Debug Password settings must be configured OR none of them.") + "\n"; - } - - if (!FileAccess::exists(dk)) { - dk = EditorSettings::get_singleton()->get("export/android/debug_keystore"); - if (!FileAccess::exists(dk)) { - valid = false; - err += TTR("Debug keystore not configured in the Editor Settings nor in the preset.") + "\n"; - } - } - - String rk = p_preset->get("keystore/release"); - String rk_user = p_preset->get("keystore/release_user"); - String rk_password = p_preset->get("keystore/release_password"); - - if ((rk.empty() || rk_user.empty() || rk_password.empty()) && (!rk.empty() || !rk_user.empty() || !rk_password.empty())) { - valid = false; - err += TTR("Either Release Keystore, Release User AND Release Password settings must be configured OR none of them.") + "\n"; - } - - if (!rk.empty() && !FileAccess::exists(rk)) { - valid = false; - err += TTR("Release keystore incorrectly configured in the export preset.") + "\n"; - } - - String sdk_path = EditorSettings::get_singleton()->get("export/android/android_sdk_path"); - if (sdk_path == "") { - err += TTR("A valid Android SDK path is required in Editor Settings.") + "\n"; - valid = false; - } else { - Error errn; - // Check for the platform-tools directory. - DirAccessRef da = DirAccess::open(sdk_path.plus_file("platform-tools"), &errn); - if (errn != OK) { - err += TTR("Invalid Android SDK path in Editor Settings."); - err += TTR("Missing 'platform-tools' directory!"); - err += "\n"; - valid = false; - } - - // Validate that adb is available - String adb_path = get_adb_path(); - if (!FileAccess::exists(adb_path)) { - err += TTR("Unable to find Android SDK platform-tools' adb command."); - err += TTR("Please check in the Android SDK directory specified in Editor Settings."); - err += "\n"; - valid = false; - } - - // Check for the build-tools directory. - DirAccessRef build_tools_da = DirAccess::open(sdk_path.plus_file("build-tools"), &errn); - if (errn != OK) { - err += TTR("Invalid Android SDK path in Editor Settings."); - err += TTR("Missing 'build-tools' directory!"); - err += "\n"; - valid = false; - } - - // Validate that apksigner is available - String apksigner_path = get_apksigner_path(); - if (!FileAccess::exists(apksigner_path)) { - err += TTR("Unable to find Android SDK build-tools' apksigner command."); - err += TTR("Please check in the Android SDK directory specified in Editor Settings."); - err += "\n"; - valid = false; - } - } - - if (!err.empty()) { - r_error = err; - } - - return valid; -} - -bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref &p_preset, String &r_error) const { - String err; - bool valid = true; - const bool custom_build_enabled = p_preset->get("custom_build/use_custom_build"); - - // Validate the project configuration. - bool apk_expansion = p_preset->get("apk_expansion/enable"); - - if (apk_expansion) { - String apk_expansion_pkey = p_preset->get("apk_expansion/public_key"); - - if (apk_expansion_pkey == "") { - valid = false; - - err += TTR("Invalid public key for APK expansion.") + "\n"; - } - } - - String pn = p_preset->get("package/unique_name"); - String pn_err; - - if (!is_package_name_valid(get_package_name(pn), &pn_err)) { - valid = false; - err += TTR("Invalid package name:") + " " + pn_err + "\n"; - } - - String etc_error = test_etc2(); - if (etc_error != String()) { - valid = false; - err += etc_error; - } - - // The PandemoniumPaymentV3 module was converted to the external PandemoniumGooglePlayBilling plugin in Pandemonium 3.2.2, - // this check helps users to notice the change to ensure that they change their settings. - String modules = ProjectSettings::get_singleton()->get("android/modules"); - if (modules.find("org/pandemoniumengine/pandemonium/PandemoniumPaymentV3") != -1) { - bool pandemonium_google_play_billing_enabled = p_preset->get("plugins/PandemoniumGooglePlayBilling"); - if (!pandemonium_google_play_billing_enabled) { - valid = false; - err += TTR("Invalid \"PandemoniumPaymentV3\" module included in the \"android/modules\" project setting (changed in Pandemonium 3.2.2).\nReplace it with the first-party \"PandemoniumGooglePlayBilling\" plugin.\nNote that the singleton was also renamed from \"PandemoniumPayments\" to \"PandemoniumGooglePlayBilling\"."); - err += "\n"; - } - } - - // Ensure that `Use Custom Build` is enabled if a plugin is selected. - String enabled_plugins_names = PluginConfigAndroid::get_plugins_names(get_enabled_plugins(p_preset)); - if (!enabled_plugins_names.empty() && !custom_build_enabled) { - valid = false; - err += TTR("\"Use Custom Build\" must be enabled to use the plugins."); - err += "\n"; - } - - if (int(p_preset->get("custom_build/export_format")) == EXPORT_FORMAT_AAB && !custom_build_enabled) { - valid = false; - err += TTR("\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."); - err += "\n"; - } - - // Check the min sdk version - int min_sdk_version = p_preset->get("version/min_sdk"); - if (min_sdk_version != DEFAULT_MIN_SDK_VERSION && !custom_build_enabled) { - valid = false; - err += TTR("Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."); - err += "\n"; - } - - // Check the target sdk version - int target_sdk_version = p_preset->get("version/target_sdk"); - if (target_sdk_version != DEFAULT_TARGET_SDK_VERSION && !custom_build_enabled) { - valid = false; - err += TTR("Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is enabled."); - err += "\n"; - } - - if (target_sdk_version < min_sdk_version) { - valid = false; - err += TTR("\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."); - err += "\n"; - } - - if (!err.empty()) { - r_error = err; - } - - return valid; -} - -List EditorExportPlatformAndroid::get_binary_extensions(const Ref &p_preset) const { - List list; - list.push_back("apk"); - list.push_back("aab"); - return list; -} - -void EditorExportPlatformAndroid::_update_custom_build_project() { - print_verbose("Updating custom build project.."); - DirAccessRef da = DirAccess::open("res://android"); - - ERR_FAIL_COND_MSG(!da, "Cannot open directory 'res://android'."); - RBMap> directory_paths; - RBMap> manifest_sections; - RBMap> gradle_sections; - da->list_dir_begin(); - String d = da->get_next(); - while (d != String()) { - if (!d.begins_with(".") && d != "build" && da->current_is_dir()) { //a dir and not the build dir - //add directories found - DirAccessRef ds = DirAccess::open(String("res://android").plus_file(d)); - if (ds) { - ds->list_dir_begin(); - String sd = ds->get_next(); - while (sd != String()) { - if (!sd.begins_with(".") && ds->current_is_dir()) { - String key = sd.to_upper(); - if (!directory_paths.has(key)) { - directory_paths[key] = List(); - } - String path = ProjectSettings::get_singleton()->get_resource_path().plus_file("android").plus_file(d).plus_file(sd); - directory_paths[key].push_back(path); - print_line("Add: " + sd + ":" + path); - } - - sd = ds->get_next(); - } - ds->list_dir_end(); - } - //parse manifest - { - FileAccessRef f = FileAccess::open(String("res://android").plus_file(d).plus_file("AndroidManifest.conf"), FileAccess::READ); - if (f) { - String section; - while (!f->eof_reached()) { - String l = f->get_line(); - String k = l.strip_edges(); - if (k.begins_with("[")) { - section = k.substr(1, k.length() - 2).strip_edges().to_upper(); - print_line("Section: " + section); - } else if (k != String()) { - if (!manifest_sections.has(section)) { - manifest_sections[section] = List(); - } - manifest_sections[section].push_back(l); - } - } - - f->close(); - } - } - //parse gradle - { - FileAccessRef f = FileAccess::open(String("res://android").plus_file(d).plus_file("gradle.conf"), FileAccess::READ); - if (f) { - String section; - while (!f->eof_reached()) { - String l = f->get_line().strip_edges(); - String k = l.strip_edges(); - if (k.begins_with("[")) { - section = k.substr(1, k.length() - 2).strip_edges().to_upper(); - print_line("Section: " + section); - } else if (k != String()) { - if (!gradle_sections.has(section)) { - gradle_sections[section] = List(); - } - gradle_sections[section].push_back(l); - } - } - } - } - } - d = da->get_next(); - } - da->list_dir_end(); - - { //fix gradle build - - String new_file; - { - FileAccessRef f = FileAccess::open("res://android/build/build.gradle", FileAccess::READ); - if (f) { - while (!f->eof_reached()) { - String l = f->get_line(); - - bool append_line = false; - if (l.begins_with("//CHUNK_")) { - String text = l.replace_first("//CHUNK_", ""); - int begin_pos = text.find("_BEGIN"); - if (begin_pos != -1) { - text = text.substr(0, begin_pos); - text = text.to_upper(); //just in case - - String end_marker = "//CHUNK_" + text + "_END"; - uint64_t pos = f->get_position(); - bool found = false; - while (!f->eof_reached()) { - l = f->get_line(); - if (l.begins_with(end_marker)) { - found = true; - break; - } - } - - new_file += "//CHUNK_" + text + "_BEGIN\n"; - - if (!found) { - ERR_PRINT("No end marker found in build.gradle for chunk: " + text); - f->seek(pos); - } else { - //add chunk lines - if (gradle_sections.has(text)) { - for (List::Element *E = gradle_sections[text].front(); E; E = E->next()) { - new_file += E->get() + "\n"; - } - } - if (f->eof_reached()) { - new_file += end_marker; - } else { - new_file += end_marker + "\n"; - } - } - } else { - append_line = true; - } - } else if (l.begins_with("//DIR_")) { - String text = l.replace_first("//DIR_", ""); - int begin_pos = text.find("_BEGIN"); - if (begin_pos != -1) { - text = text.substr(0, begin_pos); - text = text.to_upper(); //just in case - - String end_marker = "//DIR_" + text + "_END"; - uint64_t pos = f->get_position(); - bool found = false; - while (!f->eof_reached()) { - l = f->get_line(); - if (l.begins_with(end_marker)) { - found = true; - break; - } - } - - new_file += "//DIR_" + text + "_BEGIN\n"; - - if (!found) { - ERR_PRINT("No end marker found in build.gradle for dir: " + text); - f->seek(pos); - } else { - //add chunk lines - if (directory_paths.has(text)) { - for (List::Element *E = directory_paths[text].front(); E; E = E->next()) { - new_file += ",'" + E->get().replace("'", "\'") + "'"; - new_file += "\n"; - } - } - if (f->eof_reached()) { - new_file += end_marker; - } else { - new_file += end_marker + "\n"; - } - } - } else { - append_line = true; - } - } else { - append_line = true; - } - - if (append_line) { - if (f->eof_reached()) { - new_file += l; - } else { - new_file += l + "\n"; - } - } - } - } - } - - FileAccessRef f = FileAccess::open("res://android/build/build.gradle", FileAccess::WRITE); - f->store_string(new_file); - f->close(); - } - - { //fix manifest - - String new_file; - { - FileAccessRef f = FileAccess::open("res://android/build/AndroidManifest.xml", FileAccess::READ); - if (f) { - while (!f->eof_reached()) { - String l = f->get_line(); - - bool append_line = false; - if (l.begins_with(""); - if (begin_pos != -1) { - text = text.substr(0, begin_pos); - text = text.to_upper(); //just in case - - String end_marker = ""; - uint64_t pos = f->get_position(); - bool found = false; - while (!f->eof_reached()) { - l = f->get_line(); - if (l.begins_with(end_marker)) { - found = true; - break; - } - } - - new_file += "\n"; - - if (!found) { - ERR_PRINT("No end marker found in AndroidManifest.xml for chunk: " + text); - f->seek(pos); - } else { - //add chunk lines - if (manifest_sections.has(text)) { - for (List::Element *E = manifest_sections[text].front(); E; E = E->next()) { - new_file += E->get() + "\n"; - } - } - if (f->eof_reached()) { - new_file += end_marker; - } else { - new_file += end_marker + "\n"; - } - } - } else { - append_line = true; - } - - } else if (l.strip_edges().begins_with("::Element *E = manifest_sections["APPLICATION_ATTRIBS"].front(); E; E = E->next()) { - String to_add = E->get().strip_edges(); - base += " " + to_add + " "; - } - } - base += ">\n"; - new_file += base; - } - } else { - append_line = true; - } - - if (append_line) { - new_file += l; - if (!f->eof_reached()) { - new_file += "\n"; - } - } - } - } - } - - FileAccessRef f = FileAccess::open("res://android/build/AndroidManifest.xml", FileAccess::WRITE); - f->store_string(new_file); - f->close(); - } -} - -String EditorExportPlatformAndroid::get_apk_expansion_fullpath(const Ref &p_preset, const String &p_path) { - int version_code = p_preset->get("version/code"); - String package_name = p_preset->get("package/unique_name"); - String apk_file_name = "main." + itos(version_code) + "." + get_package_name(package_name) + ".obb"; - String fullpath = p_path.get_base_dir().plus_file(apk_file_name); - return fullpath; -} - -Error EditorExportPlatformAndroid::save_apk_expansion_file(const Ref &p_preset, const String &p_path) { - String fullpath = get_apk_expansion_fullpath(p_preset, p_path); - Error err = save_pack(p_preset, fullpath); - return err; -} - -void EditorExportPlatformAndroid::get_command_line_flags(const Ref &p_preset, const String &p_path, int p_flags, Vector &r_command_line_flags) { - String cmdline = p_preset->get("command_line/extra_args"); - Vector command_line_strings = cmdline.strip_edges().split(" "); - for (int i = 0; i < command_line_strings.size(); i++) { - if (command_line_strings[i].strip_edges().length() == 0) { - command_line_strings.remove(i); - i--; - } - } - - gen_export_flags(command_line_strings, p_flags); - - bool apk_expansion = p_preset->get("apk_expansion/enable"); - if (apk_expansion) { - String fullpath = get_apk_expansion_fullpath(p_preset, p_path); - String apk_expansion_public_key = p_preset->get("apk_expansion/public_key"); - - command_line_strings.push_back("--use_apk_expansion"); - command_line_strings.push_back("--apk_expansion_md5"); - command_line_strings.push_back(FileAccess::get_md5(fullpath)); - command_line_strings.push_back("--apk_expansion_key"); - command_line_strings.push_back(apk_expansion_public_key.strip_edges()); - } - - bool immersive = p_preset->get("screen/immersive_mode"); - if (immersive) { - command_line_strings.push_back("--use_immersive"); - } - - bool debug_opengl = p_preset->get("graphics/opengl_debug"); - if (debug_opengl) { - command_line_strings.push_back("--debug_opengl"); - } - - bool translucent = ProjectSettings::get_singleton()->get("display/window/per_pixel_transparency/enabled"); - if (translucent) { - command_line_strings.push_back("--translucent"); - } - - if (command_line_strings.size()) { - r_command_line_flags.resize(4); - encode_uint32(command_line_strings.size(), &r_command_line_flags.write[0]); - for (int i = 0; i < command_line_strings.size(); i++) { - print_line(itos(i) + " param: " + command_line_strings[i]); - CharString command_line_argument = command_line_strings[i].utf8(); - int base = r_command_line_flags.size(); - int length = command_line_argument.length(); - if (length == 0) { - continue; - } - r_command_line_flags.resize(base + 4 + length); - encode_uint32(length, &r_command_line_flags.write[base]); - memcpy(&r_command_line_flags.write[base + 4], command_line_argument.ptr(), length); - } - } -} - -Error EditorExportPlatformAndroid::sign_apk(const Ref &p_preset, bool p_debug, const String &export_path, EditorProgress &ep) { - int export_format = int(p_preset->get("custom_template/export_format")); - String export_label = export_format == EXPORT_FORMAT_AAB ? "AAB" : "APK"; - String release_keystore = p_preset->get("keystore/release"); - String release_username = p_preset->get("keystore/release_user"); - String release_password = p_preset->get("keystore/release_password"); - - String apksigner = get_apksigner_path(); - print_verbose("Starting signing of the " + export_label + " binary using " + apksigner); - if (!FileAccess::exists(apksigner)) { - 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; - } - - String keystore; - String password; - String user; - if (p_debug) { - keystore = p_preset->get("keystore/debug"); - password = p_preset->get("keystore/debug_password"); - user = p_preset->get("keystore/debug_user"); - - if (keystore.empty()) { - keystore = EditorSettings::get_singleton()->get("export/android/debug_keystore"); - password = EditorSettings::get_singleton()->get("export/android/debug_keystore_pass"); - user = EditorSettings::get_singleton()->get("export/android/debug_keystore_user"); - } - - if (ep.step(vformat(TTR("Signing debug %s..."), export_label), 104)) { - return ERR_SKIP; - } - - } else { - keystore = release_keystore; - password = release_password; - user = release_username; - - if (ep.step(vformat(TTR("Signing release %s..."), export_label), 104)) { - return ERR_SKIP; - } - } - - if (!FileAccess::exists(keystore)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not find keystore, unable to export.")); - return ERR_FILE_CANT_OPEN; - } - - String output; - List args; - args.push_back("sign"); - args.push_back("--verbose"); - args.push_back("--ks"); - args.push_back(keystore); - args.push_back("--ks-pass"); - args.push_back("pass:" + password); - args.push_back("--ks-key-alias"); - args.push_back(user); - args.push_back(export_path); - if (p_debug) { - // We only print verbose logs for debug builds to avoid leaking release keystore credentials. - print_verbose("Signing debug binary using: " + String("\n") + apksigner + " " + join_list(args, String(" "))); - } - int retval; - output.clear(); - - Error err = OS::get_singleton()->execute(apksigner, args, true, nullptr, &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) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("'apksigner' returned with error #%d"), retval)); - return ERR_CANT_CREATE; - } - - if (ep.step(vformat(TTR("Verifying %s..."), export_label), 105)) { - return ERR_SKIP; - } - - args.clear(); - args.push_back("verify"); - args.push_back("--verbose"); - args.push_back(export_path); - if (p_debug) { - print_verbose("Verifying signed build using: " + String("\n") + apksigner + " " + join_list(args, String(" "))); - } - - output.clear(); - - err = OS::get_singleton()->execute(apksigner, args, true, nullptr, &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) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("'apksigner' verification of %s failed."), export_label)); - return ERR_CANT_CREATE; - } - - print_verbose("Successfully completed signing build."); - return OK; -} - -void EditorExportPlatformAndroid::_clear_assets_directory() { - DirAccessRef da_res = DirAccess::create(DirAccess::ACCESS_RESOURCES); - - // Clear the APK assets directory - if (da_res->dir_exists(APK_ASSETS_DIRECTORY)) { - print_verbose("Clearing APK assets directory.."); - DirAccessRef da_assets = DirAccess::open(APK_ASSETS_DIRECTORY); - da_assets->erase_contents_recursive(); - da_res->remove(APK_ASSETS_DIRECTORY); - } - - // Clear the AAB assets directory - if (da_res->dir_exists(AAB_ASSETS_DIRECTORY)) { - print_verbose("Clearing AAB assets directory.."); - DirAccessRef da_assets = DirAccess::open(AAB_ASSETS_DIRECTORY); - da_assets->erase_contents_recursive(); - da_res->remove(AAB_ASSETS_DIRECTORY); - } -} - -void EditorExportPlatformAndroid::_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.empty()) { - print_verbose("No previously installed libraries found"); - return; - } - - Variant result; - String error_string; - int error_line; - error = JSON::parse(libs_json, result, error_string, error_line); - ERR_FAIL_COND_MSG(error, "Error parsing \"" + libs_json + "\" on line " + itos(error_line) + ": " + error_string); - - Vector libs = result; - 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 EditorExportPlatformAndroid::join_list(List parts, const String &separator) const { - String ret; - for (int i = 0; i < parts.size(); ++i) { - if (i > 0) { - ret += separator; - } - ret += parts[i]; - } - return ret; -} - -Error EditorExportPlatformAndroid::export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags) { - int export_format = int(p_preset->get("custom_template/export_format")); - bool should_sign = p_preset->get("package/signed"); - return export_project_helper(p_preset, p_debug, p_path, export_format, should_sign, p_flags); -} - -Error EditorExportPlatformAndroid::export_project_helper(const Ref &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, int p_flags) { - ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); - - String src_apk; - Error err; - - EditorProgress ep("export", TTR("Exporting for Android"), 105, true); - - bool use_custom_build = bool(p_preset->get("custom_template/use_custom_build")); - bool p_give_internet = p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG); - bool apk_expansion = p_preset->get("apk_expansion/enable"); - Vector enabled_abis = get_enabled_abis(p_preset); - - print_verbose("Exporting for Android..."); - print_verbose("- debug build: " + bool_to_string(p_debug)); - print_verbose("- export path: " + p_path); - print_verbose("- export format: " + itos(export_format)); - print_verbose("- sign build: " + bool_to_string(should_sign)); - print_verbose("- custom build enabled: " + bool_to_string(use_custom_build)); - print_verbose("- apk expansion enabled: " + bool_to_string(apk_expansion)); - print_verbose("- enabled abis: " + String(",").join(enabled_abis)); - print_verbose("- export filter: " + itos(p_preset->get_export_filter())); - print_verbose("- include filter: " + p_preset->get_include_filter()); - print_verbose("- exclude filter: " + p_preset->get_exclude_filter()); - - Ref splash_image; - Ref splash_bg_color_image; - String processed_splash_config_xml = load_splash_refs(splash_image, splash_bg_color_image); - - Ref main_image; - Ref foreground; - Ref background; - - load_icon_refs(p_preset, main_image, foreground, background); - - Vector command_line_flags; - // Write command line flags into the command_line_flags variable. - get_command_line_flags(p_preset, p_path, p_flags, command_line_flags); - - if (export_format == EXPORT_FORMAT_AAB) { - if (!p_path.ends_with(".aab")) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Invalid filename! Android App Bundle requires the *.aab extension.")); - return ERR_UNCONFIGURED; - } - if (apk_expansion) { - 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")) { - 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) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Unsupported export format!")); - return ERR_UNCONFIGURED; - } - - if (use_custom_build) { - print_verbose("Starting custom build.."); - //test that installed build version is alright - { - print_verbose("Checking build version.."); - FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::READ); - if (!f) { - 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); - f->close(); - if (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; - } - } - const String assets_directory = get_assets_directory(p_preset, export_format); - String sdk_path = EDITOR_GET("export/android/android_sdk_path"); - ERR_FAIL_COND_V_MSG(sdk_path.empty(), ERR_UNCONFIGURED, "Android SDK path must be configured in Editor Settings at 'export/android/android_sdk_path'."); - print_verbose("Android sdk path: " + sdk_path); - - // TODO: should we use "package/name" or "application/config/name"? - 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) { - 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); - // Write an AndroidManifest.xml file into the Gradle project directory. - _write_tmp_manifest(p_preset, p_give_internet, p_debug); - _update_custom_build_project(); - //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.."); - CustomExportData user_data; - user_data.assets_directory = assets_directory; - 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) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not export project files to gradle project.")); - return err; - } - if (user_data.libs.size() > 0) { - FileAccessRef fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE); - fa->store_string(JSON::print(user_data.libs, "\t")); - fa->close(); - } - } else { - print_verbose("Saving apk expansion file.."); - err = save_apk_expansion_file(p_preset, p_path); - if (err != OK) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not write expansion package file!")); - return err; - } - } - print_verbose("Storing command line flags.."); - store_file_at_path(assets_directory + "/_cl_", command_line_flags); - - print_verbose("Updating ANDROID_HOME environment to " + sdk_path); - OS::get_singleton()->set_environment("ANDROID_HOME", sdk_path); //set and overwrite if required - String build_command; - -#ifdef WINDOWS_ENABLED - build_command = "gradlew.bat"; -#else - build_command = "gradlew"; -#endif - - String build_path = ProjectSettings::get_singleton()->get_resource_path().plus_file("android/build"); - build_command = build_path.plus_file(build_command); - - String package_name = get_package_name(p_preset->get("package/unique_name")); - String version_code = itos(p_preset->get("version/code")); - String version_name = p_preset->get("version/name"); - String min_sdk_version = itos(p_preset->get("version/min_sdk")); - String target_sdk_version = itos(p_preset->get("version/target_sdk")); - String enabled_abi_string = String("|").join(enabled_abis); - String sign_flag = should_sign ? "true" : "false"; - String zipalign_flag = "true"; - - Vector enabled_plugins = get_enabled_plugins(p_preset); - String local_plugins_binaries = PluginConfigAndroid::get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_LOCAL, enabled_plugins); - String remote_plugins_binaries = PluginConfigAndroid::get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_REMOTE, enabled_plugins); - String custom_maven_repos = PluginConfigAndroid::get_plugins_custom_maven_repos(enabled_plugins); - bool clean_build_required = is_clean_build_required(enabled_plugins); - - List cmdline; - if (clean_build_required) { - cmdline.push_back("clean"); - } - - String build_type = p_debug ? "Debug" : "Release"; - if (export_format == EXPORT_FORMAT_AAB) { - String bundle_build_command = vformat("bundle%s", build_type); - cmdline.push_back(bundle_build_command); - } else if (export_format == EXPORT_FORMAT_APK) { - String apk_build_command = vformat("assemble%s", build_type); - cmdline.push_back(apk_build_command); - } - - cmdline.push_back("-p"); // argument to specify the start directory. - cmdline.push_back(build_path); // start directory. - cmdline.push_back("-Pexport_package_name=" + package_name); // argument to specify the package name. - cmdline.push_back("-Pexport_version_code=" + version_code); // argument to specify the version code. - cmdline.push_back("-Pexport_version_name=" + version_name); // argument to specify the version name. - cmdline.push_back("-Pexport_version_min_sdk=" + min_sdk_version); // argument to specify the min sdk. - cmdline.push_back("-Pexport_version_target_sdk=" + target_sdk_version); // argument to specify the target sdk. - cmdline.push_back("-Pexport_enabled_abis=" + enabled_abi_string); // argument to specify enabled ABIs. - cmdline.push_back("-Pplugins_local_binaries=" + local_plugins_binaries); // argument to specify the list of plugins local dependencies. - cmdline.push_back("-Pplugins_remote_binaries=" + remote_plugins_binaries); // argument to specify the list of plugins remote dependencies. - cmdline.push_back("-Pplugins_maven_repos=" + custom_maven_repos); // argument to specify the list of custom maven repos for the plugins dependencies. - cmdline.push_back("-Pperform_zipalign=" + zipalign_flag); // argument to specify whether the build should be zipaligned. - cmdline.push_back("-Pperform_signing=" + sign_flag); // argument to specify whether the build should be signed. - cmdline.push_back("-Ppandemonium_editor_version=" + String(VERSION_FULL_CONFIG)); - - // NOTE: The release keystore is not included in the verbose logging - // to avoid accidentally leaking sensitive information when sharing verbose logs for troubleshooting. - // Any non-sensitive additions to the command line arguments must be done above this section. - // 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) { - 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.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"); - } - if (debug_keystore.is_rel_path()) { - debug_keystore = OS::get_singleton()->get_resource_dir().plus_file(debug_keystore).simplify_path(); - } - if (!FileAccess::exists(debug_keystore)) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Could not find keystore, unable to export.")); - return ERR_FILE_CANT_OPEN; - } - - 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 (release_keystore.is_rel_path()) { - release_keystore = OS::get_singleton()->get_resource_dir().plus_file(release_keystore).simplify_path(); - } - if (!FileAccess::exists(release_keystore)) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("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); - if (result != 0) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Building of Android project failed, check output for the error. Alternatively visit docs.pandemoniumengine.org for Android build documentation.")); - return ERR_CANT_CREATE; - } - - List copy_args; - String copy_command; - if (export_format == EXPORT_FORMAT_AAB) { - copy_command = vformat("copyAndRename%sAab", build_type); - } else if (export_format == EXPORT_FORMAT_APK) { - copy_command = vformat("copyAndRename%sApk", build_type); - } - - copy_args.push_back(copy_command); - - copy_args.push_back("-p"); // argument to specify the start directory. - copy_args.push_back(build_path); // start directory. - - String export_filename = p_path.get_file(); - String export_path = p_path.get_base_dir(); - if (export_path.is_rel_path()) { - export_path = OS::get_singleton()->get_resource_dir().plus_file(export_path); - } - export_path = ProjectSettings::get_singleton()->globalize_path(export_path).simplify_path(); - - copy_args.push_back("-Pexport_path=file:" + export_path); - copy_args.push_back("-Pexport_filename=" + export_filename); - - 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) { - 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; - } - - print_verbose("Successfully completed Android custom build."); - return OK; - } - // This is the start of the Legacy build system - print_verbose("Starting legacy build system.."); - if (p_debug) { - src_apk = p_preset->get("custom_template/debug"); - } else { - src_apk = p_preset->get("custom_template/release"); - } - - src_apk = src_apk.strip_edges(); - if (src_apk == "") { - if (p_debug) { - src_apk = find_export_template("android_debug.apk"); - } else { - src_apk = find_export_template("android_release.apk"); - } - if (src_apk == "") { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Package not found: \"%s\"."), src_apk)); - return ERR_FILE_NOT_FOUND; - } - } - - if (!DirAccess::exists(p_path.get_base_dir())) { - return ERR_FILE_BAD_PATH; - } - - FileAccess *src_f = nullptr; - zlib_filefunc_def io = zipio_create_io_from_file(&src_f); - - if (ep.step(TTR("Creating APK..."), 0)) { - return ERR_SKIP; - } - - unzFile pkg = unzOpen2(src_apk.utf8().get_data(), &io); - if (!pkg) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not find template APK to export: \"%s\"."), src_apk)); - return ERR_FILE_NOT_FOUND; - } - - int ret = unzGoToFirstFile(pkg); - - zlib_filefunc_def io2 = io; - FileAccess *dst_f = nullptr; - io2.opaque = &dst_f; - - String tmp_unaligned_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport-unaligned." + uitos(OS::get_singleton()->get_unix_time()) + ".apk"); - -#define CLEANUP_AND_RETURN(m_err) \ - { \ - DirAccess::remove_file_or_error(tmp_unaligned_path); \ - return m_err; \ - } - - zipFile unaligned_apk = zipOpen2(tmp_unaligned_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io2); - - String cmdline = p_preset->get("command_line/extra_args"); - - String version_name = p_preset->get("version/name"); - String package_name = p_preset->get("package/unique_name"); - - String apk_expansion_pkey = p_preset->get("apk_expansion/public_key"); - - Vector invalid_abis(enabled_abis); - while (ret == UNZ_OK) { - //get filename - unz_file_info info; - char fname[16384]; - ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); - - bool skip = false; - - String file = String::utf8(fname); - - Vector data; - data.resize(info.uncompressed_size); - - //read - unzOpenCurrentFile(pkg); - unzReadCurrentFile(pkg, data.ptrw(), data.size()); - unzCloseCurrentFile(pkg); - - //write - if (file == "AndroidManifest.xml") { - _fix_manifest(p_preset, data, p_give_internet); - } - if (file == "resources.arsc") { - _fix_resources(p_preset, data); - } - - // Process the splash image - if ((file == SPLASH_IMAGE_EXPORT_PATH || file == LEGACY_BUILD_SPLASH_IMAGE_EXPORT_PATH) && splash_image.is_valid() && !splash_image->empty()) { - _load_image_data(splash_image, data); - } - - // Process the splash bg color image - if ((file == SPLASH_BG_COLOR_PATH || file == LEGACY_BUILD_SPLASH_BG_COLOR_PATH) && splash_bg_color_image.is_valid() && !splash_bg_color_image->empty()) { - _load_image_data(splash_bg_color_image, data); - } - - for (int i = 0; i < icon_densities_count; ++i) { - if (main_image.is_valid() && !main_image->empty()) { - if (file == launcher_icons[i].export_path) { - _process_launcher_icons(file, main_image, launcher_icons[i].dimensions, data); - } - } - if (foreground.is_valid() && !foreground->empty()) { - if (file == launcher_adaptive_icon_foregrounds[i].export_path) { - _process_launcher_icons(file, foreground, launcher_adaptive_icon_foregrounds[i].dimensions, data); - } - } - if (background.is_valid() && !background->empty()) { - if (file == launcher_adaptive_icon_backgrounds[i].export_path) { - _process_launcher_icons(file, background, launcher_adaptive_icon_backgrounds[i].dimensions, data); - } - } - } - - if (file.ends_with(".so")) { - bool enabled = false; - for (int i = 0; i < enabled_abis.size(); ++i) { - if (file.begins_with("lib/" + enabled_abis[i] + "/")) { - invalid_abis.erase(enabled_abis[i]); - enabled = true; - break; - } - } - if (!enabled) { - skip = true; - } - } - - if (file.begins_with("META-INF") && should_sign) { - skip = true; - } - - if (!skip) { - print_line("ADDING: " + file); - - // Respect decision on compression made by AAPT for the export template - const bool uncompressed = info.compression_method == 0; - - zip_fileinfo zipfi = get_zip_fileinfo(); - - zipOpenNewFileInZip(unaligned_apk, - file.utf8().get_data(), - &zipfi, - nullptr, - 0, - nullptr, - 0, - nullptr, - uncompressed ? 0 : Z_DEFLATED, - Z_DEFAULT_COMPRESSION); - - zipWriteInFileInZip(unaligned_apk, data.ptr(), data.size()); - zipCloseFileInZip(unaligned_apk); - } - - ret = unzGoToNextFile(pkg); - } - - if (!invalid_abis.empty()) { - String unsupported_arch = String(", ").join(invalid_abis); - 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); - } - - if (ep.step(TTR("Adding files..."), 1)) { - CLEANUP_AND_RETURN(ERR_SKIP); - } - err = OK; - - if (p_flags & DEBUG_FLAG_DUMB_CLIENT) { - APKExportData ed; - ed.ep = &ep; - ed.apk = unaligned_apk; - err = export_project_files(p_preset, ignore_apk_file, &ed, save_apk_so); - } else { - if (apk_expansion) { - err = save_apk_expansion_file(p_preset, p_path); - if (err != OK) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not write expansion package file!")); - return err; - } - } else { - APKExportData ed; - ed.ep = &ep; - ed.apk = unaligned_apk; - err = export_project_files(p_preset, save_apk_file, &ed, save_apk_so); - } - } - - if (err != OK) { - unzClose(pkg); - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not export project files."))); - CLEANUP_AND_RETURN(ERR_SKIP); - } - - zip_fileinfo zipfi = get_zip_fileinfo(); - zipOpenNewFileInZip(unaligned_apk, - "assets/_cl_", - &zipfi, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, // No compress (little size gain and potentially slower startup) - Z_DEFAULT_COMPRESSION); - zipWriteInFileInZip(unaligned_apk, command_line_flags.ptr(), command_line_flags.size()); - zipCloseFileInZip(unaligned_apk); - - zipClose(unaligned_apk, nullptr); - unzClose(pkg); - - if (err != OK) { - CLEANUP_AND_RETURN(err); - } - - // Let's zip-align (must be done before signing) - - static const int ZIP_ALIGNMENT = 4; - - // If we're not signing the apk, then the next step should be the last. - const int next_step = should_sign ? 103 : 105; - if (ep.step(TTR("Aligning APK..."), next_step)) { - CLEANUP_AND_RETURN(ERR_SKIP); - } - - unzFile tmp_unaligned = unzOpen2(tmp_unaligned_path.utf8().get_data(), &io); - if (!tmp_unaligned) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not unzip temporary unaligned APK."))); - CLEANUP_AND_RETURN(ERR_FILE_NOT_FOUND); - } - - ret = unzGoToFirstFile(tmp_unaligned); - - io2 = io; - dst_f = nullptr; - io2.opaque = &dst_f; - zipFile final_apk = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io2); - - // Take files from the unaligned APK and write them out to the aligned one - // in raw mode, i.e. not uncompressing and recompressing, aligning them as needed, - // following what is done in https://github.com/android/platform_build/blob/master/tools/zipalign/ZipAlign.cpp - int bias = 0; - while (ret == UNZ_OK) { - unz_file_info info; - memset(&info, 0, sizeof(info)); - - char fname[16384]; - char extra[16384]; - ret = unzGetCurrentFileInfo(tmp_unaligned, &info, fname, 16384, extra, 16384 - ZIP_ALIGNMENT, nullptr, 0); - - String file = String::utf8(fname); - - Vector data; - data.resize(info.compressed_size); - - // read - int method, level; - unzOpenCurrentFile2(tmp_unaligned, &method, &level, 1); // raw read - long file_offset = unzGetCurrentFileZStreamPos64(tmp_unaligned); - unzReadCurrentFile(tmp_unaligned, data.ptrw(), data.size()); - unzCloseCurrentFile(tmp_unaligned); - - // align - int padding = 0; - if (!info.compression_method) { - // Uncompressed file => Align - long new_offset = file_offset + bias; - padding = (ZIP_ALIGNMENT - (new_offset % ZIP_ALIGNMENT)) % ZIP_ALIGNMENT; - } - - memset(extra + info.size_file_extra, 0, padding); - - zip_fileinfo fileinfo = get_zip_fileinfo(); - zipOpenNewFileInZip2(final_apk, - file.utf8().get_data(), - &fileinfo, - extra, - info.size_file_extra + padding, - nullptr, - 0, - nullptr, - method, - level, - 1); // raw write - zipWriteInFileInZip(final_apk, data.ptr(), data.size()); - zipCloseFileInZipRaw(final_apk, info.uncompressed_size, info.crc); - - bias += padding; - - ret = unzGoToNextFile(tmp_unaligned); - } - - zipClose(final_apk, nullptr); - unzClose(tmp_unaligned); - - if (should_sign) { - // Signing must be done last as any additional modifications to the - // file will invalidate the signature. - err = sign_apk(p_preset, p_debug, p_path, ep); - if (err != OK) { - CLEANUP_AND_RETURN(err); - } - } - - CLEANUP_AND_RETURN(OK); -} - -void EditorExportPlatformAndroid::get_platform_features(List *r_features) { - r_features->push_back("mobile"); - r_features->push_back("Android"); -} - -void EditorExportPlatformAndroid::resolve_platform_feature_priorities(const Ref &p_preset, RBSet &p_features) { -} - -EditorExportPlatformAndroid::EditorExportPlatformAndroid() { - Ref img = memnew(Image(_android_logo)); - logo.instance(); - logo->create_from_image(img); - - img = Ref(memnew(Image(_android_run_icon))); - run_icon.instance(); - run_icon->create_from_image(img); - - devices_changed.set(); - plugins_changed.set(); -#ifndef ANDROID_ENABLED - check_for_changes_thread.start(_check_for_changes_poll_thread, this); -#endif -} - -EditorExportPlatformAndroid::~EditorExportPlatformAndroid() { -#ifndef ANDROID_ENABLED - quit_request.set(); - check_for_changes_thread.wait_to_finish(); -#endif -} diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h deleted file mode 100644 index 0fd0d62..0000000 --- a/platform/android/export/export_plugin.h +++ /dev/null @@ -1,261 +0,0 @@ -/*************************************************************************/ -/* export_plugin.h */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "core/config/project_settings.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/os/safe_refcount.h" -#include "core/version.h" -#include "drivers/png/png_driver_common.h" -#include "editor/editor_export.h" -#include "editor/editor_log.h" -#include "editor/editor_node.h" -#include "editor/editor_settings.h" -#include "platform/android/logo.gen.h" -#include "platform/android/run_icon.gen.h" - -#include "gradle_export_util.h" -#include "pandemonium_plugin_config.h" - -#include - -const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH( - - - - - - -)SPLASH"; - -struct LauncherIcon { - const char *export_path; - int dimensions; -}; - -class EditorExportPlatformAndroid : public EditorExportPlatform { - GDCLASS(EditorExportPlatformAndroid, EditorExportPlatform); - - Ref logo; - Ref run_icon; - - struct Device { - String id; - String name; - String description; - int api_level; - }; - - struct APKExportData { - zipFile apk; - EditorProgress *ep; - }; - - Vector plugins; - String last_plugin_names; - uint64_t last_custom_build_time = 0; - SafeFlag plugins_changed; - Mutex plugins_lock; - Vector devices; - SafeFlag devices_changed; - Mutex device_lock; - -#ifndef ANDROID_ENABLED - Thread check_for_changes_thread; - SafeFlag quit_request; - - static void _check_for_changes_poll_thread(void *ud); -#endif - - String get_project_name(const String &p_name) const; - - String get_package_name(const String &p_package) const; - - String get_assets_directory(const Ref &p_preset, int p_export_format) const; - - bool is_package_name_valid(const String &p_package, String *r_error = nullptr) const; - - static bool _should_compress_asset(const String &p_path, const Vector &p_data); - - static zip_fileinfo get_zip_fileinfo(); - - static Vector get_abis(); - - /// List the gdap files in the directory specified by the p_path parameter. - static Vector list_gdap_files(const String &p_path); - - static Vector get_plugins(); - - static Vector get_enabled_plugins(const Ref &p_presets); - - static Error store_in_apk(APKExportData *ed, const String &p_path, const Vector &p_data, int compression_method = Z_DEFLATED); - - static Error save_apk_so(void *p_userdata, const SharedObject &p_so); - - static Error save_apk_file(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total); - - static Error ignore_apk_file(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total); - - static Error copy_gradle_so(void *p_userdata, const SharedObject &p_so); - - bool _has_read_write_storage_permission(const Vector &p_permissions); - - bool _has_manage_external_storage_permission(const Vector &p_permissions); - - void _get_permissions(const Ref &p_preset, bool p_give_internet, Vector &r_permissions); - - void _write_tmp_manifest(const Ref &p_preset, bool p_give_internet, bool p_debug); - - void _fix_manifest(const Ref &p_preset, Vector &p_manifest, bool p_give_internet); - - static String _parse_string(const uint8_t *p_bytes, bool p_utf8); - - void _fix_resources(const Ref &p_preset, Vector &r_manifest); - - void _load_image_data(const Ref &p_splash_image, Vector &p_data); - - void _process_launcher_icons(const String &p_file_name, const Ref &p_source_image, int dimension, Vector &p_data); - - String load_splash_refs(Ref &splash_image, Ref &splash_bg_color_image); - - void load_icon_refs(const Ref &p_preset, Ref &icon, Ref &foreground, Ref &background); - - void store_image(const LauncherIcon launcher_icon, const Vector &data); - - void store_image(const String &export_path, const Vector &data); - - void _copy_icons_to_gradle_project(const Ref &p_preset, - const String &processed_splash_config_xml, - const Ref &splash_image, - const Ref &splash_bg_color_image, - const Ref &main_image, - const Ref &foreground, - const Ref &background); - - static Vector get_enabled_abis(const Ref &p_preset); - -public: - typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total); - -public: - virtual void get_preset_features(const Ref &p_preset, List *r_features); - - virtual void get_export_options(List *r_options); - - virtual String get_name() const; - - virtual String get_os_name() const; - - virtual Ref get_logo() const; - - virtual bool should_update_export_options(); - - virtual bool poll_export(); - - virtual int get_options_count() const; - - virtual String get_options_tooltip() const; - - virtual String get_option_label(int p_index) const; - - virtual String get_option_tooltip(int p_index) const; - - virtual Error run(const Ref &p_preset, int p_device, int p_debug_flags); - - virtual Ref get_run_icon() const; - - static String get_adb_path(); - - static String get_apksigner_path(); - - virtual bool has_valid_export_configuration(const Ref &p_preset, String &r_error, bool &r_missing_templates) const; - virtual bool has_valid_project_configuration(const Ref &p_preset, String &r_error) const; - - virtual List get_binary_extensions(const Ref &p_preset) const; - - void _update_custom_build_project(); - - inline bool is_clean_build_required(Vector enabled_plugins) { - String plugin_names = PluginConfigAndroid::get_plugins_names(enabled_plugins); - bool first_build = last_custom_build_time == 0; - bool have_plugins_changed = false; - - if (!first_build) { - have_plugins_changed = plugin_names != last_plugin_names; - if (!have_plugins_changed) { - for (int i = 0; i < enabled_plugins.size(); i++) { - if (enabled_plugins.get(i).last_updated > last_custom_build_time) { - have_plugins_changed = true; - break; - } - } - } - } - - last_custom_build_time = OS::get_singleton()->get_unix_time(); - last_plugin_names = plugin_names; - - return have_plugins_changed || first_build; - } - - String get_apk_expansion_fullpath(const Ref &p_preset, const String &p_path); - - Error save_apk_expansion_file(const Ref &p_preset, const String &p_path); - - void get_command_line_flags(const Ref &p_preset, const String &p_path, int p_flags, Vector &r_command_line_flags); - - Error sign_apk(const Ref &p_preset, bool p_debug, const String &export_path, EditorProgress &ep); - - void _clear_assets_directory(); - - void _remove_copied_libs(); - - String join_list(List parts, const String &separator) const; - - virtual Error export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags = 0); - - Error export_project_helper(const Ref &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, int p_flags); - - virtual void get_platform_features(List *r_features); - - virtual void resolve_platform_feature_priorities(const Ref &p_preset, RBSet &p_features); - - EditorExportPlatformAndroid(); - - ~EditorExportPlatformAndroid(); -}; diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp deleted file mode 100644 index d93c459..0000000 --- a/platform/android/export/gradle_export_util.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/*************************************************************************/ -/* gradle_export_util.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "gradle_export_util.h" - -#include "core/config/project_settings.h" - -int _get_android_orientation_value(OS::ScreenOrientation screen_orientation) { - switch (screen_orientation) { - case OS::SCREEN_PORTRAIT: - return 1; - case OS::SCREEN_REVERSE_LANDSCAPE: - return 8; - case OS::SCREEN_REVERSE_PORTRAIT: - return 9; - case OS::SCREEN_SENSOR_LANDSCAPE: - return 11; - case OS::SCREEN_SENSOR_PORTRAIT: - return 12; - case OS::SCREEN_SENSOR: - return 13; - case OS::SCREEN_LANDSCAPE: - default: - return 0; - } -} - -String _get_android_orientation_label(OS::ScreenOrientation screen_orientation) { - switch (screen_orientation) { - case OS::SCREEN_PORTRAIT: - return "portrait"; - case OS::SCREEN_REVERSE_LANDSCAPE: - return "reverseLandscape"; - case OS::SCREEN_REVERSE_PORTRAIT: - return "reversePortrait"; - case OS::SCREEN_SENSOR_LANDSCAPE: - return "userLandscape"; - case OS::SCREEN_SENSOR_PORTRAIT: - return "userPortrait"; - case OS::SCREEN_SENSOR: - return "fullUser"; - case OS::SCREEN_LANDSCAPE: - default: - return "landscape"; - } -} - -// Utility method used to create a directory. -Error create_directory(const String &p_dir) { - if (!DirAccess::exists(p_dir)) { - DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_RESOURCES); - ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'."); - Error err = filesystem_da->make_dir_recursive(p_dir); - ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'."); - memdelete(filesystem_da); - } - 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 &p_data) { - String dir = p_path.get_base_dir(); - Error err = create_directory(dir); - if (err != OK) { - return err; - } - FileAccess *fa = FileAccess::open(p_path, FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create file '" + p_path + "'."); - fa->store_buffer(p_data.ptr(), p_data.size()); - memdelete(fa); - return OK; -} - -// Writes string 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_string_at_path(const String &p_path, const String &p_data) { - String dir = p_path.get_base_dir(); - Error err = create_directory(dir); - if (err != OK) { - if (OS::get_singleton()->is_stdout_verbose()) { - print_error("Unable to write data into " + p_path); - } - return err; - } - FileAccess *fa = FileAccess::open(p_path, FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create file '" + p_path + "'."); - fa->store_string(p_data); - memdelete(fa); - return OK; -} - -// Implementation of EditorExportSaveFunction. -// This method will only be called as an input to export_project_files. -// It is used by the export_project_files method to save all the asset files into the gradle project. -// It's functionality mirrors that of the method save_apk_file. -// This method will be called ONLY when custom build is enabled. -Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total) { - CustomExportData *export_data = (CustomExportData *)p_userdata; - String dst_path = p_path.replace_first("res://", export_data->assets_directory + "/"); - print_verbose("Saving project files from " + p_path + " into " + dst_path); - Error err = store_file_at_path(dst_path, p_data); - return err; -} - -String _android_xml_escape(const String &p_string) { - // Android XML requires strings to be both valid XML (`xml_escape()`) but also - // to escape characters which are valid XML but have special meaning in Android XML. - // https://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling - // Note: Didn't handle U+XXXX unicode chars, could be done if needed. - return p_string - .replace("@", "\\@") - .replace("?", "\\?") - .replace("'", "\\'") - .replace("\"", "\\\"") - .replace("\n", "\\n") - .replace("\t", "\\t") - .xml_escape(false); -} - -// Creates strings.xml files inside the gradle project for different locales. -Error _create_project_name_strings_files(const Ref &p_preset, const String &project_name) { - print_verbose("Creating strings resources for supported locales for project " + project_name); - // Stores the string into the default values directory. - String processed_default_xml_string = vformat(pandemonium_project_name_xml_string, _android_xml_escape(project_name)); - store_string_at_path("res://android/build/res/values/pandemonium_project_name_string.xml", processed_default_xml_string); - - // Searches the Gradle project res/ directory to find all supported locales - DirAccessRef da = DirAccess::open("res://android/build/res"); - if (!da) { - if (OS::get_singleton()->is_stdout_verbose()) { - print_error("Unable to open Android resources directory."); - } - return ERR_CANT_OPEN; - } - da->list_dir_begin(); - while (true) { - String file = da->get_next(); - if (file == "") { - break; - } - if (!file.begins_with("values-")) { - // NOTE: This assumes all directories that start with "values-" are for localization. - continue; - } - String locale = file.replace("values-", "").replace("-r", "_"); - String property_name = "application/config/name_" + locale; - String locale_directory = "res://android/build/res/" + file + "/pandemonium_project_name_string.xml"; - if (ProjectSettings::get_singleton()->has_setting(property_name)) { - String locale_project_name = ProjectSettings::get_singleton()->get(property_name); - String processed_xml_string = vformat(pandemonium_project_name_xml_string, _android_xml_escape(locale_project_name)); - print_verbose("Storing project name for locale " + locale + " under " + locale_directory); - store_string_at_path(locale_directory, processed_xml_string); - } else { - // TODO: Once the legacy build system is deprecated we don't need to have xml files for this else branch - store_string_at_path(locale_directory, processed_default_xml_string); - } - } - da->list_dir_end(); - return OK; -} - -String bool_to_string(bool v) { - return v ? "true" : "false"; -} - -String _get_gles_tag() { - bool min_gles3 = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name") == "GLES3" && - !ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2"); - return min_gles3 ? " \n" : ""; -} - -String _get_screen_sizes_tag(const Ref &p_preset) { - String manifest_screen_sizes = " get(feature_name)); - String xml_entry = vformat("\n android:%sScreens=\"%s\"", sizes[i], feature_support); - manifest_screen_sizes += xml_entry; - } - manifest_screen_sizes += " />\n"; - return manifest_screen_sizes; -} - -String _get_activity_tag(const Ref &p_preset) { - String orientation = _get_android_orientation_label( - OS::get_singleton()->get_screen_orientation_from_string(GLOBAL_GET("display/window/handheld/orientation"))); - String manifest_activity_text = vformat( - " \n", - bool_to_string(p_preset->get("package/exclude_from_recents")), - orientation, - bool_to_string(bool(GLOBAL_GET("display/window/size/resizable")))); - manifest_activity_text += " \n"; - manifest_activity_text += " \n"; - return manifest_activity_text; -} - -String _get_application_tag(const Ref &p_preset, bool p_has_read_write_storage_permission) { - String manifest_application_text = vformat( - " \n\n", - bool_to_string(p_preset->get("user_data_backup/allow")), - bool_to_string(p_preset->get("package/classify_as_game")), - bool_to_string(p_preset->get("package/retain_data_on_uninstall")), - bool_to_string(p_has_read_write_storage_permission)); - - manifest_application_text += " \n"; - manifest_application_text += _get_activity_tag(p_preset); - manifest_application_text += " \n"; - return manifest_application_text; -} diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h deleted file mode 100644 index 7b0d045..0000000 --- a/platform/android/export/gradle_export_util.h +++ /dev/null @@ -1,88 +0,0 @@ -/*************************************************************************/ -/* gradle_export_util.h */ -/*************************************************************************/ -/* This file is part of: */ -/* PANDEMONIUM 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. */ -/*************************************************************************/ - -#ifndef PANDEMONIUM_GRADLE_EXPORT_UTIL_H -#define PANDEMONIUM_GRADLE_EXPORT_UTIL_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" - -const String pandemonium_project_name_xml_string = R"( - - - %s - -)"; - -struct CustomExportData { - String assets_directory; - bool debug; - Vector libs; -}; - -int _get_android_orientation_value(OS::ScreenOrientation screen_orientation); - -String _get_android_orientation_label(OS::ScreenOrientation screen_orientation); - -// Utility method used to create a directory. -Error create_directory(const String &p_dir); - -// 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 &p_data); - -// Writes string 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_string_at_path(const String &p_path, const String &p_data); - -// Implementation of EditorExportSaveFunction. -// This method will only be called as an input to export_project_files. -// It is used by the export_project_files method to save all the asset files into the gradle project. -// It's functionality mirrors that of the method save_apk_file. -// This method will be called ONLY when custom build is enabled. -Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total); - -// Creates strings.xml files inside the gradle project for different locales. -Error _create_project_name_strings_files(const Ref &p_preset, const String &project_name); - -String bool_to_string(bool v); - -String _get_gles_tag(); - -String _get_screen_sizes_tag(const Ref &p_preset); - -String _get_activity_tag(const Ref &p_preset); - -String _get_application_tag(const Ref &p_preset, bool p_has_read_write_storage_permission); - -#endif //PANDEMONIUM_GRADLE_EXPORT_UTIL_H diff --git a/platform/android/export/pandemonium_plugin_config.cpp b/platform/android/export/pandemonium_plugin_config.cpp deleted file mode 100644 index 234f974..0000000 --- a/platform/android/export/pandemonium_plugin_config.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/*************************************************************************/ -/* pandemonium_plugin_config.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "pandemonium_plugin_config.h" - -const char *PluginConfigAndroid::PLUGIN_CONFIG_EXT = ".gdap"; - -const char *PluginConfigAndroid::CONFIG_SECTION = "config"; -const char *PluginConfigAndroid::CONFIG_NAME_KEY = "name"; -const char *PluginConfigAndroid::CONFIG_BINARY_TYPE_KEY = "binary_type"; -const char *PluginConfigAndroid::CONFIG_BINARY_KEY = "binary"; - -const char *PluginConfigAndroid::DEPENDENCIES_SECTION = "dependencies"; -const char *PluginConfigAndroid::DEPENDENCIES_LOCAL_KEY = "local"; -const char *PluginConfigAndroid::DEPENDENCIES_REMOTE_KEY = "remote"; -const char *PluginConfigAndroid::DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY = "custom_maven_repos"; - -const char *PluginConfigAndroid::BINARY_TYPE_LOCAL = "local"; -const char *PluginConfigAndroid::BINARY_TYPE_REMOTE = "remote"; - -const char *PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR = "|"; - -/* - * Set of prebuilt plugins. - * Currently unused, this is just for future reference: - */ -// static const PluginConfigAndroid MY_PREBUILT_PLUGIN = { -// /*.valid_config =*/true, -// /*.last_updated =*/0, -// /*.name =*/"PandemoniumPayment", -// /*.binary_type =*/"local", -// /*.binary =*/"res://android/build/libs/plugins/PandemoniumPayment.release.aar", -// /*.local_dependencies =*/{}, -// /*.remote_dependencies =*/String("com.android.billingclient:billing:2.2.1").split("|"), -// /*.custom_maven_repos =*/{} -// }; - -String PluginConfigAndroid::resolve_local_dependency_path(String plugin_config_dir, String dependency_path) { - String absolute_path; - if (!dependency_path.empty()) { - if (dependency_path.is_abs_path()) { - absolute_path = ProjectSettings::get_singleton()->globalize_path(dependency_path); - } else { - absolute_path = plugin_config_dir.plus_file(dependency_path); - } - } - - return absolute_path; -} - -PluginConfigAndroid PluginConfigAndroid::resolve_prebuilt_plugin(PluginConfigAndroid prebuilt_plugin, String plugin_config_dir) { - PluginConfigAndroid resolved = prebuilt_plugin; - resolved.binary = resolved.binary_type == PluginConfigAndroid::BINARY_TYPE_LOCAL ? resolve_local_dependency_path(plugin_config_dir, prebuilt_plugin.binary) : prebuilt_plugin.binary; - if (!prebuilt_plugin.local_dependencies.empty()) { - resolved.local_dependencies.clear(); - for (int i = 0; i < prebuilt_plugin.local_dependencies.size(); i++) { - resolved.local_dependencies.push_back(resolve_local_dependency_path(plugin_config_dir, prebuilt_plugin.local_dependencies[i])); - } - } - return resolved; -} - -Vector PluginConfigAndroid::get_prebuilt_plugins(String plugins_base_dir) { - Vector prebuilt_plugins; - // prebuilt_plugins.push_back(resolve_prebuilt_plugin(MY_PREBUILT_PLUGIN, plugins_base_dir)); - return prebuilt_plugins; -} - -bool PluginConfigAndroid::is_plugin_config_valid(PluginConfigAndroid plugin_config) { - bool valid_name = !plugin_config.name.empty(); - bool valid_binary_type = plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_LOCAL || - plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_REMOTE; - - bool valid_binary = false; - if (valid_binary_type) { - valid_binary = !plugin_config.binary.empty() && - (plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_REMOTE || - FileAccess::exists(plugin_config.binary)); - } - - bool valid_local_dependencies = true; - if (!plugin_config.local_dependencies.empty()) { - for (int i = 0; i < plugin_config.local_dependencies.size(); i++) { - if (!FileAccess::exists(plugin_config.local_dependencies[i])) { - valid_local_dependencies = false; - break; - } - } - } - return valid_name && valid_binary && valid_binary_type && valid_local_dependencies; -} - -uint64_t PluginConfigAndroid::get_plugin_modification_time(const PluginConfigAndroid &plugin_config, const String &config_path) { - uint64_t last_modified = FileAccess::get_modified_time(config_path); - last_modified = MAX(last_modified, FileAccess::get_modified_time(plugin_config.binary)); - - for (int i = 0; i < plugin_config.local_dependencies.size(); i++) { - String local_dependency = plugin_config.local_dependencies.get(i); - last_modified = MAX(last_modified, FileAccess::get_modified_time(local_dependency)); - } - - return last_modified; -} - -PluginConfigAndroid PluginConfigAndroid::load_plugin_config(Ref config_file, const String &path) { - PluginConfigAndroid plugin_config = {}; - - if (config_file.is_valid()) { - Error err = config_file->load(path); - if (err == OK) { - String config_base_dir = path.get_base_dir(); - - plugin_config.name = config_file->get_value(PluginConfigAndroid::CONFIG_SECTION, PluginConfigAndroid::CONFIG_NAME_KEY, String()); - plugin_config.binary_type = config_file->get_value(PluginConfigAndroid::CONFIG_SECTION, PluginConfigAndroid::CONFIG_BINARY_TYPE_KEY, String()); - - String binary_path = config_file->get_value(PluginConfigAndroid::CONFIG_SECTION, PluginConfigAndroid::CONFIG_BINARY_KEY, String()); - plugin_config.binary = plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_LOCAL ? resolve_local_dependency_path(config_base_dir, binary_path) : binary_path; - - if (config_file->has_section(PluginConfigAndroid::DEPENDENCIES_SECTION)) { - Vector local_dependencies_paths = config_file->get_value(PluginConfigAndroid::DEPENDENCIES_SECTION, PluginConfigAndroid::DEPENDENCIES_LOCAL_KEY, Vector()); - if (!local_dependencies_paths.empty()) { - for (int i = 0; i < local_dependencies_paths.size(); i++) { - plugin_config.local_dependencies.push_back(resolve_local_dependency_path(config_base_dir, local_dependencies_paths[i])); - } - } - - plugin_config.remote_dependencies = config_file->get_value(PluginConfigAndroid::DEPENDENCIES_SECTION, PluginConfigAndroid::DEPENDENCIES_REMOTE_KEY, Vector()); - plugin_config.custom_maven_repos = config_file->get_value(PluginConfigAndroid::DEPENDENCIES_SECTION, PluginConfigAndroid::DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY, Vector()); - } - - plugin_config.valid_config = is_plugin_config_valid(plugin_config); - plugin_config.last_updated = get_plugin_modification_time(plugin_config, path); - } - } - - return plugin_config; -} - -String PluginConfigAndroid::get_plugins_binaries(String type, Vector plugins_configs) { - String plugins_binaries; - if (!plugins_configs.empty()) { - Vector binaries; - for (int i = 0; i < plugins_configs.size(); i++) { - PluginConfigAndroid config = plugins_configs[i]; - if (!config.valid_config) { - continue; - } - - if (config.binary_type == type) { - binaries.push_back(config.binary); - } - - if (type == PluginConfigAndroid::BINARY_TYPE_LOCAL) { - binaries.append_array(config.local_dependencies); - } - - if (type == PluginConfigAndroid::BINARY_TYPE_REMOTE) { - binaries.append_array(config.remote_dependencies); - } - } - - plugins_binaries = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(binaries); - } - - return plugins_binaries; -} - -String PluginConfigAndroid::get_plugins_custom_maven_repos(Vector plugins_configs) { - String maven_repos; - if (!plugins_configs.empty()) { - Vector repos_urls; - for (int i = 0; i < plugins_configs.size(); i++) { - PluginConfigAndroid config = plugins_configs[i]; - if (!config.valid_config) { - continue; - } - - repos_urls.append_array(config.custom_maven_repos); - } - - maven_repos = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(repos_urls); - } - return maven_repos; -} - -String PluginConfigAndroid::get_plugins_names(Vector plugins_configs) { - String plugins_names; - if (!plugins_configs.empty()) { - Vector names; - for (int i = 0; i < plugins_configs.size(); i++) { - PluginConfigAndroid config = plugins_configs[i]; - if (!config.valid_config) { - continue; - } - - names.push_back(config.name); - } - plugins_names = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(names); - } - - return plugins_names; -} diff --git a/platform/android/export/pandemonium_plugin_config.h b/platform/android/export/pandemonium_plugin_config.h deleted file mode 100644 index f1afa39..0000000 --- a/platform/android/export/pandemonium_plugin_config.h +++ /dev/null @@ -1,106 +0,0 @@ -/*************************************************************************/ -/* pandemonium_plugin_config.h */ -/*************************************************************************/ -/* This file is part of: */ -/* PANDEMONIUM 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. */ -/*************************************************************************/ - -#ifndef ANDROID_PANDEMONIUM_PLUGIN_CONFIG_H -#define ANDROID_PANDEMONIUM_PLUGIN_CONFIG_H - -#include "core/error/error_list.h" -#include "core/io/config_file.h" -#include "core/config/project_settings.h" -#include "core/string/ustring.h" - -/* - 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. -- **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.pandemonium.example:my-plugin:0.0.0"). - -The `dependencies` section and fields are optional and defined as follow: -- **local**: contains a list of local `.aar` binary files the plugin depends on. The local binary dependencies must also be located in the `res://android/plugins` directory. -- **remote**: contains a list of remote binary gradle dependencies for the plugin. -- **custom_maven_repos**: contains a list of urls specifying custom maven repos required for the plugin's dependencies. - - See https://github.com/pandemoniumengine/pandemonium/issues/38157#issuecomment-618773871 - */ -struct PluginConfigAndroid { - static const char *PLUGIN_CONFIG_EXT; - - static const char *CONFIG_SECTION; - static const char *CONFIG_NAME_KEY; - static const char *CONFIG_BINARY_TYPE_KEY; - static const char *CONFIG_BINARY_KEY; - - static const char *DEPENDENCIES_SECTION; - static const char *DEPENDENCIES_LOCAL_KEY; - static const char *DEPENDENCIES_REMOTE_KEY; - static const char *DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY; - - static const char *BINARY_TYPE_LOCAL; - static const char *BINARY_TYPE_REMOTE; - - static const char *PLUGIN_VALUE_SEPARATOR; - - // Set to true when the config file is properly loaded. - bool valid_config = false; - // Unix timestamp of last change to this plugin. - uint64_t last_updated = 0; - - // Required config section - String name; - String binary_type; - String binary; - - // Optional dependencies section - Vector local_dependencies; - Vector remote_dependencies; - Vector custom_maven_repos; - - static String resolve_local_dependency_path(String plugin_config_dir, String dependency_path); - - static PluginConfigAndroid resolve_prebuilt_plugin(PluginConfigAndroid prebuilt_plugin, String plugin_config_dir); - - static Vector get_prebuilt_plugins(String plugins_base_dir); - - static bool is_plugin_config_valid(PluginConfigAndroid plugin_config); - - static uint64_t get_plugin_modification_time(const PluginConfigAndroid &plugin_config, const String &config_path); - - static PluginConfigAndroid load_plugin_config(Ref config_file, const String &path); - - static String get_plugins_binaries(String type, Vector plugins_configs); - - static String get_plugins_custom_maven_repos(Vector plugins_configs); - - static String get_plugins_names(Vector plugins_configs); -}; - -#endif // ANDROID_PANDEMONIUM_PLUGIN_CONFIG_H diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp deleted file mode 100644 index b16353e..0000000 --- a/platform/android/file_access_android.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/*************************************************************************/ -/* file_access_android.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "file_access_android.h" -#include "core/string/print_string.h" - -AAssetManager *FileAccessAndroid::asset_manager = NULL; - -String FileAccessAndroid::get_path() const { - return path_src; -} - -String FileAccessAndroid::get_path_absolute() const { - return absolute_path; -} - -Error FileAccessAndroid::_open(const String &p_path, int p_mode_flags) { - path_src = p_path; - - String path = fix_path(p_path).simplify_path(); - absolute_path = path; - - if (path.begins_with("/")) { - path = path.substr(1, path.length()); - } else if (path.begins_with("res://")) { - path = path.substr(6, path.length()); - } - - 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) { - return ERR_CANT_OPEN; - } - - //ERR_FAIL_COND_V(!a,ERR_FILE_NOT_FOUND); - len = AAsset_getLength(a); - pos = 0; - eof = false; - - return OK; -} - -void FileAccessAndroid::close() { - if (!a) { - return; - } - - AAsset_close(a); - a = NULL; -} - -bool FileAccessAndroid::is_open() const { - return a != NULL; -} - -void FileAccessAndroid::seek(uint64_t p_position) { - ERR_FAIL_COND(!a); - - AAsset_seek(a, p_position, SEEK_SET); - pos = p_position; - if (pos > len) { - pos = len; - eof = true; - } else { - eof = false; - } -} - -void FileAccessAndroid::seek_end(int64_t p_position) { - ERR_FAIL_COND(!a); - AAsset_seek(a, p_position, SEEK_END); - pos = len + p_position; -} - -uint64_t FileAccessAndroid::get_position() const { - return pos; -} - -uint64_t FileAccessAndroid::get_len() const { - return len; -} - -bool FileAccessAndroid::eof_reached() const { - return eof; -} - -uint8_t FileAccessAndroid::get_8() const { - if (pos >= len) { - eof = true; - return 0; - } - - uint8_t byte; - AAsset_read(a, &byte, 1); - pos++; - return byte; -} - -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); - - if (pos + p_length > len) { - eof = true; - } - - if (r >= 0) { - pos += r; - if (pos > len) { - pos = len; - } - } - return r; -} - -Error FileAccessAndroid::get_error() const { - return eof ? ERR_FILE_EOF : OK; // not sure what else it may happen -} - -void FileAccessAndroid::flush() { - ERR_FAIL(); -} - -void FileAccessAndroid::store_8(uint8_t p_dest) { - ERR_FAIL(); -} - -bool FileAccessAndroid::file_exists(const String &p_path) { - String path = fix_path(p_path).simplify_path(); - if (path.begins_with("/")) - path = path.substr(1, path.length()); - else if (path.begins_with("res://")) - path = path.substr(6, path.length()); - - AAsset *at = AAssetManager_open(asset_manager, path.utf8().get_data(), AASSET_MODE_STREAMING); - - if (!at) - return false; - - AAsset_close(at); - return true; -} - -FileAccessAndroid::FileAccessAndroid() { - a = NULL; - eof = false; -} - -FileAccessAndroid::~FileAccessAndroid() { - close(); -} diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h deleted file mode 100644 index def4c3b..0000000 --- a/platform/android/file_access_android.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef FILE_ACCESS_ANDROID_H -#define FILE_ACCESS_ANDROID_H -/*************************************************************************/ -/* file_access_android.h */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "core/os/file_access.h" -#include -#include -#include -//#include - -class FileAccessAndroid : public FileAccess { - mutable AAsset *a; - mutable uint64_t len; - mutable uint64_t pos; - mutable bool eof; - - String absolute_path; - String path_src; - -public: - static AAssetManager *asset_manager; - - virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual void close(); ///< close a file - virtual bool is_open() const; ///< true when file is open - - /// returns the path for the current open file - virtual String get_path() const; - /// returns the absolute path for the current open file - virtual String get_path_absolute() const; - - 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_len() const; ///< get size of the file - - virtual bool eof_reached() const; ///< reading passed EOF - - 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 void flush(); - 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 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(); - ~FileAccessAndroid(); -}; - -#endif // FILE_ACCESS_ANDROID_H diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp deleted file mode 100644 index df23ffc..0000000 --- a/platform/android/file_access_filesystem_jandroid.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/*************************************************************************/ -/* file_access_filesystem_jandroid.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "file_access_filesystem_jandroid.h" - -#include "core/os/os.h" -#include "thread_jandroid.h" - -#include - -jobject FileAccessFilesystemJAndroid::file_access_handler = nullptr; -jclass FileAccessFilesystemJAndroid::cls; - -jmethodID FileAccessFilesystemJAndroid::_file_open = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_get_size = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_seek = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_seek_end = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_read = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_tell = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_eof = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_set_eof = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_close = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_write = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_flush = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_exists = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_last_modified = nullptr; - -String FileAccessFilesystemJAndroid::get_path() const { - return path_src; -} - -String FileAccessFilesystemJAndroid::get_path_absolute() const { - return absolute_path; -} - -Error FileAccessFilesystemJAndroid::_open(const String &p_path, int p_mode_flags) { - if (is_open()) { - close(); - } - - if (_file_open) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED); - - String path = fix_path(p_path).simplify_path(); - jstring js = env->NewStringUTF(path.utf8().get_data()); - int res = env->CallIntMethod(file_access_handler, _file_open, js, p_mode_flags); - env->DeleteLocalRef(js); - - if (res <= 0) { - switch (res) { - case 0: - default: - return ERR_FILE_CANT_OPEN; - - case -1: - return ERR_FILE_NOT_FOUND; - } - } - - id = res; - path_src = p_path; - absolute_path = path; - return OK; - } else { - return ERR_UNCONFIGURED; - } -} - -void FileAccessFilesystemJAndroid::close() { - if (!is_open()) { - return; - } - - if (_file_close) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - env->CallVoidMethod(file_access_handler, _file_close, id); - } - id = 0; -} - -bool FileAccessFilesystemJAndroid::is_open() const { - return id != 0; -} - -void FileAccessFilesystemJAndroid::seek(uint64_t p_position) { - if (_file_seek) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use."); - env->CallVoidMethod(file_access_handler, _file_seek, id, p_position); - } -} - -void FileAccessFilesystemJAndroid::seek_end(int64_t p_position) { - if (_file_seek_end) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use."); - env->CallVoidMethod(file_access_handler, _file_seek_end, id, p_position); - } -} - -uint64_t FileAccessFilesystemJAndroid::get_position() const { - if (_file_tell) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); - return env->CallLongMethod(file_access_handler, _file_tell, id); - } else { - return 0; - } -} - -uint64_t FileAccessFilesystemJAndroid::get_len() const { - if (_file_get_size) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); - return env->CallLongMethod(file_access_handler, _file_get_size, id); - } else { - return 0; - } -} - -bool FileAccessFilesystemJAndroid::eof_reached() const { - if (_file_eof) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - ERR_FAIL_COND_V_MSG(!is_open(), false, "File must be opened before use."); - return env->CallBooleanMethod(file_access_handler, _file_eof, id); - } else { - return false; - } -} - -void FileAccessFilesystemJAndroid::_set_eof(bool eof) { - if (_file_set_eof) { - ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use."); - - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - env->CallVoidMethod(file_access_handler, _file_set_eof, id, eof); - } -} - -uint8_t FileAccessFilesystemJAndroid::get_8() const { - ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); - uint8_t byte; - get_buffer(&byte, 1); - return byte; -} - -String FileAccessFilesystemJAndroid::get_line() const { - ERR_FAIL_COND_V_MSG(!is_open(), String(), "File must be opened before use."); - - const size_t buffer_size_limit = 2048; - const uint64_t file_size = get_len(); - const uint64_t start_position = get_position(); - - String result; - LocalVector line_buffer; - size_t current_buffer_size = 0; - uint64_t line_buffer_position = 0; - - while (true) { - size_t line_buffer_size = MIN(buffer_size_limit, file_size - get_position()); - if (line_buffer_size <= 0) { - const_cast(this)->_set_eof(true); - break; - } - - current_buffer_size += line_buffer_size; - line_buffer.resize(current_buffer_size); - - uint64_t bytes_read = get_buffer(&line_buffer[line_buffer_position], current_buffer_size - line_buffer_position); - if (bytes_read <= 0) { - break; - } - - for (; bytes_read > 0; line_buffer_position++, bytes_read--) { - uint8_t elem = line_buffer[line_buffer_position]; - if (elem == '\n' || elem == '\0') { - // Found the end of the line - const_cast(this)->seek(start_position + line_buffer_position + 1); - if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position, true)) { - return String(); - } - return result; - } - } - } - - if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position, true)) { - return String(); - } - return result; -} - -uint64_t FileAccessFilesystemJAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const { - if (_file_read) { - ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); - if (p_length == 0) { - return 0; - } - - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - - jobject j_buffer = env->NewDirectByteBuffer(p_dst, p_length); - int length = env->CallIntMethod(file_access_handler, _file_read, id, j_buffer); - env->DeleteLocalRef(j_buffer); - return length; - } else { - return 0; - } -} - -void FileAccessFilesystemJAndroid::store_8(uint8_t p_dest) { - store_buffer(&p_dest, 1); -} - -void FileAccessFilesystemJAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) { - if (_file_write) { - ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use."); - if (p_length == 0) { - return; - } - - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - - jobject j_buffer = env->NewDirectByteBuffer((void *)p_src, p_length); - env->CallVoidMethod(file_access_handler, _file_write, id, j_buffer); - env->DeleteLocalRef(j_buffer); - } -} - -Error FileAccessFilesystemJAndroid::get_error() const { - if (eof_reached()) { - return ERR_FILE_EOF; - } - return OK; -} - -void FileAccessFilesystemJAndroid::flush() { - if (_file_flush) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use."); - env->CallVoidMethod(file_access_handler, _file_flush, id); - } -} - -bool FileAccessFilesystemJAndroid::file_exists(const String &p_path) { - if (_file_exists) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - - String path = fix_path(p_path).simplify_path(); - jstring js = env->NewStringUTF(path.utf8().get_data()); - bool result = env->CallBooleanMethod(file_access_handler, _file_exists, js); - env->DeleteLocalRef(js); - return result; - } else { - return false; - } -} - -uint64_t FileAccessFilesystemJAndroid::_get_modified_time(const String &p_file) { - if (_file_last_modified) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - - String path = fix_path(p_file).simplify_path(); - jstring js = env->NewStringUTF(path.utf8().get_data()); - uint64_t result = env->CallLongMethod(file_access_handler, _file_last_modified, js); - env->DeleteLocalRef(js); - return result; - } else { - return 0; - } -} - -void FileAccessFilesystemJAndroid::setup(jobject p_file_access_handler) { - JNIEnv *env = get_jni_env(); - file_access_handler = env->NewGlobalRef(p_file_access_handler); - - jclass c = env->GetObjectClass(file_access_handler); - cls = (jclass)env->NewGlobalRef(c); - - _file_open = env->GetMethodID(cls, "fileOpen", "(Ljava/lang/String;I)I"); - _file_get_size = env->GetMethodID(cls, "fileGetSize", "(I)J"); - _file_tell = env->GetMethodID(cls, "fileGetPosition", "(I)J"); - _file_eof = env->GetMethodID(cls, "isFileEof", "(I)Z"); - _file_set_eof = env->GetMethodID(cls, "setFileEof", "(IZ)V"); - _file_seek = env->GetMethodID(cls, "fileSeek", "(IJ)V"); - _file_seek_end = env->GetMethodID(cls, "fileSeekFromEnd", "(IJ)V"); - _file_read = env->GetMethodID(cls, "fileRead", "(ILjava/nio/ByteBuffer;)I"); - _file_close = env->GetMethodID(cls, "fileClose", "(I)V"); - _file_write = env->GetMethodID(cls, "fileWrite", "(ILjava/nio/ByteBuffer;)V"); - _file_flush = env->GetMethodID(cls, "fileFlush", "(I)V"); - _file_exists = env->GetMethodID(cls, "fileExists", "(Ljava/lang/String;)Z"); - _file_last_modified = env->GetMethodID(cls, "fileLastModified", "(Ljava/lang/String;)J"); -} - -FileAccessFilesystemJAndroid::FileAccessFilesystemJAndroid() { - id = 0; -} - -FileAccessFilesystemJAndroid::~FileAccessFilesystemJAndroid() { - if (is_open()) { - close(); - } -} diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h deleted file mode 100644 index 8c335f6..0000000 --- a/platform/android/file_access_filesystem_jandroid.h +++ /dev/null @@ -1,100 +0,0 @@ -/*************************************************************************/ -/* file_access_filesystem_jandroid.h */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#ifndef FILE_ACCESS_FILESYSTEM_JANDROID_H -#define FILE_ACCESS_FILESYSTEM_JANDROID_H - -#include "core/os/file_access.h" -#include "java_pandemonium_lib_jni.h" - -class FileAccessFilesystemJAndroid : public FileAccess { - static jobject file_access_handler; - static jclass cls; - - static jmethodID _file_open; - static jmethodID _file_get_size; - static jmethodID _file_seek; - static jmethodID _file_seek_end; - static jmethodID _file_tell; - static jmethodID _file_eof; - static jmethodID _file_set_eof; - static jmethodID _file_read; - static jmethodID _file_write; - static jmethodID _file_flush; - static jmethodID _file_close; - static jmethodID _file_exists; - static jmethodID _file_last_modified; - - int id; - String absolute_path; - String path_src; - - void _set_eof(bool eof); - -public: - virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual void close(); ///< close a file - virtual bool is_open() const; ///< true when file is open - - /// returns the path for the current open file - virtual String get_path() const; - /// returns the absolute path for the current open file - virtual String get_path_absolute() const; - - 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_len() const; ///< get size of the file - - virtual bool eof_reached() const; ///< reading passed EOF - - virtual uint8_t get_8() const; ///< get a byte - virtual String get_line() const; ///< get a line - virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; - - 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_buffer(const uint8_t *p_src, uint64_t p_length); - - virtual bool file_exists(const String &p_path); ///< return true if a file exists - - static void setup(jobject p_file_access_handler); - - virtual uint64_t _get_modified_time(const String &p_file); - 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; } - - FileAccessFilesystemJAndroid(); - ~FileAccessFilesystemJAndroid(); -}; - -#endif // FILE_ACCESS_FILESYSTEM_JANDROID_H diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml deleted file mode 100644 index 13b4c8e..0000000 --- a/platform/android/java/app/AndroidManifest.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/platform/android/java/app/assetPacks/installTime/build.gradle b/platform/android/java/app/assetPacks/installTime/build.gradle deleted file mode 100644 index b06faac..0000000 --- a/platform/android/java/app/assetPacks/installTime/build.gradle +++ /dev/null @@ -1,8 +0,0 @@ -apply plugin: 'com.android.asset-pack' - -assetPack { - packName = "installTime" // Directory name for the asset pack - dynamicDelivery { - deliveryType = "install-time" // Delivery mode - } -} diff --git a/platform/android/java/app/assets/.gitignore b/platform/android/java/app/assets/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/platform/android/java/app/assets/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle deleted file mode 100644 index b95d7c9..0000000 --- a/platform/android/java/app/build.gradle +++ /dev/null @@ -1,288 +0,0 @@ -// Gradle build config for Pandemonium Engine's Android port. -// -// Do not remove/modify comments ending with BEGIN/END, they are used to inject -// addon-specific configuration. -buildscript { - apply from: 'config.gradle' - - repositories { - google() - mavenCentral() -//CHUNK_BUILDSCRIPT_REPOSITORIES_BEGIN -//CHUNK_BUILDSCRIPT_REPOSITORIES_END - } - dependencies { - classpath libraries.androidGradlePlugin - classpath libraries.kotlinGradlePlugin -//CHUNK_BUILDSCRIPT_DEPENDENCIES_BEGIN -//CHUNK_BUILDSCRIPT_DEPENDENCIES_END - } -} - -plugins { - id 'com.android.application' - id 'org.jetbrains.kotlin.android' -} - -apply from: 'config.gradle' - -allprojects { - repositories { - google() - mavenCentral() -//CHUNK_ALLPROJECTS_REPOSITORIES_BEGIN -//CHUNK_ALLPROJECTS_REPOSITORIES_END - - // Pandemonium user plugins custom maven repos - String[] mavenRepos = getPandemoniumPluginsMavenRepos() - if (mavenRepos != null && mavenRepos.size() > 0) { - for (String repoUrl : mavenRepos) { - maven { - url repoUrl - } - } - } - } -} - -configurations { - // Initializes a placeholder for the devImplementation dependency configuration. - devImplementation {} -} - -dependencies { - implementation libraries.kotlinStdLib - implementation libraries.androidxFragment - - if (rootProject.findProject(":lib")) { - implementation project(":lib") - } else if (rootProject.findProject(":pandemonium:lib")) { - implementation project(":pandemonium:lib") - } else { - // Custom build mode. In this scenario this project is the only one around and the Pandemonium - // library is available through the pre-generated pandemonium-lib.*.aar android archive files. - debugImplementation fileTree(dir: 'libs/debug', include: ['*.jar', '*.aar']) - devImplementation fileTree(dir: 'libs/dev', include: ['*.jar', '*.aar']) - releaseImplementation fileTree(dir: 'libs/release', include: ['*.jar', '*.aar']) - } - - // Pandemonium user plugins remote dependencies - String[] remoteDeps = getPandemoniumPluginsRemoteBinaries() - if (remoteDeps != null && remoteDeps.size() > 0) { - for (String dep : remoteDeps) { - implementation dep - } - } - - // Pandemonium user plugins local dependencies - String[] pluginsBinaries = getPandemoniumPluginsLocalBinaries() - if (pluginsBinaries != null && pluginsBinaries.size() > 0) { - implementation files(pluginsBinaries) - } - -//CHUNK_DEPENDENCIES_BEGIN -//CHUNK_DEPENDENCIES_END -} - -android { - compileSdkVersion versions.compileSdk - buildToolsVersion versions.buildTools - ndkVersion versions.ndkVersion - - compileOptions { - sourceCompatibility versions.javaVersion - targetCompatibility versions.javaVersion - } - - kotlinOptions { - jvmTarget = versions.javaVersion - } - - assetPacks = [":assetPacks:installTime"] - - defaultConfig { - // The default ignore pattern for the 'assets' directory includes hidden files and directories which are used by Pandemonium projects. - aaptOptions { - ignoreAssetsPattern "!.svn:!.git:!.gitignore:!.ds_store:!*.scc:_*:!CVS:!thumbs.db:!picasa.ini:!*~" - } - - ndk { - String[] export_abi_list = getExportEnabledABIs() - abiFilters export_abi_list - } - - manifestPlaceholders = [pandemoniumEditorVersion: getPandemoniumEditorVersion()] - - // Feel free to modify the application id to your own. - applicationId getExportPackageName() - versionCode getExportVersionCode() - versionName getExportVersionName() - minSdkVersion getExportMinSdkVersion() - targetSdkVersion getExportTargetSdkVersion() - - missingDimensionStrategy 'products', 'template' -//CHUNK_ANDROID_DEFAULTCONFIG_BEGIN -//CHUNK_ANDROID_DEFAULTCONFIG_END - } - - lintOptions { - abortOnError false - disable 'MissingTranslation', 'UnusedResources' - } - - ndkVersion versions.ndkVersion - - packagingOptions { - exclude 'META-INF/LICENSE' - exclude 'META-INF/NOTICE' - - // 'doNotStrip' is enabled for development within Android Studio - if (shouldNotStrip()) { - doNotStrip '**/*.so' - } - } - - signingConfigs { - debug { - if (hasCustomDebugKeystore()) { - storeFile new File(getDebugKeystoreFile()) - storePassword getDebugKeystorePassword() - keyAlias getDebugKeyAlias() - keyPassword getDebugKeystorePassword() - } - } - - release { - File keystoreFile = new File(getReleaseKeystoreFile()) - if (keystoreFile.isFile()) { - storeFile keystoreFile - storePassword getReleaseKeystorePassword() - keyAlias getReleaseKeyAlias() - keyPassword getReleaseKeystorePassword() - } - } - } - - buildTypes { - - debug { - // Signing and zip-aligning are skipped for prebuilt builds, but - // performed for custom builds. - zipAlignEnabled shouldZipAlign() - if (shouldSign()) { - signingConfig signingConfigs.debug - } else { - signingConfig null - } - } - - dev { - initWith debug - // Signing and zip-aligning are skipped for prebuilt builds, but - // performed for custom builds. - zipAlignEnabled shouldZipAlign() - if (shouldSign()) { - signingConfig signingConfigs.debug - } else { - signingConfig null - } - } - - release { - // Signing and zip-aligning are skipped for prebuilt builds, but - // performed for custom builds. - zipAlignEnabled shouldZipAlign() - if (shouldSign()) { - signingConfig signingConfigs.release - } else { - signingConfig null - } - } - } - - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = [ - 'src' -//DIR_SRC_BEGIN -//DIR_SRC_END - ] - res.srcDirs = [ - 'res' -//DIR_RES_BEGIN -//DIR_RES_END - ] - aidl.srcDirs = [ - 'aidl' -//DIR_AIDL_BEGIN -//DIR_AIDL_END - ] - assets.srcDirs = [ - 'assets' -//DIR_ASSETS_BEGIN -//DIR_ASSETS_END - ] - } - debug.jniLibs.srcDirs = [ - 'libs/debug' -//DIR_JNI_DEBUG_BEGIN -//DIR_JNI_DEBUG_END - ] - dev.jniLibs.srcDirs = [ - 'libs/dev' -//DIR_JNI_DEV_BEGIN -//DIR_JNI_DEV_END - ] - release.jniLibs.srcDirs = [ - 'libs/release' -//DIR_JNI_RELEASE_BEGIN -//DIR_JNI_RELEASE_END - ] - } - - applicationVariants.all { variant -> - variant.outputs.all { output -> - output.outputFileName = "android_${variant.name}.apk" - } - } -} - -task copyAndRenameDebugApk(type: Copy) { - from "$buildDir/outputs/apk/debug/android_debug.apk" - into getExportPath() - rename "android_debug.apk", getExportFilename() -} - -task copyAndRenameDevApk(type: Copy) { - from "$buildDir/outputs/apk/dev/android_dev.apk" - into getExportPath() - rename "android_dev.apk", getExportFilename() -} - -task copyAndRenameReleaseApk(type: Copy) { - from "$buildDir/outputs/apk/release/android_release.apk" - into getExportPath() - rename "android_release.apk", getExportFilename() -} - -task copyAndRenameDebugAab(type: Copy) { - from "$buildDir/outputs/bundle/debug/build-debug.aab" - into getExportPath() - rename "build-debug.aab", getExportFilename() -} - -task copyAndRenameDevAab(type: Copy) { - from "$buildDir/outputs/bundle/dev/build-dev.aab" - into getExportPath() - rename "build-dev.aab", getExportFilename() -} - -task copyAndRenameReleaseAab(type: Copy) { - from "$buildDir/outputs/bundle/release/build-release.aab" - into getExportPath() - rename "build-release.aab", getExportFilename() -} - -//CHUNK_GLOBAL_BEGIN -//CHUNK_GLOBAL_END diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle deleted file mode 100644 index 0fc1fa2..0000000 --- a/platform/android/java/app/config.gradle +++ /dev/null @@ -1,315 +0,0 @@ -ext.versions = [ - androidGradlePlugin: '7.2.1', - compileSdk : 33, - minSdk : 19, // Also update 'platform/android/export/export_plugin.cpp#DEFAULT_MIN_SDK_VERSION' - targetSdk : 33, // Also update 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION' - buildTools : '33.0.2', - kotlinVersion : '1.7.0', - fragmentVersion : '1.3.6', - nexusPublishVersion: '1.1.0', - javaVersion : 11, - 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:$versions.kotlinVersion", - androidxFragment : "androidx.fragment:fragment:$versions.fragmentVersion", -] - -ext.getExportPackageName = { -> - // Retrieve the app id from the project property set by the Pandemonium build command. - String appId = project.hasProperty("export_package_name") ? project.property("export_package_name") : "" - // Check if the app id is valid, otherwise use the default. - if (appId == null || appId.isEmpty()) { - appId = "com.pandemonium.game" - } - return appId -} - -ext.getExportVersionCode = { -> - String versionCode = project.hasProperty("export_version_code") ? project.property("export_version_code") : "" - if (versionCode == null || versionCode.isEmpty()) { - versionCode = "1" - } - try { - return Integer.parseInt(versionCode) - } catch (NumberFormatException ignored) { - return 1 - } -} - -ext.getExportVersionName = { -> - String versionName = project.hasProperty("export_version_name") ? project.property("export_version_name") : "" - if (versionName == null || versionName.isEmpty()) { - versionName = "1.0" - } - return versionName -} - -ext.getExportMinSdkVersion = { -> - String minSdkVersion = project.hasProperty("export_version_min_sdk") ? project.property("export_version_min_sdk") : "" - if (minSdkVersion == null || minSdkVersion.isEmpty()) { - minSdkVersion = "$versions.minSdk" - } - try { - return Integer.parseInt(minSdkVersion) - } catch (NumberFormatException ignored) { - return versions.minSdk - } -} - -ext.getExportTargetSdkVersion = { -> - String targetSdkVersion = project.hasProperty("export_version_target_sdk") ? project.property("export_version_target_sdk") : "" - if (targetSdkVersion == null || targetSdkVersion.isEmpty()) { - targetSdkVersion = "$versions.targetSdk" - } - try { - return Integer.parseInt(targetSdkVersion) - } catch (NumberFormatException ignored) { - return versions.targetSdk - } -} - -ext.getPandemoniumEditorVersion = { -> - String editorVersion = project.hasProperty("pandemonium_editor_version") ? project.property("pandemonium_editor_version") : "" - if (editorVersion == null || editorVersion.isEmpty()) { - // Try the library version first - editorVersion = getPandemoniumLibraryVersionName() - - if (editorVersion.isEmpty()) { - // Fallback value. - editorVersion = "custom_build" - } - } - return editorVersion -} - -ext.getPandemoniumLibraryVersionCode = { -> - String versionName = "" - int versionCode = 1 - (versionName, versionCode) = getPandemoniumLibraryVersion() - return versionCode -} - -ext.getPandemoniumLibraryVersionName = { -> - String versionName = "" - int versionCode = 1 - (versionName, versionCode) = getPandemoniumLibraryVersion() - return versionName -} - -ext.getPandemoniumLibraryVersion = { -> - // Attempt to read the version from the `version.py` file. - String libraryVersionName = "" - int libraryVersionCode = 1 - - File versionFile = new File("../../../version.py") - if (versionFile.isFile()) { - List requiredKeys = ["major", "minor", "patch", "status", "module_config"] - def map = [:] - - List lines = versionFile.readLines() - for (String line in lines) { - String[] keyValue = line.split("=") - String key = keyValue[0].trim() - String value = keyValue[1].trim().replaceAll("\"", "") - - if (requiredKeys.contains(key)) { - if (!value.isEmpty()) { - map[key] = value - } - requiredKeys.remove(key) - } - } - - if (requiredKeys.empty) { - libraryVersionName = map.values().join(".") - try { - libraryVersionCode = Integer.parseInt(map["patch"]) + - (Integer.parseInt(map["minor"]) * 100) + - (Integer.parseInt(map["major"]) * 10000) - } catch (NumberFormatException ignore) {} - } - } - - if (libraryVersionName.isEmpty()) { - // Fallback value in case we're unable to read the file. - libraryVersionName = "custom_build" - } - return [libraryVersionName, libraryVersionCode] -} - -final String VALUE_SEPARATOR_REGEX = "\\|" - -// get the list of ABIs the project should be exported to -ext.getExportEnabledABIs = { -> - String enabledABIs = project.hasProperty("export_enabled_abis") ? project.property("export_enabled_abis") : ""; - if (enabledABIs == null || enabledABIs.isEmpty()) { - enabledABIs = "armeabi-v7a|arm64-v8a|x86|x86_64|" - } - Set exportAbiFilter = []; - for (String abi_name : enabledABIs.split(VALUE_SEPARATOR_REGEX)) { - if (!abi_name.trim().isEmpty()){ - exportAbiFilter.add(abi_name); - } - } - return exportAbiFilter; -} - -ext.getExportPath = { - String exportPath = project.hasProperty("export_path") ? project.property("export_path") : "" - if (exportPath == null || exportPath.isEmpty()) { - exportPath = "." - } - return exportPath -} - -ext.getExportFilename = { - String exportFilename = project.hasProperty("export_filename") ? project.property("export_filename") : "" - if (exportFilename == null || exportFilename.isEmpty()) { - exportFilename = "pandemonium_android" - } - return exportFilename -} - -/** - * Parse the project properties for the 'plugins_maven_repos' property and return the list - * of maven repos. - */ -ext.getPandemoniumPluginsMavenRepos = { -> - Set mavenRepos = [] - - // Retrieve the list of maven repos. - if (project.hasProperty("plugins_maven_repos")) { - String mavenReposProperty = project.property("plugins_maven_repos") - if (mavenReposProperty != null && !mavenReposProperty.trim().isEmpty()) { - for (String mavenRepoUrl : mavenReposProperty.split(VALUE_SEPARATOR_REGEX)) { - mavenRepos += mavenRepoUrl.trim() - } - } - } - - return mavenRepos -} - -/** - * Parse the project properties for the 'plugins_remote_binaries' property and return - * it for inclusion in the build dependencies. - */ -ext.getPandemoniumPluginsRemoteBinaries = { -> - Set remoteDeps = [] - - // Retrieve the list of remote plugins binaries. - if (project.hasProperty("plugins_remote_binaries")) { - String remoteDepsList = project.property("plugins_remote_binaries") - if (remoteDepsList != null && !remoteDepsList.trim().isEmpty()) { - for (String dep: remoteDepsList.split(VALUE_SEPARATOR_REGEX)) { - remoteDeps += dep.trim() - } - } - } - return remoteDeps -} - -/** - * Parse the project properties for the 'plugins_local_binaries' property and return - * their binaries for inclusion in the build dependencies. - */ -ext.getPandemoniumPluginsLocalBinaries = { -> - Set binDeps = [] - - // Retrieve the list of local plugins binaries. - if (project.hasProperty("plugins_local_binaries")) { - String pluginsList = project.property("plugins_local_binaries") - if (pluginsList != null && !pluginsList.trim().isEmpty()) { - for (String plugin : pluginsList.split(VALUE_SEPARATOR_REGEX)) { - binDeps += plugin.trim() - } - } - } - - 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()) { - keystoreFile = "." - } - return keystoreFile -} - -ext.getReleaseKeystorePassword = { -> - String keystorePassword = project.hasProperty("release_keystore_password") ? project.property("release_keystore_password") : "" - return keystorePassword -} - -ext.getReleaseKeyAlias = { -> - String keyAlias = project.hasProperty("release_keystore_alias") ? project.property("release_keystore_alias") : "" - return keyAlias -} - -ext.isAndroidStudio = { -> - def sysProps = System.getProperties() - return sysProps != null && sysProps['idea.platform.prefix'] != null -} - -ext.shouldZipAlign = { -> - String zipAlignFlag = project.hasProperty("perform_zipalign") ? project.property("perform_zipalign") : "" - if (zipAlignFlag == null || zipAlignFlag.isEmpty()) { - if (isAndroidStudio()) { - zipAlignFlag = "true" - } else { - zipAlignFlag = "false" - } - } - return Boolean.parseBoolean(zipAlignFlag) -} - -ext.shouldSign = { -> - String signFlag = project.hasProperty("perform_signing") ? project.property("perform_signing") : "" - if (signFlag == null || signFlag.isEmpty()) { - if (isAndroidStudio()) { - signFlag = "true" - } else { - signFlag = "false" - } - } - return Boolean.parseBoolean(signFlag) -} - -ext.shouldNotStrip = { -> - return isAndroidStudio() || project.hasProperty("doNotStrip") -} diff --git a/platform/android/java/app/gradle.properties b/platform/android/java/app/gradle.properties deleted file mode 100644 index d203e76..0000000 --- a/platform/android/java/app/gradle.properties +++ /dev/null @@ -1,25 +0,0 @@ -# Pandemonium custom build Gradle settings. -# These properties apply when running custom build from the Pandemonium editor. -# NOTE: This should be kept in sync with 'pandemonium/platform/android/java/gradle.properties' except -# where otherwise specified. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -android.enableJetifier=true -android.useAndroidX=true - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx4536m - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true - -org.gradle.warning.mode=all - -# Enable resource optimizations for release build. -# NOTE: This is turned off for template release build in order to support the build legacy process. -android.enableResourceOptimizations=true diff --git a/platform/android/java/app/res/drawable-nodpi/splash.png b/platform/android/java/app/res/drawable-nodpi/splash.png deleted file mode 100644 index b6bdb20..0000000 Binary files a/platform/android/java/app/res/drawable-nodpi/splash.png and /dev/null differ diff --git a/platform/android/java/app/res/drawable-nodpi/splash_bg_color.png b/platform/android/java/app/res/drawable-nodpi/splash_bg_color.png deleted file mode 100644 index 0af5c11..0000000 Binary files a/platform/android/java/app/res/drawable-nodpi/splash_bg_color.png and /dev/null differ diff --git a/platform/android/java/app/res/drawable/splash_drawable.xml b/platform/android/java/app/res/drawable/splash_drawable.xml deleted file mode 100644 index 30627b9..0000000 --- a/platform/android/java/app/res/drawable/splash_drawable.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - diff --git a/platform/android/java/app/res/values-en/pandemonium_project_name_string.xml b/platform/android/java/app/res/values-en/pandemonium_project_name_string.xml deleted file mode 100644 index c369591..0000000 --- a/platform/android/java/app/res/values-en/pandemonium_project_name_string.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - pandemonium-project-name-en - diff --git a/platform/android/java/app/res/values-hu/pandemonium_project_name_string.xml b/platform/android/java/app/res/values-hu/pandemonium_project_name_string.xml deleted file mode 100644 index d3dcea2..0000000 --- a/platform/android/java/app/res/values-hu/pandemonium_project_name_string.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - pandemonium-project-name-hu - diff --git a/platform/android/java/app/res/values/pandemonium_project_name_string.xml b/platform/android/java/app/res/values/pandemonium_project_name_string.xml deleted file mode 100644 index 2149dec..0000000 --- a/platform/android/java/app/res/values/pandemonium_project_name_string.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - pandemonium-project-name - diff --git a/platform/android/java/app/res/values/themes.xml b/platform/android/java/app/res/values/themes.xml deleted file mode 100644 index 1f97f9f..0000000 --- a/platform/android/java/app/res/values/themes.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - diff --git a/platform/android/java/app/settings.gradle b/platform/android/java/app/settings.gradle deleted file mode 100644 index 237d44a..0000000 --- a/platform/android/java/app/settings.gradle +++ /dev/null @@ -1,15 +0,0 @@ -// This is the root directory of the Pandemonium 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/app/src/com/pandemonium/game/PandemoniumApp.java b/platform/android/java/app/src/com/pandemonium/game/PandemoniumApp.java deleted file mode 100644 index 1fbaf98..0000000 --- a/platform/android/java/app/src/com/pandemonium/game/PandemoniumApp.java +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************/ -/* PandemoniumApp.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 com.pandemonium.game; - -import org.pandemoniumengine.pandemonium.FullScreenPandemoniumApp; - -import android.os.Bundle; - -/** - * Template activity for Pandemonium Android custom builds. - * Feel free to extend and modify this class for your custom logic. - */ -public class PandemoniumApp extends FullScreenPandemoniumApp { - @Override - public void onCreate(Bundle savedInstanceState) { - setTheme(R.style.PandemoniumAppMainTheme); - super.onCreate(savedInstanceState); - } -} diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle deleted file mode 100644 index 8b5e2b8..0000000 --- a/platform/android/java/build.gradle +++ /dev/null @@ -1,330 +0,0 @@ - -buildscript { - apply from: 'app/config.gradle' - - repositories { - google() - mavenCentral() - } - dependencies { - classpath libraries.androidGradlePlugin - classpath libraries.kotlinGradlePlugin - } -} - -plugins { - id 'io.github.gradle-nexus.publish-plugin' -} - -apply from: 'app/config.gradle' -//apply from: 'scripts/publish-root.gradle' - -allprojects { - repositories { - google() - mavenCentral() - } -} - -ext { - supportedAbis = ["armv7", "arm64v8", "x86", "x86_64"] - supportedTargetsMap = [release: "release", dev: "debug", debug: "release_debug"] - supportedFlavors = ["editor", "template"] - - // Used by gradle to specify which architecture to build for by default when running - // `./gradlew build` (this command is usually used by Android Studio). - // If building manually on the command line, it's recommended to use the - // `./gradlew generatePandemoniumTemplates` build command instead after running the `scons` command(s). - // The {selectedAbis} values must be from the {supportedAbis} values. - selectedAbis = ["arm64v8"] -} - -def rootDir = "../../.." -def binDir = "$rootDir/bin/" - -def getSconsTaskName(String flavor, String buildType, String abi) { - return "compilePandemoniumNativeLibs" + flavor.capitalize() + buildType.capitalize() + abi.capitalize() -} - -/** - * Copy the generated 'android_debug.apk' binary template into the Pandemonium bin directory. - * Depends on the app build task to ensure the binary is generated prior to copying. - */ -task copyDebugBinaryToBin(type: Copy) { - dependsOn ':app:assembleDebug' - from('app/build/outputs/apk/debug') - into(binDir) - include('android_debug.apk') -} - -/** - * Copy the generated 'android_dev.apk' binary template into the Pandemonium bin directory. - * Depends on the app build task to ensure the binary is generated prior to copying. - */ -task copyDevBinaryToBin(type: Copy) { - dependsOn ':app:assembleDev' - from('app/build/outputs/apk/dev') - into(binDir) - include('android_dev.apk') -} - -/** - * Copy the generated 'android_release.apk' binary template into the Pandemonium bin directory. - * Depends on the app build task to ensure the binary is generated prior to copying. - */ -task copyReleaseBinaryToBin(type: Copy) { - dependsOn ':app:assembleRelease' - from('app/build/outputs/apk/release') - into(binDir) - include('android_release.apk') -} - -/** - * Copy the Pandemonium android library archive debug file into the app module debug libs directory. - * Depends on the library build task to ensure the AAR file is generated prior to copying. - */ -task copyDebugAARToAppModule(type: Copy) { - dependsOn ':lib:assembleTemplateDebug' - from('lib/build/outputs/aar') - into('app/libs/debug') - include('pandemonium-lib.debug.aar') -} - -/** - * Copy the Pandemonium android library archive debug file into the root bin directory. - * Depends on the library build task to ensure the AAR file is generated prior to copying. - */ -task copyDebugAARToBin(type: Copy) { - dependsOn ':lib:assembleTemplateDebug' - from('lib/build/outputs/aar') - into(binDir) - include('pandemonium-lib.debug.aar') -} - -/** - * Copy the Pandemonium android library archive dev file into the app module dev libs directory. - * Depends on the library build task to ensure the AAR file is generated prior to copying. - */ -task copyDevAARToAppModule(type: Copy) { - dependsOn ':lib:assembleTemplateDev' - from('lib/build/outputs/aar') - into('app/libs/dev') - include('pandemonium-lib.dev.aar') -} - -/** - * Copy the Pandemonium android library archive dev file into the root bin directory. - * Depends on the library build task to ensure the AAR file is generated prior to copying. - */ -task copyDevAARToBin(type: Copy) { - dependsOn ':lib:assembleTemplateDev' - from('lib/build/outputs/aar') - into(binDir) - include('pandemonium-lib.dev.aar') -} - -/** - * Copy the Pandemonium android library archive release file into the app module release libs directory. - * Depends on the library build task to ensure the AAR file is generated prior to copying. - */ -task copyReleaseAARToAppModule(type: Copy) { - dependsOn ':lib:assembleTemplateRelease' - from('lib/build/outputs/aar') - into('app/libs/release') - include('pandemonium-lib.release.aar') -} - -/** - * Copy the Pandemonium android library archive release file into the root bin directory. - * Depends on the library build task to ensure the AAR file is generated prior to copying. - */ -task copyReleaseAARToBin(type: Copy) { - dependsOn ':lib:assembleTemplateRelease' - from('lib/build/outputs/aar') - into(binDir) - include('pandemonium-lib.release.aar') -} - -/** - * Generate Pandemonium custom build template by zipping the source files from the app directory, as well - * as the AAR files generated by 'copyDebugAAR', 'copyDevAAR' and 'copyReleaseAAR'. - * The zip file also includes some gradle tools to allow building of the custom build. - */ -task zipCustomBuild(type: Zip) { - onlyIf { generatePandemoniumTemplates.state.executed || generateDevTemplate.state.executed } - doFirst { - logger.lifecycle("Generating Pandemonium custom build template") - } - from(fileTree(dir: 'app', excludes: ['**/build/**', '**/.gradle/**', '**/*.iml']), fileTree(dir: '.', includes: ['gradlew', 'gradlew.bat', 'gradle/**'])) - include '**/*' - archiveFileName = 'android_source.zip' - destinationDirectory = file(binDir) -} - -def templateExcludedBuildTask() { - // We exclude these gradle tasks so we can run the scons command manually. - def excludedTasks = [] - if (!isAndroidStudio()) { - logger.lifecycle("Excluding Android studio build tasks") - for (String flavor : supportedFlavors) { - for (String buildType : supportedTargetsMap.keySet()) { - if (buildType == "release" && flavor == "editor") { - // The editor can't be used with target=release as debugging tools are then not - // included, and it would crash on errors instead of reporting them. - continue - } - - for (String abi : selectedAbis) { - excludedTasks += ":lib:" + getSconsTaskName(flavor, buildType, abi) - } - } - } - } - return excludedTasks -} - -def templateBuildTasks() { - def tasks = [] - - // Only build the apks and aar files for which we have native shared libraries. - for (String target : supportedTargetsMap.keySet()) { - File targetLibs = new File("lib/libs/" + target) - if (targetLibs != null - && targetLibs.isDirectory() - && targetLibs.listFiles() != null - && targetLibs.listFiles().length > 0) { - String capitalizedTarget = target.capitalize() - // Copy the generated aar library files to the custom build directory. - tasks += "copy" + capitalizedTarget + "AARToAppModule" - // Copy the generated aar library files to the bin directory. - tasks += "copy" + capitalizedTarget + "AARToBin" - // Copy the prebuilt binary templates to the bin directory. - tasks += "copy" + capitalizedTarget + "BinaryToBin" - } else { - logger.lifecycle("No native shared libs for target $target. Skipping build.") - } - } - - return tasks -} - -def isAndroidStudio() { - def sysProps = System.getProperties() - return sysProps != null && sysProps['idea.platform.prefix'] != null -} - -task copyEditorDebugBinaryToBin(type: Copy) { - dependsOn ':editor:assembleDebug' - from('editor/build/outputs/apk/debug') - into(binDir) - include('android_editor.apk') -} - -task copyEditorDevBinaryToBin(type: Copy) { - dependsOn ':editor:assembleDev' - from('editor/build/outputs/apk/dev') - into(binDir) - include('android_editor_dev.apk') -} - -/** - * Generate the Pandemonium Editor Android apk. - * - * Note: The Pandemonium 'tools' shared libraries must have been generated (via scons) prior to running - * this gradle task. The task will only build the apk(s) for which the shared libraries is - * available. - */ -task generatePandemoniumEditor { - gradle.startParameter.excludedTaskNames += templateExcludedBuildTask() - - def tasks = [] - - for (String target : supportedTargetsMap.keySet()) { - if (target == "release") { - // The editor can't be used with target=release as debugging tools are then not - // included, and it would crash on errors instead of reporting them. - continue - } - File targetLibs = new File("lib/libs/tools/" + target) - if (targetLibs != null - && targetLibs.isDirectory() - && targetLibs.listFiles() != null - && targetLibs.listFiles().length > 0) { - tasks += "copyEditor${target.capitalize()}BinaryToBin" - } - } - - dependsOn = tasks -} - -/** - * Master task used to coordinate the tasks defined above to generate the set of Pandemonium templates. - */ -task generatePandemoniumTemplates { - gradle.startParameter.excludedTaskNames += templateExcludedBuildTask() - dependsOn = templateBuildTasks() - - finalizedBy 'zipCustomBuild' -} - -task clean(type: Delete) { - dependsOn 'cleanPandemoniumEditor' - dependsOn 'cleanPandemoniumTemplates' -} - -/** - * Generates the same output as generatePandemoniumTemplates but with dev symbols - */ -task generateDevTemplate { - // add parameter to set symbols to true - gradle.startParameter.projectProperties += [doNotStrip: true] - - gradle.startParameter.excludedTaskNames += templateExcludedBuildTask() - dependsOn = templateBuildTasks() - - finalizedBy 'zipCustomBuild' -} - -/** -* Clean the generated editor artifacts. - */ -task cleanPandemoniumEditor(type: Delete) { - // Delete the generated native tools libs - delete("lib/libs/tools") - - // Delete the library generated AAR files - delete("lib/build/outputs/aar") - - // Delete the generated binary apks - delete("editor/build/outputs/apk") - - // Delete the Pandemonium editor apks in the Pandemonium bin directory - delete("$binDir/android_editor.apk") - delete("$binDir/android_editor_dev.apk") -} - -/** - * Clean the generated template artifacts. - */ -task cleanPandemoniumTemplates(type: Delete) { - // Delete the generated native libs - delete("lib/libs") - - // Delete the library generated AAR files - delete("lib/build/outputs/aar") - - // Delete the app libs directory contents - delete("app/libs") - - // Delete the generated binary apks - delete("app/build/outputs/apk") - - // Delete the Pandemonium templates in the Pandemonium bin directory - delete("$binDir/android_debug.apk") - delete("$binDir/android_dev.apk") - delete("$binDir/android_release.apk") - delete("$binDir/android_source.zip") - delete("$binDir/pandemonium-lib.debug.aar") - delete("$binDir/pandemonium-lib.dev.aar") - delete("$binDir/pandemonium-lib.release.aar") -} diff --git a/platform/android/java/editor/build.gradle b/platform/android/java/editor/build.gradle deleted file mode 100644 index adda4ea..0000000 --- a/platform/android/java/editor/build.gradle +++ /dev/null @@ -1,81 +0,0 @@ -// Gradle build config for Pandemonium Engine's Android port. -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 { - compileSdkVersion versions.compileSdk - buildToolsVersion versions.buildTools - ndkVersion versions.ndkVersion - - defaultConfig { - // The 'applicationId' suffix allows to install Pandemonium 3.x(v3) and 4.x(v4) on the same device - applicationId "org.pandemoniumengine.editor.v3" - versionCode getPandemoniumLibraryVersionCode() - versionName getPandemoniumLibraryVersionName() - minSdkVersion versions.minSdk - targetSdkVersion versions.targetSdk - missingDimensionStrategy 'products', 'editor' - } - - compileOptions { - sourceCompatibility versions.javaVersion - targetCompatibility versions.javaVersion - } - - kotlinOptions { - jvmTarget = versions.javaVersion - } - - buildTypes { - dev { - initWith debug - applicationIdSuffix ".dev" - } - - debug { - initWith release - - // Need to swap with the release signing config when this is ready for public release. - signingConfig signingConfigs.debug - } - - release { - // This buildtype is disabled below. - // The editor can't be used with target=release only, as debugging tools are then not - // included, and it would crash on errors instead of reporting them. - } - } - - packagingOptions { - // 'doNotStrip' is enabled for development within Android Studio - if (shouldNotStrip()) { - doNotStrip '**/*.so' - } - } - - // Disable 'release' buildtype. - // The editor can't be used with target=release only, as debugging tools are then not - // included, and it would crash on errors instead of reporting them. - variantFilter { variant -> - if (variant.buildType.name == "release") { - setIgnore(true) - } - } - - applicationVariants.all { variant -> - variant.outputs.all { output -> - def suffix = variant.name == "dev" ? "_dev" : "" - output.outputFileName = "android_editor${suffix}.apk" - } - } -} diff --git a/platform/android/java/editor/src/.gitignore b/platform/android/java/editor/src/.gitignore deleted file mode 100644 index c081ec3..0000000 --- a/platform/android/java/editor/src/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!/debug diff --git a/platform/android/java/editor/src/main/AndroidManifest.xml b/platform/android/java/editor/src/main/AndroidManifest.xml deleted file mode 100644 index b451c1d..0000000 --- a/platform/android/java/editor/src/main/AndroidManifest.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumEditor.kt b/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumEditor.kt deleted file mode 100644 index 0a5277e..0000000 --- a/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumEditor.kt +++ /dev/null @@ -1,396 +0,0 @@ -/*************************************************************************/ -/* PandemoniumEditor.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.pandemoniumengine.editor - -import org.pandemoniumengine.pandemonium.FullScreenPandemoniumApp -import org.pandemoniumengine.pandemonium.utils.PermissionsUtil -import org.pandemoniumengine.pandemonium.utils.ProcessPhoenix -import org.pandemoniumengine.pandemonium.PandemoniumLib - -import android.Manifest -import android.app.ActivityManager -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.os.* -import android.util.Log -import android.widget.Toast - -import androidx.window.layout.WindowMetricsCalculator; - -import java.util.* -import kotlin.math.min - -/** - * Base class for the Pandemonium 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 Pandemonium engine up and running at the same time. - * - * It also plays the role of the primary editor window. - */ -open class PandemoniumEditor : FullScreenPandemoniumApp() { - companion object { - private val TAG = PandemoniumEditor::class.java.simpleName - - private const val WAIT_FOR_DEBUGGER = false - - private const val EXTRA_COMMAND_LINE_PARAMS = "command_line_params" - - private const val EDITOR_ID = 777 - private const val EDITOR_ARG = "--editor" - private const val EDITOR_ARG_SHORT = "-e" - private const val EDITOR_PROCESS_NAME_SUFFIX = ":PandemoniumEditor" - - private const val GAME_ID = 667 - private const val GAME_PROCESS_NAME_SUFFIX = ":PandemoniumGame" - - private const val PROJECT_MANAGER_ID = 555 - private const val PROJECT_MANAGER_ARG = "--project-manager" - private const val PROJECT_MANAGER_ARG_SHORT = "-p" - private const val PROJECT_MANAGER_PROCESS_NAME_SUFFIX = ":PandemoniumProjectManager" - - /** - * Sets of constants to specify the window to use to run the project. - * - * Should match the values in 'editor/editor_settings.cpp' for the - * 'run/window_placement/android_window' setting. - */ - private const val ANDROID_WINDOW_AUTO = 0 - private const val ANDROID_WINDOW_SAME_AS_EDITOR = 1 - private const val ANDROID_WINDOW_SIDE_BY_SIDE_WITH_EDITOR = 2 - } - - private val commandLineParams = ArrayList() - - override fun onCreate(savedInstanceState : Bundle?) { - // We exclude certain permissions from the set we request at startup, as they'll be - // requested on demand based on use-cases. - PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO)) - - val params = intent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS) - Log.d(TAG, "Received parameters ${params.contentToString()}") - updateCommandLineParams(params) - - if (BuildConfig.BUILD_TYPE == "dev" && WAIT_FOR_DEBUGGER) { - Debug.waitForDebugger(); - } - - super.onCreate(savedInstanceState); - } - - override fun onPandemoniumSetupCompleted() { - super.onPandemoniumSetupCompleted() - val longPressEnabled = enableLongPressGestures() - val panScaleEnabled = enablePanAndScaleGestures() - - checkForProjectPermissionsToEnable() - - runOnUiThread { - // Enable long press, panning and scaling gestures - pandemoniumFragment?.renderView?.inputHandler?.apply { - enableLongPress(longPressEnabled) - enablePanningAndScalingGestures(panScaleEnabled) - } - } - } - - /** - * Check for project permissions to enable - */ - protected open fun checkForProjectPermissionsToEnable() { - // Check for RECORD_AUDIO permission - val audioInputEnabled = java.lang.Boolean.parseBoolean(PandemoniumLib.getGlobal("audio/enable_audio_input")); - if (audioInputEnabled) { - PermissionsUtil.requestPermission(Manifest.permission.RECORD_AUDIO, this) - } - } - - private fun updateCommandLineParams(args: Array?) { - // Update the list of command line params with the new args - commandLineParams.clear() - if (!args.isNullOrEmpty()) { - commandLineParams.addAll(listOf(*args)) - } - if (BuildConfig.BUILD_TYPE == "dev") { - commandLineParams.add("--benchmark") - } - } - - override fun getCommandLine() = commandLineParams - - override fun onNewPandemoniumInstanceRequested(args: Array): Int { - // Parse the arguments to figure out which activity to start. - var targetClass: Class<*> = PandemoniumGame::class.java - var instanceId = GAME_ID - - // Whether we should launch the new pandemonium instance in an adjacent window - // https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_LAUNCH_ADJACENT - var launchAdjacent = shouldGameLaunchAdjacent() - - for (arg in args) { - if (EDITOR_ARG == arg || EDITOR_ARG_SHORT == arg) { - targetClass = PandemoniumEditor::class.java - launchAdjacent = false - instanceId = EDITOR_ID - break - } - - if (PROJECT_MANAGER_ARG == arg || PROJECT_MANAGER_ARG_SHORT == arg) { - targetClass = PandemoniumProjectManager::class.java - launchAdjacent = false - instanceId = PROJECT_MANAGER_ID - break - } - } - - // Launch a new activity - val newInstance = Intent(this, targetClass).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra(EXTRA_COMMAND_LINE_PARAMS, args) - - if (launchAdjacent) { - newInstance.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT) - } - - if (targetClass == javaClass) { - Log.d(TAG, "Restarting $targetClass with parameters ${args.contentToString()}") - ProcessPhoenix.triggerRebirth(this, newInstance) - } else { - Log.d(TAG, "Starting $targetClass with parameters ${args.contentToString()}") - newInstance.putExtra(EXTRA_NEW_LAUNCH, true) - startActivity(newInstance) - } - - return instanceId - } - - override fun enableForStealingFocus(processId: Int) { - if (shouldGameLaunchAdjacent()) { - return; - } - - var reorder_intent : Intent? = null; - - when (processId) { - GAME_ID -> { - reorder_intent = Intent(this, PandemoniumGame::class.java); - } - EDITOR_ID -> { - reorder_intent = Intent(this, PandemoniumEditor::class.java); - } - PROJECT_MANAGER_ID -> { - reorder_intent = Intent(this, PandemoniumProjectManager::class.java); - } - else -> { - // An unknown PID means the original editor instance - reorder_intent = Intent(this, PandemoniumEditor::class.java); - } - } - - if (reorder_intent != null) { - reorder_intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - reorder_intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - startActivity(reorder_intent); - } - } - - override fun moveWindowToForeground() { - if (shouldGameLaunchAdjacent()) { - return; - } - - var reorder_intent : Intent = Intent(this, javaClass); - reorder_intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - reorder_intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - startActivity(reorder_intent); - } - - override fun onPandemoniumForceQuit(pandemoniumInstanceId: Int): Boolean { - val targetClass: Class<*>? - val processNameSuffix: String - - when (pandemoniumInstanceId) { - GAME_ID -> { - processNameSuffix = GAME_PROCESS_NAME_SUFFIX - targetClass = PandemoniumGame::class.java - } - EDITOR_ID -> { - processNameSuffix = EDITOR_PROCESS_NAME_SUFFIX - targetClass = PandemoniumEditor::class.java - } - PROJECT_MANAGER_ID -> { - processNameSuffix = PROJECT_MANAGER_PROCESS_NAME_SUFFIX - targetClass = PandemoniumProjectManager::class.java - } - else -> { - processNameSuffix = "" - targetClass = null - } - } - - if (targetClass == javaClass) { - Log.d(TAG, "Force quitting $targetClass") - ProcessPhoenix.forceQuit(this) - return true - } - - if (processNameSuffix.isBlank()) { - return false - } - - val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager - val runningProcesses = activityManager.runningAppProcesses - for (runningProcess in runningProcesses) { - if (runningProcess.processName.endsWith(processNameSuffix)) { - if (targetClass == null) { - // Killing process directly - Log.v(TAG, "Killing Pandemonium process ${runningProcess.processName}") - Process.killProcess(runningProcess.pid) - } else { - // Activity is running; sending a request for self termination. - Log.v(TAG, "Sending force quit request to $targetClass running on process ${runningProcess.processName}") - val forceQuitIntent = Intent(this, targetClass).putExtra(EXTRA_FORCE_QUIT, true) - startActivity(forceQuitIntent) - } - - return true - } - } - - return false - } - - // 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 Android Editor sets its own orientation via its AndroidManifest - */ - protected open fun overrideOrientationRequest() = true - - /** - * Enable long press gestures for the Pandemonium Android editor. - */ - protected open fun enableLongPressGestures() = - java.lang.Boolean.parseBoolean(PandemoniumLib.getEditorSetting("interface/touchscreen/enable_long_press_as_right_click")) - - /** - * Enable pan and scale gestures for the Pandemonium Android editor. - */ - protected open fun enablePanAndScaleGestures() = - java.lang.Boolean.parseBoolean(PandemoniumLib.getEditorSetting("interface/touchscreen/enable_pan_and_scale_gestures")) - - - - protected open fun shouldGameLaunchAdjacent(): Boolean { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - try { - when (Integer.parseInt(PandemoniumLib.getEditorSetting("run/window_placement/android_window"))) { - ANDROID_WINDOW_SAME_AS_EDITOR -> false - ANDROID_WINDOW_SIDE_BY_SIDE_WITH_EDITOR -> true - else -> { - // ANDROID_WINDOW_AUTO - isInMultiWindowMode || isLargeScreen - } - } - } catch (e: NumberFormatException) { - // Fall-back to the 'Auto' behavior - isInMultiWindowMode || isLargeScreen - } - } else { - false - } - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - // Check if we got the MANAGE_EXTERNAL_STORAGE permission - if (requestCode == PermissionsUtil.REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - if (!Environment.isExternalStorageManager()) { - Toast.makeText( - this, - R.string.denied_storage_permission_error_msg, - Toast.LENGTH_LONG - ).show() - } - } - } - } - - override fun onRequestPermissionsResult( - requestCode: Int, - permissions: Array, - grantResults: IntArray - ) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - // Check if we got access to the necessary storage permissions - if (requestCode == PermissionsUtil.REQUEST_ALL_PERMISSION_REQ_CODE) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { - var hasReadAccess = false - var hasWriteAccess = false - for (i in permissions.indices) { - if (Manifest.permission.READ_EXTERNAL_STORAGE == permissions[i] && grantResults[i] == PackageManager.PERMISSION_GRANTED) { - hasReadAccess = true - } - if (Manifest.permission.WRITE_EXTERNAL_STORAGE == permissions[i] && grantResults[i] == PackageManager.PERMISSION_GRANTED) { - hasWriteAccess = true - } - } - if (!hasReadAccess || !hasWriteAccess) { - Toast.makeText( - this, - R.string.denied_storage_permission_error_msg, - Toast.LENGTH_LONG - ).show() - } - } - } - } -} diff --git a/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumGame.kt b/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumGame.kt deleted file mode 100644 index dac7148..0000000 --- a/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumGame.kt +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************/ -/* PandemoniumGame.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.pandemoniumengine.editor - -import android.content.Intent -import android.os.* - -/** - * Drives the 'run project' window of the Pandemonium Editor. - */ -class PandemoniumGame : PandemoniumEditor() { - private var isAdjacentFlagSet = false - - override fun overrideOrientationRequest() = false - - override fun enableLongPressGestures() = false - - override fun enablePanAndScaleGestures() = false - - override fun checkForProjectPermissionsToEnable() { - // Nothing to do.. by the time we get here, the project permissions will have already - // been requested by the Editor window. - } - - override fun onCreate(savedInstanceState : Bundle?) { - isAdjacentFlagSet = (getIntent().getFlags() and Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0; - - super.onCreate(savedInstanceState); - } - - override fun shouldGameLaunchAdjacent(): Boolean { - return isAdjacentFlagSet - } -} diff --git a/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumProjectManager.kt b/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumProjectManager.kt deleted file mode 100644 index 1eec77c..0000000 --- a/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumProjectManager.kt +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************/ -/* PandemoniumProjectManager.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.pandemoniumengine.editor - -/** - * Launcher activity for the Pandemonium Android Editor. - * - * It presents the user with the project manager interface. - * Upon selection of a project, this activity (via its parent logic) starts the - * [PandemoniumEditor] activity. - */ - -class PandemoniumProjectManager : PandemoniumEditor() { - override fun checkForProjectPermissionsToEnable() { - // Nothing to do here.. we have yet to select a project to load. - } - - override fun shouldGameLaunchAdjacent(): Boolean { - return false - } -} - diff --git a/platform/android/java/editor/src/main/res/values/dimens.xml b/platform/android/java/editor/src/main/res/values/dimens.xml deleted file mode 100644 index 4b05895..0000000 --- a/platform/android/java/editor/src/main/res/values/dimens.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - 600dp - 800dp - \ No newline at end of file diff --git a/platform/android/java/editor/src/main/res/values/strings.xml b/platform/android/java/editor/src/main/res/values/strings.xml deleted file mode 100644 index 590cfc1..0000000 --- a/platform/android/java/editor/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - Pandemonium Editor - Missing storage access permission! - \ No newline at end of file diff --git a/platform/android/java/gradle.properties b/platform/android/java/gradle.properties deleted file mode 100644 index 7ed5419..0000000 --- a/platform/android/java/gradle.properties +++ /dev/null @@ -1,28 +0,0 @@ -# Project-wide Gradle settings. -# NOTE: This should be kept in sync with 'pandemonium/platform/android/java/app/gradle.properties' except -# where otherwise specified. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -android.enableJetifier=true -android.useAndroidX=true - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx4536m - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true - -org.gradle.warning.mode=all - -# Disable resource optimizations for template release build. -# NOTE: This is turned on for custom build in order to improve the release build. -android.enableResourceOptimizations=false diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.jar b/platform/android/java/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e708b1c..0000000 Binary files a/platform/android/java/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.properties b/platform/android/java/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index aa991fc..0000000 --- a/platform/android/java/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/platform/android/java/gradlew b/platform/android/java/gradlew deleted file mode 100755 index 4f906e0..0000000 --- a/platform/android/java/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# 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 -# -# https://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. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/platform/android/java/gradlew.bat b/platform/android/java/gradlew.bat deleted file mode 100644 index 107acd3..0000000 --- a/platform/android/java/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -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 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml deleted file mode 100644 index d354656..0000000 --- a/platform/android/java/lib/AndroidManifest.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/platform/android/java/lib/THIRDPARTY.md b/platform/android/java/lib/THIRDPARTY.md deleted file mode 100644 index 2496b59..0000000 --- a/platform/android/java/lib/THIRDPARTY.md +++ /dev/null @@ -1,39 +0,0 @@ -# Third-party libraries - -This file list third-party libraries used in the Android source folder, -with their provenance and, when relevant, modifications made to those files. - -## com.android.vending.billing - -- Upstream: https://github.com/googlesamples/android-play-billing/tree/master/TrivialDrive/app/src/main -- Version: git (7a94c69, 2019) -- License: Apache 2.0 - -Overwrite the file `aidl/com/android/vending/billing/IInAppBillingService.aidl`. - -## com.google.android.vending.expansion.downloader - -- Upstream: https://github.com/google/play-apk-expansion/tree/master/apkx_library -- Version: git (9ecf54e, 2017) -- License: Apache 2.0 - -Overwrite all files under: - -- `src/com/google/android/vending/expansion/downloader` - -Some files have been modified for yet unclear reasons. -See the `patches/com.google.android.vending.expansion.downloader.patch` file. - -## com.google.android.vending.licensing - -- Upstream: https://github.com/google/play-licensing/tree/master/lvl_library/ -- Version: git (eb57657, 2018) with modifications -- License: Apache 2.0 - -Overwrite all files under: - -- `aidl/com/android/vending/licensing` -- `src/com/google/android/vending/licensing` - -Some files have been modified to silence linter errors or fix downstream issues. -See the `patches/com.google.android.vending.licensing.patch` file. diff --git a/platform/android/java/lib/aidl/com/android/vending/licensing/ILicenseResultListener.aidl b/platform/android/java/lib/aidl/com/android/vending/licensing/ILicenseResultListener.aidl deleted file mode 100644 index 869cb16..0000000 --- a/platform/android/java/lib/aidl/com/android/vending/licensing/ILicenseResultListener.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * 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 com.android.vending.licensing; - -oneway interface ILicenseResultListener { - void verifyLicense(int responseCode, String signedData, String signature); -} diff --git a/platform/android/java/lib/aidl/com/android/vending/licensing/ILicensingService.aidl b/platform/android/java/lib/aidl/com/android/vending/licensing/ILicensingService.aidl deleted file mode 100644 index 9541a20..0000000 --- a/platform/android/java/lib/aidl/com/android/vending/licensing/ILicensingService.aidl +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * 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 com.android.vending.licensing; - -import com.android.vending.licensing.ILicenseResultListener; - -oneway interface ILicensingService { - void checkLicense(long nonce, String packageName, in ILicenseResultListener listener); -} diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle deleted file mode 100644 index 265eeb7..0000000 --- a/platform/android/java/lib/build.gradle +++ /dev/null @@ -1,165 +0,0 @@ -plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' -} - -dependencies { - implementation libraries.kotlinStdLib - implementation libraries.androidxFragment -} - -def pathToRootDir = "../../../../" - -android { - compileSdkVersion versions.compileSdk - buildToolsVersion versions.buildTools - ndkVersion versions.ndkVersion - - defaultConfig { - minSdkVersion versions.minSdk - targetSdkVersion versions.targetSdk - - manifestPlaceholders = [pandemoniumLibraryVersion: getPandemoniumLibraryVersionName()] - } - - compileOptions { - sourceCompatibility versions.javaVersion - targetCompatibility versions.javaVersion - } - - kotlinOptions { - jvmTarget = versions.javaVersion - } - - buildTypes { - dev { - initWith debug - } - } - - flavorDimensions "products" - productFlavors { - editor {} - template {} - } - - lintOptions { - abortOnError false - disable 'MissingTranslation', 'UnusedResources' - } - - packagingOptions { - exclude 'META-INF/LICENSE' - exclude 'META-INF/NOTICE' - - // 'doNotStrip' is enabled for development within Android Studio - if (shouldNotStrip()) { - doNotStrip '**/*.so' - } - } - - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src'] - res.srcDirs = ['res'] - aidl.srcDirs = ['aidl'] - assets.srcDirs = ['assets'] - } - - debug.jniLibs.srcDirs = ['libs/debug'] - dev.jniLibs.srcDirs = ['libs/dev'] - release.jniLibs.srcDirs = ['libs/release'] - - // Editor jni library - editorDebug.jniLibs.srcDirs = ['libs/tools/debug'] - editorDev.jniLibs.srcDirs = ['libs/tools/dev'] - } - - // Disable 'editorRelease'. - // The editor can't be used with target=release as debugging tools are then not - // included, and it would crash on errors instead of reporting them. - variantFilter { variant -> - if (variant.name == "editorRelease") { - setIgnore(true) - } - } - - libraryVariants.all { variant -> - def flavorName = variant.getFlavorName() - - if (flavorName == null || flavorName == "") { - throw new GradleException("Invalid product flavor: $flavorName") - } - - boolean toolsFlag = flavorName == "editor" - - def buildType = variant.buildType.name - if (buildType == null || buildType == "" || !supportedTargetsMap.containsKey(buildType)) { - throw new GradleException("Invalid build type: $buildType") - } - - def sconsTarget = supportedTargetsMap[buildType] - if (sconsTarget == null || sconsTarget == "") { - throw new GradleException("Invalid scons target: $sconsTarget") - } - - // Update the name of the generated library - def outputSuffix = "${buildType}.aar" - if (toolsFlag) { - outputSuffix = "tools.$outputSuffix" - } - - variant.outputs.all { output -> - output.outputFileName = "pandemonium-lib.${outputSuffix}" - } - - // Find scons' executable path - File sconsExecutableFile = null - def sconsName = "scons" - def sconsExts = (org.gradle.internal.os.OperatingSystem.current().isWindows() - ? [".bat", ".cmd", ".ps1", ".exe"] - : [""]) - logger.lifecycle("Looking for $sconsName executable path") - for (ext in sconsExts) { - String sconsNameExt = sconsName + ext - logger.lifecycle("Checking $sconsNameExt") - - sconsExecutableFile = org.gradle.internal.os.OperatingSystem.current().findInPath(sconsNameExt) - if (sconsExecutableFile != null) { - // We're done! - break - } - - // Check all the options in path - List allOptions = org.gradle.internal.os.OperatingSystem.current().findAllInPath(sconsNameExt) - if (!allOptions.isEmpty()) { - // Pick the first option and we're done! - sconsExecutableFile = allOptions.get(0) - break - } - } - - if (sconsExecutableFile == null) { - throw new GradleException("Unable to find executable path for the '$sconsName' command.") - } else { - logger.lifecycle("Found executable path for $sconsName: ${sconsExecutableFile.absolutePath}") - } - - for (String selectedAbi : selectedAbis) { - if (!supportedAbis.contains(selectedAbi)) { - throw new GradleException("Invalid selected abi: $selectedAbi") - } - - // Creating gradle task to generate the native libraries for the selected abi. - def taskName = getSconsTaskName(flavorName, buildType, selectedAbi) - tasks.create(name: taskName, type: Exec) { - executable sconsExecutableFile.absolutePath - args "--directory=${pathToRootDir}", "platform=android", "tools=${toolsFlag}", "target=${sconsTarget}", "android_arch=${selectedAbi}", "-j" + Runtime.runtime.availableProcessors() - } - - // Schedule the tasks so the generated libs are present before the aar file is packaged. - tasks["merge${flavorName.capitalize()}${buildType.capitalize()}JniLibFolders"].dependsOn taskName - } - } -} diff --git a/platform/android/java/lib/patches/com.google.android.vending.expansion.downloader.patch b/platform/android/java/lib/patches/com.google.android.vending.expansion.downloader.patch deleted file mode 100644 index c0b19ab..0000000 --- a/platform/android/java/lib/patches/com.google.android.vending.expansion.downloader.patch +++ /dev/null @@ -1,300 +0,0 @@ -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java -index ad6ea0de6..452c7d148 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java -@@ -32,6 +32,9 @@ import android.os.Messenger; - import android.os.RemoteException; - import android.util.Log; - -+// -- PANDEMONIUM start -- -+import java.lang.ref.WeakReference; -+// -- PANDEMONIUM end -- - - - /** -@@ -118,29 +121,46 @@ public class DownloaderClientMarshaller { - /** - * Target we publish for clients to send messages to IncomingHandler. - */ -- final Messenger mMessenger = new Messenger(new Handler() { -+ // -- PANDEMONIUM start -- -+ private final MessengerHandlerClient mMsgHandler = new MessengerHandlerClient(this); -+ final Messenger mMessenger = new Messenger(mMsgHandler); -+ -+ private static class MessengerHandlerClient extends Handler { -+ private final WeakReference mDownloader; -+ public MessengerHandlerClient(Stub downloader) { -+ mDownloader = new WeakReference<>(downloader); -+ } -+ - @Override - public void handleMessage(Message msg) { -- switch (msg.what) { -- case MSG_ONDOWNLOADPROGRESS: -- Bundle bun = msg.getData(); -- if ( null != mContext ) { -- bun.setClassLoader(mContext.getClassLoader()); -- DownloadProgressInfo dpi = (DownloadProgressInfo) msg.getData() -- .getParcelable(PARAM_PROGRESS); -- mItf.onDownloadProgress(dpi); -- } -- break; -- case MSG_ONDOWNLOADSTATE_CHANGED: -- mItf.onDownloadStateChanged(msg.getData().getInt(PARAM_NEW_STATE)); -- break; -- case MSG_ONSERVICECONNECTED: -- mItf.onServiceConnected( -- (Messenger) msg.getData().getParcelable(PARAM_MESSENGER)); -- break; -+ Stub downloader = mDownloader.get(); -+ if (downloader != null) { -+ downloader.handleMessage(msg); - } - } -- }); -+ } -+ -+ private void handleMessage(Message msg) { -+ switch (msg.what) { -+ case MSG_ONDOWNLOADPROGRESS: -+ Bundle bun = msg.getData(); -+ if (null != mContext) { -+ bun.setClassLoader(mContext.getClassLoader()); -+ DownloadProgressInfo dpi = (DownloadProgressInfo)msg.getData() -+ .getParcelable(PARAM_PROGRESS); -+ mItf.onDownloadProgress(dpi); -+ } -+ break; -+ case MSG_ONDOWNLOADSTATE_CHANGED: -+ mItf.onDownloadStateChanged(msg.getData().getInt(PARAM_NEW_STATE)); -+ break; -+ case MSG_ONSERVICECONNECTED: -+ mItf.onServiceConnected( -+ (Messenger)msg.getData().getParcelable(PARAM_MESSENGER)); -+ break; -+ } -+ } -+ // -- PANDEMONIUM end -- - - public Stub(IDownloaderClient itf, Class downloaderService) { - mItf = itf; -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java -index 979352299..3771d19c9 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java -@@ -25,6 +25,9 @@ import android.os.Message; - import android.os.Messenger; - import android.os.RemoteException; - -+// -- PANDEMONIUM start -- -+import java.lang.ref.WeakReference; -+// -- PANDEMONIUM end -- - - - /** -@@ -108,32 +111,49 @@ public class DownloaderServiceMarshaller { - - private static class Stub implements IStub { - private IDownloaderService mItf = null; -- final Messenger mMessenger = new Messenger(new Handler() { -+ // -- PANDEMONIUM start -- -+ private final MessengerHandlerServer mMsgHandler = new MessengerHandlerServer(this); -+ final Messenger mMessenger = new Messenger(mMsgHandler); -+ -+ private static class MessengerHandlerServer extends Handler { -+ private final WeakReference mDownloader; -+ public MessengerHandlerServer(Stub downloader) { -+ mDownloader = new WeakReference<>(downloader); -+ } -+ - @Override - public void handleMessage(Message msg) { -- switch (msg.what) { -- case MSG_REQUEST_ABORT_DOWNLOAD: -- mItf.requestAbortDownload(); -- break; -- case MSG_REQUEST_CONTINUE_DOWNLOAD: -- mItf.requestContinueDownload(); -- break; -- case MSG_REQUEST_PAUSE_DOWNLOAD: -- mItf.requestPauseDownload(); -- break; -- case MSG_SET_DOWNLOAD_FLAGS: -- mItf.setDownloadFlags(msg.getData().getInt(PARAMS_FLAGS)); -- break; -- case MSG_REQUEST_DOWNLOAD_STATE: -- mItf.requestDownloadStatus(); -- break; -- case MSG_REQUEST_CLIENT_UPDATE: -- mItf.onClientUpdated((Messenger) msg.getData().getParcelable( -- PARAM_MESSENGER)); -- break; -+ Stub downloader = mDownloader.get(); -+ if (downloader != null) { -+ downloader.handleMessage(msg); - } - } -- }); -+ } -+ -+ private void handleMessage(Message msg) { -+ switch (msg.what) { -+ case MSG_REQUEST_ABORT_DOWNLOAD: -+ mItf.requestAbortDownload(); -+ break; -+ case MSG_REQUEST_CONTINUE_DOWNLOAD: -+ mItf.requestContinueDownload(); -+ break; -+ case MSG_REQUEST_PAUSE_DOWNLOAD: -+ mItf.requestPauseDownload(); -+ break; -+ case MSG_SET_DOWNLOAD_FLAGS: -+ mItf.setDownloadFlags(msg.getData().getInt(PARAMS_FLAGS)); -+ break; -+ case MSG_REQUEST_DOWNLOAD_STATE: -+ mItf.requestDownloadStatus(); -+ break; -+ case MSG_REQUEST_CLIENT_UPDATE: -+ mItf.onClientUpdated((Messenger)msg.getData().getParcelable( -+ PARAM_MESSENGER)); -+ break; -+ } -+ } -+ // -- PANDEMONIUM end -- - - public Stub(IDownloaderService itf) { - mItf = itf; -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java -index e4b1b0f1c..36cd6aacf 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java -@@ -24,7 +24,10 @@ import android.os.StatFs; - import android.os.SystemClock; - import android.util.Log; - --import com.android.vending.expansion.downloader.R; -+// -- PANDEMONIUM start -- -+//import com.android.vending.expansion.downloader.R; -+import org.pandemoniumengine.pandemonium.R; -+// -- PANDEMONIUM end -- - - import java.io.File; - import java.text.SimpleDateFormat; -@@ -146,12 +149,14 @@ public class Helpers { - } - return ""; - } -- return String.format("%.2f", -+ // -- PANDEMONIUM start -- -+ return String.format(Locale.ENGLISH, "%.2f", - (float) overallProgress / (1024.0f * 1024.0f)) - + "MB /" + -- String.format("%.2f", (float) overallTotal / -+ String.format(Locale.ENGLISH, "%.2f", (float) overallTotal / - (1024.0f * 1024.0f)) - + "MB"; -+ // -- PANDEMONIUM end -- - } - - /** -@@ -184,7 +189,9 @@ public class Helpers { - } - - public static String getSpeedString(float bytesPerMillisecond) { -- return String.format("%.2f", bytesPerMillisecond * 1000 / 1024); -+ // -- PANDEMONIUM start -- -+ return String.format(Locale.ENGLISH, "%.2f", bytesPerMillisecond * 1000 / 1024); -+ // -- PANDEMONIUM end -- - } - - public static String getTimeRemaining(long durationInMilliseconds) { -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java -index 12edd97ab..a0e1165cc 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java -@@ -26,6 +26,10 @@ import android.net.NetworkInfo; - import android.telephony.TelephonyManager; - import android.util.Log; - -+// -- PANDEMONIUM start -- -+import android.annotation.SuppressLint; -+// -- PANDEMONIUM end -- -+ - /** - * Contains useful helper functions, typically tied to the application context. - */ -@@ -51,6 +55,7 @@ class SystemFacade { - return null; - } - -+ @SuppressLint("MissingPermission") - NetworkInfo activeInfo = connectivity.getActiveNetworkInfo(); - if (activeInfo == null) { - if (Constants.LOGVV) { -@@ -69,6 +74,7 @@ class SystemFacade { - return false; - } - -+ @SuppressLint("MissingPermission") - NetworkInfo info = connectivity.getActiveNetworkInfo(); - boolean isMobile = (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE); - TelephonyManager tm = (TelephonyManager) mContext -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java -index f1536e80e..4b214b22d 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java -@@ -16,7 +16,11 @@ - - package com.google.android.vending.expansion.downloader.impl; - --import com.android.vending.expansion.downloader.R; -+// -- PANDEMONIUM start -- -+//import com.android.vending.expansion.downloader.R; -+import org.pandemoniumengine.pandemonium.R; -+// -- PANDEMONIUM end -- -+ - import com.google.android.vending.expansion.downloader.DownloadProgressInfo; - import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller; - import com.google.android.vending.expansion.downloader.Helpers; -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java -index b2e0e7af0..c114b8a64 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java -@@ -146,8 +146,12 @@ public class DownloadThread { - - try { - PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); -- wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Constants.TAG); -- wakeLock.acquire(); -+ // -- PANDEMONIUM start -- -+ //wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Constants.TAG); -+ //wakeLock.acquire(); -+ wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "org.pandemonium.game:wakelock"); -+ wakeLock.acquire(20 * 60 * 1000L /*20 minutes*/); -+ // -- PANDEMONIUM end -- - - if (Constants.LOGV) { - Log.v(Constants.TAG, "initiating download for " + mInfo.mFileName); -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java -index 4babe476f..8d41a7690 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java -@@ -50,6 +50,10 @@ import android.provider.Settings.Secure; - import android.telephony.TelephonyManager; - import android.util.Log; - -+// -- PANDEMONIUM start -- -+import android.annotation.SuppressLint; -+// -- PANDEMONIUM end -- -+ - import java.io.File; - - /** -@@ -578,6 +582,7 @@ public abstract class DownloaderService extends CustomIntentService implements I - Log.w(Constants.TAG, - "couldn't get connectivity manager to poll network state"); - } else { -+ @SuppressLint("MissingPermission") - NetworkInfo activeInfo = mConnectivityManager - .getActiveNetworkInfo(); - updateNetworkState(activeInfo); diff --git a/platform/android/java/lib/patches/com.google.android.vending.licensing.patch b/platform/android/java/lib/patches/com.google.android.vending.licensing.patch deleted file mode 100644 index 8ae188d..0000000 --- a/platform/android/java/lib/patches/com.google.android.vending.licensing.patch +++ /dev/null @@ -1,42 +0,0 @@ -diff --git a/platform/android/java/src/com/google/android/vending/licensing/PreferenceObfuscator.java b/platform/android/java/src/com/google/android/vending/licensing/PreferenceObfuscator.java -index 7c42bfc28..feb579af0 100644 ---- a/platform/android/java/src/com/google/android/vending/licensing/PreferenceObfuscator.java -+++ b/platform/android/java/src/com/google/android/vending/licensing/PreferenceObfuscator.java -@@ -45,6 +45,9 @@ public class PreferenceObfuscator { - public void putString(String key, String value) { - if (mEditor == null) { - mEditor = mPreferences.edit(); -+ // -- PANDEMONIUM start -- -+ mEditor.apply(); -+ // -- PANDEMONIUM end -- - } - String obfuscatedValue = mObfuscator.obfuscate(value, key); - mEditor.putString(key, obfuscatedValue); -diff --git a/platform/android/java/src/com/google/android/vending/licensing/util/Base64.java b/platform/android/java/src/com/google/android/vending/licensing/util/Base64.java -index a0d2779af..a8bf65f9c 100644 ---- a/platform/android/java/src/com/google/android/vending/licensing/util/Base64.java -+++ b/platform/android/java/src/com/google/android/vending/licensing/util/Base64.java -@@ -31,6 +31,10 @@ package com.google.android.vending.licensing.util; - * @version 1.3 - */ - -+// -- PANDEMONIUM start -- -import org.pandemoniumengine.pandemonium.BuildConfig; -+// -- PANDEMONIUM end -- -+ - /** - * Base64 converter class. This code is not a full-blown MIME encoder; - * it simply converts binary data to base64 data and back. -@@ -341,7 +345,11 @@ public class Base64 { - e += 4; - } - -- assert (e == outBuff.length); -+ // -- PANDEMONIUM start -- -+ //assert (e == outBuff.length); -+ if (BuildConfig.DEBUG && e != outBuff.length) -+ throw new RuntimeException(); -+ // -- PANDEMONIUM end -- - return outBuff; - } - diff --git a/platform/android/java/lib/res/layout/downloading_expansion.xml b/platform/android/java/lib/res/layout/downloading_expansion.xml deleted file mode 100644 index 34c2757..0000000 --- a/platform/android/java/lib/res/layout/downloading_expansion.xml +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - -