Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OS.get_external_data_dir() to get Android external directory #49435

Merged
merged 1 commit into from
Jun 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions core/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions core/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ class _OS : public Object {
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;
Expand Down
5 changes: 5 additions & 0 deletions core/os/os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions core/os/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ class OS {
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 {
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/OS.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,10 @@ public String getDataDir() {
return activity.getFilesDir().getAbsolutePath();
}

public String getExternalDataDir() {
return activity.getExternalFilesDir(null).getAbsolutePath();
}

public String getLocale() {
return Locale.getDefault().toString();
}
Expand Down
12 changes: 12 additions & 0 deletions platform/android/java_godot_io_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 2 additions & 0 deletions platform/android/java_godot_io_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class GodotIOJavaWrapper {

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;
Expand All @@ -66,6 +67,7 @@ class GodotIOJavaWrapper {

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();
Expand Down
43 changes: 26 additions & 17 deletions platform/android/os_android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 ".";
}

Expand Down
1 change: 1 addition & 0 deletions platform/android/os_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class OS_Android : public OS_Unix {

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;
Expand Down