- set up your dev machine and built static libraries
- pyqtdeployed your app so it is ready to deploy
This part discusses:
- deploying your app to a test target machine
- debugging your app
More about pyqtdeploy work flow
The pyqtdeploy GUI lets you choose your work flow. That is, in the ‘Build’ step, you can choose optional steps: qmake, make, ‘run app’. For example, you can choose none of those, and Build will only create a .pro file.
Then you can switch to:
- the command line
- or Qt Creator (a GUI app)
and resume the work flow (qmake, make, deploying, and running.)
(I’m haven’t tried ‘run’ in pyqtdeploy for target Android, I always switch to another tool.)
pyqtdeploy developer notes
The pyqtdeploy directory contains a file DeveloperNotes.txt. These notes are by the developer of pyqtdeploy but are useful hints about Android development. The author of the notes has said the notes are NOT definitive and should be used with care. I have found typos there.
Deploying using the command line
Follow the instructions in the developer notes. I.e. :
# Assert you ran qmake and make in pyqtdeploy, but not run # cd to dir that pyqtdeploy created cd ~/hellobuild/build export ANDROID_NDK_ROOT=$HOME/android-ndk-r10 export ANDROID_SDK_ROOT=$HOME/android-sdk-linux
# configure install make install INSTALL_ROOT=deploy # make deployable /home/bootch/Qt/5.3/android_armv7/bin/androiddeployqt \ --input android-lib*.so-deployment-settings.json \ --output deploy
# deploy adb install -r deploy/bin/QtApp-debug.apk
echo Now go to AVD and run app
This only installs your app to a target device. You subsequently must use the target device’s GUI to run your app.
If you get:
this means you omitted the -r flag, which means reinstall. An alternative is to manually uninstall the app first (on the device, choose Settings>Apps, then select your app, then choose the Uninstall button.)
Deploying using Qt Creator
When you choose the ‘Run’ icon in Qt Creator, it builds, deploys, and runs your app. So it is more automated, but harder to understand what Qt Creator is actually doing on your behalf.
Debugging pyqtdeployed apps on android
First, refresh the tools
The tools (especially pqytdeploy, SIP, and PyQt but also Qt and Python) are updated frequently. You should use the latest versions, which may have fixed some Android crashes.
Remember that pyqtdeploy is the tool that helps build static Python, etc. libraries. So if you update pyqtdeploy, you should probably rebuild static Python starting with invoking pyqtdeploy (so that any new patches known by pyqtdeploy are applied.)
Stderr and Android logcat
Unfortunately, Python prints exceptions to stdout/stderr. These by default are dedirected to /dev/null on Android (which means they disappear.)
On android, the system log is called ‘logcat’. To see it remotely:
>adb logcat > logcat.tmp >Ctl-C >vi logcat.tmp
Its a circular file. Fileness means it persists (even across your debugging sessions.) Circular means it wraps around, overwriting older data. Pragmatically, one debug session never seems to wrap around on itself. The end of the file is always the latest log entries? You can clear it by rebooting the device (powering it off.)
Redirecting stderr to logcat
You should be able to configure your target device to redirect stdout and stderr to logcat. To do this requires:
- a rooted real device
- an AVD (virtual device)
An AVD is always rooted (you have superuser privileges to bypass all security and do what you want).
Rooting a real device is an adventure unto itself, so I chose not to do it yet. But the advantage is that a real device eliminates the simulator layer, and is quicker to boot and so forth than an AVD. You can still do certain debugging on an un-rooted real device, you just won’t be able to see Python exceptions directed to stderr.
!!! If a device is not rooted, the adb commands to redirect stdio fail quietly. So you still won’t see stderr in the logcat.
To do it you can:
- issue adb commands
- create a persistent configuration file
adb commands to redirect stdout/stderr
>adb shell stop >adb shell setprop log.redirect-stdio true >adb shell start
Remember this doesn’t persist if you reboot the device (whether and AVD or a real device.)
If the device is rooted real device, you must precede that with >adb root. (AVD’s are always rooted, so >adb root is not necessary.)
- use a debugger such as gdb (which is built into Qt Creator)
- harness code with print statements
- simple code analysis using crash dumps and Python exception tracebacks
It depends on where the bugs are:
- in the Python interpreter
- in your pyqtdeploy build process
- in your app’s Python code
It is not uncommon to find bugs in the Python interpreter, since the Android platform is not supported by Python.org. (the pyqtdeploy process patches the Python interpreter, and you might find that another patch is required.)
The pyqtdeploy build process is intricate. It is not uncommmon to find that you have not frozen a needed Python module (and then you might get an ImportError exception.)
Once you get as far as running your own app’s Python code, you probably have installed an exception hook, and can display the exception and traceback on the GUI of the device. (But probably, you are only porting to Android, and have worked out most of your app’s bugs on another platform, except for any Android specific code.)
Harnessing pyqtdeploy apps on android
I experienced the need to harness (since my app seemed to crash before Qt Creator’s debugger could even get started properly and without any Python exceptions.)
This means writing C code. You can use:
- qWarning() C function. It is properly redirected to Android logcat.
- __android_log foo C function.
If you need to harness the Python interpreter, you might need to study how to write Python extensions, for example to convert a PyObject * to a representation that is a C string suitable for qWarning().
I harnessed pyqtdeploy_start.cpp and Python/import.c.
Here is the code I used:
Building a debug version of Python
reading an Android crash dump
packaging using Qt Creator