Skip to Content
Technical Articles
Author's profile photo Daniel Van Leeuwen

Step by Step with the SAP Cloud Platform SDK for Android — Part 6a — Syncing an Offline Store

Previous (Offline OData)   Home   Next (Using a Foreground Service when Syncing)

An offline enabled app should perform a sync periodically to ensure the data on the client is up to date and to send any locally made changes to the backend. The user might want to pull the latest changes from the backend multiple times in a day or session, and therefore the app should provide an easy way to accomplish this task.

The following steps demonstrate how to add a sync button enabling a user-initiated sync.

  1. Add the following XML code to res\layout\activity_main.xml under the other button xml elements.
    <Button
        android:id="@+id/b_offlineSync"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="performSync"
        android:enabled="false"
        android:text="Sync" />
  2. Add the following method to MainActivity.java
    public void performSync(View v) {
        toastAMessage("Performing offline store sync.");
        Log.d(myTag, "Performing offline store sync.");
        Log.d(myTag, "Beginning offline store upload.");
        myOfflineDataProvider.upload(() -> {
            toastAMessage("Completed upload, beginning download.");
            Log.d(myTag, "Completed upload, beginning download.");
            myOfflineDataProvider.download(() -> {
                toastAMessage("Completed download, sync complete.");
                Log.d(myTag, "Completed download, sync complete.");
            }, e -> {
                toastAMessage("Failed to download the offline store, sync failed with error: " + e.toString());
                Log.d(myTag, "Failed to download the offline store, sync failed with error: " + e.toString());
            });
        }, e -> {
            toastAMessage("Failed to upload the offline store, sync failed with error: " + e.toString());
            Log.d(myTag, "Failed to upload the offline store, sync failed with error: " + e.toString());
        });
    }
    

    A sync is composed of two operations, upload and download that can be performed independently.

  3. Add the following line to the success callback of the myOfflineDataProvider.open() call, below the line offlineODataButton.setEnabled(true);
    findViewById(R.id.b_offlineSync).setEnabled(true);

  4. Run the app. Notice now that there is a sync button. When the user presses this button, some toast messages detail the progress of the sync.
  5. Next, we’ll add some code to notify the user to the progress of the sync operation. In the setupOfflineOData() method, add the following delegate definition.
    
    OfflineODataDelegate delegate = new OfflineODataDelegate() {
        @Override
        public void updateDownloadProgress(OfflineODataProvider provider, OfflineODataProgress progress) {
            super.updateDownloadProgress(provider, progress);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // As an example, log the # of bytes received
                    Log.d(myTag, "Download Bytes Received: " + progress.getBytesReceived());
                }
            });
        }
    
        @Override
        public void updateFileDownloadProgress(OfflineODataProvider provider, OfflineODataFileDownloadProgress progress) {
            super.updateFileDownloadProgress(provider, progress);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // As an example, log the # of bytes received
                    Log.d(myTag, "Update File Download Bytes Received: " + progress.getBytesReceived());
                }
            });
        }
    };
    
  6. In the setupOfflineOData method, change the
    myOfflineDataProvider = new OfflineODataProvider(url, offParam, myOkHttpClient, null, null);
    line so that it includes the new delegate

    myOfflineDataProvider = new OfflineODataProvider(url, offParam, myOkHttpClient, null, delegate);
  7. Run the app again and perform a sync by clicking the button. Consult Android Studio’s logs, and filter them using your debugging tag, “myDebuggingTag”. You should see the delegate methods being executed as the OfflineODataDelegate object is used.
  8. The app should ensure that no errors occurred during the sync. This is a job for the ErrorArchive. The ErrorArchive is used to collect errors caused when using OData. The app can show the user the conflicts and let the user decide how to handle each error. For more information on error handling, see the SAP Handling Errors and Conflicts documentation, as well as the page on Handling Failed Requests. The ErrorArchive is a list of entities that have the properties listed in the ErrorArchive Entity Properties list.
  9. To query the error archive, add the following code to the success callback in the download call in the performSync(View v) method, as shown in the screenshot below.
    
    // Get ErrorArchive entity set
    EntitySet errorArchiveSet = myOfflineServiceContainer.getEntitySet("ErrorArchive");
    EntityType errorArchiveType = errorArchiveSet.getEntityType();
    
    Property affectedEntityNavProp = errorArchiveType.getProperty("AffectedEntity");
    Property requestIDProp = errorArchiveType.getProperty("RequestID");
    // more properties such as RequestBody, RequestMethod, RequestURL, Message
    // CustomTag, Domain, HTTpStatusCode, Code, and InnerError
    
    DataQuery query = new DataQuery().from(errorArchiveSet).orderBy(requestIDProp);
    EntityValueList errorEntities = myOfflineServiceContainer.executeQuery(query).getEntityList();
    
    // Iterate through the entities that have errors
    for (EntityValue errorEntity : errorEntities) {
        myOfflineServiceContainer.loadProperty(affectedEntityNavProp, errorEntity);
        EntityValue affectedEntity = affectedEntityNavProp.getEntity(errorEntity);
        // Process each affected entity
        // For this example application, we just log the entity
        Log.d(myTag,"Error found: " + affectedEntity.toString());
    }
    

Previous (Offline OData)   Home   Next (Using a Foreground Service when Syncing)

Assigned Tags

      3 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Christoffer Fuss
      Christoffer Fuss

      Great Post, Thanks. Is it possible to send delta tokens to the odata service in the download method? I use the Syclo Exchange Framework in my backend to handle delta tokens but I dont know, how can I pass those delta tokens from the client. Do you have an example for that?

      Best Regards,

      Chris

      Author's profile photo Daniel Van Leeuwen
      Daniel Van Leeuwen
      Blog Post Author

      More information on delta tokens can be found about the track_deltas setting at

      https://help.sap.com/doc/c2d571df73104f72b9f1b73e06c5609a/Latest/en-US/docs/user-guide/odata/Offline_OData_Defining_Application_Configuration_File.html#delta-tracking

       

      How to track OData deltas.

      • AUTO If the OData service supports delta change tracking on the defining query, the delta links returned are used when downloading the data. If the OData service does not support delta change tracking on the defining query, the mobile service tracks the changes so that only changed data is exchanged between the client and the mobile services.

      You might try enabling a server trace as mentioned in the below blog posting while you try out this feature.  You could then see the OData requests being made during download calls.

      https://blogs.sap.com/2018/12/08/step-by-step-with-the-sap-cloud-platform-sdk-for-android-part-12-server-logging-and-tracing/

       

      Hope that helps,

      Dan van Leeuwen

      Author's profile photo Christoffer Fuss
      Christoffer Fuss

      Thanks again. I have done all that and it is not working. I opend a new question on this topic and hopefully someone can help:

      https://answers.sap.com/questions/12717361/odata-offline-delta-download-refresh.html

      Best Regards,

      Chris