Building for Android

As of version 1.11.0, Panda3D supports building an Android app that can be uploaded to the Google Play Store. There are a few extra details to be taken into account when deploying for Android.

The process will automatically create an Android App Bundle, which is the format required for submitting an application to the Google Play Store. If necessary, it is possible to convert such a bundle to an .apk file, as explained below.

Configuring

When building for Android, there are a few changes that need to be made to the setup.py file compared to a desktop build.

Firstly, an application_id needs to be chosen to uniquely identify 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. As an example, we might publish the Asteroids example on the Play Store as org.panda3d.samples.asteroids.

Caution

Once the application has been uploaded to the Google Play Store, it is no longer possible to change the identifier.

Secondly, there must be an android_version_code defined. This is an integer that starts at 1 and is incremented whenever a new version is uploaded to the Play Store. You will still have your regular version string that is displayed to the user; the version code is just an internal version number used by the Play Store.

Furthermore, you need to switch Panda to use the pandagles2 or pandagles renderer, since the regular pandagl renderer is not available on Android. Use pandagles2 if the application uses shaders, pandagles if it relies on the fixed-function pipeline. It’s also possible to set one as a fallback if the other will not load, as shown in the example below.

There are other options you can set that control the Android build specifically. See the List of Build Options and look for the keys prefixed with android_ for more details.

An example file for the Asteroids sample program follows below. If you are building a multi-platform app, it may be useful to have multiple versions of setup.py, one for the desktop version and one for the mobile version.

from setuptools import setup

# Set renderer to pandagles2 (shaders) with pandagles (FFP) as fallback
PRC_DATA = '''
load-display pandagles2
aux-display pandagles

notify-level info
gl-debug true
'''

setup(
    name='Asteroids',
    version='1.0.0',
    options={
        'build_apps': {
            # Uniquely identifies the app
            'application_id': 'org.panda3d.samples.asteroids',

            # Update this for every version uploaded to the Play Store
            'android_version_code': 1,

            'gui_apps': {
                'asteroids': 'main.py',
            },
            'plugins': [
                # Note use of pandagles2/pandagles instead of pandagl
                'pandagles2',
                'pandagles',
                'p3openal_audio',
            ],
            'include_patterns': [
                '**/*.png',
                '**/*.jpg',
                '**/*.egg',
            ],
            'extra_prc_data': PRC_DATA,

            'icons': {'*': 'logo.png'},
        },
    },
    # Choosing a classifier in the Games category makes it marked a "Game"
    classifiers=['Topic :: Games/Entertainment'],
)

Building

If the configuration has been updated appropriately, the following command will generate an App Bundle in the dist directory:

python setup.py bdist_apps

If no .aab file was generated, you should carefully study the output of the bdist_apps command for error messages. There may be an error in your configuration.

Note

Building for Android requires the use of Python 3.8 or newer.

Testing

To test an app, it is convenient to be able to directly install the app onto a target device. This can be done using the Android Debug Bridge. This section assumes you have already installed the Android Studio command-line tools and paired with a device. This process is explained here:

https://developer.android.com/studio/command-line/adb

The .aab bundle generated by the bdist_apps command is designed to be uploaded to the Google Play Store and cannot be directly installed on a device. You will first need to create an .apk file. This can be done using the bundletool utility.

First, convert the generated bundle into an .apks archive. You will need to pass in your signing key. The command below has been broken up into multiple lines for readability:

bundletool build-apks
    --bundle dist/asteroids-0.0.0_android.aab \
    --output packages.apks \
    --ks-key-alias androiddebugkey \
    --ks-pass pass:android \
    --ks debug.ks \
    --verbose

The resulting packages.apks file is a ZIP archive containing several individual .apk packages. You can extract the appropriate .apk file using any utility that can read ZIP files, but you can also directly install them to a connected device using bundletool:

bundletool install-apks --apks packages.apks

Or you can extract the .apk and install it using the Debug Bridge:

adb install asteroids.apk

Debugging

All Panda3D and Python output is routed to the Android log. To see the log output, you can simply run this command:

adb logcat

Messages from the game will be listed under the “Panda3D” or “Python” tags for Panda3D log output and standard output, respectively. To filter out the flood of messages from other utilities, but keep important messages, you can specify a filter:

adb logcat 'Panda3D:V' 'Python:V' 'threaded_app:V' '*:F'

Signing the Bundle

Before you can upload the app to the Play Store, it needs to be signed using an upload certificate. This can be done in a separate call to the jarsigner utility, but it is easier to let it be done directly by bdist_apps.

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

Never share the private key with anyone! It is used to prove that the uploaded app truly comes from you and not from an unauthorized attacker! It is fine to share the certificate file, though, and you will need to upload it to the Google Play Console later.

Simply modify the setup.py as shown below to add a signature:

setup(
    ...
    options={
        'build_apps': {
            ...
        },
        'bdist_apps': {
            'signing_certificate': 'cert.pem',
            'signing_private_key': 'private.pem',
        },
    },
    ...
)

Tip

If you already have an upload key generated using keytool or Android Studio that you would like to use, you can convert it to a PEM certificate using the following command:

keytool -export -rfc -keystore path-to-keystore.jks -alias my-key -file certificate.pem

If on the other hand you don’t want bdist_apps to do the signing, you can sign it yourself using the jarsigner tool:

jarsigner -keystore path-to-keystore.jks mygame.aab my-key

Submitting to the Play Store

Once you have tested the application thoroughly and verified that it meets the Android app quality guidelines, you can upload the app to the Google Play Store.

To do this, you will need to create an account for you on your company on the Google Play Console and register the app with Create App in the upper-right corner. Note that there is a one-time registration fee of $25 USD to sign up for a developer account.

The Play Store can handle signing the final application for you, but you do need to sign the .aab file with an upload key before you can upload it to the Play Store. The easiest way to do this is to have it done automatically by bdist_apps, as explained in the previous section.

It is recommended to first create an Internal testing release, which allows you to test the app and send it to others for testing before finishing the store listing. Once there, use Create release in the top-right corner, fill in the details, and upload the .aab file generated by bdist_apps.

Note that if you want to upload a second version, you need to change the android_version_code, or it will be rejected by the Play Store.