Some time ago I published a simple database with a fake Pizza Shop menu on Azure. Using a Delphi application similar to the one discussed in this article I wrote some time ago, I published a local database on Azure Tables, using Azure Blobs for the pictures of the various pizzas.

Later I wrote an iOS client (in parallel to a desktop version for Windows and Mac, with very similar code), that let you retrieve the list, get details on one entry, and place an order (posting data to another Azure table), including the location (latitude and longitude) information taken from the device using the location sensor.

Yesterday, in a couple of hours I cleaned up the user interface a bit and built an Android app, with the new coming version of Delphi. Notice that while on iOS i had to put in some extra effort for OpenSSL support, on Android this is part of the platform and there is no extra requirement. All I had to do was configure the AzureConnection component and add this to the OnCreate event handler:

  TableService := TAzureTableService.Create(AzureConnectionInfo1);
BlobService := TAzureBlobService.Create(AzureConnectionInfo1);

The main form has a button to retrieve/refresh the list of pizzas:

procedure TForm4.ButtonRefreshClick(Sender: TObject);
rowsList: TList<TCloudTableRow>;
aRow: TCloudTableRow;
item: TListViewitem;
rowsList := TableService.QueryEntities(tablename);
ButtonRefresh.Text := Format ('Found %d pizza(s)', [rowsList.Count]);
for aRow in rowsList do
item := ListView1.Items.Add;
item.Text := aRow.GetColumn(XML_ROWKEY).Value;
item.Tag := StrToIntDef(aRow.GetColumn(XML_PARTITION).Value, 0);

Notice how I keep the numeric partition key in the Tag of the list view items, since I need it later for getting the record and the images. This is the Android screen, after fetching the list of pizzas:

As a user selects a pizza, the name and id are used to fetch the record data, the blob, and populate the second tab of the form:

procedure TForm4.ListView1ItemClick(const Sender: TObject;
const AItem: TListViewItem);
aRow: TCloudTableRow;
memStream: TMemoryStream;
ShowMessage ('About to get details for ' + AItem.Text +
' (' + IntToStr (aItem.Tag) + ')' );

TabControl1.ActiveTab := TabItem2;

aRow := TableService.QueryEntity(tablename,
IntToStr (aItem.Tag), AItem.Text);
if Assigned (aRow) then
Label2.Text := aRow.GetColumn(XML_ROWKEY).Value;
SpeedButton2.Text := 'Order for ' + aRow.GetColumn('price').Value + '$';
Label3.Text := aRow.GetColumn('description').Value;

memStream := TMemoryStream.Create;
BlobService.GetBlob(tablename, aRow.GetColumn(XML_PARTITION).Value + '.jpg', memStream, '');
memStream.Position := 0;

The main calls here are QueryEntity and GetBlob. Notice the code for loading the image using a stream: That code works identically on Windows, Mac, iOS, and now Android. In fact 99% of the code of this demo works across all four platforms. This is the output on Android, with the description and the image of the selected pizza:

At the bottom, there is an "order" button with the price, which is going to post a new record on a second azure table, inserting the location information (obtain from the sensor):

procedure TForm4.SpeedButton2Click(Sender: TObject);
  RowObj: TCloudTableRow;
  RowObj := TCloudTableRow.Create;
  RowObj.SetColumn (XML_ROWKEY, user_name);
  OrderId := OrderId + 1;
  RowObj.SetColumn (XML_PARTITION, IntToStr (OrderId));
  RowObj.SetColumn('latitude',  LocationSensor1.Sensor.Latitude.ToString);
  RowObj.SetColumn('longitude',  LocationSensor1.Sensor.Longitude.ToString);
  RowObj.SetColumn('pizza',  Label2.Text);
  TableService.InsertEntity(orderstable, RowObj);

  ShowMessage ('Your order for ' + Label2.Text + ' was sent');

The output is a simple confirmation message:

This is all it takes to consume and produce Azure data and blobs on your Android phone, using the support classes already available in the past few versions of Delphi.  And, again, the same source code (with some UI differences) will work perfectly on all 4 platforms Delphi is about to support.