Add partial support for Android scoped storage.

This is done by providing API access to app specific directories which don't have any limitations and allows us to bump the target sdk version to 30.
In addition, we're also bumping the min sdk version to 19 as version 18 is no longer supported by Google Play Services and only account of 0.3% of Android devices.
This commit is contained in:
ne0fhyk 2021-07-10 18:39:31 -07:00
parent cfdac0973c
commit 3a00ff1cce
23 changed files with 121 additions and 263 deletions

View file

@ -456,10 +456,6 @@ 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();
}
String _OS::get_config_dir() const {
// Exposed as `get_config_dir()` instead of `get_config_path()` for consistency with other exposed OS methods.
return OS::get_singleton()->get_config_path();
@ -483,8 +479,8 @@ bool _OS::is_debug_build() const {
#endif
}
String _OS::get_system_dir(SystemDir p_dir) const {
return OS::get_singleton()->get_system_dir(OS::SystemDir(p_dir));
String _OS::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
return OS::get_singleton()->get_system_dir(OS::SystemDir(p_dir), p_shared_storage);
}
String _OS::get_keycode_string(uint32_t p_code) const {
@ -567,8 +563,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_system_dir", "dir", "shared_storage"), &_OS::get_system_dir, DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_config_dir"), &_OS::get_config_dir);
ClassDB::bind_method(D_METHOD("get_data_dir"), &_OS::get_data_dir);
ClassDB::bind_method(D_METHOD("get_cache_dir"), &_OS::get_cache_dir);

View file

@ -229,10 +229,9 @@ public:
SYSTEM_DIR_RINGTONES,
};
String get_system_dir(SystemDir p_dir) const;
String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const;
String get_user_data_dir() const;
String get_external_data_dir() const;
String get_config_dir() const;
String get_data_dir() const;
String get_cache_dir() const;

View file

@ -277,18 +277,13 @@ 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();
}
// Access system-specific dirs like Documents, Downloads, etc.
String OS::get_system_dir(SystemDir p_dir) const {
String OS::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
return ".";
}

View file

@ -250,7 +250,6 @@ 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 {
@ -264,7 +263,7 @@ public:
SYSTEM_DIR_RINGTONES,
};
virtual String get_system_dir(SystemDir p_dir) const;
virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const;
virtual Error move_to_trash(const String &p_path) { return FAILED; }

View file

@ -197,12 +197,6 @@
Returns the path to the current engine executable.
</description>
</method>
<method name="get_external_data_dir" qualifiers="const">
<return type="String" />
<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" />
<description>
@ -270,9 +264,11 @@
<method name="get_system_dir" qualifiers="const">
<return type="String" />
<argument index="0" name="dir" type="int" enum="OS.SystemDir" />
<argument index="1" name="shared_storage" type="bool" default="true" />
<description>
Returns the actual path to commonly used folders across different platforms. Available locations are specified in [enum SystemDir].
[b]Note:[/b] This method is implemented on Android, Linux, macOS and Windows.
[b]Note:[/b] Shared storage is implemented on Android and allows to differentiate between app specific and shared directories. Shared directories have additional restrictions on Android.
</description>
</method>
<method name="get_thread_caller_id" qualifiers="const">

View file

@ -717,6 +717,10 @@ Error EditorExportPlatformAndroid::copy_gradle_so(void *p_userdata, const Shared
return OK;
}
bool EditorExportPlatformAndroid::_has_storage_permission(const Vector<String> &p_permissions) {
return p_permissions.find("android.permission.READ_EXTERNAL_STORAGE") != -1 || p_permissions.find("android.permission.WRITE_EXTERNAL_STORAGE") != -1;
}
void EditorExportPlatformAndroid::_get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions) {
const char **aperms = android_perms;
while (*aperms) {
@ -763,12 +767,17 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref<EditorExportPres
Vector<String> perms;
_get_permissions(p_preset, p_give_internet, perms);
for (int i = 0; i < perms.size(); i++) {
manifest_text += vformat(" <uses-permission android:name=\"%s\" />\n", perms.get(i));
String permission = perms.get(i);
if (permission == "android.permission.WRITE_EXTERNAL_STORAGE" || permission == "android.permission.READ_EXTERNAL_STORAGE") {
manifest_text += vformat(" <uses-permission android:name=\"%s\" android:maxSdkVersion=\"29\" />\n", permission);
} else {
manifest_text += vformat(" <uses-permission android:name=\"%s\" />\n", permission);
}
}
manifest_text += _get_xr_features_tag(p_preset);
manifest_text += _get_instrumentation_tag(p_preset);
manifest_text += _get_application_tag(p_preset);
manifest_text += _get_application_tag(p_preset, _has_storage_permission(perms));
manifest_text += "</manifest>\n";
String manifest_path = vformat("res://android/build/src/%s/AndroidManifest.xml", (p_debug ? "debug" : "release"));
@ -824,6 +833,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
Vector<String> perms;
// Write permissions into the perms variable.
_get_permissions(p_preset, p_give_internet, perms);
bool has_storage_permission = _has_storage_permission(perms);
while (ofs < (uint32_t)p_manifest.size()) {
uint32_t chunk = decode_uint32(&p_manifest[ofs]);
@ -913,6 +923,10 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
}
}
if (tname == "application" && attrname == "requestLegacyExternalStorage") {
encode_uint32(has_storage_permission ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]);
}
if (tname == "application" && attrname == "allowBackup") {
encode_uint32(backup_allowed, &p_manifest.write[iofs + 16]);
}

View file

@ -134,6 +134,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
static Error copy_gradle_so(void *p_userdata, const SharedObject &p_so);
bool _has_storage_permission(const Vector<String> &p_permissions);
void _get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions);
void _write_tmp_manifest(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, bool p_debug);

View file

@ -235,18 +235,20 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
return manifest_activity_text;
}
String _get_application_tag(const Ref<EditorExportPreset> &p_preset) {
String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_storage_permission) {
String manifest_application_text = vformat(
" <application android:label=\"@string/godot_project_name_string\"\n"
" android:allowBackup=\"%s\"\n"
" android:icon=\"@mipmap/icon\"\n"
" android:isGame=\"%s\"\n"
" android:hasFragileUserData=\"%s\"\n"
" tools:replace=\"android:allowBackup,android:isGame,android:hasFragileUserData\"\n"
" android:requestLegacyExternalStorage=\"%s\"\n"
" tools:replace=\"android:allowBackup,android:isGame,android:hasFragileUserData,android:requestLegacyExternalStorage\"\n"
" tools:ignore=\"GoogleAppIndexingWarning\">\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_preset->get("package/retain_data_on_uninstall")),
bool_to_string(p_has_storage_permission));
manifest_application_text += _get_activity_tag(p_preset);
manifest_application_text += " </application>\n";

View file

@ -81,6 +81,6 @@ String _get_instrumentation_tag(const Ref<EditorExportPreset> &p_preset);
String _get_activity_tag(const Ref<EditorExportPreset> &p_preset);
String _get_application_tag(const Ref<EditorExportPreset> &p_preset);
String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_storage_permission);
#endif //GODOT_GRADLE_EXPORT_UTIL_H

View file

@ -22,6 +22,7 @@
android:icon="@mipmap/icon"
android:isGame="true"
android:hasFragileUserData="false"
android:requestLegacyExternalStorage="false"
tools:ignore="GoogleAppIndexingWarning" >
<!-- Records the version of the Godot editor used for building -->

View file

@ -1,8 +1,8 @@
ext.versions = [
androidGradlePlugin: '4.2.1',
compileSdk : 29,
minSdk : 18,
targetSdk : 29,
androidGradlePlugin: '4.2.2',
compileSdk : 30,
minSdk : 19,
targetSdk : 30,
buildTools : '30.0.3',
supportCoreUtils : '1.0.0',
kotlinVersion : '1.5.10',

View file

@ -49,7 +49,6 @@ import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
@ -68,15 +67,12 @@ import android.os.Environment;
import android.os.Messenger;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings.Secure;
import android.view.Display;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
@ -471,7 +467,6 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
final Activity activity = getActivity();
io = new GodotIO(activity);
io.unique_id = Secure.getString(activity.getContentResolver(), Secure.ANDROID_ID);
GodotLib.io = io;
netUtils = new GodotNetUtils(activity);
mSensorManager = (SensorManager)activity.getSystemService(Context.SENSOR_SERVICE);

View file

@ -30,15 +30,19 @@
package org.godotengine.godot;
import org.godotengine.godot.input.*;
import org.godotengine.godot.input.GodotEditText;
import android.app.Activity;
import android.content.*;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.AssetManager;
import android.graphics.Point;
import android.net.Uri;
import android.os.*;
import android.os.Build;
import android.os.Environment;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseArray;
@ -47,14 +51,16 @@ import android.view.DisplayCutout;
import android.view.WindowInsets;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
// Wrapper for native library
public class GodotIO {
AssetManager am;
final Activity activity;
private static final String TAG = GodotIO.class.getSimpleName();
private final AssetManager am;
private final Activity activity;
private final String uniqueId;
GodotEditText edit;
final int SCREEN_LANDSCAPE = 0;
@ -65,167 +71,6 @@ public class GodotIO {
final int SCREEN_SENSOR_PORTRAIT = 5;
final int SCREEN_SENSOR = 6;
/////////////////////////
/// FILES
/////////////////////////
public int last_file_id = 1;
static class AssetData {
public boolean eof = false;
public String path;
public InputStream is;
public int len;
public int pos;
}
SparseArray<AssetData> streams;
public int file_open(String path, boolean write) {
//System.out.printf("file_open: Attempt to Open %s\n",path);
//Log.v("MyApp", "TRYING TO OPEN FILE: " + path);
if (write)
return -1;
AssetData ad = new AssetData();
try {
ad.is = am.open(path);
} catch (Exception e) {
//System.out.printf("Exception on file_open: %s\n",path);
return -1;
}
try {
ad.len = ad.is.available();
} catch (Exception e) {
System.out.printf("Exception availabling on file_open: %s\n", path);
return -1;
}
ad.path = path;
ad.pos = 0;
++last_file_id;
streams.put(last_file_id, ad);
return last_file_id;
}
public int file_get_size(int id) {
if (streams.get(id) == null) {
System.out.printf("file_get_size: Invalid file id: %d\n", id);
return -1;
}
return streams.get(id).len;
}
public void file_seek(int id, int bytes) {
if (streams.get(id) == null) {
System.out.printf("file_get_size: Invalid file id: %d\n", id);
return;
}
//seek sucks
AssetData ad = streams.get(id);
if (bytes > ad.len)
bytes = ad.len;
if (bytes < 0)
bytes = 0;
try {
if (bytes > (int)ad.pos) {
int todo = bytes - (int)ad.pos;
while (todo > 0) {
todo -= ad.is.skip(todo);
}
ad.pos = bytes;
} else if (bytes < (int)ad.pos) {
ad.is = am.open(ad.path);
ad.pos = bytes;
int todo = bytes;
while (todo > 0) {
todo -= ad.is.skip(todo);
}
}
ad.eof = false;
} catch (IOException e) {
System.out.printf("Exception on file_seek: %s\n", e);
return;
}
}
public int file_tell(int id) {
if (streams.get(id) == null) {
System.out.printf("file_read: Can't tell eof for invalid file id: %d\n", id);
return 0;
}
AssetData ad = streams.get(id);
return ad.pos;
}
public boolean file_eof(int id) {
if (streams.get(id) == null) {
System.out.printf("file_read: Can't check eof for invalid file id: %d\n", id);
return false;
}
AssetData ad = streams.get(id);
return ad.eof;
}
public byte[] file_read(int id, int bytes) {
if (streams.get(id) == null) {
System.out.printf("file_read: Can't read invalid file id: %d\n", id);
return new byte[0];
}
AssetData ad = streams.get(id);
if (ad.pos + bytes > ad.len) {
bytes = ad.len - ad.pos;
ad.eof = true;
}
if (bytes == 0) {
return new byte[0];
}
byte[] buf1 = new byte[bytes];
int r = 0;
try {
r = ad.is.read(buf1);
} catch (IOException e) {
System.out.printf("Exception on file_read: %s\n", e);
return new byte[bytes];
}
if (r == 0) {
return new byte[0];
}
ad.pos += r;
if (r < bytes) {
byte[] buf2 = new byte[r];
for (int i = 0; i < r; i++)
buf2[i] = buf1[i];
return buf2;
} else {
return buf1;
}
}
public void file_close(int id) {
if (streams.get(id) == null) {
System.out.printf("file_close: Can't close invalid file id: %d\n", id);
return;
}
streams.remove(id);
}
/////////////////////////
/// DIRECTORIES
/////////////////////////
@ -236,9 +81,9 @@ public class GodotIO {
public String path;
}
public int last_dir_id = 1;
private int last_dir_id = 1;
SparseArray<AssetDir> dirs;
private final SparseArray<AssetDir> dirs;
public int dir_open(String path) {
AssetDir ad = new AssetDir();
@ -257,7 +102,6 @@ public class GodotIO {
return -1;
}
//System.out.printf("Opened dir: %s\n",path);
++last_dir_id;
dirs.put(last_dir_id, ad);
@ -320,9 +164,14 @@ public class GodotIO {
GodotIO(Activity p_activity) {
am = p_activity.getAssets();
activity = p_activity;
//streams = new HashMap<Integer, AssetData>();
streams = new SparseArray<>();
dirs = new SparseArray<>();
String androidId = Settings.Secure.getString(activity.getContentResolver(),
Settings.Secure.ANDROID_ID);
if (androidId == null) {
androidId = "";
}
uniqueId = androidId;
}
/////////////////////////
@ -331,7 +180,6 @@ public class GodotIO {
public int openURI(String p_uri) {
try {
Log.v("MyApp", "TRYING TO OPEN URI: " + p_uri);
String path = p_uri;
String type = "";
if (path.startsWith("/")) {
@ -357,12 +205,12 @@ public class GodotIO {
}
}
public String getDataDir() {
return activity.getFilesDir().getAbsolutePath();
public String getCacheDir() {
return activity.getCacheDir().getAbsolutePath();
}
public String getExternalDataDir() {
return activity.getExternalFilesDir(null).getAbsolutePath();
public String getDataDir() {
return activity.getFilesDir().getAbsolutePath();
}
public String getLocale() {
@ -456,51 +304,58 @@ public class GodotIO {
public static final int SYSTEM_DIR_PICTURES = 6;
public static final int SYSTEM_DIR_RINGTONES = 7;
public String getSystemDir(int idx) {
String what = "";
public String getSystemDir(int idx, boolean shared_storage) {
String what;
switch (idx) {
case SYSTEM_DIR_DESKTOP: {
//what=Environment.DIRECTORY_DOCUMENTS;
what = Environment.DIRECTORY_DOWNLOADS;
case SYSTEM_DIR_DESKTOP:
default: {
what = null; // This leads to the app specific external root directory.
} break;
case SYSTEM_DIR_DCIM: {
what = Environment.DIRECTORY_DCIM;
} break;
} break;
case SYSTEM_DIR_DOCUMENTS: {
what = Environment.DIRECTORY_DOWNLOADS;
//what=Environment.DIRECTORY_DOCUMENTS;
what = Environment.DIRECTORY_DOCUMENTS;
} break;
case SYSTEM_DIR_DOWNLOADS: {
what = Environment.DIRECTORY_DOWNLOADS;
} break;
case SYSTEM_DIR_MOVIES: {
what = Environment.DIRECTORY_MOVIES;
} break;
case SYSTEM_DIR_MUSIC: {
what = Environment.DIRECTORY_MUSIC;
} break;
case SYSTEM_DIR_PICTURES: {
what = Environment.DIRECTORY_PICTURES;
} break;
case SYSTEM_DIR_RINGTONES: {
what = Environment.DIRECTORY_RINGTONES;
} break;
}
if (what.equals(""))
return "";
return Environment.getExternalStoragePublicDirectory(what).getAbsolutePath();
if (shared_storage) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Log.w(TAG, "Shared storage access is limited on Android 10 and higher.");
}
if (TextUtils.isEmpty(what)) {
return Environment.getExternalStorageDirectory().getAbsolutePath();
} else {
return Environment.getExternalStoragePublicDirectory(what).getAbsolutePath();
}
} else {
return activity.getExternalFilesDir(what).getAbsolutePath();
}
}
protected static final String PREFS_FILE = "device_id.xml";
protected static final String PREFS_DEVICE_ID = "device_id";
public static String unique_id = "";
public String getUniqueID() {
return unique_id;
return uniqueId;
}
}

View file

@ -48,8 +48,8 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
}
_open_URI = p_env->GetMethodID(cls, "openURI", "(Ljava/lang/String;)I");
_get_cache_dir = p_env->GetMethodID(cls, "getCacheDir", "()Ljava/lang/String;");
_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");
@ -59,7 +59,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
_hide_keyboard = p_env->GetMethodID(cls, "hideKeyboard", "()V");
_set_screen_orientation = p_env->GetMethodID(cls, "setScreenOrientation", "(I)V");
_get_screen_orientation = p_env->GetMethodID(cls, "getScreenOrientation", "()I");
_get_system_dir = p_env->GetMethodID(cls, "getSystemDir", "(I)Ljava/lang/String;");
_get_system_dir = p_env->GetMethodID(cls, "getSystemDir", "(IZ)Ljava/lang/String;");
}
}
@ -82,22 +82,22 @@ Error GodotIOJavaWrapper::open_uri(const String &p_uri) {
}
}
String GodotIOJavaWrapper::get_user_data_dir() {
if (_get_data_dir) {
String GodotIOJavaWrapper::get_cache_dir() {
if (_get_cache_dir) {
JNIEnv *env = get_jni_env();
ERR_FAIL_COND_V(env == nullptr, String());
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_data_dir);
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_cache_dir);
return jstring_to_string(s, env);
} else {
return String();
}
}
String GodotIOJavaWrapper::get_external_data_dir() {
if (_get_external_data_dir) {
String GodotIOJavaWrapper::get_user_data_dir() {
if (_get_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);
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_data_dir);
return jstring_to_string(s, env);
} else {
return String();
@ -200,11 +200,11 @@ int GodotIOJavaWrapper::get_screen_orientation() {
}
}
String GodotIOJavaWrapper::get_system_dir(int p_dir) {
String GodotIOJavaWrapper::get_system_dir(int p_dir, bool p_shared_storage) {
if (_get_system_dir) {
JNIEnv *env = get_jni_env();
ERR_FAIL_COND_V(env == nullptr, String("."));
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_system_dir, p_dir);
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_system_dir, p_dir, p_shared_storage);
return jstring_to_string(s, env);
} else {
return String(".");

View file

@ -46,8 +46,8 @@ private:
jclass cls;
jmethodID _open_URI = 0;
jmethodID _get_cache_dir = 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,8 +66,8 @@ public:
jobject get_instance();
Error open_uri(const String &p_uri);
String get_cache_dir();
String get_user_data_dir();
String get_external_data_dir();
String get_locale();
String get_model();
int get_screen_dpi();
@ -80,7 +80,7 @@ public:
void set_vk_height(int p_height);
void set_screen_orientation(int p_orient);
int get_screen_orientation();
String get_system_dir(int p_dir);
String get_system_dir(int p_dir, bool p_shared_storage);
};
#endif /* !JAVA_GODOT_IO_WRAPPER_H */

View file

@ -213,6 +213,10 @@ String OS_Android::get_model_name() const {
return OS_Unix::get_model_name();
}
String OS_Android::get_data_path() const {
return get_user_data_dir();
}
String OS_Android::get_user_data_dir() const {
if (data_dir_cache != String())
return data_dir_cache;
@ -225,11 +229,11 @@ String OS_Android::get_user_data_dir() const {
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;
String OS_Android::get_cache_path() const {
String cache_dir = godot_io_java->get_cache_dir();
if (cache_dir != "") {
cache_dir = _remove_symlink(cache_dir);
return cache_dir;
}
return ".";
}
@ -242,8 +246,8 @@ String OS_Android::get_unique_id() const {
return OS::get_unique_id();
}
String OS_Android::get_system_dir(SystemDir p_dir) const {
return godot_io_java->get_system_dir(p_dir);
String OS_Android::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
return godot_io_java->get_system_dir(p_dir, p_shared_storage);
}
void OS_Android::set_display_size(const Size2i &p_size) {

View file

@ -110,14 +110,15 @@ 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_data_path() const override;
virtual String get_cache_path() const override;
virtual String get_resource_dir() const override;
virtual String get_locale() const override;
virtual String get_model_name() const override;
virtual String get_unique_id() const override;
virtual String get_system_dir(SystemDir p_dir) const override;
virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
void vibrate_handheld(int p_duration_ms) override;

View file

@ -273,7 +273,7 @@ String OS_LinuxBSD::get_cache_path() const {
}
}
String OS_LinuxBSD::get_system_dir(SystemDir p_dir) const {
String OS_LinuxBSD::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
String xdgparam;
switch (p_dir) {

View file

@ -84,7 +84,7 @@ public:
virtual String get_data_path() const override;
virtual String get_cache_path() const override;
virtual String get_system_dir(SystemDir p_dir) const override;
virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
virtual Error shell_open(String p_uri) override;

View file

@ -84,7 +84,7 @@ public:
virtual String get_bundle_resource_dir() const override;
virtual String get_godot_dir_name() const override;
virtual String get_system_dir(SystemDir p_dir) const override;
virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
Error shell_open(String p_uri) override;

View file

@ -395,7 +395,7 @@ String OS_OSX::get_godot_dir_name() const {
return String(VERSION_SHORT_NAME).capitalize();
}
String OS_OSX::get_system_dir(SystemDir p_dir) const {
String OS_OSX::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
NSSearchPathDirectory id;
bool found = true;

View file

@ -681,7 +681,7 @@ String OS_Windows::get_godot_dir_name() const {
return String(VERSION_SHORT_NAME).capitalize();
}
String OS_Windows::get_system_dir(SystemDir p_dir) const {
String OS_Windows::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
KNOWNFOLDERID id;
switch (p_dir) {

View file

@ -150,7 +150,7 @@ public:
virtual String get_cache_path() const override;
virtual String get_godot_dir_name() const override;
virtual String get_system_dir(SystemDir p_dir) const override;
virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
virtual String get_user_data_dir() const override;
virtual String get_unique_id() const override;