1 from __future__ import annotations
6 from functools import lru_cache
7 from typing import cast
9 from .api import PlatformDirsABC
12 class Android(PlatformDirsABC):
14 Follows the guidance `from here <https://android.stackexchange.com/a/216132>`_. Makes use of the
15 `appname <platformdirs.api.PlatformDirsABC.appname>` and
16 `version <platformdirs.api.PlatformDirsABC.version>`.
20 def user_data_dir(self) -> str:
21 """:return: data directory tied to the user, e.g. ``/data/user/<userid>/<packagename>/files/<AppName>``"""
22 return self._append_app_name_and_version(cast(str, _android_folder()), "files")
25 def site_data_dir(self) -> str:
26 """:return: data directory shared by users, same as `user_data_dir`"""
27 return self.user_data_dir
30 def user_config_dir(self) -> str:
32 :return: config directory tied to the user, e.g. ``/data/user/<userid>/<packagename>/shared_prefs/<AppName>``
34 return self._append_app_name_and_version(cast(str, _android_folder()), "shared_prefs")
37 def site_config_dir(self) -> str:
38 """:return: config directory shared by the users, same as `user_config_dir`"""
39 return self.user_config_dir
42 def user_cache_dir(self) -> str:
43 """:return: cache directory tied to the user, e.g. e.g. ``/data/user/<userid>/<packagename>/cache/<AppName>``"""
44 return self._append_app_name_and_version(cast(str, _android_folder()), "cache")
47 def user_state_dir(self) -> str:
48 """:return: state directory tied to the user, same as `user_data_dir`"""
49 return self.user_data_dir
52 def user_log_dir(self) -> str:
54 :return: log directory tied to the user, same as `user_cache_dir` if not opinionated else ``log`` in it,
55 e.g. ``/data/user/<userid>/<packagename>/cache/<AppName>/log``
57 path = self.user_cache_dir
59 path = os.path.join(path, "log")
63 def user_documents_dir(self) -> str:
65 :return: documents directory tied to the user e.g. ``/storage/emulated/0/Documents``
67 return _android_documents_folder()
70 def user_runtime_dir(self) -> str:
72 :return: runtime directory tied to the user, same as `user_cache_dir` if not opinionated else ``tmp`` in it,
73 e.g. ``/data/user/<userid>/<packagename>/cache/<AppName>/tmp``
75 path = self.user_cache_dir
77 path = os.path.join(path, "tmp")
82 def _android_folder() -> str | None:
83 """:return: base folder for the Android OS or None if cannot be found"""
85 # First try to get path to android app via pyjnius
86 from jnius import autoclass
88 Context = autoclass("android.content.Context") # noqa: N806
89 result: str | None = Context.getFilesDir().getParentFile().getAbsolutePath()
91 # if fails find an android folder looking path on the sys.path
92 pattern = re.compile(r"/data/(data|user/\d+)/(.+)/files")
94 if pattern.match(path):
95 result = path.split("/files")[0]
102 @lru_cache(maxsize=1)
103 def _android_documents_folder() -> str:
104 """:return: documents folder for the Android OS"""
105 # Get directories with pyjnius
107 from jnius import autoclass
109 Context = autoclass("android.content.Context") # noqa: N806
110 Environment = autoclass("android.os.Environment") # noqa: N806
111 documents_dir: str = Context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath()
113 documents_dir = "/storage/emulated/0/Documents"