Skip to Content
Technical Articles

Step by Step with the SAP Cloud Platform SDK for Android — Part 6 — Offline OData

Previous (Online OData)   Home   Next (Remembering Credentials)

A mobile application may not always be used in areas where a network connection is present or if it is, it may have high latency. The Offline OData framework enables the application to work against a local database instead of making online requests to read or update data.

The following are some additional sources of documentation on this topic.
Introduction to Offline API
Offline Applications Overview (SCPms docs)
Defining an Application Configuration File
Offline Enable Your Android Application

The following steps demonstrate how to enable the app to access data from a local database enabling it to work without network connectivity.

  1. Modify the app’s build.gradle to include the Offline OData library.
    implementation 'com.sap.cloud.android:offline-odata:2.1.2'
  2. Add the following variables to MainActivity.
    private ESPMContainer myOfflineServiceContainer;
    private OfflineODataProvider myOfflineDataProvider;
    
  3. Add the following method.
    private void setupOfflineOData() {
        Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.sap.cloud.mobile.odata");
        //logger.setLevel(Level.ALL);
        AndroidSystem.setContext(getApplicationContext());
    
        try {
            URL url = new URL(serviceURL + "/" + connectionID);
            OfflineODataParameters offParam = new OfflineODataParameters();
            offParam.setEnableRepeatableRequests(false);
            myOfflineDataProvider = new OfflineODataProvider(url, offParam, myOkHttpClient, null, null);
            OfflineODataDefiningQuery myDefiningQuery = new OfflineODataDefiningQuery("Products", "Products", false);
            myOfflineDataProvider.addDefiningQuery(myDefiningQuery);
        } catch (OfflineODataException e) {
            e.printStackTrace();
        }
        catch (MalformedURLException e) {
            e.printStackTrace();
        }
    
        myOfflineDataProvider.open(() -> {
            Log.d(myTag, "Offline store opened");
            toastAMessage("Offline store opened");
            final Button offlineODataButton = (Button) findViewById(R.id.b_offlineOData);
            Handler handler = new Handler(Looper.getMainLooper());
            handler.post(new Runnable() {
                @Override
                public void run() {
                    offlineODataButton.setEnabled(true);
                }
            });
            myOfflineServiceContainer = new ESPMContainer(myOfflineDataProvider);
    
        }, (OfflineODataException offlineOdataException) -> {
            Log.d(myTag, "Offline store did not open.", offlineOdataException);
            toastAMessage("Offline store failed to open.  " + offlineOdataException.getMessage());
        });
    }
    
  4. In the onRegister method in the updateUICallback add the below code to the onFailure and onResponse methods as shown below. If the app is started and there is no network connection, onFailure is called.
    setupOfflineOData();

  5. Add the following code to the onOfflineOData method.
    if (myOfflineServiceContainer != null) {
        List<Product> products = myOfflineServiceContainer.getProducts();
        toastAMessage(products.size() + " products returned");
        for (Product product : products) {
            Log.d(myTag, product.getName());
        }
    }
    else {
        Log.d(myTag, "Offline service container is null.");
        toastAMessage("Offline service container is null.");
    }
    
  6. Run the example with a network connection. The first time the store is opened, a database will be created on the server and downloaded to the device. The Offline OData button will become enabled once the store has been opened. The results of pressing the Offline OData button are shown below.
  7. Turn on airplane mode and click on the Offline OData button and notice that the data is successfully returned as the query is fulfilled from the offline store on the device.

The Offline Sample and the following sections demonstrate more advanced features of offline apps. These are optional sections.

Syncing an Offline Store
Using a Foreground Service when Syncing
Using ILOData

Previous (Online OData)   Home   Next (Remembering Credentials)

4 Comments
You must be Logged on to comment or reply to a post.
  • Hi,

    I’m facing problem with metadata here. earlier we used to declare group of defining queries/requests. my service url (metadata has duplicate entity type ex: customers & CUSTOMERS) because of this i’m getting offline store exception saying

    Note : CUSTOMERS & Customers are replaced by some values.

    com.sap.cloud.mobile.odata.offline.OfflineODataException: :1

    EntityType Error: EntityType Name=’CUSTOMERS’ collides with EntityType Name=’Customers’. Each definition must have a unique name. You can use the ALLOW_CASE_CONFLICTS option to allow names differing only in case, but preferably the schema should be changed to avoid names differing only in case.
    <EntityType Name=”CUSTOMERS” sap:content-version=”1″>…
    at com.sap.cloud.mobile.odata.offline.internal.OfflineODataConverter.createOfflineODataException(OfflineODataConverter.java:111)

     

     

    private void setupOfflineStore() {
      
        AndroidSystem.setContext(context);
    
        try {
            URL url = new URL(finalURL);
            OfflineODataParameters offParam = new OfflineODataParameters();
            offParam.setEnableRepeatableRequests(false);
            offlineODataProvider = new OfflineODataProvider(url, offParam,ClientProvider.get(), null, null);
          
            offlineODataProvider.addDefiningQuery(new OfflineODataDefiningQuery("CP", "CP", false));
        } catch (OfflineODataException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
       openOfflineStore();
    }
    
    above code I'm using as per tutorial.
    
    In the above I've declared only one defining query 'CP' but, I'm getting error on different entity type. 
    I've also setup an offline configuration to my application in Cockpit to allow case sensitive.
    
    How to resolve this error?.
    
    Thanks & Regards,
    Hemanth.

     

  • Hi,

     

    I have followed the above tutorial to open the store, the store is getting opened. But, I can’t see any data in offline DB. I think only schema has downloaded/ I’m not sure.

    Later I’ve tried opening the offlinestore and I’ve used this method to download the db

    offlineODataProvider.download(
        () -> {
            // Proceed to use the offline store after download is successfully completed,
            // for example notifying UI for appropriate action
            ...
        },
        (error) -> {
            // Handle the error, for example logging the error or retrying download
            ...
        }
    );
    
    Then I can see the data in it.
    
    Question 1 ) Every time do we need to download the DB after opening the app??
    Questoin 2 ) After creating some records in client db, what if we change the metadata(Added few defining requests) and install it in device and whether this will clear the DB which has existing records and create/download new db in client device?
    fortunately schema will be changed here....
    
    Regards Hemanth.