welcome[bot]: Thanks for opening your first pull request here! 💖 Please check out our [contributing guidelines](https://kivy.org/docs/contribute.html).

olivier-boesch: I modified the code to walk through os.environ keys and search for ANDROID_* keys. If I find one then we are on Android.
tshirtman: Hm, this method wasn't really great to start with, and this increases the risk of false positive, if we don't find a better way to discriminate, i'd be fine with merging that, but i do wonder if we can't use something more specific like checking the presence of /default.prop or the existence of the logcat command, or the /system/xbin existing and being in the PATH, all of these i think being very rare things for a linux system that is not android.
matham: I agree with @tshirtman - this seems pretty risky because I may have a variable named android in my env for unrelated reasons.
olivier-boesch: I integrated your propositions. the three conditions that @tshirtman told are checked. 'android' is returned as platform if they are all met. works for my phone (s6 running android 7) and my tablet (lenovo M10 running android 8.1). Still returns 'linux' on my computer.

Can you test ?
tshirtman: oh and also the unittest for it must be adapted!
olivier-boesch: > oh and also the unittest for it must be adapted!
> https://github.com/kivy/kivy/pull/6798/checks?check_run_id=542406623#step:8:70

huu.. I'll work on this... mocking path and file existence doesn't seem easy...
olivier-boesch: PEP8 Ok.
code seems ok.
Unit test seems ok.


olivier-boesch: > Looks good to me, Thanks!

I'm happy to help. Kivy is a wonderful tool. :)
diff --git a/kivy/utils.py b/kivy/utils.py
index 15455e884..628c30598 100644
--- a/kivy/utils.py
+++ b/kivy/utils.py
@@ -424,9 +424,12 @@ def format_bytes_to_human(size, precision=2):
 
 def _get_platform():
     # On Android sys.platform returns 'linux2', so prefer to check the
-    # presence of python-for-android environment variables (ANDROID_ARGUMENT
-    # or ANDROID_PRIVATE).
-    if 'ANDROID_ARGUMENT' in environ:
+    # existence of system specific commands and files
+    if (
+            path.exists('/default.prop')
+            and path.exists('/system/bin/logcat')
+            and path.exists('/system/xbin')
+    ):
         return 'android'
     elif environ.get('KIVY_BUILD', '') == 'ios':
         return 'ios'

incorrect platform detection on Android
The platform in the module kiv.utils returns linux on Android platform. It should return  Android.

Tested on a M10 Lenovo tablet running Android 8.1 with pydroid3.

diff --git a/kivy/tests/test_utils.py b/kivy/tests/test_utils.py
index 7954846da..0e5ad781c 100644
--- a/kivy/tests/test_utils.py
+++ b/kivy/tests/test_utils.py
@@ -191,10 +191,21 @@ class UtilsTest(unittest.TestCase):
         assert first == second
 
     def test_Platform_android(self):
-        with patch.dict('os.environ', {'ANDROID_ARGUMENT': ''}):
+        # modified os.path.exists function
+        # for test purpose
+        def modified_path_exists(p):
+            valid_paths = ['/default.prop',
+                           '/system/bin/logcat',
+                           '/system/xbin']
+            if p in valid_paths:
+                return True
+            return False
+
+        with patch(target='os.path.exists',
+                   side_effect=modified_path_exists):
             pf = _get_platform()
             self.assertTrue(pf == 'android')
-        self.assertNotIn('ANDROID_ARGUMENT', os.environ)
+        self.assertFalse(os.path.exists('/default.prop'))
 
     def test_Platform_ios(self):
         with patch.dict('os.environ', {'KIVY_BUILD': 'ios'}):

pip install -e .[dev,full]
parse_log_pytest
pytest
pytest pytest-cov pytest-xdist pytest-mock pytest-asyncio
apt-get update apt-get install -y libsdl2-dev libsdl2-ttf-dev libsdl2-image-dev libsdl2-mixer-dev libgstreamer1.0-dev gstreamer1.0-alsa gstreamer1.0-plugins-base libsmpeg-dev libswscale-dev libavformat-dev libavcodec-dev libjpeg-dev libtiff5-dev libx11-dev libmtdev-dev build-essential libgl1-mesa-dev libgles2-mesa-dev xvfb pulseaudio xsel
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
actdiag==3.0.0
alabaster==0.7.16
altgraph==0.17.4
babel==2.17.0
blockdiag==3.0.0
certifi==2025.1.31
charset-normalizer==3.4.1
coverage==7.8.0
docutils==0.21.2
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
execnet==2.1.1
flake8==7.2.0
funcparserlib==2.0.0a0
idna==3.10
imagesize==1.4.1
importlib_metadata==8.6.1
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
Jinja2==3.1.6
-e git+https://github.com/kivy/kivy.git@ede9bd1b806619dda022ab438964ce1b48645521#egg=Kivy
Kivy-Garden==0.1.5
MarkupSafe==3.0.2
mccabe==0.7.0
nwdiag==3.0.0
packaging @ file:///croot/packaging_1734472117206/work
pillow==11.1.0
pluggy @ file:///croot/pluggy_1733169602837/work
pycodestyle==2.13.0
pyflakes==3.3.2
Pygments==2.19.1
pyinstaller==6.12.0
pyinstaller-hooks-contrib==2025.2
pytest @ file:///croot/pytest_1738938843180/work
pytest-asyncio==0.26.0
pytest-cov==6.0.0
pytest-mock==3.14.0
pytest-xdist==3.6.1
requests==2.32.3
seqdiag==3.0.0
snowballstemmer==2.2.0
Sphinx==7.4.7
sphinxcontrib-actdiag==3.0.0
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-blockdiag==3.0.0
sphinxcontrib-devhelp==2.0.0
sphinxcontrib-htmlhelp==2.1.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-nwdiag==2.0.0
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-seqdiag==3.0.0
sphinxcontrib-serializinghtml==2.0.0
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typing_extensions==4.13.0
urllib3==2.3.0
webcolors==24.11.1
zipp==3.21.0

name: kivy
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - actdiag==3.0.0
      - alabaster==0.7.16
      - altgraph==0.17.4
      - babel==2.17.0
      - blockdiag==3.0.0
      - certifi==2025.1.31
      - charset-normalizer==3.4.1
      - coverage==7.8.0
      - docutils==0.21.2
      - execnet==2.1.1
      - flake8==7.2.0
      - funcparserlib==2.0.0a0
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==8.6.1
      - jinja2==3.1.6
      - kivy==2.0.0rc1
      - kivy-garden==0.1.5
      - markupsafe==3.0.2
      - mccabe==0.7.0
      - nwdiag==3.0.0
      - pillow==11.1.0
      - pycodestyle==2.13.0
      - pyflakes==3.3.2
      - pygments==2.19.1
      - pyinstaller==6.12.0
      - pyinstaller-hooks-contrib==2025.2
      - pytest-asyncio==0.26.0
      - pytest-cov==6.0.0
      - pytest-mock==3.14.0
      - pytest-xdist==3.6.1
      - requests==2.32.3
      - seqdiag==3.0.0
      - snowballstemmer==2.2.0
      - sphinx==7.4.7
      - sphinxcontrib-actdiag==3.0.0
      - sphinxcontrib-applehelp==2.0.0
      - sphinxcontrib-blockdiag==3.0.0
      - sphinxcontrib-devhelp==2.0.0
      - sphinxcontrib-htmlhelp==2.1.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-nwdiag==2.0.0
      - sphinxcontrib-qthelp==2.0.0
      - sphinxcontrib-seqdiag==3.0.0
      - sphinxcontrib-serializinghtml==2.0.0
      - typing-extensions==4.13.0
      - urllib3==2.3.0
      - webcolors==24.11.1
      - zipp==3.21.0
prefix: /opt/conda/envs/kivy

kivy/tests/test_utils.py::UtilsTest::test_Platform_android
kivy/tests/test_utils.py::UtilsTest::test_Platform_cygwin kivy/tests/test_utils.py::UtilsTest::test_Platform_darwin kivy/tests/test_utils.py::UtilsTest::test_Platform_freebsd kivy/tests/test_utils.py::UtilsTest::test_Platform_ios kivy/tests/test_utils.py::UtilsTest::test_Platform_linux2 kivy/tests/test_utils.py::UtilsTest::test_Platform_unknown kivy/tests/test_utils.py::UtilsTest::test_Platform_win32 kivy/tests/test_utils.py::UtilsTest::test_QueryDict kivy/tests/test_utils.py::UtilsTest::test_SafeList_clear kivy/tests/test_utils.py::UtilsTest::test_SafeList_iterate kivy/tests/test_utils.py::UtilsTest::test_SafeList_iterate_reverse kivy/tests/test_utils.py::UtilsTest::test_boundary kivy/tests/test_utils.py::UtilsTest::test_deprecated kivy/tests/test_utils.py::UtilsTest::test_difference kivy/tests/test_utils.py::UtilsTest::test_escape_markup kivy/tests/test_utils.py::UtilsTest::test_format_bytes_to_human kivy/tests/test_utils.py::UtilsTest::test_get_color_from_hex_alpha kivy/tests/test_utils.py::UtilsTest::test_get_color_from_hex_noalpha kivy/tests/test_utils.py::UtilsTest::test_get_hex_from_color_alpha kivy/tests/test_utils.py::UtilsTest::test_get_hex_from_color_noalpha kivy/tests/test_utils.py::UtilsTest::test_get_random_color_fixed_alpha kivy/tests/test_utils.py::UtilsTest::test_get_random_color_random_alpha kivy/tests/test_utils.py::UtilsTest::test_interpolate_multi kivy/tests/test_utils.py::UtilsTest::test_interpolate_solo kivy/tests/test_utils.py::UtilsTest::test_intersection kivy/tests/test_utils.py::UtilsTest::test_is_color_transparent kivy/tests/test_utils.py::UtilsTest::test_reify kivy/tests/test_utils.py::UtilsTest::test_strtotuple
kivy/utils.py
kivy/utils.py