Documentation issues and errors

The cloud pack documentation seems to be lacking some important information.

First of all, the Google Drive information for getting a client ID and secret is incorrect.  Selecting "Web Application" is wrong.  That now requires an HTTPS connection, causing the connection to fail.  This wasted several hours of my time.  Someone else had posted this problem months ago, but it was not corrected.  "Other" must be selected.  HTTP must be used.

Second, there is no clear information about what happens when Connect, DoAuth, GetFolderList, etc. fail, what exceptions are thrown, and how to recover.  Information about what happens when the connection becomes stale or the token has expired would help.  Does GetFolderList try to refresh the token, for example?

When using GetFolderList, the returned items cannot be used in another call to GetFolderList.  That causes an exception "Missing ID" (at least for Google Drive).  Instead GetFolderListHierarchical must be used.

Third (critical), there is no mention if the functions are blocking or non-blocking.  It appears that all the functions are blocking, which causes significant problems for large downloads on Android.  There is no information on whether or not the classes can be used on a thread.  Can they?  That would be a requirement for Android.  On Windows, the ProcessMessages call would not be thread safe, therefore different code would be required for Windows and Android.

What is the recommended way to handle a large upload/download on Android?

Thank you for notifying us about the issues you encountered.

- We always try to keep our documentation as up-to-date as possible.
However, please note that at the pace some services are changing functionality, interfaces, etc. we can't always adapt our documentation immediately.

- Calls like GetFolderList will fail if the access token is expired. You can use the RefreshTokens call to get a renewed access token.
You can use logging to get more information when a request fails. Logging can be enabled by setting the Logging property to True and LogLevel to llDetail on most components in the TMS FMX Cloud Pack. The LOG file is generated automatically in the machine's Documents folder.

- The documentation indicates that the Folder parameter of the GetFolderList call requires an ID value. Did you check if the TTMSFMXCloudItem you used had a valid ID assigned?

- Unfortunately threading is not supported for the TMS FMX Cloud Pack.

As an alternative you can try using the new TMS FNC Cloud Pack instead. Calls in TMS FNC Cloud Pack are all handled asynchronously.
A fully functional trial version is available from the product page:

The TMS FNC Cloud Pack sounds promising.  Does it support threads?  How is download progress handled?


the TMS FNC Cloud Pack uses asynchronous request handling, which means that the request execution is handled in a separate thread and an appropriate event is called, synchronized with the main thread. While executing one or multiple requests asynchronously, you can keep using the application. The download progress is also handled asynchronously, via a separate event OnRequestProgress
I could not find any mention of "event", "thread", or "asynchronous" in the FNC manual.  You may want to consider adding some of that information to the manual.

Is it possible to create and execute a request on a separate thread, or would that have to be done (synchronized) on the main thread?

Would it be possible to exchange the FMX Cloud license for the FNC Cloud license?  It appears to be a better fit for my intended use.


There are 2 documents, one for adding/registering API, Client-ID and Secret keys for each service that is supported by TMS FNC Cloud Pack, and then one core PDF that explains how to work with the requests and asynchronous behaviour. The one you are looking after is at the following URL:

In this documentation you'll notice that a request is executed from the main thread, but is already handled internally via a separate thread. There is no need to handle this yourself via threads. The event callback is automatically synchronized with the main thread, so accessing main thread UI components is thread safe from this event. Below is a sample:

procedure TRequestForm.DoRequestExecute(const ARequestResult:
 //File Download Finished
procedure TRequestForm.DownloadFile;
 c: TTMSFNCSimpleCloudBase;
 c := TTMSFNCSimpleCloudBase.Create;
 c.Request.Host := '';
 c.Request.Path := '/download';
 c.Request.Query := 'fileid=123';
 c.Request.Name := 'Download File';
 c.Request.Method := rmGET;


The services that are supported in TMS FNC Cloud Pack also adopt this way of handling requests. Each call made to the service has its corresponding callback event that can be accessed at designtime or runtime.

Pieter Scheldeman2019-07-02 15:41:36

You can send an email with a request to change your license to:
Thanks for the exchange.  The FNC Cloud Pack is working well so far.  However I think there needs to be much more information in the documentation/guides, so I hope you don't mind some feedback:
- Explain and list all the events that are available and when they occur
- OnRequestXXX and related events are called from a worker thread and not synchronized with main thread.
- What happens when .Connect() fails?  What event is called (if any)?
- Provide details for TTMSFNCCloudBaseRequestResult
- Mention any .jar files required for Android.  Are they needed?
- What happens when the token is stale and needs to be refreshed?  Is OnRequestComplete called with an unsuccessful response at first?  If so, what ResponseCode is given?

Also events and properties such as OnGesture, OnTap, Touch, Size, Width, and Height don't seem appropriate for non-visual components.

Perhaps an FNC Cloud Pack forum could be added for future posts.
How do you cancel a long download?

When downloading a large file (80MB), the OnRequestProgress event is never called until the end (Windows, FMX).  Smaller files seem to work fine.

The following may be another bug (note the comment):

procedure TTMSFNCCustomCloudBase.DoRequestProgress(
  const ARequestResult: TTMSFNCCloudBaseRequestResult; AProgress: single; AUpload: Boolean);
  if Assigned(ARequestResult) then
    if Assigned(ARequestResult) then    /** Should this be: Assigned(ARequestResult.RequestProgress)? **/
      ARequestResult.RequestProgress(AProgress, AUpload);
    if Assigned(OnRequestProgress) then
      OnRequestProgress(Self, ARequestResult, AProgress, AUpload);

It appears that the reason no progress events are called is because getting the "content length" fails, so lpdword is zero.  Progress events are not called when that is zero.  Without progress events, there is no easy way to cancel the task.

In components having a DownloadInt function, a size value is passed to the function but never
used.  That size could be used instead of the content length.  A member would need to be added to

TTMSFNCCloudBaseRequest (such as ResultContentLength) and assigned in the DownloadInt

When lpdword is zero, it can be set to TTMSFNCCloudBaseRequest.ResultContentLength instead.
Also lpdword needs to be a 64 bit value for very large files.

Hopefully these changes can be made quickly.  After August 1st C++ Builder will not be usable for Android apps.

Dear Chris,

The OnRequestProgress is triggered, but only if the resulttype of the request is set to be a file or stream. When it is a string, the OnRequestProgress is triggered at the end of the request. For file downloading, please configure the request to download directly to a file, or to a stream.

Clearly you have not read all my recent posts.  Obviously I am
using the Download function to download the file.  I'll try contacting support directly instead.

The same with the GMail client


Can you please explain exactly what problem you encountered with the GMail client?