I have been experimenting with writing Android apps using Python. Currently, there appear to be two contending ways to do this: Kivy, which looks promising and focuses on providing a clean, cross-platform way to manage multi-touch interfaces; and PGS4A, or Pygame Subset for Android, which is pretty much what it sounds like: a toolchain for packaging an application, written in Python using Pygame, into a single .apk file.
I will focus on PGS4A here. I like what I have seen so far, and not just for my own recreation. When tackling graphics in Python, students often gravitate toward Pygame on their own. I like the idea of providing a relatively straightforward means of deploying students’ projects from desktop to smart phone, even if only as a “teaser” demonstration of this kind of portability.
The documentation on PGS4A is reasonably good, but I did encounter a few hiccups that are worth recording. In particular, I wanted to see if I could get an app working that involved GUI widgets, which are not provided by Pygame out of the box. Following is a hopefully more complete list of start-to-finish instructions, including how to use additional modules like PGU (Python Game Utilities), a Pygame-based GUI widget library.
- Install Python 2.7, adding C:/Python27 to your PATH environment variable. (Where the operating system matters, I’ll focus on Windows here, because if you’re using Linux, then you already know what you’re doing, don’t you?) Note that the link is to the site for Visual Python, which isn’t needed here, but is a handy one-stop shop that includes several useful modules, like Numpy, under the hood.
- Install Pygame 1.9.1.
- Install PGU 0.18 by unpacking the zip archive to a temporary folder, and running setup.py install.
- At this point, you should be able to develop and run Pygame applications on your desktop.
Installing Pygame Subset for Android
- Install the Java Development Kit (JDK), setting the environment variable JAVA_HOME to point to the JDK installation folder, and adding %JAVA_HOME%/bin to your PATH.
- Install PGS4A 0.9.4 by unpacking the zip archive to a permanent folder (e.g., C:/pgs4a), and running android.py installsdk. For development purposes, I recommend creating a signing key during the installation process, to make the build/deploy/test cycle simpler (you don’t have to keep entering your keystore password). You can always re-sign with a more secure key later.
Creating an app
At this point, you are ready to create an app. In the pgs4a folder, create an app folder containing all required files. At a minimum, this includes main.py, which must have a main() function. The example on the PGS4A site works on Android, but is missing some housekeeping required to also work cleanly on your desktop. Following is a modified example:
"""Example app using PGS4A (Pygame Subset for Android). This example is taken from: http://pygame.renpy.org/android-packaging.html#aside-a-simple-game with the following modifications: 1. Check for ev.type == pygame.QUIT. 2. Call pygame.quit() explicitly. This is required on Windows when running from IDLE. """ import pygame # Import the android module. If we can't import it, set it to None - this # lets us test it, and check to see if we want android-specific behavior. try: import android except ImportError: android = None # Event constant. TIMEREVENT = pygame.USEREVENT # The FPS the game runs at. FPS = 30 # Color constants. RED = (255, 0, 0, 255) GREEN = (0, 255, 0, 255) def main(): pygame.init() # Set the screen size. screen = pygame.display.set_mode((480, 800)) # Map the back button to the escape key. if android: android.init() android.map_key(android.KEYCODE_BACK, pygame.K_ESCAPE) # Use a timer to control FPS. pygame.time.set_timer(TIMEREVENT, 1000 / FPS) # The color of the screen. color = RED while True: ev = pygame.event.wait() # Android-specific: if android: if android.check_pause(): android.wait_for_resume() # Draw the screen based on the timer. if ev.type == TIMEREVENT: screen.fill(color) pygame.display.flip() # When the touchscreen is pressed, change the color to green. elif ev.type == pygame.MOUSEBUTTONDOWN: color = GREEN # When it's released, change the color to RED. elif ev.type == pygame.MOUSEBUTTONUP: color = RED # When the user hits back, ESCAPE is sent. Handle it and end # the game. elif ev.type == pygame.KEYDOWN and ev.key == pygame.K_ESCAPE: break elif ev.type == pygame.QUIT: break pygame.quit() # This isn't run on Android. if __name__ == "__main__": main()
In addition, you must include in the app folder any other dependent files or modules used by your program (e.g., fonts, sprite images, the PGU module, etc.). For example, pygame.font.Font(None, font_size) does not work, since the Pygame default font is not explicitly included in PGS4A.
Which brings us to PGU. You will need 3 things in your app folder to use PGU GUI widgets:
- ConfigParser.py. This module is required by PGU, and is bundled with Python (in C:/Python27/Lib), but it’s not included in PGS4A, so you must put a copy in your app folder.
- The PGU module itself, copied from C:/Python27/Lib/site-packages/pgu to pgs4a/app/pgu.
- The GUI “look and feel” themes are in C:/Python27/share/pgu; copy these to pgs4a/app/share/pgu.
Finally, those GUI themes use some TARGA .tga image files, which PGS4A currently does not support. Fortunately, this was easy to fix: just convert those .tga files to .png, and change the corresponding filename extensions in the config.txt files in pgs4a/app/share.
Once all of these code files are in place, from the pgs4a folder, run android.py configure app, followed by android.py build app release (or android.py build app release install if you have an emulator or physical device connected). The resulting .apk file is in pgs4a/bin.