Castle Game Engine defines a number of useful Android services and iOS services to integrate with various 3rd-party libraries, SDKs to provide additional functionality to your application.
This page documents how you can add new services for Android.
All the Android services require that you have an
integrated Android project type (default now), not
base. With the
integrated project type, our final Android project has it’s own activity class (
MainActivity, descendant of
tools/build-tool/data/android/integrated/app/src/main/java/net/sourceforge/castleengine/MainActivity.java), and it has Java code that is "summed" by adding all the files from
and subdirectories of
base project type (you can request it by
CastleEngineManifest.xml) is not suitable to implement additional services.
This project type on Android (constructed from code in
tools/build-tool/data/android/base/ ) does not contain any Java code. It is possible thanks to using Android
NativeActivity class. The activity type of our game can be simply declared as
NativeActivity then, for Android build tools, and there’s no need to create our own Java activity class, or to write any Java code at all. This possibility was explicitly documented at the
NativeActivity docs from Google.
This allows our application to render, update, listen for touch events, in general use all the NDK functionality (including standard Unix library, e.g. to open files, and some Android-specific things like logging). For some simple games this is enough.
But any integrations that require Java libraries are impossible to implement in this case. The NDK libraries only provide some basic functionality, they absolutely do not cover the functionality offered by the Java API on Android.
It’s easy to add your own Android services, if you need to integrate with some Android library not covered by existing Android services. Create your service inside the
castle_game_engine/tools/build-tool/data/android/integrated-services/xxx/ directory. The files there are copied to the final Android project, expanding macros inside. Most of the files are simply copied (but avoiding overwriting), but some files are merged in a special way:
AndroidManifest.xml of each service is merged with the main
AndroidManifest.xml in a smart way, only adding the new permissions and new elements/attributes inside the
build.gradle files inside the services have a special XML syntax. See the example services like
helpshift. They are merged into the final (non-XML)
build.gradle file in a smart way.
Each service may also insert a snippet of Java code to the
MainActivity.java file. This is typically used to initialize the service-specific Java class, like
When developing new services, it’s useful to inspect the generated Android project in the
castle-engine-output/android/project. This is created by the build tool by merging all the services with base project template. Look there after running
castle-engine package --target=android.
The main code of a service is usually a class descending from the
ServiceAbstract class. It has some methods that you can override, like
onStart, and so on — they are called when the appropriate lifecycle event occurs on the
MainActivity. The idea is that our
MainActivity should be a relatively small class, that simply "passes on" the events to every service.
To communicate with the services from the Object Pascal code, use the
CastleMessaging unit. Our units like
CastleGameService are simply thin "wrappers" using
CastleMessaging unit under the hood — see at their sources to know how it works, it is very straightfoward.
This way you can write Java code and utilize any Android Java API, and communicate with Pascal.
CastleMessaging is a simple asynchronous communication mechanism between Pascal and Java, using it is easy (you have ready methods on both Pascal and Java side, and you don’t need to deal with JNI).
On the Pascal side, use
CastleMessaging unit, that exposes a singleton
Messaging.Send(['message-1','some-parameter']) to send something.
Register your callback like
Messaging.OnReceive.Add(@MessageReceived) to receive something.
Typically, you wrap sending and receiving messages in a nice Pascal API. Examples of it are in the CGE
On the Java side, you create a class descending from
ServiceAbstract. Such class can override
messageReceived method to receive messages, and use
messageSend to send messages. Examples of it are CGE services inside
See e.g. Google Play Games handling:
the Pascal part is in
the Java part is in
The Java code of this particular service is no longer straightforward (it has a lot of functionality by now…), but it shows how to pass messages back and forth.
For something simpler, see the "vibrate" service:
the Java side is in
and the Pascal side is a trivial function
CastleMessaging is not supposed to be an "API for all communication", but in practice it works very well in all existing services — since it’s natural for asynchronous processing (where many things are done in some thread, and/or wait for network or user input before returning any result).
The exact messages are not documented anywhere, since they are the "internal" API between Pascal and Java code. You should just cross-reference the
ServiceGooglePlayGames.java and see that what one sends — the other receives:) When creating new service, you just invent your own messages, using any non-conflicting names.
In the Java part, you use the full power of Java APIs on Android, that are necessary to access various Android stuff. On the Pascal side, you create a thin wrappers that merely send/receive messages. Final games should use the Pascal API, without being aware of any "messages" underneath, e.g. see how
castle-engine/examples/2d_dragon_spine_android_game/ uses the
The disadvantage of
A service can be to add a dynamic library (SO, file like
libxxx.so) to your Android project.
This should be compiled for all Android architectures, so you actually need 2 versions:
Arm 32-bit (called just
arm by various tools)
and Arm 64-bit (called
aarch64 by various tools).
In theory, only one of them can suffice, but then your application will only support one Android architecture. You would then build the application like
castle-engine --cpu=arm --os=android (to make 32-bit-only application)
castle-engine --cpu=aarch64 --os=android (to make 64-bit-only application).
For now, we strongly advise that you provide both SO versions, and compile your APK for both architectures using simple
Example services that includes SO files see:
They contain just a few trivial files, and two SO files (for Arm 32-bit and 64-bit).
To improve this documentation just edit the source of this page in AsciiDoctor (simple wiki-like syntax) and create a pull request to Castle Game Engine WWW (cge-www) repository.
Copyright Michalis Kamburelis and Castle Game Engine Contributors.
This webpage is also open-source and we welcome pull requests to improve it.