Repository: kivy/kivy

Issue:
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.


Discussion:
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. :)

Patch:
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'


Test patch:
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'}):