Add OS.get_external_data_dir() to get Android external directory

This commit is contained in:
Marcel Admiraal 2021-06-08 17:43:10 +01:00
parent 9539e4e39e
commit b3a962945e
10 changed files with 64 additions and 17 deletions

View file

@ -643,6 +643,10 @@ String _OS::get_user_data_dir() const {
return OS::get_singleton()->get_user_data_dir();
}
String _OS::get_external_data_dir() const {
return OS::get_singleton()->get_external_data_dir();
}
bool _OS::is_debug_build() const {
#ifdef DEBUG_ENABLED
return true;
@ -743,6 +747,7 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_static_memory_peak_usage"), &_OS::get_static_memory_peak_usage);
ClassDB::bind_method(D_METHOD("get_user_data_dir"), &_OS::get_user_data_dir);
ClassDB::bind_method(D_METHOD("get_external_data_dir"), &_OS::get_external_data_dir);
ClassDB::bind_method(D_METHOD("get_system_dir", "dir"), &_OS::get_system_dir);
ClassDB::bind_method(D_METHOD("get_unique_id"), &_OS::get_unique_id);

View file

@ -237,6 +237,7 @@ public:
String get_system_dir(SystemDir p_dir) const;
String get_user_data_dir() const;
String get_external_data_dir() const;
Error set_thread_name(const String &p_name);
Thread::ID get_thread_caller_id() const;

View file

@ -310,6 +310,11 @@ String OS::get_user_data_dir() const {
return ".";
}
// Android OS path to app's external data storage
String OS::get_external_data_dir() const {
return get_user_data_dir();
};
// Absolute path to res://
String OS::get_resource_dir() const {
return ProjectSettings::get_singleton()->get_resource_path();

View file

@ -252,6 +252,7 @@ public:
virtual String get_bundle_resource_dir() const;
virtual String get_user_data_dir() const;
virtual String get_external_data_dir() const;
virtual String get_resource_dir() const;
enum SystemDir {

View file

@ -221,6 +221,13 @@
Returns the path to the current engine executable.
</description>
</method>
<method name="get_external_data_dir" qualifiers="const">
<return type="String">
</return>
<description>
On Android, returns the absolute directory path where user data can be written to external storage if available. On all other platforms, this will return the same location as [method get_user_data_dir].
</description>
</method>
<method name="get_granted_permissions" qualifiers="const">
<return type="PackedStringArray">
</return>

View file

@ -452,6 +452,10 @@ public class GodotIO {
return activity.getFilesDir().getAbsolutePath();
}
public String getExternalDataDir() {
return activity.getExternalFilesDir(null).getAbsolutePath();
}
public String getLocale() {
return Locale.getDefault().toString();
}

View file

@ -49,6 +49,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
_open_URI = p_env->GetMethodID(cls, "openURI", "(Ljava/lang/String;)I");
_get_data_dir = p_env->GetMethodID(cls, "getDataDir", "()Ljava/lang/String;");
_get_external_data_dir = p_env->GetMethodID(cls, "getExternalDataDir", "()Ljava/lang/String;");
_get_locale = p_env->GetMethodID(cls, "getLocale", "()Ljava/lang/String;");
_get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;");
_get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I");
@ -92,6 +93,17 @@ String GodotIOJavaWrapper::get_user_data_dir() {
}
}
String GodotIOJavaWrapper::get_external_data_dir() {
if (_get_external_data_dir) {
JNIEnv *env = get_jni_env();
ERR_FAIL_COND_V(env == nullptr, String());
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_external_data_dir);
return jstring_to_string(s, env);
} else {
return String();
}
}
String GodotIOJavaWrapper::get_locale() {
if (_get_locale) {
JNIEnv *env = get_jni_env();

View file

@ -47,6 +47,7 @@ private:
jmethodID _open_URI = 0;
jmethodID _get_data_dir = 0;
jmethodID _get_external_data_dir = 0;
jmethodID _get_locale = 0;
jmethodID _get_model = 0;
jmethodID _get_screen_DPI = 0;
@ -66,6 +67,7 @@ public:
Error open_uri(const String &p_uri);
String get_user_data_dir();
String get_external_data_dir();
String get_locale();
String get_model();
int get_screen_dpi();

View file

@ -45,6 +45,23 @@
#include "java_godot_io_wrapper.h"
#include "java_godot_wrapper.h"
String _remove_symlink(const String &dir) {
// Workaround for Android 6.0+ using a symlink.
// Save the current directory.
char current_dir_name[2048];
getcwd(current_dir_name, 2048);
// Change directory to the external data directory.
chdir(dir.utf8().get_data());
// Get the actual directory without the potential symlink.
char dir_name_wihout_symlink[2048];
getcwd(dir_name_wihout_symlink, 2048);
// Convert back to a String.
String dir_without_symlink(dir_name_wihout_symlink);
// Restore original current directory.
chdir(current_dir_name);
return dir_without_symlink;
}
class AndroidLogger : public Logger {
public:
virtual void logv(const char *p_format, va_list p_list, bool p_err) {
@ -199,26 +216,18 @@ String OS_Android::get_user_data_dir() const {
String data_dir = godot_io_java->get_user_data_dir();
if (data_dir != "") {
//store current dir
char real_current_dir_name[2048];
getcwd(real_current_dir_name, 2048);
//go to data dir
chdir(data_dir.utf8().get_data());
//get actual data dir, so we resolve potential symlink (Android 6.0+ seems to use symlink)
char data_current_dir_name[2048];
getcwd(data_current_dir_name, 2048);
//cache by parsing utf8
data_dir_cache.parse_utf8(data_current_dir_name);
//restore original dir so we don't mess things up
chdir(real_current_dir_name);
data_dir_cache = _remove_symlink(data_dir);
return data_dir_cache;
}
return ".";
}
String OS_Android::get_external_data_dir() const {
String data_dir = godot_io_java->get_external_data_dir();
if (data_dir != "") {
data_dir = _remove_symlink(data_dir);
return data_dir;
}
return ".";
}

View file

@ -111,6 +111,7 @@ public:
virtual Error shell_open(String p_uri) override;
virtual String get_user_data_dir() const override;
virtual String get_external_data_dir() const override;
virtual String get_resource_dir() const override;
virtual String get_locale() const override;
virtual String get_model_name() const override;