Delphi Handbooks Collection


Delphi XE Handbook


Delphi 2010 Handbook


January 3, 2014

A Splash Screen for Delphi on Android

Differently form iOS, Android lacks an initial splash bitmap, but you can build one to improve startup time (or its perception).

Differently from iOS, Android lacks an initial splash bitmap, but you can build one to improve startup time (or its perception). In fact, it is not that you can make things faster, but the user will get the initial screen in a shorter time than he or she will get the main form, if this takes time to initialize. You'd want to do this when the main form has many controls, requires database or file access, needs to load images, access to remote data, or anything that takes extra time. In all of these scenarios, an initial splash screen (like the one I've used in my Play Store app covered on log.marcocantu.com/blog/my_son_first_play_store_app.html) will be handy.

There are two approaches I can think of. One would be an initial screen that is never displayed again, the second would be a splash screen that acts as main menu for the application, and can be used over time. For my app, I implemented the second approach, and this is what I'm going to cover. Also, in my specific case, there are two alternative secondary forms you can go to from the main splash screen form.

First, we need to have the initial form show fast. This form should have little or no initialization code. It might have an image, covering most of its surface, plus some buttons (initially not visible, in my case). Here is the actual form at design time, and below its form definition:

      object Form2: TForm2
  object ImageControl1: TImageControl
    Align = alClient
    Bitmap = ...
  end
      object GridPanelLayout1: TGridPanelLayout
    Align = alBottom
    Height = 71.000000000000000000
    ColumnCollection = <
      item
        Value = 50.000000000000000000
      end
      item
        Value = 50.000000000000000000
      end>
    ControlCollection = <
      item
        Column = 0
        Control = Button1
        Row = 0
      end
      item
        Column = 1
        Control = Button2
        Row = 0
      end>
    RowCollection = <
      item
        Value = 100.000000000000000000
      end>
    object Button1: TButton
      Align = alClient
      Text = 'Collection'
      Visible = False
    end     object Button2: TButton
      Align = alClient
      Text = 'New Figuret'
      Visible = False
    end   end
      object ToolBar1: TToolBar
    Height = 48.000000000000000000
    object Label1: TLabel
      Align = alClient
      Text = 'My Mini Figures'
      TextAlign = taCenter
    end   end   object Timer1: TTimer
    Interval = 100
    OnTimer = Timer1Timer
  end end
      

There are a few things to notice in this FMX file definition:

  • There is a toolbar with a label covering its surface (alClient) and centered text, which acts as a title
  • There is an image covering the entire screen surface (but the toolbar and the bottom area)
  • There are two buttons at the bottom. To make them half of the screen each, I added them to a GridPanelLayout with a single row and two columns, using 50% of the width each. The two buttons are aligned to the area of each of the two cells.
  • A timer, with a short interval

Besides the UI elements, what is important for this splash screen to show faster, is to avoid creating the other forms at startup (in the main project file). However, you cannot create the secondary forms in the OnCreate handler of the main form (as you won't see it on screen until after the OnCreate event handler has finished executing). One options would have been to start a secondary thread. Another (simpler) option I've used in my code is to rely on a  timer. After the form has been created and displayed, the timer will kick in (possibly waiting a few milliseconds) and execute the following code:

      procedure TForm2.Timer1Timer(Sender: TObject);
begin
  Form1 := TForm1.Create(Application);
  Form4 := TForm4.Create(Application);
  Button2.Visible := True;
  Button1.Visible := True;
  Timer1.Enabled := False;
end;

As you can see, when the timer fires the app creates the two secondary forms (which takes a few seconds on my phone, as the program loads 60 or so images from files) and enables the two buttons. This delay and the actual initialization of the real mani form takes place while the splash screen is visible. Without this trick, the user will have a black screen... and the Android system might also indicate the app is not responding and refuse to start it.

Needless to say you'll have to adapt this splash screen code to your specific scenario, but I think it is worth using this approach in any application with a non trivial initialization. Again, you can test this in action by getting the app from the Play Store at https://play.google.com/store/apps/details?id=com.marcocantu.MyMiniFigures.

 





 

12 Comments

A Splash Screen for Delphi on Android 

 I would put the timer1.enabled := false; as the first line of code in 
the timers eventhandler. Wouldnt your way risk the timer stumbling 
on itself?

Do you kick the timer in the onCreate of the form, or just set it 
enabled := true at designtime?
Comment by Jens Fudge on January 3, 15:43

A Splash Screen for Delphi on Android 

Jens,

  yes, disabling the timer first might be safer, but given all the code runs 
in the main thread, there isn't a chance that the timer code will be 
executed a second time before the first is done. 

I enable it at design time, but setting it in OnCreate will be identical. 
Comment by Marco Cantu [http://www.marcocantu.com] on January 3, 16:10

A Splash Screen for Delphi on Android 

 I have used a TPanel


procedure TfrmMain.DoClick(Sender: TObject); 
begin 
 pnl.AnimateFloat('Position.y', - pnl.Height, 1.0); end;

procedure TfrmMain.FormActivate(Sender: TObject); begin 
 pnl.AnimateFloat('Position.y', Self.Height div 4,  1.0); 
end;

procedure TfrmMain.FormCreate(Sender: TObject); 
begin 
//create the panel 
pnl:= TPanel.Create(self); pnl.Parent:= self;
pnl.Width:= ClientWidth div 2; 
pnl.Height:= ClientHeight div 4; 
pnl.Position.X:= (ClientWidth div 2) -
(trunc(pnl.Width) div 2); 
pnl.Position.Y:= - pnl.Height; 
pnl.OnClick:= DoClick; 
//create the label 
lbl:= TLabel.Create(pnl); 
lbl.Parent:= pnl; 
lbl.Text:= 'Hello World'; 
lbl.TextAlign:= TTextAlign.taCenter; 
lbl.Align:= TAlignLayout.alClient; 
end;
Comment by Shane Holmes on January 3, 17:05

A Splash Screen for Delphi on Android 

In CodeRage Brian Long demonstrated way to have proper 
fast loading splash image on Android like in FM iOS 
apps. The code does also some hardware checking for 
NEON support etc. It involves quite bit of hacking 
with Java classes etc.

My question is - why is not Embarcadero doing that by 
default in FM Android and show app icon as splash 
screen by default to give better user impression on 
loading app, similarly to FM iOS? Why users must hack 
around and use workarounds to provide basic 
functionality for Android apps?

Second video on his page, at about 30 minutes.

http://blog.blong.com/2013/10/my-coderage-session-
files.html
Comment by AT on January 3, 21:22

A Splash Screen for Delphi on Android 

Hi Marco,

did you ever consider to use an anonymous timer? I
blogged (http://blog.kassebaum.eu/?p=238) about it.

-- 
Thanks,

Roman
Comment by Roman on January 4, 11:25

A Splash Screen for Delphi on Android 

 HI
the 2nd version method is a great idea
works great for me my android app
as the splash screen shows in 1 second
and then I hide that once all the rest of the program
is finished updating/loading doing what it needs to
do, etc
Thanks
Brian
Comment by Brian Hamilton [http://www.weather-display.com] on January 6, 18:23

A Splash Screen for Delphi on Android 

I haven't done any Android development yet with 
newest Delphi so I might be way off but why wouldn't 
you use FMX.Forms.TApplication.OnIdle event to decide 
when you start loading of aplication main form. This 
way you can start loading of application main form as 
soon as loading of splash screen is finished.
Comment by SilverWarior on January 7, 12:25

A Splash Screen for Delphi on Android -> Anonymous timer 

 I totally agree with Roman. An anonymous timer is
something very usefull here for example. 

I am using them extensively for Asynchronous
Programming since we do not have things like Async or
Await in Delphi yet.

VCL Anonymous timer look like this:

Timer1:=TTimer.Create(Form1);
 Timer1.Interval:=1000;
  Timer1.OnTimer:=TNotifyEventDispatcher.Create(Form1,
  procedure (Sender: TObject)
  begin
     Timer1.enabled:=false;
// code something
   end);

For this code to work you need the
TNotifyEventDispatcher class that you can find in this
link:

http://stackoverflow.com/questions/8025481/vcl-events-with-anonymous-methods-what-do-you-think-about-this-implementation

I am using anonymous timer to wait efficiently in the
Main Thread (the VCL thread). 

The anonymous timer is typically written in a
procedure containing a case structure that I can
callback from the anonymous timer. The case structure
(with enumeration instead of integer) is used so that
I reenter in the procedure after the anonymous timer.

Before the anonymous timer I start usually a 2. thread
or a non-blocking procedure that make something in the
background





Comment by alexandre jacquot on January 7, 15:30

A Splash Screen for Delphi on Android 

@AT,@Marco

I totally agree, given the delays that you get when the 
FM app starts up, we need the ability for it to display 
an image when the app starts - just like iOS.

Writing a splash screen is fine, but it still a good 1-
2 second wait depending on the hardware until it 
appears. Its not a good first impression when someone 
is using your app for the first time.

Steve.
Comment by Steve Childs on January 9, 12:18

A Splash Screen for Delphi on Android 

Hi. I tried many times with a very simple app that 
has 2 forms: the splash and the secondary with 
absolutely no success. Details are below:

- Splash form: Empty, only the Fill property was set 
to Gradient in order to distinguish this form with 
black background after start.
- Secondary form: Empty, similar to Splash form but 
the Fill is of different color.

After many unsuccessful tries I decided to just write 
a new app with just 1 empty form and, surprise, it 
starts the same 4-5 seconds on my Galaxy Note 2.

Even more puzzled is that Marco's simple app starts 
very fast. What is the reason?

Note: I use Delphi XE5 (Not the updated versions)
Comment by Tran [] on January 25, 11:54

A Splash Screen for Delphi on Android 

May be many of us try to make same sample. I can not 
reach less then 4 sec on Galaxy S3. 
Marco, Please give a sample code to check it. I can not 
reach 2 sec as demo app.
XE5 Update 2
LuboG 
Comment by LuboG on February 21, 16:31

A Splash Screen for Delphi on Android 

 LuboG, did you try my app, form the app store? does it behave in the 
same way? A better option is to have the image in the manifest, as 
explained in the link below (http://www.fmxexpress.com/add-a-splash-
screen-with-the-android-manifest-for-delphi-xe5-firemonkey-apps/)

-Marco
Comment by Marco Cantu [http://www.fmxexpress.com/add-a-splash-screen-with-the-android-manifest-for-delphi-xe5-firemonkey-apps/] on February 21, 17:49


Post Your Comment

Click here for posting your feedback to this blog.

There are currently 0 pending (unapproved) messages.