Tuesday, June 3, 2014

Access Marvel Developer API with Delphi XE6



Marvel has recent made available The Marvel Comics API, that allows developers everywhere to access information about Marvel Universe. "The Marvel Comics API is a RESTful service which provides methods for accessing specific resources at canonical URLs and for searching and filtering sets of resources by various criteria. All representations are encoded as JSON objects".



So my idea is to access these API with the Delphi REST Client Library and create an awesome app.
Let's start!
At First we need to register to the developers program, once registered we will be given 2 keys one public and the other private that will be used to call the Marvel API. For more information about the service, resources, authentication and so on I refer you to the official Pages: General Info - Getting Started - Interactive API tester.
You can access six resource types using the API:

  • Comics
  • Comic Series
  • Comic Stories
  • Comic events and crossovers
  • Creators
  • Characters

In this first demo app I get information only about characters of Marvel Universe.




I created an HeaderFooter Mobile Application by the wizard, modified the text of prebuilt label for the Title ("Marvel Character"), added a TLabel for the name of the Character, a TImage that is the representative image for the character and finally I insert the mainly 3 components of the REST Client Library: RESTClient, RESTRequest and RESTResponse.
The Marvel Comics API’s base endpoint is http://gateway.marvel.com/v1/public so I put this URL in the BaseURL property of the RESTClient.



The RESTRequest represent the resource in the REST pattern and in this case represent the character. I defined the Resource property in this way: characters?limit=1&offset={OFFSET}&ts={TS}&apikey={APIKEY}&hash={HASH}.
There are 3 parameters:
  • limit - that represent the number of the result, in this case 1 result for time because we can see 1 character at time on the form
  • offset - that indicate the distance from the first character
  • ts - a timestamp (or other long string which can change on a request-by-request basis)
  •  apikey - your public key
  • hash - a md5 digest of the ts parameter, your private key and your public key (e.g. md5(ts+privateKey+publicKey)
This is the snippet code of request:

procedure THeaderFooterForm.ExecuteRequest;
var
  TS: string;
  imd5: TIdHashMessageDigest;
  HASHStr: string;
begin
  // StartWait show a progress dialog until the request is finished
  StartWait;
  TS := IntToStr(DateTimeToUnix(Now));
  RESTRequest1.Params.ParameterByName('OFFSET').Value := FOffSet.ToString;
  RESTRequest1.Params.ParameterByName('TS').Value := TS;
  RESTRequest1.Params.ParameterByName('APIKEY').Value := PUBLIC_KEY;
  imd5 := TIdHashMessageDigest5.Create;
  try
    HASHStr := TS + PRIVATE_KEY + PUBLIC_KEY;
    RESTRequest1.Params.ParameterByName('HASH').Value :=
      imd5.HashStringAsHex(HASHStr).ToLower;
    RESTRequest1.ExecuteAsync(OnAfterRequest);
  finally
    imd5.Free;
  end;
end;

Once the call give a result will need to parse the JSON response to take the name of the character and its image, obviously respecting the JSON structure described in the official documentation:

procedure THeaderFooterForm.OnAfterRequest;
var
  RetObject: TJSONObject;
  RetData: TJSONObject;
  MResult: TJSONObject;
  Loader: TImageLoaderThread;
  Thumbnail: TJSONObject;
begin
  try
    RetObject := TJSONObject.ParseJSONValue(RESTResponse1.Content)
      as TJSONObject;
    RetData := RetObject.GetValue('data') as TJSONObject;
    MResult := (RetData.GetValue('results') as TJSONArray).Get(0)
      as TJSONObject;
    Thumbnail := MResult.GetValue('thumbnail') as TJSONObject;
    Text1.Text := MResult.GetValue('name').Value;
    // TImageLoaderThread is a custom class to retrieve the image in a background thread
    // and 2 anonymous methods to notify when thread finish download image and when bitmap is ready  
    Loader := TImageLoaderThread.Create(true, nil, OnBitmapLoaded);
    Loader.ImgURL := Thumbnail.GetValue('path').Value + '.' +
      Thumbnail.GetValue('extension').Value;
    Loader.Start;
  finally
    StopWait;
  end;
end;

The image is provided by another URL so I have to make another request for the image.
Both the request (info character + image) are completed by background threads so it doesn't block the GUI.
Here some screeenshot about final app





The app run on Android device but the code work on Android, iOS, Windows and Mac.
In the next post I will improve the app creating a master-detail structure that allowing to search character by other criteria!
The code was loaded on my github repository.

3 comments :

  1. Hello, daniele, can u please share the TImageLoaderThread class? my email is dison@dpsoftwares.com

    ReplyDelete
  2. Hello, daniele, can u please share the TImageLoaderThread class? my email is lherreria@hotmail.com

    ReplyDelete