Skip to content

Overview

The Enhanced Progress API provides expanded details about the progress of various operations, such as initial open, upload, download and send store. The progress is measured in steps. The information includes: the operation ID of the current operation, the total number of steps in the operation, the current step number, the name of the step, the time of last update, a parameter array for the current step, and a default message.

Default messages have been translated into these supported languages. Based on the language of the device, default messages of the corresponding language are displayed as part of the progress information.

The step information is updated either by the mobile client or by the server, depending on where the step is running.

Remarks

  • An application may have multiple defining queries in an initial open or download operation. The processing of all defining queries is treated as a single step, while the defining query name and URL will be updated in the parameter array.

  • An application may have multiple requests to send to the server in an upload operation. The processing of all requests is treated as a single step, while the request number is updated in the parameter array of this step.

  • A batch request may contain multiple requests. When processing a batch request, the server provides an individual description for each request.

  • The cloudProgressPullInterval parameter controls how often status is pulled from the server. The default interval is 2000 ms.

    • To get more frequent progress updates, developers can adjust cloudProgressPullInterval to be a shorter interval.
    • To avoid the server being overloaded, the minimum pulling interval is 500 ms.
  • The total number of steps is the total number of possible steps that can occur for the operation.

    • Steps can be skipped. The total number of steps includes conditional steps. But if the condition is not met, these steps will be skipped.
    • The total number of steps can increase during runtime. When a metadata change or delta link expiration is detected, the total number of steps will increase to include the additional required steps.

Table of Steps

The following table lists the steps currently supported by Offline OData, along with the associated default messages in English.

Step Message Variable Parameters
buildingEntityStore Performing step <currentStepNumber> of <totalNumberOfSteps>: Building the entity store
creatingBootStrapDatabase Performing step <currentStepNumber> of <totalNumberOfSteps>: Creating bootstrap database
creatingRequestQueueDatabase Performing step <currentStepNumber> of <totalNumberOfSteps>: Creating request queue database
downloadingEntityStore Performing step <currentStepNumber> of <totalNumberOfSteps>: Downloading entity store. Received of bytes so far Parameters[0]: received bytes Parameters[1]: total bytes
erasingExpiredRequests Performing step <currentStepNumber> of <totalNumberOfSteps>: Erasing expired requests
loadingMetadata Performing step <currentStepNumber> of <totalNumberOfSteps>: Loading metadata
performingRequestQueueMerge Performing step <currentStepNumber> of <totalNumberOfSteps>: Performing request queue merge
performingTransactionMerge Performing step <currentStepNumber> of <totalNumberOfSteps>: Performing transaction merge
performingCreateDeleteMerge Performing step <currentStepNumber> of <totalNumberOfSteps>: Performing create delete merge
processingDefiningQueries Performing step <currentStepNumber> of <totalNumberOfSteps>: Processing defining queries using Parameters[0]: request name Parameters[1]: request url
processingRequests Performing step <currentStepNumber> of <totalNumberOfSteps>: Processing requests. Processing modification request of Parameters[0]: request number Parameters[1]: total request number
reapplyingChanges Performing step <currentStepNumber> of <totalNumberOfSteps>: Reapplying changes
analyzingReceivedData Performing step <currentStepNumber> of <totalNumberOfSteps>: Receiving data from the client
receivingDataFromServer Performing step <currentStepNumber> of <totalNumberOfSteps>: Receiving data from the server. Received bytes so far Parameters[0]: received bytes
removingDeletedRelationships Performing step <currentStepNumber> of <totalNumberOfSteps>: Removing deleted relationships
removingRemoveAfterUploadRequests Performing step <currentStepNumber> of <totalNumberOfSteps>: Removing RemoveAfterUpload requests
sendingDataToServer Performing step <currentStepNumber> of <totalNumberOfSteps>: Sending data to the server. Sent bytes so far Parameters[0]: sent bytes
sendingEntityStoreDatabase Performing step <currentStepNumber> of <totalNumberOfSteps>: Sending entity store database.
sendingRequestQueueDatabase Performing step <currentStepNumber> of <totalNumberOfSteps>: Sending request queue database.
uploadPreprocessing Performing step <currentStepNumber> of <totalNumberOfSteps>: Pre-processing requests before uploading
waitingForDownload Performing step <currentStepNumber> of <totalNumberOfSteps>: Waiting for download

Sample Code

Prepare to initialize an OfflineODataProvider.

// Note: you need to replace variable values below starting with "YOUR" with your own values.
String storeName = "YOUR_STORE_NAME";
String host = "YOUR_SERVER_HOST";
int port = "YOUR_PORT";
String serviceName = "YOUR_SERVICE_NAME";
String url = "https://" + host + ":" + port + "/" + serviceName + "/";
URL myServiceRoot = new URL(url);

// Set up an instance of OfflineODataParameters. See OfflineODataParameters class document for details.
OfflineODataParameters storeParams = new OfflineODataParameters();
storeParams.setStoreName(storeName);
// Note: you need to replace variable values below starting with "YOUR" with your own values.
val storeName = "YOUR_STORE_NAME"
val host = "YOUR_SERVER_HOST"
val port = "YOUR_PORT"
val serviceName = "YOUR_SERVICE_NAME"
val url = "https://${host}:${port}/${serviceName}/"
val myServiceRoot = URL(url)

// Set up an instance of OfflineODataParameters. See OfflineODataParameters class document for details.
val storeParams = OfflineODataParameters()
storeParams.storeName = storeName

Create a class adopting interface OfflineODataProviderDelegate to enable the callback mechanism.

public class OfflineODataProviderDelegateSample implements
OfflineODataProviderDelegate
{
...
class OfflineODataProviderDelegateSample: OfflineODataProviderDelegate
{
...

Implement app logic relating to progress status inside these inherited functions for different offline operations, such as open, upload, download, and send store.

@Override
public void updateOpenProgress( @NonNull OfflineODataProvider provider, @NonNull OfflineODataProviderOperationProgress progress ) {
   /*
   updateYourOwnProgressBar( progress )

   In this instance, “progress” is the structure that contains all the step information, such as step number and default message. Here, you can apply logic against this progress information.
   For example, you can implement the UpdateYourOwnProgressBar function to update the progress bar by continuously adjusting the percent complete (current step number / total number of steps). You can also implement a function to update the status with information about what is being processed in the current step.
   */
}
@Override
public void updateDownloadProgress( @NonNull OfflineODataProvider provider, @NonNull OfflineODataProviderDownloadProgress progress ) {
   // Include progress status update for Download
   // updateYourOwnProgressBar( progress )
}
@Override
public void updateUploadProgress( @NonNull OfflineODataProvider provider, @NonNull OfflineODataProviderOperationProgress progress ) {
   // Include progress status update for Upload
   // updateYourOwnProgressBar( progress )
}
@Override
public void updateFailedRequest( @NonNull OfflineODataProvider provider, @NonNull OfflineODataFailedRequest request ) {
   // Include progress status update for Failed Requests
   // updateYourOwnProgressBar( request )
}
@Override
public void updateSendStoreProgress( @NonNull OfflineODataProvider provider, @NonNull OfflineODataProviderOperationProgress progress ) {
   // Include progress status update for Send Store
   // updateYourOwnProgressBar( progress )
}
override fun updateOpenProgress(provider: OfflineODataProvider, progress: OfflineODataProviderOperationProgress) {
   /*
   updateYourOwnProgressBar( progress )

   In this instance, “progress” is the structure that contains all the step information, such as step number and default message. Here, you can apply logic against this progress information.
   For example, you can implement the UpdateYourOwnProgressBar function to update the progress bar by continuously adjusting the percent complete (current step number / total number of steps). You can also implement a function to update the status with information about what is being processed in the current step.
   */
}

override fun updateDownloadProgress(provider: OfflineODataProvider, progress: OfflineODataProviderDownloadProgress) {
   // Include progress status update for Download
   // updateYourOwnProgressBar( progress )
}

override fun updateUploadProgress(provider: OfflineODataProvider, progress: OfflineODataProviderOperationProgress) {
   // Include progress status update for Upload
   // updateYourOwnProgressBar( progress )
}

override fun updateFailedRequest(provider: OfflineODataProvider, request: OfflineODataFailedRequest) {
   // Include progress status update for Failed Requests
   // updateYourOwnProgressBar( request )
}

override fun updateSendStoreProgress(provider: OfflineODataProvider, progress: OfflineODataProviderOperationProgress) {
   // Include progress status update for Send Store
   // updateYourOwnProgressBar( progress )
}

Set the frequency for the app to fetch status from the server by changing the default value of cloudProgressPullInterval and fine-tune as needed. In this example, we change it from its default value 2000 ms to 600 ms.

@Override
public int getCloudProgressPullInterval()
{
   return 600;
   // The default cloud progress status pull interval is 2000ms. Here you can set it to a time period of your choice.
}
override fun getCloudProgressPullInterval(): Int
{
   return 600
   // The default cloud progress status pull interval is 2000ms. Here you can set it to a time period of your choice.
}

Initialize an OfflineODataProvider instance with a delegate, and create a DataService instance.

// Set up a delegate instance.
OfflineODataProviderDelegateSample myDelegate = new OfflineODataProviderDelegateSample();
OfflineODataProvider provider = new OfflineODataProvider(serviceRoot, parameters, httpClient, myDelegate);
DataService service = new DataService(provider);
// Set up a delegate instance.
val myDelegate = OfflineODataProviderDelegateSample()
val provider = OfflineODataProvider(serviceRoot, parameters, httpClient, myDelegate)
val service = DataService(provider)

The app performs its own work. In this example, the app performs an initial open.

// Add defining query for Customers, Orders, OrderItems and Products
OfflineODataDefiningQuery customerDef = new OfflineODataDefiningQuery( "Customers", "Customers", false );
this.provider.addDefiningQuery( customerDef );
this.provider.addDefiningQuery( new OfflineODataDefiningQuery( "Orders", "Orders", false ) );
this.provider.addDefiningQuery( new OfflineODataDefiningQuery( "OrderItems", "OrderItems", false ) );
this.provider.addDefiningQuery( new OfflineODataDefiningQuery( "Products", "Products", false ) );
this.provider.open(successHandler, failureHandler);
// Add defining query for Customers, Orders, OrderItems and Products
val customerDef = OfflineODataDefiningQuery( "Customers", "Customers", false )
this.provider.addDefiningQuery( customerDef )
this.provider.addDefiningQuery( OfflineODataDefiningQuery( "Orders", "Orders", false ) )
this.provider.addDefiningQuery( OfflineODataDefiningQuery( "OrderItems", "OrderItems", false ) )
this.provider.addDefiningQuery( OfflineODataDefiningQuery( "Products", "Products", false ) )
this.provider.open(successHandler, failureHandler)

In this example, progress information will be appended into the "updates" array. You can implement your own function here to process progress information. For instance, use progress information to update a progress bar, then you can see the progress bar moving forward during the initial open:

private void updateYourOwnProgressBar(@NonNull OfflineODataProviderOperationProgress progress) {
   ProgressBar progressBar = findViewById(R.id.progressBar);
   progressBar.setIndeterminate(false);
   progressBar.setMax(progress.getTotalNumberOfSteps());
   progressBar.setProgress(progress.getCurrentStepNumber());
}
private fun updateYourOwnProgressBar(progress: OfflineODataProviderOperationProgress) {
   val progressBar = findViewById(R.id.progressBar)
   progressBar.isIndeterminate = false
   progressBar.max = progress.totalNumberOfSteps
   progressBar.progress = progress.currentStepNumber
}

Note

You must make sure the updating of progress bar is in a UI thread or a coroutine scope.

For the structure and default values of the progress status information, see OfflineODataProviderDelegate, below.

OfflineODataProviderDelegate

Delegates are used to get progress updates while an OfflineODataProvider is opening, downloading, downloading files, uploading, sending the store to the server, and gathering information about requests that fail during an upload. The public protocol is OfflineODataProviderDelegate.

Application developers can adopt from the OfflineODataProviderDelegate public protocol, and then make extensions to the predefined functions of each progress phase.

For more details please refer to the OfflineODataProviderDelegate section of the online help.

Supported Languages

Default messages are available in these languages: * Arabic (ar) * Bosnian (bs) * Bulgarian (bg) * Croatian (hr) * Czech (cs) * Danish (da) * Dutch (nl) * English (en) * French (fr) * German (de) * Greek (el) * Hebrew (he) * Hungarian (hu) * Italian (it) * Japanese (ja) * Korean (ko) * Malay (ms) * Norwegian (no) * Polish (pl) * Portuguese (pt) * Romanian (ro) * Russian (ru) * Simplified Chinese (zh-Hans) * Slovak (sk) * Slovenian (sl) * Spanish (es) * Swedish (sv) * Traditional Chinese (zh-Hant) * Turkish (tr) * Ukrainian (uk)


Last update: November 24, 2020