It is now possible to experimentally deploy a game for Android using bdist_apps
, without building Panda from source. This process will produce an Android App Bundle, which can be uploaded straight to the Play Store (I tested that it works), or you can use bundletool to generate an .apk you can install on your device directly. I am posting some instructions here for those who want to try it out.
Note that it is NOT production-ready yet. Notably missing is support for serializing and deserializing application state.
Please let me know if you have any questions or find other stuff that doesn’t work!
REQUIREMENTS
You must use Python 3.13, since that’s the first version of Python to officially support Android, and what I used to build the Android wheels.
You need to install the latest version of Panda3D on the host. One of these builds, fresh off the buildbot, should do the trick. Building the latest master branch from GitHub works too.
You also need to download compiled Panda3D wheels for Android. These aren’t really wheels that you could install with pip, since binary wheels aren’t supported on Android, but the deployment system needs to work with wheels:
https://rdb.name/panda3d-1.11.0-cp313-cp313-android_arm64.whl
https://rdb.name/panda3d-1.11.0-cp313-cp313-android_armv7a.whl
https://rdb.name/panda3d-1.11.0-cp313-cp313-android_x86_64.whl
https://rdb.name/panda3d-1.11.0-cp313-cp313-android_x86.whl
CREATING A CERTIFICATE
bdist_apps
can automatically sign the bundle using an upload key. This is optional, but before it can be uploaded to the Play Store it needs to be signed one way or the other. You can alternatively use jarsigner (part of the JDK) to do this after the fact.
You can generate a certificate yourself, if you don’t have one already. The following openssl
command can be used:
openssl genpkey -algorithm RSA -aes256 -out private.pem
openssl req -new -x509 -sha256 -days 365 -key private.pem > cert.pem
If you are already an Android app developer and want to use an existing key, you can export it to PEM using keytool
, or sign it manually using jarsigner
. Let me know if you need help with this.
CONFIGURING
There is some specific stuff needed in the setup.py
file for Android. Here is an annotated version that packages the Android sample:
from setuptools import setup
# Necessary to switch Panda to the OpenGL ES 1 or 2 renderer
# pandagles2 supports shaders, but no fixed-function pipeline
# pandagles supports fixed-function pipeline, but no shaders
PRC_DATA = '''
load-display pandagles2
aux-display pandagles
notify-level info
gl-debug true
'''
setup(
name="Asteroids",
version="1.0.0",
options={
'build_apps': {
# This field is required by Android and uniquely identifies the app.
# It is usually based on the inverse of the developer's domain name
# (e.g. "gamestudio.com" becomes "com.gamestudio"), followed by any
# other components as needed to further identify the application.
'application_id': 'org.panda3d.samples.asteroids',
# This should be an integer that starts at 1 and is incremented with
# every app update. This is just internal, whereas the ``version``
# metadata field is used to show an arbitrary dot-separated version
# string to the user. Every time you upload a new release to the
# Play Console, this number must be updated.
'android_version_code': 1,
'gui_apps': {
'asteroids': 'main.py',
},
'platforms': ['android'],
'plugins': [
# Note use of pandagles2/pandagles instead of pandagl
'pandagles2',
'pandagles',
'p3openal_audio',
],
'include_patterns': [
'**/*.png',
'**/*.jpg',
'**/*.egg',
],
'extra_prc_data': PRC_DATA,
# Required icon resolutions: 48x48, 72x72, 96x96, 144x144, 192x192
# ..but make sure you author the logo in at least 512x512 since that
# is the required resolution for the Play Store
'icons': {'*': 'logo.png'},
},
'bdist_apps': {
'signing_certificate': 'cert.pem',
'signing_private_key': 'private.pem',
# optional: Panda will otherwise ask passphrase on command-line
#'signing_passphrase': 'panda3d_is_cool',
},
},
# Choosing a classifier in the Games category makes it marked a "Game"
classifiers=['Topic :: Games/Entertainment'],
)
And change your requirements.txt
to point it to the path where you downloaded the Android wheels:
-f /path/to/android/wheels
panda3d
BUILDING
Just run:
python3.13 setup.py bdist_apps
This will generate an .aab
file in the dist
directory. If you want to install it on a device, you first need to use bundletool to turn it into an .apks
file (which is really a zip file containing multiple .apk files, one for each architecture):
bundletool build-apks
--bundle dist/Asteroids-1.0.0_android.aab \
--output packages.apks \
--ks-key-alias androiddebugkey \
--ks-pass pass:android \
--ks debug.ks \
--verbose
Note that bundletool also takes a signing key. This is used to sign the .apk files, which is normally done by the Play Store, and is usually a separate key from the upload key. Generate it using keytool:
keytool -genkey -v -keystore debug.ks -alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000
OK, now that you’ve got an .apks
file, you can extract the individual .apk
files using any zip utility, or you can install it directly to your device (requires adb to be set up):
bundletool install-apks --apks packages.apks
DEBUGGING
There is no stdout/stderr on Android. Instead, all output is being routed to Android’s log system. You can use adb to follow the log stream. The log is extremely verbose without any filters, so I recommend using a set of filters like this one:
adb logcat -v brief -v color 'Panda3D:V' 'python.stdout:V' 'python.stderr:V' 'threaded_app:V' 'AndroidRuntime:I' 'linker:W' '*:F'
LIMITATIONS
Only Python 3.13 is supported for now. No multi-touch support yet, only single touches supported.
No Cg shaders or shader generator supported. This will be addressed soon, when the shaderpipeline branch is merged.
Some thirdparty packages (ARToolKit, OpenSSL, OpenCV, VRPN) are not yet included.
Minimum supported version is Android 5.0 (API level 21), the lowest supported by the Play Store, but we can look into lowering this requirement if people find this necessary.
You can’t really use thirdparty Python packages that contain binary code, because binary wheels for Android aren’t really a thing (yet).
BUILDING FROM SOURCE
If you want to build the Android wheels from source, use these thirdparty packages, built for the four major achitectures:
https://rdb.name/thirdparty-android.tar.gz
This includes Python 3.13, you also need to use Python 3.13 on the host. I built Python with some patches, which you can get from this repo.
I used the following makepanda commands:
export ANDROID_SDK_ROOT=/home/rdb/local/android
python3.13 makepanda/makepanda.py --everything --outputdir built-droid-arm64 --arch arm64 --target android-21 --threads 6 --wheel
python3.13 makepanda/makepanda.py --everything --outputdir built-droid-armv7a --arch arm --target android-21 --threads 6 --wheel
python3.13 makepanda/makepanda.py --everything --outputdir built-droid-x86_64 --arch x86_64 --target android-21 --threads 6 --wheel
python3.13 makepanda/makepanda.py --everything --outputdir built-droid-x86 --arch x86 --target android-21 --threads 6 --wheel