Repository: kivy/python-for-android

Issue:
apk size growing
### Versions

* Python:  3.8.2
* OS:   Win10/WSL/Ubuntu20.04
* Kivy: 1.11.1
* Cython: 0.29.17

### Description
Building "Hello World" in an empty directory:

buildozer init        
buildozer android debug

Results in an apk that is 28MB

p4a 2020.4.29 (NDK 19c, SDK 29, armeapi-v7a ) also gives 28MB
p4a 2020.4.29 (NDK 19c, SDK 29, arm64-v8a ) gives 21MB

Not long ago this was 12MB 

Is 28MB the new normal?


### buildozer.spec

Command:
```sh
// REPLACE ME: buildozer command ran? e.g. buildozer android debug
```

Spec file:
```
// REPLACE ME: Paste your buildozer.spec file here
```

### Logs

```
// REPLACE ME: Paste the build ouput containing the error
```


Discussion:

Patch:
diff --git a/pythonforandroid/bootstraps/common/build/build.py b/pythonforandroid/bootstraps/common/build/build.py
index 8d3bee6e..a91ac71e 100644
--- a/pythonforandroid/bootstraps/common/build/build.py
+++ b/pythonforandroid/bootstraps/common/build/build.py
@@ -680,6 +680,9 @@ tools directory of the Android SDK.
                     const='release', default='debug',
                     help='Build your app as a non-debug release build. '
                          '(Disables gdb debugging among other things)')
+    ap.add_argument('--with-debug-symbols', dest='with_debug_symbols',
+                    action='store_const', const=True, default=False,
+                    help='Will keep debug symbols from `.so` files.')
     ap.add_argument('--add-jar', dest='add_jar', action='append',
                     help=('Add a Java .jar to the libs, so you can access its '
                           'classes with pyjnius. You can specify this '
diff --git a/pythonforandroid/bootstraps/sdl2/__init__.py b/pythonforandroid/bootstraps/sdl2/__init__.py
index 3476abb6..5f7c9cee 100644
--- a/pythonforandroid/bootstraps/sdl2/__init__.py
+++ b/pythonforandroid/bootstraps/sdl2/__init__.py
@@ -47,7 +47,7 @@ class SDL2GradleBootstrap(Bootstrap):
                 with open('blacklist.txt', 'a') as fileh:
                     fileh.write('\nsqlite3/*\nlib-dynload/_sqlite3.so\n')
 
-        if not self.ctx.build_as_debuggable:
+        if not self.ctx.with_debug_symbols:
             self.strip_libraries(arch)
         self.fry_eggs(site_packages_dir)
         super().assemble_distribution()
diff --git a/pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml
index f9b5afe3..f6676517 100644
--- a/pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml
+++ b/pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml
@@ -7,7 +7,7 @@
     <!-- Android 2.3.3 -->
     <uses-sdk android:minSdkVersion="{{ args.min_sdk_version }}" android:targetSdkVersion="{{ android_api }}" />
 
-    <application>
+    <application {% if debug %}android:debuggable="true"{% endif %} >
         {% for name in service_names %}
         <service android:name="{{ args.package }}.Service{{ name|capitalize }}"
                  android:process=":service_{{ name }}"
diff --git a/pythonforandroid/bootstraps/service_only/__init__.py b/pythonforandroid/bootstraps/service_only/__init__.py
index 806794ad..41016d73 100644
--- a/pythonforandroid/bootstraps/service_only/__init__.py
+++ b/pythonforandroid/bootstraps/service_only/__init__.py
@@ -46,7 +46,7 @@ class ServiceOnlyBootstrap(Bootstrap):
                 with open('blacklist.txt', 'a') as fileh:
                     fileh.write('\nsqlite3/*\nlib-dynload/_sqlite3.so\n')
 
-        if not self.ctx.build_as_debuggable:
+        if not self.ctx.with_debug_symbols:
             self.strip_libraries(arch)
         self.fry_eggs(site_packages_dir)
         super().assemble_distribution()
diff --git a/pythonforandroid/bootstraps/service_only/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/service_only/build/templates/AndroidManifest.tmpl.xml
index f3eb3bef..95a5ed1e 100644
--- a/pythonforandroid/bootstraps/service_only/build/templates/AndroidManifest.tmpl.xml
+++ b/pythonforandroid/bootstraps/service_only/build/templates/AndroidManifest.tmpl.xml
@@ -45,6 +45,7 @@
          An example Java class can be found in README-android.txt
     -->
     <application android:label="@string/app_name"
+                 {% if debug %}android:debuggable="true"{% endif %}
                  android:icon="@drawable/icon"
                  android:allowBackup="true"
                  android:theme="{{args.android_apptheme}}{% if not args.window %}.Fullscreen{% endif %}"
diff --git a/pythonforandroid/bootstraps/webview/__init__.py b/pythonforandroid/bootstraps/webview/__init__.py
index b90f3319..24b4cf4b 100644
--- a/pythonforandroid/bootstraps/webview/__init__.py
+++ b/pythonforandroid/bootstraps/webview/__init__.py
@@ -43,7 +43,7 @@ class WebViewBootstrap(Bootstrap):
                 with open('blacklist.txt', 'a') as fileh:
                     fileh.write('\nsqlite3/*\nlib-dynload/_sqlite3.so\n')
 
-        if not self.ctx.build_as_debuggable:
+        if not self.ctx.with_debug_symbols:
             self.strip_libraries(arch)
         self.fry_eggs(site_packages_dir)
         super().assemble_distribution()
diff --git a/pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml
index 8b6b4ca9..ae28b8b2 100644
--- a/pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml
+++ b/pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml
@@ -51,6 +51,7 @@
                  android:theme="{{args.android_apptheme}}{% if not args.window %}.Fullscreen{% endif %}"
                  android:hardwareAccelerated="true"
                  android:usesCleartextTraffic="true"
+                 {% if debug %}android:debuggable="true"{% endif %}
                  >
         {% for l in args.android_used_libs %}
         <uses-library android:name="{{ l }}" />
diff --git a/pythonforandroid/build.py b/pythonforandroid/build.py
index fba23ce0..9bed914d 100644
--- a/pythonforandroid/build.py
+++ b/pythonforandroid/build.py
@@ -82,9 +82,12 @@ class Context:
     '''A build context. If anything will be built, an instance this class
     will be instantiated and used to hold all the build state.'''
 
-    # Whether to build with debugging symbols
+    # Whether to make a debug or release build
     build_as_debuggable = False
 
+    # Whether to strip debug symbols in `.so` files
+    with_debug_symbols = False
+
     env = environ.copy()
     # the filepath of toolchain.py
     root_dir = None
@@ -831,7 +834,7 @@ def run_pymodules_install(ctx, modules, project_dir=None,
                 )
 
         # Strip object files after potential Cython or native code builds:
-        if not ctx.build_as_debuggable:
+        if not ctx.with_debug_symbols:
             standard_recipe.strip_object_files(
                 ctx.archs[0], env, build_dir=ctx.build_dir
             )
diff --git a/pythonforandroid/recipe.py b/pythonforandroid/recipe.py
index 6128074e..3933dd78 100644
--- a/pythonforandroid/recipe.py
+++ b/pythonforandroid/recipe.py
@@ -1072,7 +1072,7 @@ class CythonRecipe(PythonRecipe):
                 info('First build appeared to complete correctly, skipping manual'
                      'cythonising.')
 
-            if not self.ctx.build_as_debuggable:
+            if not self.ctx.with_debug_symbols:
                 self.strip_object_files(arch, env)
 
     def strip_object_files(self, arch, env, build_dir=None):
diff --git a/pythonforandroid/toolchain.py b/pythonforandroid/toolchain.py
index 3ba4f5b8..19b35242 100644
--- a/pythonforandroid/toolchain.py
+++ b/pythonforandroid/toolchain.py
@@ -196,6 +196,14 @@ def build_dist_from_args(ctx, dist, args):
         ctx.recipe_build_order))
     info('Dist will also contain modules ({}) installed from pip'.format(
         ', '.join(ctx.python_modules)))
+    info(
+        'Dist will be build in mode {build_mode}{with_debug_symbols}'.format(
+            build_mode='debug' if ctx.build_as_debuggable else 'release',
+            with_debug_symbols=' (with debug symbols)'
+            if ctx.with_debug_symbols
+            else '',
+        )
+    )
 
     ctx.distribution = dist
     ctx.prepare_bootstrap(bs)
@@ -518,6 +526,10 @@ class ToolchainCL:
             const='release', default='debug',
             help='Build your app as a non-debug release build. '
                  '(Disables gdb debugging among other things)')
+        parser_packaging.add_argument(
+            '--with-debug-symbols', dest='with_debug_symbols',
+            action='store_const', const=True, default=False,
+            help='Will keep debug symbols from `.so` files.')
         parser_packaging.add_argument(
             '--keystore', dest='keystore', action='store', default=None,
             help=('Keystore for JAR signing key, will use jarsigner '
@@ -593,6 +605,8 @@ class ToolchainCL:
             args.unknown_args += ["--private", args.private]
         if hasattr(args, "build_mode") and args.build_mode == "release":
             args.unknown_args += ["--release"]
+        if hasattr(args, "with_debug_symbols") and args.with_debug_symbols:
+            args.unknown_args += ["--with-debug-symbols"]
         if hasattr(args, "ignore_setup_py") and args.ignore_setup_py:
             args.use_setup_py = False
 
@@ -612,6 +626,9 @@ class ToolchainCL:
         self.ctx.build_as_debuggable = getattr(
             args, "build_mode", "debug"
         ) == "debug"
+        self.ctx.with_debug_symbols = getattr(
+            args, "with_debug_symbols", False
+        )
 
         have_setup_py_or_similar = False
         if getattr(args, "private", None) is not None:


Test patch:
diff --git a/tests/test_build.py b/tests/test_build.py
index f76a1dab..727205bd 100644
--- a/tests/test_build.py
+++ b/tests/test_build.py
@@ -19,7 +19,7 @@ class TestBuildBasic(unittest.TestCase):
         assert m_info.call_args_list[-1] == mock.call(
             'No Python modules and no setup.py to process, skipping')
 
-    def test_strip_if_debuggable(self):
+    def test_strip_if_with_debug_symbols(self):
         ctx = mock.Mock()
         ctx.python_recipe.major_minor_version_string = "python3.6"
         ctx.get_site_packages_dir.return_value = "test-doesntexist"
@@ -38,12 +38,13 @@ class TestBuildBasic(unittest.TestCase):
                 mock.patch('pythonforandroid.build.run_setuppy_install'):
             m_project_has_setup_py.return_value = False
 
-            # Make sure it is NOT called when debug build:
-            ctx.build_as_debuggable = True
+            # Make sure it is NOT called when `with_debug_symbols` is true:
+            ctx.with_debug_symbols = True
             assert run_pymodules_install(ctx, modules, project_dir) is None
             assert m_CythonRecipe().strip_object_files.called is False
 
-            # Make sure strip object files IS called when release build:
-            ctx.build_as_debuggable = False
+            # Make sure strip object files IS called when
+            # `with_debug_symbols` is fasle:
+            ctx.with_debug_symbols = False
             assert run_pymodules_install(ctx, modules, project_dir) is None
             assert m_CythonRecipe().strip_object_files.called is True