android.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. from __future__ import annotations
  2. import os
  3. import re
  4. import sys
  5. from functools import lru_cache
  6. from typing import cast
  7. from .api import PlatformDirsABC
  8. class Android(PlatformDirsABC):
  9. """
  10. Follows the guidance `from here <https://android.stackexchange.com/a/216132>`_. Makes use of the
  11. `appname <platformdirs.api.PlatformDirsABC.appname>` and
  12. `version <platformdirs.api.PlatformDirsABC.version>`.
  13. """
  14. @property
  15. def user_data_dir(self) -> str:
  16. """:return: data directory tied to the user, e.g. ``/data/user/<userid>/<packagename>/files/<AppName>``"""
  17. return self._append_app_name_and_version(cast(str, _android_folder()), "files")
  18. @property
  19. def site_data_dir(self) -> str:
  20. """:return: data directory shared by users, same as `user_data_dir`"""
  21. return self.user_data_dir
  22. @property
  23. def user_config_dir(self) -> str:
  24. """
  25. :return: config directory tied to the user, e.g. ``/data/user/<userid>/<packagename>/shared_prefs/<AppName>``
  26. """
  27. return self._append_app_name_and_version(cast(str, _android_folder()), "shared_prefs")
  28. @property
  29. def site_config_dir(self) -> str:
  30. """:return: config directory shared by the users, same as `user_config_dir`"""
  31. return self.user_config_dir
  32. @property
  33. def user_cache_dir(self) -> str:
  34. """:return: cache directory tied to the user, e.g. e.g. ``/data/user/<userid>/<packagename>/cache/<AppName>``"""
  35. return self._append_app_name_and_version(cast(str, _android_folder()), "cache")
  36. @property
  37. def user_state_dir(self) -> str:
  38. """:return: state directory tied to the user, same as `user_data_dir`"""
  39. return self.user_data_dir
  40. @property
  41. def user_log_dir(self) -> str:
  42. """
  43. :return: log directory tied to the user, same as `user_cache_dir` if not opinionated else ``log`` in it,
  44. e.g. ``/data/user/<userid>/<packagename>/cache/<AppName>/log``
  45. """
  46. path = self.user_cache_dir
  47. if self.opinion:
  48. path = os.path.join(path, "log")
  49. return path
  50. @property
  51. def user_documents_dir(self) -> str:
  52. """
  53. :return: documents directory tied to the user e.g. ``/storage/emulated/0/Documents``
  54. """
  55. return _android_documents_folder()
  56. @property
  57. def user_runtime_dir(self) -> str:
  58. """
  59. :return: runtime directory tied to the user, same as `user_cache_dir` if not opinionated else ``tmp`` in it,
  60. e.g. ``/data/user/<userid>/<packagename>/cache/<AppName>/tmp``
  61. """
  62. path = self.user_cache_dir
  63. if self.opinion:
  64. path = os.path.join(path, "tmp")
  65. return path
  66. @lru_cache(maxsize=1)
  67. def _android_folder() -> str | None:
  68. """:return: base folder for the Android OS or None if cannot be found"""
  69. try:
  70. # First try to get path to android app via pyjnius
  71. from jnius import autoclass
  72. Context = autoclass("android.content.Context") # noqa: N806
  73. result: str | None = Context.getFilesDir().getParentFile().getAbsolutePath()
  74. except Exception:
  75. # if fails find an android folder looking path on the sys.path
  76. pattern = re.compile(r"/data/(data|user/\d+)/(.+)/files")
  77. for path in sys.path:
  78. if pattern.match(path):
  79. result = path.split("/files")[0]
  80. break
  81. else:
  82. result = None
  83. return result
  84. @lru_cache(maxsize=1)
  85. def _android_documents_folder() -> str:
  86. """:return: documents folder for the Android OS"""
  87. # Get directories with pyjnius
  88. try:
  89. from jnius import autoclass
  90. Context = autoclass("android.content.Context") # noqa: N806
  91. Environment = autoclass("android.os.Environment") # noqa: N806
  92. documents_dir: str = Context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath()
  93. except Exception:
  94. documents_dir = "/storage/emulated/0/Documents"
  95. return documents_dir
  96. __all__ = [
  97. "Android",
  98. ]