Skip to Content

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)

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply