Simple Firemonkey mobile application for Android step-by-step

Today I'll show you how to create simple mobile application for Android using Delphi in few minutes. And if you have an Apple device, you'll only translate it for iOS.

All the development will be carried out on Windows platform as a 32bit application, only the result will be adapted for target device or platform. Our application allows to enter ID and returns business record for given company (business name, address and more) in JSON format – result will be processed and displayed within an application.

Prerequisities

  • Delphi with Mobile development
  • an Android device on which USB debugging is enabled

Let's start

In first step, create a new application, i.e. select Multi Device Application and Header/Footer layout. As soon as first step is done, save basic app anywhere you like.

Mobile Development

Mobile Development

Several last versions allow Firemonkey to use View technology, where user can define exact look of the app on various resolutions (we define Master and customize it then). Working with Master only will be enough for us because application adapts itself and detailed resolution settings won't be necessary.

Mobile Development

View options – Master enoughs

Now is pretty important to set Layout – it means assure app to customize target device in case if layout for various resolutions is not set. We can choose among many Layout options (you can imagine as a panel with certain behavior), but let's use TListBox component (another reasonable option is MultiView or TListView).

Mobile Development

To be frank, do forget VCL based TListBox, this is strongly different solution. Each Item within the list can be a component with type at pleasure, with different style, and can contain further miscellaneous components.

ListBox in action

Choose ListBox and place it onto the Form with setting Align=alClient.

Titles

Now we will insert particular items which will represent a cornerstone of our user interface. Starting with title (I've already inserted it there).

Mobile Development

In the next step add an Item on ListBox through context menu:

Mobile Development

and set desired style:

Mobile Development

Finally, type title text.

Items

Intended look is depicted below:

Mobile Development

So we insert TListBoxItem ten times and set Style if necessary. Edit field is common TEdit but with special style and Align set to alCenter (however, you can use any other align method).

How do we create delete key for TEdit? Simply click at TEdit and add TClearEditButton by means of context menu, that's all.

Mobile Development

Please observe tree structure regarding TEdit. FireMonkey allows to combine components as you like and as you need. Styles what are able to "do miracles" are additional value too.

Well, we've created basic user interface. This UI will be adapted according to target platform while compiling.

Main programme

At this moment, we can compile application for target platform, i.e. for Windows, iOS, Mac OSX or Android. I strictly recommend to develop completely using Windows target and tune up e.g. for Android – it's more comfortable regarding speed of compiling and deployment.

Mobile Development

You can see I wrote no-one line of code until now and we'll fix it just now. How it will work? We are about to use certain Czech local webservice that can return business information for given company (based on its ID, so called IČO) in JSON format. So we simply create URL, download data using THTTPClient Delphi component and parse and display returned data by means of multiplatform System.JSON.

Code for Button


uses
  //  Windows,
  System.Net.httpclient,
  System.JSON;
{$R *.fmx}

procedure THeaderFooterForm.Button1Click(Sender: TObject);
var
  oClient: THTTPClient;
  oStream: TStringStream;
  iStatus: Integer;
  sResponse: string;
  oJsonValue: TJSONValue;
  s: string;
  o: TObject;
const
  ciLen = length('ico_back('); // odpoved obsahuje kus JS
begin
  oClient := THTTPClient.Create;
  oStream := TStringStream.Create;
  try
    // pro ladeni
    iStatus := oClient.Get('http://data.fin.cz/json/subject/45274649.js', oStream, nil).StatusCode;
//    iStatus := oClient.Get('http://data.fin.cz/json/subject/'+edtICO.Text+'.js', oStream, nil).StatusCode;
    iStatus := iStatus div 200;
    if iStatus <> 1 then
    begin
      edtName.Text := 'Error:'+iStatus.ToString;
      Exit;
    end;
    sResponse := oStream.DataString.Substring(ciLen);
    sResponse := sResponse.Remove(Length(sResponse) - 1);
  finally
    oStream.DisposeOf; // ignoruj ARC 
    oClient.DisposeOf;
  end;
(*
 'ico_back({id:''25247484'',count:1,name:''AB - AKCIMA, s.r.o.'',
 url:''http://rejstrik-firem.kurzy.cz/25247484/ab-akcima-sro/'',
 addr_main:{city:''Cheb'',citypart:''Cheb'',street:''Havl\u00ED\u010Dkova 1803/2'',
 zip:''35002'',no:''1803/2'',code:{city:''554481'',district:''CZ0411''}},
 vat:{id:''CZ25247484''},date:{start:''2000-08-03'',last:''2014-09-01'',end:null}})'
*)
  sResponse := NormaliseJSON(sResponse);
//  Windows.MessageBox(0, Pchar(sResponse), nil, 0);

  oJsonValue := TJSONObject.parseJSONValue(sResponse);
  if oJsonValue is TJSONObject then
  begin
    s := TJSONObject(oJsonValue).Values['id'].Value;
    edtName.Text := TJSONObject(oJsonValue).Values['name'].Value;
    o := TJSONObject(oJsonValue).Values['addr_main'];
    if o is TJSONObject then
    begin
      edtAdr1.Text := TJSONObject(o).Values['street'].Value;
      edtAdr2.Text := TJSONObject(o).Values['citypart'].Value;
      edtPost.Text := TJSONObject(o).Values['zip'].Value;
    end;
  end;

First part of code downloads JSON, second one goes through and returns requested information. It's straightforward except NormaliseJSON which partially edits returned JSON.


function THeaderFooterForm.NormaliseJSON(const s: string): string;
var
  c: char;
  bInQuote: Boolean;
begin
  Result := '';
  bInQuote := False;
  for c in s do
  begin
    if c = '''' then
    begin
      bInQuote := not bInQuote;
      Result := Result + '"';
      continue;
    end;
    if bInQuote then
      Result := Result + c
    else
     if CharInSet(c, ['{', ',']) then
      Result := Result + c+ '"'
    else
     if CharInSet(c, [':']) then
      Result := Result + '"'+c
     else
      Result := Result + c
  end;
  Result := Result + '';
end;

Try it out for Windows, translate for Android and we've done.

Notes

Be aware of zero-terminated strings in mobile applications – if you do not want to use switch which turns it off, simply remember that all the functions called by String.xxxx start from zero.

Mobile Development

Size of Application

Remove all unnecessary parts from your app via the Project Manager. Final application compile as a Release, package size is in my case 6 119 782 bytes.

Mobile Development

It should have been video tutorial initially but it wouldn't be good. In addition, I like rather textual instruction so I'm sorry for that :-)

About the Author

Ing. Radek Červinka
Embarcadero MVP
Web: Delphi.cz
Twitter: @delphi.cz