Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Dan_vL
Product and Topic Expert
Product and Topic Expert
0 Kudos
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
0 Kudos
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.

 
Dan_vL
Product and Topic Expert
Product and Topic Expert
0 Kudos
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.
Dan_vL
Product and Topic Expert
Product and Topic Expert
Are you following the example in this tutorial using the sample back end?

The first time that you open the offline store, it is created, populated and downloaded from the server.

The next time you open the offline store, you will notice that it opens much quicker as it already exists on the device.

As a developer you control when the database can be updated from the back-end by calling download or when to pass any changes from the database to the back-end by calling upload.

Here is the documentation link that talks about updates to the metadata.  In an offline app, the recommendation is for updates to be additive only.
https://help.sap.com/doc/c2d571df73104f72b9f1b73e06c5609a/Latest/en-US/docs/user-guide/odata/Offline...

Regards,
Dan van Leeuwen