Brian Long Consultancy & Training Services
This is an update to a Delphi XE5 version of the same article.
Accompanying source files available through this download
Delphi XE4, XE5 and XE6 all support building iOS applications. One of the neat things about a Delphi iOS app is that it automatically gets a splash screen by default. You simply customise which image is to be used and away you go.
This all works straightforwardly because iOS is set up ready to pop up the splash screen as specified in the application's configuration data during the loading/invocation process.
Unfortunately Android has no equivalent in-built splash screen behaviour, and as a consequence Delphi XE5 and XE6 Android apps do not get a similar splash screen created for them. This is a little disappointing as, given the average large size of a Delphi Android app, its load time (certainly the first load time of the first invocation, at least) is often rather longer than we might wish on our users.
The Android package (.apk file) is an archive containing the compiled Delphi code in an Android native library, as well a bunch of compiled Java startup and support code in a classes.dex file and an optimised/crunched version of the various necessary Android resources and the application manifest. On first invocation the (sizeable) native library is pulled out of the archive by the Android package loader and stored outside for future immediate availability.
This operation can be quite tardy on devices that don't have cutting edge hardware and it's only when the library has been extracted that execution of your Delphi code can actually start. When an Android app starts, the FMX startup kicks off and does various setup jobs, such as copying any suitably located asset files from the package out onto the device storage and running the initialization sections of all units compiled into the library.
So the question arises as to how we can rectify this Delphi omission and set up a splash screen for an Android app built with XE6.
It turns out there are several choices available to us. They vary in difficulty (to implement) and effectiveness, so let's briefly run through the available options.
Back in January 2014, Marco Cantý blogged about how to set up a splash screen for Delphi XE5 Android apps and this was re-posted on FMX Express here, by simply using a Delphi form in your Android app to do the job. If this form is the main form then the first thing the user sees is the splash screen, just as with a Delphi Win32 application.
The main argument against this approach is that the splash screen still won't appear until the native library has been extracted from the app package (on first invocation), the compiled Java startup startup code has been loaded and requested to call into the native Delphi library, the previously extracted Delphi library has then been loaded for execution purposes and all the FMX startup has run. On any moderate hardware the user is still likely to have a few seconds looking at a black screen waiting for the Delphi native code to start running, and quite possibly rather more than a few.
This is certainly the most straightforward approach to the problem but doesn't really help with the need for a splash screen caused by the very nature of Delphi Android apps - the time it takes to start executing Delphi code.
A splendid OS native solution to the problem is to modify your application's personal Android app theme. This involves adding a styles file in the Android resource directory tree, which defines an Android app theme, along with a referenced splash image. The Android manifest is then tweaked to reference the theme defined in this styles file.
This is quite straightforward, although it involves several steps and a few things set up in the Deployment Manager.
You can see the details of this approach in this Chinese blog post from November 2013 (if you read it in Chrome it will offer to translate it for you). Another run-through appears on this Korean blog post from February 2014, which has an accompanying sample application available. These are both referenced in this FMX Express post.
One down side to this approach is that after the splash screen has been displayed, if the app is running on an unsupported Android OS version (Delphi doesn't support versions older than Android 2.3, and doesn't support Android 3.x - Honeycomb - at all, or the initial release of Ice Cream Sandwich - Android 4.0) then the app can still head onwards to fail gracelessly later.
Note that as of Delphi XE7 and RAD Studio XE7 this is the approach used to implement the default splash screen support.
The third option was actually the first one to be publicised as an option for Delphi XE5 Android apps and I showed the technique in one of my two CodeRage 8 sessions back in October 2013, with the code made available in this blog post and reposted on FMX Express here.
This is the most complicated approach to the problem but has the advantage that it implements a splash screen in much the same way as Java Android programmers commonly implement splash screens. As soon as Android has loaded the application package and started running the main activity's code then the splash screen will appear, as the main activity either is the splash screen or directly invokes the splash screen.
The splash screen is actually written as Java code to accomplish this, and it is designed with a standard Android activity layout. One opportunity afforded by this approach is to run some sanity checking code to ensure the Android OS version is actually compatible with Delphi applications. The original release also checked the CPU was appropriate but Delphi XE6 now does this.
This third option was the approach I took when considering how to solve this problem and so the rest of this article looks at how we can accomplish the goal.
Delphi apps on Android are native code libraries starting at a few megabytes in size in size, packaged into an .apk file along with some compiled Java, a few resources and an Android manifest. The native ARM code can communicate with the Java world using the Java Bridge (or JNI Bridge as it is sometimes called), but this relies on Delphi representations of the Java classes being present.
This is quite like Delphi for Win32 talking to Windows APIs - many APIs are pre-declared for you and some you need to create the declarations for yourself, if they aren't catered for by the Delphi RTL. Similarly Delphi XE6 has many Android classes represented, but many more are not, so there is good scope for being required to get on top of Delphi's Java Bridge to call into the Android API.
FireMonkey provides much functionality necessary for business applications needing access to data and display it to the user, but some common aspects of the Android OS are not 'wrapped up' in FireMonkey classes. In cases where this isn't simply a case of calling into more APIs whose declarations need to declared with Java Bridge interfaces this poses a problem.
Some examples of areas of the Android OS that are not wrapped up in XE5 and are difficult to incorporate are:
In Delphi XE6 these things and more require additional Java code to implement. Then some light hacking is needed to make use of this Java code in a Delphi package, which tends to get in the IDE's way, so IDE building/installing of the application becomes interesting and debugging becomes next to impossible. These consequences tend to force you into managing a pair of synchronised projects:
The specifics of the approach will require some of the aforementioned light hacking. This may seem rather onerous and cumbersome for such a simple result as creating a splash screen, but becoming familiar with circumventing the normal Delphi build cycle becomes useful when you decide you need some of the other Android aspects that also require some of the same jiggery-pokery.
One of the benefits of this splash screen implementation approach is that it does take the opportunity to do some checking and fail gracefully if the OS is not suitable for running a Delphi XE6 app.
The steps required for the splash screen setup are as follows:
That's quite a daunting list but fear not. Fortunately many of the Java-oriented steps can be wrapped up by a suitably crafted batch (.bat) file or command script (.cmd) file. And I'm sure if you really wanted to, you could also create a PowerShell script to do the same, but I've stuck with the old scripting that I know how to work with.
Android resource files usually reside in a
res folder under the project
directory, so we'll stick with that norm.
There are three resource files required to get the splash screen running as required here:
The layout resource is a file called
and contains this layout:
This defines an Android layout that fills its parent (essentially the screen) and
has an image view control centred inside it containing a drawable resource (an image)
splash. The image will be stretched to fill the screen.
Note that with
the Delphi XE5 version the image was just centred in the screen (using the
centerInside value instead of
fitXY), as the background
defaulted to a solid black. However with Delphi XE6 the background defaults to a
graduated black to grey background, and so if the image is smaller than the screen
then you have a non-too-pleasant graduated area spilling out around the edges. You
can experiment on various devices and see what you prefer.
To set up the image we can either create a suitable file as
or, as is the case in this example, we can have the Deployment
Manager do that later.
Finally, the string values file is called
looks like this:
This string value will get referenced from the Java code. The point of having string
constants isolated into value files allows easy translation. You can simply add
another file called
res\values-fr\strings.xml and redefine any or all
of your strings in the original file in French and, if the app is run on a device
set to French, the French string will automatically be used by the app.
The Java splash screen activity class is in a file in the project directory called
java\src\com\blong\test\SplashActivity.java and looks like this:
On creation it hides the Android title bar and goes full screen, then loads up the activity layout resource we saw earlier. Then it starts a thread to run for a few seconds in the background, hopefully giving the native library chance to be copied from the Android package (if necessary) and brought into memory. When the background thread has run for 3 seconds (or the user has touched the splash screen) it then launches the FireMonkey activity to take over and execute the application as usual.
Seeing as this custom Java code will execute before any of the Delphi code can run it seems an ideal place to add in some code that checks out the OS version to ensure they match Delphi's requirements.
Here's my code that does this when the splash activity starts up:
There's nothing much to say about the code in there. However it neatly finishes off a Delphi XE6 application, which without any such checks may potentially fail unpleasantly.
java project subdirectory is a batch file called
Before invoking the batch file you must ensure you have added a few directories
from the Android SDK and the JDK to your System path. You can do this either:
PATHenvironment variable using steps outlined here or here
Note that the required directories will vary depending on whether you already had
an Android SDK installed, or whether you let Delphi install the Android SDK and, if
so, where you told it to install it. For example you may have already installed
the Android SDK in
C:\Android\android-sdk-windows, or Delphi may have
installed it into
or you may have given Delphi a specific target directory, meaning the Android SDK
path is in, say,
Directories to add to the path are:
build-toolsdirectory, which might be
C:\Users\Public\Documents\Embarcadero\Studio\14.0\PlatformSDKs\adt-bundle-windows-x86-20131030\sdk\android-4.4or somewhere else altogether.
bindirectory, which will be something along the lines of
C:\Program Files (x86)\Java\jdk1.6.0_23\binor
I'd certainly recommend extending the Windows search path permanently through the
environment variables option in the system properties dialog so you can run Android
SDK commands and Java commands at any point going forwards, but if you wanted to
SET commands at the command prompt or from within the batch file
they might look a little like this:
Once the system path has been updated you will be able to successfully launch the following executables from a command prompt. If you updated the global path then it will be any command prompt launched after you've made the change. If you changed a local environment by running commands at a command prompt then you can run the commands from that command prompt. The commands are:
If you cannot launch any of these commands then go back and review your path settings as they are likely wrong.
To run the build script requires you to first launch a RAD Studio Command Prompt - you can do this in Windows 7 or Windows 8.x by going to the Start menu or Start screen and typing:
and then selecting the RAD Studio Command Prompt item that is found. Or you can just hunt through the program groups to find it.
Before changing to the directory that contains the batch file using the
<path_to_batch_file_dir> command you must open the batch file in
an editor and make appropriate edits to ensure the various environment variables
set at the start are correct. This is what the batch file looks like:
You should modify the
set commands for the following environment variables
and ensure they refer to appropriate exising directories:
ANDROID- this should point at the Android SDK installation directory, e.g.
ANDROID_PLATFORM- this needs to be set to one of the installed Android SDK platform directories, found in the Android SDK's
platformdirectory. The Delphi installed SDK installs the
DX_LIB- This needs to be set to the directory containing the
dx.jarDalvik support library. This is found in the
libdirectory 2 levels under the Android SDK's
build-toolsdirectory. You will need to look to find the correct intermediate directory for your SDK installation. The batch file suggests this may either be something like
android-4.4or something like
EMBO_DEX- should point at a
classes.dexfile shipped with Delphi. My installation has one stored as
C:\Program Files (x86)\Embarcadero\Studio\14.0\lib\android\debug\classes.dexbut the environment variable value is surrounded in quotes due to the spaces in the path.
In the RAD Studio Command Prompt you should change directory to the one containing
the build batch file and then invoke it by running:
This should proceed to:
dx.batAndroid SDK script
DexMergerclass in the
If any of these steps fails then you should review the environment variables and see which one has not been set correctly.
In the case that the
dx command fails with the error:
bad class file magic (cafebabe) or version (0033.0000)
then this has a specific cause. You have JDK 1.7 installed (this is what Delphi
will install for you), but
dx expects Java code as compiled by JDK
To resolve this issue, you can either switch back to JDK 1.6 or modify the javac.exe command-line to have some additional command-line switches, which force the JDK 1.7 compiler to emit JDK 1.6 compatible Java byte code.
Edit the build script batch file to include this in the javac command-line:
-source 1.6 -target 1.6
Now try and rebuild and the error should not recur.
After a successful build you will have a new
classes.dex file in the
java\output\dex directory, which contains the new splash
screen code in addition to all the regular FMX Java code and Android support library
included there by default.
At last it is time to open the sample project in the Delphi XE6 IDE. The functionality in the application is irrelevant and in this case it is intensely trivial. However we have a little more setup to do in the IDE, so choose the Project, Deployment menu item, which gives us this:
There are a couple of things to note about what is set up here:
classes.dexfile from the RAD Studio directory has been de-selected. Instead, the newly created
java\output\dexdirectory has been selected to be deployed to the same place: the Android package's
classesdirectory. This gets all our splash screen startup Java code on board within the Android package file.
splash_activity.xml, is set to be deployed to the
strings.xml, is set to be deployed to the
res\drawabledirectory. You can choose whatever splash image you like, but the sample project uses the launch screen that Delphi XE5 offers for iPad apps:
You should note that the Deployment Manager in Delphi XE5 had a problem with substituting
alternate versions of
classes.dex into Android application packages.
The problem is logged in Quality Central as QC 118472.
The issue manifests itself by Delphi automatically re-selecting the default shipped
classes.dex when you switch configurations in the Deployment Manager.
This overrides the replacement version and so things very much stop going according
The problem appears to have been fixed in Delphi XE6, but the QC report is still open. So in case it still happens, just more intermittently, it seems sensible to mention it.
In order for the splash screen activity to be launched when Android loads the application package the Android manifest must be updated to reflect this requirement.
When you first compile a Delphi project that is set to target Android, an Android
manifest template is written into the project directory by the name of
This is a templatised file that is expanded during compilation cycle into the real
AndroidManifest.xml file in the project's
The Android manifest for a Delphi Android app normally specifies that the FireMonkey
com.embarcadero.firemonkey.FMXNativeActivity, is the default
activity by virtue of a nested intent filter. The activity in the manifest template
file looks like this by default:
To make the splash screen be the main startup activity, which will launch the FireMonkey activity, this needs to be updated to look as follows. Essentially we have another activity defined, and that new activity takes the intent filter from the FireMonkey activity.
You can see the actvity is defined by its package-qualified class name and is specified to always display in portrait mode.
The application can now be compiled to a native Android library and then deployed onto an Android application package (.apk file) using the Project, Compile SplashScreenTestXE6 and Project, Deploy libSplashScreenTestXE6.so menu items respectively.
If you wish you can skip those two steps and have them done implicitly by choosing
the Run, Run Without Debugging menu item (or by pressing
This will install the app. If it is already installed then the app will be re-installed,
preserving any data that the app has already built up.
Note that despite choosing the Run Without Debugging menu item, the application
will not be launched on the target device. The same is true if you choose Run, Run
F9). This is due to another shortcoming of the IDE in which it assumes
the launch activity will be the FireMonkey activity and so is unable to contend
with the situation we have here where the launch activity has been switched. This
issue is open in Quality Central as QC 118450.
Clearly with the issues with launching the application there is no possibility of debugging your code. You cannot attach to a running Android process as you can with a Windows process, for example.
If you need to actively debug (as opposed to some agricultural equivalent such as
using calls to
Log.d from the
FMX.Types unit) then it is incumbent
upon you to set up a pair of almost-mirror projects. One project will have all these
hacks described thus far on this page, and will enable a splash screen in your application.
The other project will use the same application logic and units, but will ignore
all aspects of setting up a splash screen. Consequently this second project should
support regular Android app debugging.
Setting up an Android splash screen is feasible. There are three ways to do it and they have various pros and cons. The approach detailed at length on this page is the most cumbersome to set up but offers the most benefits - a splash screen, suitability checking of the OS and familiarity with using custom Java code to achoieve your ends, which can be useful in various areas of Android development with Delphi.
Go back to the top of this page