eda80935123cb5db7e18d7fb82fe5f71991d7af8
[SubU] /
1 from __future__ import annotations
2
3 import os
4 import re
5 import sys
6 from functools import lru_cache
7 from typing import cast
8
9 from .api import PlatformDirsABC
10
11
12 class Android(PlatformDirsABC):
13     """
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>`.
17     """
18
19     @property
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")
23
24     @property
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
28
29     @property
30     def user_config_dir(self) -> str:
31         """
32         :return: config directory tied to the user, e.g. ``/data/user/<userid>/<packagename>/shared_prefs/<AppName>``
33         """
34         return self._append_app_name_and_version(cast(str, _android_folder()), "shared_prefs")
35
36     @property
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
40
41     @property
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")
45
46     @property
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
50
51     @property
52     def user_log_dir(self) -> str:
53         """
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``
56         """
57         path = self.user_cache_dir
58         if self.opinion:
59             path = os.path.join(path, "log")
60         return path
61
62     @property
63     def user_documents_dir(self) -> str:
64         """
65         :return: documents directory tied to the user e.g. ``/storage/emulated/0/Documents``
66         """
67         return _android_documents_folder()
68
69     @property
70     def user_runtime_dir(self) -> str:
71         """
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``
74         """
75         path = self.user_cache_dir
76         if self.opinion:
77             path = os.path.join(path, "tmp")
78         return path
79
80
81 @lru_cache(maxsize=1)
82 def _android_folder() -> str | None:
83     """:return: base folder for the Android OS or None if cannot be found"""
84     try:
85         # First try to get path to android app via pyjnius
86         from jnius import autoclass
87
88         Context = autoclass("android.content.Context")  # noqa: N806
89         result: str | None = Context.getFilesDir().getParentFile().getAbsolutePath()
90     except Exception:
91         # if fails find an android folder looking path on the sys.path
92         pattern = re.compile(r"/data/(data|user/\d+)/(.+)/files")
93         for path in sys.path:
94             if pattern.match(path):
95                 result = path.split("/files")[0]
96                 break
97         else:
98             result = None
99     return result
100
101
102 @lru_cache(maxsize=1)
103 def _android_documents_folder() -> str:
104     """:return: documents folder for the Android OS"""
105     # Get directories with pyjnius
106     try:
107         from jnius import autoclass
108
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()
112     except Exception:
113         documents_dir = "/storage/emulated/0/Documents"
114
115     return documents_dir
116
117
118 __all__ = [
119     "Android",
120 ]