No project directory on Android
Opened this issue ยท 14 comments
I am calling the following on Android
directories::ProjectDirs::from("me", "nikl", "game");
and get back None
. The package identifier is me.nikl.game
and the app is running on a real device with Android 12.
Is there anything I need to setup or configure to get a proper project directory on Android?
Hi @NiklasEi,
that should work, can you check whether BaseDirs
and UserDirs
also return None
? Using the dirs
crate, can you check what dirs::home_dir()
returns?
Thanks,
Simon
Hey @soc,
I just checked and yes, both BaseDirs
and UserDirs
return None
. The same goes for dirs::home_dir()
.
I am testing this on a galaxy S10+ if that's of any help.
I am getting the same response from dirs::home_dir()
on two different emulated pixel phones. Should this crate work for android emulators?
I suspect that home_dir
is the culprit and everything else are just the result of that returning None
.
Does Android have any sensible definition of a home directory?
Looking at the implementation, https://github.com/dirs-dev/dirs-sys-rs/blob/main/src/lib.rs#L33, we rely on the environment variable and do not offer a fallback. Can you check whether the env var is set on Android?
Running adb shell
with my device connected via USB followed by echo $HOME
I get /
back, which is not the correct directory for an app to write to or read from.
It seems that the intended way of getting the correct directory is calling Context#getFilesDir, which according to the android stackexchange should point to /data/data/<app>/files
or /data/users/<n>/<app>/files
depending on your setup.
I tried some paths in my app and managed to write and read from /data/data/me.nikl.game/files
๐ฅณ
I might have found something with env variables: https://cs.android.com/android/platform/superproject/+/refs/heads/master:frameworks/base/core/java/android/os/Environment.java;drc=a3bb1640c5a3422645b8493ee0bb00eab4266c32;l=98
The env variable ANDROID_DATA
is set to /data
on my device. It still might be an issue to hard code the /data/<identifier>/files
in case we should be using /users/<n>/<identifier>/files
instead. I haven't understood in what scenario the second path is chosen.
There seem to be multiple possible directories for a given application and I cannot see another way to get the intended one from a simple environment variable. See https://cs.android.com/android/platform/superproject/+/refs/heads/master:frameworks/base/core/java/android/app/ContextImpl.java;l=2950
I ended up using the actual app context via android-activity
. Interestingly, this returns /data/user/0/me.nikl.game/files
and not /data/data/me.nikl.game/files
(which also works though).
I think it would make sense to generally use Android-level APIs in the implementation instead of trying to pretend that Android is just another Linux as dirs
or std
does ... ๐ค
I might have found something with env variables: cs.android.com/android/platform/superproject/+/refs/heads/master:frameworks/base/core/java/android/os/Environment.java;drc=a3bb1640c5a3422645b8493ee0bb00eab4266c32;l=98 The env variable
ANDROID_DATA
is set to/data
on my device. It still might be an issue to hard code the/data/<identifier>/files
in case we should be using/users/<n>/<identifier>/files
instead. I haven't understood in what scenario the second path is chosen.There seem to be multiple possible directories for a given application and I cannot see another way to get the intended one from a simple environment variable. See cs.android.com/android/platform/superproject/+/refs/heads/master:frameworks/base/core/java/android/app/ContextImpl.java;l=2950
iirc some android phones offer multi-user functionality and this is why they have this structure
@NiklasEi here you can see how the tauri project looks up directories on Android https://github.com/tauri-apps/tauri/blob/48b1fd74b1df5c3628d00aaae9371dd094466fe5/core/tauri/src/path/android.rs
I would recommend against implementing this in directories
. It will require FFI calls to JNI, at a minimum, and will significantly increase the complexity of the library. Android is definitely not just another linux, certainly not in terms of userspace, and definitely doesn't implement the XDG Base Directories spec.
Another point against this is that the actual location that an app can write to on Android is an implementation detail. I'm pretty sure it's not guaranteed anywhere, so it can be altered by the device vendor. Android fragmentation is a massive problem and it's not a maintenance burden that directories should take on, IMHO.
Trying to bypass the Android APIs to get this implemented in directories is just asking for trouble. Google breaks things like this on each new version of Android, and it's painful enough if you are using the offical APIs!
I am also against adding complexity via FFIs.
It's probably better to have something that works on a number of devices than none.
What do you think about trying to detect write access heuristically?
/data/user/0/me.nikl.game/files and not /data/data/me.nikl.game/files (which also works though).
Wouldn't /data/data simply be a physical link or a symbolic link to /data/user/0/.... which makes it possible to simplify usage when a person connects in an authorized manner on a android? I haven't checked.
We could start from the existence of ANDROID_DATA:
-
choose ANDROID_DATA/data or ANDROID_DATA/user as root by simply reading the existence of these folders.
2.1 if "user" loop over the <identifier> in descending order
2.1.1 Check the existence of a folder "me.nickl.game"/file/.directory-rs/ or try to create it? -> OK = path found
2.2 if not "data", Check the existence of a folder "me.nickl.game"/file/.directory-rs or create it? -> OK = path found
This location could then serve as the root for the lib?
What do you think ? Do you see any contraindication?
- I see
ANDROID_STORAGE
andEXTERNAL_STORAGE
we can use too.
My guess is we can always write here : $ANDROID_STORAGE/self/primary
for shared internal directory
- I confirm
/data/data
has the same inode number than/data/user/0
-> HARD LINK
My guess is we can always write here : $ANDROID_DATA/data/<package identifier>/files
for private app directory.
I ask chat-gpt and mixtral 8x7B-32768 about that and AI confirm.
Heuristic detection is certainly usefulness.
Real question is now where to map home_dir()
:-) Mixtral answer $ANDROID_DATA/data/<package identifier>/files
.
$ANDROID_STORAGE/self/primary
can be see like a mount from UNIX point of view.