Skip to content

Android FAQ

Michalis Kamburelis edited this page Feb 18, 2019 · 31 revisions

Questions related to Android development.

What Android devices are supported

Any Android >= 4.1 (platform android-16). Reasons:

  • Android 2.0 (platform android-5) is necessary, to have OpenGL ES 2.0.
  • Android 2.3 (platform android-9) is necessary, to NativeActivity and EGL.
  • Android 4.1 (platform android-16) is necessary, because
    • New executables (with PIC) can run only on Android 4.1+ (according to http://wiki.freepascal.org/Android ).
    • New Android NDK just supports only >= 16.
    • In theory, you could workaround it, by explicitly compiling Android library without PIC support, and sticking to an ancient version of Android NDK. But this would give you an application that, in turn, doesn't work on newer phones (since platform 23, PIC support is required).

Loading and packaging game data

Simple answer:

  1. When developing a game, put all your game data under the "data/" subdirectory.
  2. Then load it wrapping in ApplicationData, for example use LoadImage(ApplicationData('gui/blabla.png')) to load an image stored under data/gui/blabla.png.

The above approach makes your code 100% working on both Android and standalone platforms. Our build tool will automatically package the data/ subdirectory correctly.

Longer explanation about what happens under the hood:

In an Android application, you can read files on a normal filesystem, just like on any other Unix. Like file:///sdcard/my_texture.png. However, it's not a proper way to distribute your game read-only data. The game data should be placed as the "assets" inside the apk file, and opened using special Android functions. We support it seamlessly in the Castle Game Engine:

  • Our build tool automatically packs files inside the data/ subdirectory as Android "assets".
  • Our file-reading routines (the Download function, and everything opening files/URLs built on top of it) support a special protocol assets:/ to access Android assets. So you can open URL like assets:/my_texture.png. Usage of assets:/ protocol in URL to mark Android assets is consistent at least with Qt.
  • Finally, the ApplicationData function returns a path under assets:/ on Android.

In effect, when you use the build tool and the ApplicationData on Android, you seamlessly read data from your apk "assets".

Saving user preferences and savegames

Simply use the global UserConfig (in CastleConfig unit) to load/save your settings. See http://castle-engine.sourceforge.net/tutorial_user_prefs.php . The same mechanism works for saving preferences with standalone (desktop) applications.

Just like with standalone code, you have to explicitly call UserConfig.Load and UserConfig.Save when necessary. You will usually call UserConfig.Load in your Application.OnInitialize handler, to load user preferences at the beginning of your application. You will usually call UserConfig.Save when user confirms the preferences change, or simply immediately --- the exact moment depends on the game UI flow. Don't wait too long before saving the user preferences --- on Android, your application may be killed at any moment.

Signing a release apk

To create a "release" apk (one that you can distribute, e.g. through WWW or by uploading it to Google Play) you need to create your private key, and use it to sign your packages. See Android signing documentation http://developer.android.com/tools/publishing/app-signing.html for description how to create and manage your key store.

Once you have your keys, you need to tell our build tool to use them. You do this by creating AndroidSigningProperties.txt file at the top of your project (along the CastleEngineManifest.xml file). Add there these lines:

key.store=<path-to-your-keystore>
key.alias=<key-alias-in-your-keystore>
key.store.password=<my-password>
key.alias.password=<my-password>

This will allow you to create release apk files (our build tool will automatically use it when making a "package" in "release" mode).

Logging

Use our CastleLog unit (see http://castle-engine.sourceforge.net/tutorial_log.php). Be sure to call InitializeLog as early as possible but after setting the OnGetApplicationName. Later use WritelnLog or WritelnWarning from your code. This is shown in http://castle-engine.sourceforge.net/tutorial_mobile.php example, and in engine examples like examples/portable_game_skeleton/game.pas.

On Android, these logs are send to the standard Android logging API. The logs are visible as part of "logcat", visible using many tools, e.g. command-line "adb logcat". It's usually comfortable to filter by your program name, e.g. "adb logcat | grep androiddemo" (although, in case of mysterious crashes at startup, take a look at the full log, not filtered; some important startup info may not be marked with application name).

Is it possible to test our games using Android emulator from SDK?

Yes! (But it will be really slow...)

With new versions of Android emulator it is possible to run OpenGL ES applications (see http://android-developers.blogspot.com/2012/04/faster-emulator-with-better-hardware.html , emulator can now handle apps using OpenGL ES 2.0 and hard floats). Although the applications run very slow in the emulator, but that's a general problem with Android emulator.

Note: you will need to check "Use Host GPU" in emulator options. Otherwise the app will stop and in the log (Android logcat) you will see a message "Emulator without GPU emulation detected.". Also, make sure your device is created with sufficient space (on Internal storage or SD Card).

Testing mobile (OpenGL ES) rendering without an Android

You can compile a standalone program, for your normal OS, using OpenGLES instead of the traditional desktop OpenGL. This way you can test how your application looks like before actually compiling it for Android. The differences between desktop (OpenGL) and mobile (OpenGLES) are usually very small, due to the small number of things not yet implemented on OpenGLES.

Just define OpenGLES symbol in src/castleconf.inc inside the engine sources. Or add -dOpenGLES to your fpc.cfg file, or to the <compiler_options> in your CastleEngineManifest.xml. Then recompile (the engine and your game).

Be sure to also install an OpenGL ES library (with EGL). Unlike normal OpenGL, it is not something automatically installed on your OS.

  • On Linux, you can install OpenGL ES + EGL by installing packages libgles2-mesa-dev and libegl1-mesa-dev (these are Debian names, other distros probably have something similar).

  • On Windows, you can install:

    • Mali OpenGL ES 2.0 Emulator by ARM.

    • Angle. Official usage and download instructions are here, but it may be easiest to just copy libEGL.dll and libGLESv2.dll from your Google Chrome installation, like C:\Program Files (x86)\Google\Chrome\Application\64.0.3282.119. Just copy these two DLL files to the directory of your game .exe.

      Note that you will need to compile your application for the same architecture as Google Chrome, which is most probably 64-bit Windows, not 32-bit. So make sure to choose 64-bit Windows and CPU as target (e.g. in Lazarus project compilation options, or using CGE build tool like castle-engine.exe compile --os=win64 --cpu=x86_64).

    • Also this post has useful links: http://www.g-truc.net/post-0457.html .

Debugging running application (on an Android device) using ndk-gdb

If you use our build tool for compilation, the debug apk is already prepared such that you can debug it with "ndk-gdb". You must run ndk-gdb within the output Android project, like this:

  1. Create a debug Android package:

    castle-engine package --os=android --cpu=arm --mode=debug
    

    Install the apk and run it using any way you like, for example by

    castle-engine install --os=android --cpu=arm
    castle-engine run --os=android --cpu=arm
    
  2. Run ndk-gdb by

    cd <my-project-directory>/castle-engine-output/android/project/app/src/main/
    ndk-gdb
    

    Then debug, using ndk-gdb console just like a usual GDB.

    You can set breakpoints (and the tab key will auto-complete symbols, including Pascal symbols (uppercased)). Below is a sample ndk-gdb session. As you can see, breakpoints on Pascal symbols work (like internal fpc_raiseexception, or function WindowRender defined in game.pas). Line numbers, printing values of variables, and everything else works fine as well :)

    (gdb) break fpc_raiseexception 
    Breakpoint 1 at 0xa1d29bdc
    (gdb) break WINDOWRENDER 
    Breakpoint 2 at 0xa1d39e58: file game.pas, line 328.
    (gdb) continue 
    Continuing.
    [Switching to Thread 4909.4926]
    
    Thread 10 "ine.androiddemo" hit Breakpoint 2, WINDOWRENDER (CONTAINER=0xb3992a60) at game.pas:328
    328	begin
    (gdb) print YELLOW 
    $1 = {1, 1, 0, 1}
    (gdb) delete breakpoints 
    Delete all breakpoints? (y or n) y
    (gdb) continue 
    Continuing.
    

It is probably possible to use Lazarus to even have a graphical debugger. TODO: if you have working instructions how to use ndk-gdb with Lazarus, please improve this wiki page!

Random hints:

  • Setting a breakpoint on fpc_raiseexception is very useful -- this way you can catch all FPC exceptions.

  • You can run ndk-gdb --launch to set up breakpoints before the application launches. When ndk-gdb --launch starts, you set up breakpoints in the GDB command-line, and when ready you execute continue in GDB.

  • If you get an error around the [ .. readlink /system/bin/ps ..] failing, a workaround is to edit <ndk>/python-packages/gdbrunner/__init__.py and set ps_script = "ps".

Getting useful backtrace of a crash (on an Android device) using ndk-stack

Similar to the above instructions for ndk-gdb, you should compile your application in the debug mode, and enter the directory of resulting Android project:

  1. Create a debug Android package:

    castle-engine package --os=android --cpu=arm --mode=debug
    

    Install the apk and run it using any way you like, for example by

    castle-engine install --os=android --cpu=arm
    castle-engine run --os=android --cpu=arm
    
  2. Run the live logs from your device, and filter them through ndk-stack like this:

    cd <my-project-directory>/castle-engine-output/android/project/app/src/main/
    # if your applications runs using 32-bit Android CPU (Arm)
    adb logcat | ndk-stack -sym ./obj/local/armeabi-v7a
    # if your applications runs using 64-bit Android CPU (Aarch64)
    adb logcat | ndk-stack -sym ./obj/local/arm64-v8a
    

    This assumes that the Android tools, including Android NDK tools, are available on your environment variable $PATH. See http://developer.android.com/ndk/guides/ndk-stack.html for more information about the ndk-stack.

Now when the application crashes, you will see a nice backtrace, with a filename and line number indicating where the crash occured.

WideString manager

In short, don't worry about it: WideString manager is automatically handled for you. This means that strings with international characters just work.

Note that WideString manager may not be installed when units "initialization" section is run. (This is a limitation of some Android versions.) But it will for sure be installed when Application.OnInitialize is called.

Background: Having a WideString manager is important if you use WideStrings (e.g. with standard FPC units to handle XML, like DOM) with non-ASCII characters (e.g. regional characters specific to some language). Our engine uses UTF-8 for displaying strings with TCastleFont, and VRML/X3D use UTF-8 encoding by default. So we need to be able to convert between WideStrings and AnsiStrings with UTF-8. This is what the "WideString manager" is for.

Our engine includes and correctly initializes manager from CastleAndroidCWString, which is a slightly modified version of FPC CWString for Android (to initialize with delay, required by some Android versions).

Notes about compiling with hard floats (-CfVFPV3)

The compiler flag -CfVFPV3 is necessary to enable hardware floats, this way the engine works much faster. Our [build Tool](Build Tool) automatically uses it when compiling your project. You should also have FPC standard units compiled with this option (following our Android wiki page).

It is possible to compile and use our engine without -CfVFPV3 (in which case make sure you use FPC standard units also compiled without -CfVFPV3), things will work, they will just be much slower. E.g. in Darkest Before the Dawn loading time drops from 6 (hard floats) to 36 (no hard floats) seconds, and frames per second during game drop from 40 (hard floats) to 10 (no hard floats).

To summarize: you don't have to, but we really strongly advice using hard floats (-CfVFPV3). Be sure to compile both FPC standard units and engine units with -CfVFPV3 turned on.

Note that every unit has to be compiled with -CfVFPV3 (hard floats). It is especially important to remember it when compiling packages from Lazarus, since they also depend on standard Lazarus "fcllaz" package, which does not by default get compiled with -CfVFPV3.

It's then easiest to just add

#ifdef ANDROID
-CfVFPV3
#endif

to your fpc.cfg. This will automatically make everything compiled for Android (from Lazarus or from command-line) use -CfVFPV3. Otherwise, you will have to modify packages like "fcllaz" to add -CfVFPV3 to compilation options on Android.

How to speedup Gradle building

You can put org.gradle.jvmargs=-Xmx2048M in your ~/.gradle/gradle.properties. (We don't do it in every project, because it may unfortunately fail to work on some Windows machines, even when they have a lot of RAM...)

Castle Game Engine:

Wiki Contents:

Build Tool:

Mobile devices:

Other:

Upgrading:

Clone this wiki locally
You can’t perform that action at this time.