python-for-android icon indicating copy to clipboard operation
python-for-android copied to clipboard

Making a Kivy System app on Android

Open sebinho opened this issue 1 year ago • 1 comments

Let me explain what I am trying to do. I have an Orange Pi 5 Plus on which I am running Android 12. I did build a Kivy application that is working well (Kivy can be used to make Applications using Python). But some very specific reasons, I would like to make this application a system app.

When I installed the application normally with no special privileges, it works well. When I recompile Android12 and integrate the app on the product partition, it does not work.

When I launch the application, I first get an error message displayed on the scree saying: Could not extract /product/priv-app/myapp/lib/arm64/libpybundle data.

Then when I look at logcat, I see FATAL exception related to UnsatisfiedLinkError: No implementation found for void org.libsdl.app.SDLActivity.nativeSetenv.

Here is the log I get.

10-19 23:06:46.136   610  3321 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=org.test.myapp/org.kivy.android.PythonActivity bnds=[1276,609][1592,761]} from uid 10079
10-19 23:06:46.171   610   667 I ActivityManager: Start proc 3338:org.test.myapp/1000 for pre-top-activity {org.test.myapp/org.kivy.android.PythonActivity}
--------- beginning of main
10-19 23:06:46.248  3338  3338 V GraphicsEnvironment: ANGLE Developer option for 'org.test.myapp' set to: 'default'
10-19 23:06:46.248  3338  3338 V GraphicsEnvironment: ANGLE GameManagerService for org.test.myapp: false
--------- beginning of crash
10-19 23:06:46.369  3338  3338 E AndroidRuntime: FATAL EXCEPTION: SDLActivity
10-19 23:06:46.369  3338  3338 E AndroidRuntime: Process: org.test.myapp, PID: 3338
10-19 23:06:46.369  3338  3338 E AndroidRuntime: java.lang.UnsatisfiedLinkError: No implementation found for void org.libsdl.app.SDLActivity.nativeSetenv(java.lang.String, java.lang.String) (tried Java_org_libsdl_app_SDLActivity_nativeSetenv and Java_org_libsdl_app_SDLActivity_nativeSetenv__Ljava_lang_String_2Ljava_lang_String_2)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at org.libsdl.app.SDLActivity.nativeSetenv(Native Method)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at org.kivy.android.PythonActivity$UnpackFilesTask.onPostExecute(PythonActivity.java:158)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at org.kivy.android.PythonActivity$UnpackFilesTask.onPostExecute(PythonActivity.java:102)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at android.os.AsyncTask.finish(AsyncTask.java:771)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at android.os.AsyncTask.access$900(AsyncTask.java:199)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:788)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at android.os.Handler.dispatchMessage(Handler.java:106)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at android.os.Looper.loopOnce(Looper.java:201)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at android.os.Looper.loop(Looper.java:288)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at android.app.ActivityThread.main(ActivityThread.java:7870)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at java.lang.reflect.Method.invoke(Native Method)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
10-19 23:06:46.369  3338  3338 E AndroidRuntime:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
10-19 23:06:46.370   610  2995 W ActivityTaskManager:   Force finishing activity org.test.myapp/org.kivy.android.PythonActivity
10-19 23:06:46.393   610  1339 I ActivityManager: Process org.test.myapp (pid 3338) has died: fg  TOP 
10-19 23:06:46.393   610  1050 I WindowManager: WIN DEATH: Window{bf9e3f6 u0 org.test.myapp/org.kivy.android.PythonActivity}
10-19 23:06:46.393   610  1050 W InputManager-JNI: Input channel object 'bf9e3f6 org.test.myapp/org.kivy.android.PythonActivity (client)' was disposed without first being removed with the input manager!
10-19 23:06:46.394   610   702 I WindowManager: WIN DEATH: Window{138fccd u0 org.test.myapp/org.kivy.android.PythonActivity}
10-19 23:06:46.394   610   702 W InputManager-JNI: Input channel object '138fccd org.test.myapp/org.kivy.android.PythonActivity (client)' was disposed without first being removed with the input manager!
10-19 23:06:46.413   610   661 W InputManager-JNI: Input channel object 'af93b09 Splash Screen org.test.myapp (client)' was disposed without first being removed with the input manager!
10-19 23:06:46.871   610   660 W ActivityTaskManager: Activity top resumed state loss timeout for ActivityRecord{b390ac2 u0 org.test.myapp/org.kivy.android.PythonActivity t-1 f}}

Does anybody have a clue what is going wrong? Any help would be much appreciated. Thanks

I am expecting the application to run the same way as a user app.

sebinho avatar Oct 19 '24 21:10 sebinho

Adding some context to this issue.

When I look at the logcat for when I try to open the application for the first time, I can see that there is an issue when trying to extract the app data. It cannot find the *.so files that are actually contained within the APK. See log below

10-20 12:19:21.271  2332  2361 V PythonActivity: Ready to unpack
10-20 12:19:21.272  2332  2361 V pythonutil: Unpacking private app
10-20 12:19:21.272  2332  2361 V pythonutil: Data version is ef1b7004a93c1d23484e74edb34cf6112ffd2755
10-20 12:19:21.273  2332  2361 V pythonutil: Extracting private assets.
10-20 12:19:21.275  2332  2361 V python  : extracting data/
10-20 12:19:21.276  2332  2361 V python  : extracting data/images/
10-20 12:19:21.276  2332  2361 V python  : extracting data/images/logo_white.png
10-20 12:19:21.278  2332  2361 V python  : extracting data/images/logo_app.png
10-20 12:19:21.279  2332  2361 V python  : extracting data/images/logo_app_loading.png
10-20 12:19:21.281  2332  2361 V python  : extracting listdevices.kv
10-20 12:19:21.281  2332  2361 V python  : extracting main.pyc
10-20 12:19:21.281  2332  2361 V python  : extracting sitecustomize.pyc
10-20 12:19:21.282  2332  2361 V python  : extracting p4a_env_vars.txt
10-20 12:19:21.283  2332  2361 V pythonutil: Unpacking /product/priv-app/myapp/lib/arm64/libpybundle app
10-20 12:19:21.283  2332  2361 V pythonutil: Data version is ef1b7004a93c1d23484e74edb34cf6112ffd2755
10-20 12:19:21.283  2332  2361 V pythonutil: Extracting /product/priv-app/myapp/lib/arm64/libpybundle assets.
10-20 12:19:21.284  2332  2361 E python  : opening up extract tar
10-20 12:19:21.284  2332  2361 E python  : java.io.FileNotFoundException: /product/priv-app/myapp/lib/arm64/libpybundle.so: open failed: ENOENT (No such file or directory)
10-20 12:19:21.284  2332  2361 E python  : 	at libcore.io.IoBridge.open(IoBridge.java:575)
10-20 12:19:21.284  2332  2361 E python  : 	at java.io.FileInputStream.<init>(FileInputStream.java:160)
10-20 12:19:21.284  2332  2361 E python  : 	at java.io.FileInputStream.<init>(FileInputStream.java:115)
10-20 12:19:21.284  2332  2361 E python  : 	at org.renpy.android.AssetExtract.extractTar(AssetExtract.java:43)
10-20 12:19:21.284  2332  2361 E python  : 	at org.kivy.android.PythonUtil.unpackPyBundle(PythonUtil.java:241)
10-20 12:19:21.284  2332  2361 E python  : 	at org.kivy.android.PythonActivity$UnpackFilesTask.doInBackground(PythonActivity.java:108)
10-20 12:19:21.284  2332  2361 E python  : 	at org.kivy.android.PythonActivity$UnpackFilesTask.doInBackground(PythonActivity.java:102)
10-20 12:19:21.284  2332  2361 E python  : 	at android.os.AsyncTask$3.call(AsyncTask.java:394)
10-20 12:19:21.284  2332  2361 E python  : 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
10-20 12:19:21.284  2332  2361 E python  : 	at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)
10-20 12:19:21.284  2332  2361 E python  : 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
10-20 12:19:21.284  2332  2361 E python  : 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
10-20 12:19:21.284  2332  2361 E python  : 	at java.lang.Thread.run(Thread.java:920)
10-20 12:19:21.284  2332  2361 E python  : Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
10-20 12:19:21.284  2332  2361 E python  : 	at libcore.io.Linux.open(Native Method)
10-20 12:19:21.284  2332  2361 E python  : 	at libcore.io.ForwardingOs.open(ForwardingOs.java:567)
10-20 12:19:21.284  2332  2361 E python  : 	at libcore.io.BlockGuardOs.open(BlockGuardOs.java:273)
10-20 12:19:21.284  2332  2361 E python  : 	at libcore.io.ForwardingOs.open(ForwardingOs.java:567)
10-20 12:19:21.284  2332  2361 E python  : 	at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7756)
10-20 12:19:21.284  2332  2361 E python  : 	at libcore.io.IoBridge.open(IoBridge.java:561)
10-20 12:19:21.284  2332  2361 E python  : 	... 12 more

So it seems that it cannot find libpybundle.so but it is contained within my APK. Here is the content of my APK file:

.
├── AndroidManifest.xml
├── assets
│   └── private.tar
├── classes2.dex
├── classes3.dex
├── classes4.dex
├── classes5.dex
├── classes.dex
├── lib
│   └── arm64
│       ├── libaddition.so
│       ├── libcrypto1.1.so
│       ├── libffi.so
│       ├── libmain.so
│       ├── libpybundle.so
│       ├── libpython3.11.so
│       ├── libSDL2_image.so
│       ├── libSDL2_mixer.so
│       ├── libSDL2.so
│       ├── libSDL2_ttf.so
│       ├── libsqlite3.so
│       └── libssl1.1.so
├── META-INF
│   ├── CERT.RSA
│   ├── CERT.SF
│   ├── com
│   │   └── android
│   │       └── build
│   │           └── gradle
│   │               └── app-metadata.properties
│   └── MANIFEST.MF
├── res
│   ├── drawable
│   │   └── presplash.jpg
│   ├── drawable-hdpi-v4
│   │   └── ic_launcher.png
│   ├── drawable-mdpi-v4
│   │   └── ic_launcher.png
│   ├── drawable-xhdpi-v4
│   │   └── ic_launcher.png
│   ├── drawable-xxhdpi-v4
│   │   └── ic_launcher.png
│   ├── layout
│   │   ├── chooser_item.xml
│   │   ├── main.xml
│   │   ├── project_chooser.xml
│   │   └── project_empty.xml
│   ├── mipmap
│   │   └── icon.png
│   └── xml
│       └── device_filter.xml
└── resources.arsc

As I mentioned originally, the app is working well when simply installed using adb install myapp.apk, so when it is located in the /data/ user space. But it does not work if I try to make it a system app. To make it a system app, I added the following section in the AndroidManifest.xml:

coreApp="true"
android:sharedUserId="android.uid.system"

Any idea what is going wrong? Not sure that anybody ever tried to make a Kivy application a system app...

sebinho avatar Oct 20 '24 12:10 sebinho

I think your android system supports multiple abis try apk with armebai-v7a.

T-Dynamos avatar Oct 21 '24 02:10 T-Dynamos

thanks for your proposal. I was able to find a fix for this issue. But I could not find a way to make it a system app while baking it directly into the super.img partition.

I had to build my application like a normal user application. Then I install it with adb install appname.apk. Finally I had to manually make it a system application with the following commands (using adb).

$ adb root
$ adb remount
$ adb shell mount -o rw,remount /system
$ adb shell
# Now find where your app is installed, typically in /data/app/~~XXXXXXX~~/appnameXXX/
# Example: ~~05uHorpdBvctQMKGK8P-PQ==/pl.solidexplorer2-SM049IQ_DyHHyV829yTloA==/
$ mkdir /system/priv-app/myapp
$ cp -rf /data/app/~~XXXXXXX~~/appnameXXX/* /system/priv-app/myapp

Once this is done, make sure to uninstall the original app and then reboot the system.

$ adb shell mount -o ro,remount /system
$ adb reboot

Hopefully this can be of help to others in the future. But I could not find a way to properly integrate the app directly onto Android partition.

sebinho avatar Oct 21 '24 12:10 sebinho