Path: blob/master/platform/android/java_godot_io_wrapper.cpp
10277 views
/**************************************************************************/1/* java_godot_io_wrapper.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "java_godot_io_wrapper.h"3132#include "core/math/rect2.h"33#include "core/variant/variant.h"3435// JNIEnv is only valid within the thread it belongs to, in a multi threading environment36// we can't cache it.37// For GodotIO we call all access methods from our thread and we thus get a valid JNIEnv38// from get_jni_env().3940GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instance) {41godot_io_instance = p_env->NewGlobalRef(p_godot_io_instance);42if (godot_io_instance) {43cls = p_env->GetObjectClass(godot_io_instance);44if (cls) {45cls = (jclass)p_env->NewGlobalRef(cls);46} else {47// this is a pretty serious fail.. bail... pointers will stay 048return;49}5051_open_URI = p_env->GetMethodID(cls, "openURI", "(Ljava/lang/String;)I");52_get_cache_dir = p_env->GetMethodID(cls, "getCacheDir", "()Ljava/lang/String;");53_get_temp_dir = p_env->GetMethodID(cls, "getTempDir", "()Ljava/lang/String;");54_get_data_dir = p_env->GetMethodID(cls, "getDataDir", "()Ljava/lang/String;");55_get_display_cutouts = p_env->GetMethodID(cls, "getDisplayCutouts", "()[I"),56_get_display_safe_area = p_env->GetMethodID(cls, "getDisplaySafeArea", "()[I"),57_get_locale = p_env->GetMethodID(cls, "getLocale", "()Ljava/lang/String;");58_get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;");59_get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I");60_get_scaled_density = p_env->GetMethodID(cls, "getScaledDensity", "()F");61_get_screen_refresh_rate = p_env->GetMethodID(cls, "getScreenRefreshRate", "(D)D");62_get_unique_id = p_env->GetMethodID(cls, "getUniqueID", "()Ljava/lang/String;");63_show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;IIII)V");64_hide_keyboard = p_env->GetMethodID(cls, "hideKeyboard", "()V");65_has_hardware_keyboard = p_env->GetMethodID(cls, "hasHardwareKeyboard", "()Z");66_set_screen_orientation = p_env->GetMethodID(cls, "setScreenOrientation", "(I)V");67_get_screen_orientation = p_env->GetMethodID(cls, "getScreenOrientation", "()I");68_get_system_dir = p_env->GetMethodID(cls, "getSystemDir", "(IZ)Ljava/lang/String;");69_get_display_rotation = p_env->GetMethodID(cls, "getDisplayRotation", "()I");70}71}7273GodotIOJavaWrapper::~GodotIOJavaWrapper() {74JNIEnv *env = get_jni_env();75ERR_FAIL_NULL(env);7677env->DeleteGlobalRef(cls);78env->DeleteGlobalRef(godot_io_instance);79}8081jobject GodotIOJavaWrapper::get_instance() {82return godot_io_instance;83}8485Error GodotIOJavaWrapper::open_uri(const String &p_uri) {86if (_open_URI) {87JNIEnv *env = get_jni_env();88ERR_FAIL_NULL_V(env, ERR_UNAVAILABLE);89jstring jStr = env->NewStringUTF(p_uri.utf8().get_data());90Error result = env->CallIntMethod(godot_io_instance, _open_URI, jStr) ? ERR_CANT_OPEN : OK;91env->DeleteLocalRef(jStr);92return result;93} else {94return ERR_UNAVAILABLE;95}96}9798String GodotIOJavaWrapper::get_cache_dir() {99if (_get_cache_dir) {100JNIEnv *env = get_jni_env();101ERR_FAIL_NULL_V(env, String());102jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_cache_dir);103return jstring_to_string(s, env);104} else {105return String();106}107}108109String GodotIOJavaWrapper::get_temp_dir() {110if (_get_temp_dir) {111JNIEnv *env = get_jni_env();112ERR_FAIL_NULL_V(env, String());113jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_temp_dir);114return jstring_to_string(s, env);115} else {116return String();117}118}119120String GodotIOJavaWrapper::get_user_data_dir(const String &p_user_dir) {121if (_get_data_dir) {122JNIEnv *env = get_jni_env();123ERR_FAIL_NULL_V(env, String());124jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_data_dir);125return jstring_to_string(s, env);126} else {127return String();128}129}130131String GodotIOJavaWrapper::get_locale() {132if (_get_locale) {133JNIEnv *env = get_jni_env();134ERR_FAIL_NULL_V(env, String());135jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_locale);136return jstring_to_string(s, env);137} else {138return String();139}140}141142String GodotIOJavaWrapper::get_model() {143if (_get_model) {144JNIEnv *env = get_jni_env();145ERR_FAIL_NULL_V(env, String());146jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_model);147return jstring_to_string(s, env);148} else {149return String();150}151}152153int GodotIOJavaWrapper::get_screen_dpi() {154if (_get_screen_DPI) {155JNIEnv *env = get_jni_env();156ERR_FAIL_NULL_V(env, 160);157return env->CallIntMethod(godot_io_instance, _get_screen_DPI);158} else {159return 160;160}161}162163float GodotIOJavaWrapper::get_scaled_density() {164if (_get_scaled_density) {165JNIEnv *env = get_jni_env();166ERR_FAIL_NULL_V(env, 1.0f);167return env->CallFloatMethod(godot_io_instance, _get_scaled_density);168} else {169return 1.0f;170}171}172173float GodotIOJavaWrapper::get_screen_refresh_rate(float fallback) {174if (_get_screen_refresh_rate) {175JNIEnv *env = get_jni_env();176if (env == nullptr) {177ERR_PRINT("An error occurred while trying to get screen refresh rate.");178return fallback;179}180return (float)env->CallDoubleMethod(godot_io_instance, _get_screen_refresh_rate, (double)fallback);181}182ERR_PRINT("An error occurred while trying to get the screen refresh rate.");183return fallback;184}185186TypedArray<Rect2> GodotIOJavaWrapper::get_display_cutouts() {187TypedArray<Rect2> result;188ERR_FAIL_NULL_V(_get_display_cutouts, result);189JNIEnv *env = get_jni_env();190ERR_FAIL_NULL_V(env, result);191jintArray returnArray = (jintArray)env->CallObjectMethod(godot_io_instance, _get_display_cutouts);192jint arrayLength = env->GetArrayLength(returnArray);193jint *arrayBody = env->GetIntArrayElements(returnArray, JNI_FALSE);194int cutouts = arrayLength / 4;195for (int i = 0; i < cutouts; i++) {196int x = arrayBody[i * 4];197int y = arrayBody[i * 4 + 1];198int width = arrayBody[i * 4 + 2];199int height = arrayBody[i * 4 + 3];200Rect2 cutout(x, y, width, height);201result.append(cutout);202}203env->ReleaseIntArrayElements(returnArray, arrayBody, 0);204return result;205}206207Rect2i GodotIOJavaWrapper::get_display_safe_area() {208Rect2i result;209ERR_FAIL_NULL_V(_get_display_safe_area, result);210JNIEnv *env = get_jni_env();211ERR_FAIL_NULL_V(env, result);212jintArray returnArray = (jintArray)env->CallObjectMethod(godot_io_instance, _get_display_safe_area);213ERR_FAIL_COND_V(env->GetArrayLength(returnArray) != 4, result);214jint *arrayBody = env->GetIntArrayElements(returnArray, JNI_FALSE);215result = Rect2i(arrayBody[0], arrayBody[1], arrayBody[2], arrayBody[3]);216env->ReleaseIntArrayElements(returnArray, arrayBody, 0);217return result;218}219220String GodotIOJavaWrapper::get_unique_id() {221if (_get_unique_id) {222JNIEnv *env = get_jni_env();223ERR_FAIL_NULL_V(env, String());224jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_unique_id);225return jstring_to_string(s, env);226} else {227return String();228}229}230231bool GodotIOJavaWrapper::has_vk() {232return (_show_keyboard != nullptr) && (_hide_keyboard != nullptr);233}234235bool GodotIOJavaWrapper::has_hardware_keyboard() {236if (_has_hardware_keyboard) {237JNIEnv *env = get_jni_env();238ERR_FAIL_NULL_V(env, false);239return env->CallBooleanMethod(godot_io_instance, _has_hardware_keyboard);240} else {241return false;242}243}244245void GodotIOJavaWrapper::show_vk(const String &p_existing, int p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) {246if (_show_keyboard) {247JNIEnv *env = get_jni_env();248ERR_FAIL_NULL(env);249jstring jStr = env->NewStringUTF(p_existing.utf8().get_data());250env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_type, p_max_input_length, p_cursor_start, p_cursor_end);251env->DeleteLocalRef(jStr);252}253}254255void GodotIOJavaWrapper::hide_vk() {256if (_hide_keyboard) {257JNIEnv *env = get_jni_env();258ERR_FAIL_NULL(env);259env->CallVoidMethod(godot_io_instance, _hide_keyboard);260}261}262263void GodotIOJavaWrapper::set_screen_orientation(int p_orient) {264if (_set_screen_orientation) {265JNIEnv *env = get_jni_env();266ERR_FAIL_NULL(env);267env->CallVoidMethod(godot_io_instance, _set_screen_orientation, p_orient);268}269}270271int GodotIOJavaWrapper::get_screen_orientation() {272if (_get_screen_orientation) {273JNIEnv *env = get_jni_env();274ERR_FAIL_NULL_V(env, 0);275return env->CallIntMethod(godot_io_instance, _get_screen_orientation);276} else {277return 0;278}279}280281String GodotIOJavaWrapper::get_system_dir(int p_dir, bool p_shared_storage) {282if (_get_system_dir) {283JNIEnv *env = get_jni_env();284ERR_FAIL_NULL_V(env, String("."));285jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_system_dir, p_dir, p_shared_storage);286return jstring_to_string(s, env);287} else {288return String(".");289}290}291292int GodotIOJavaWrapper::get_display_rotation() {293if (_get_display_rotation) {294JNIEnv *env = get_jni_env();295ERR_FAIL_NULL_V(env, 0);296return env->CallIntMethod(godot_io_instance, _get_display_rotation);297} else {298return 0;299}300}301302// SafeNumeric because it can be changed from non-main thread and we need to303// ensure the change is immediately visible to other threads.304static SafeNumeric<int> virtual_keyboard_height;305306int GodotIOJavaWrapper::get_vk_height() {307return virtual_keyboard_height.get();308}309310void GodotIOJavaWrapper::set_vk_height(int p_height) {311virtual_keyboard_height.set(p_height);312}313314315