Skip to Content
Technical Articles
Author's profile photo JaiR S

Delta Tracking for Offline Mobile Hybrid Application

offline Mobile Hybrid application using the cloud build.

/* hybrid capacity bootstrap
*
* This has to happen after sapui5 bootstrap, and before first application page is loaded.
*/

sap.hybrid = {
loadCordova: false,

setCordova: function () {
sap.hybrid.loadCordova = true;
},

packUrl: function (url, route) {
var result;
if (route.manual) { // routes requires a manually created Mobile Destination with Rewrite on Backend and via CP App set
result = route.path; // keep the original path
} else {
var connection = (fiori_client_appConfig.appID + “_” + route.destination).substr(0, 63); // max length cap by SCPms DB
result = “/” + connection;
}
var path = url.substring(route.path.endsWith(“/”) ? route.path.length – 1 : route.path.length); // the remaining URL path
result += (route.entryPath ? route.entryPath : “”) + path;
return result;
},

appLogon: function (appConfig) {
var context = {};
var url = appConfig.fioriURL;
if (url && (url.indexOf(“https://”) === 0 || url.indexOf(“http://”) === 0)) {
if (url.indexOf(“https://”) === 0) {
context.https = true;
url = url.substring(“https://”.length);
} else {
context.https = false;
url = url.substring(“http://”.length);
}

if (url.indexOf(“?”) >= 0) {
url = url.substring(0, url.indexOf(“?”));
}
if (url.indexOf(“/”) >= 0) {
url = url.split(“/”)[0];
}
if (url.indexOf(“:”) >= 0) {
context.serverHost = url.split(“:”)[0];
context.serverPort = url.split(“:”)[1];
}
}

// set auth element
if (appConfig.auth) {
context.auth = appConfig.auth;
}

// If communicatorId is set then use it to be compatible with existing values. Otherwise, use the default “REST”.
// By doing so logon core does not need to send ping request to server root URL, which will cause authentication issue.
// It occurs when the root URL uses a different auth method from the application’s endpoint URL, as application can only handle authentication on its own endpoint URL.
context.communicatorId = appConfig.communicatorId ? appConfig.communicatorId : “REST”;

// Set disablePasscode to true if you want to hide the passcode screen
context.custom = {
disablePasscode: false
};

if (“serverHost” in context && “serverPort” in context && “https” in context) {
// start SCPms logon
sap.hybrid.kapsel.doLogonInit(context, appConfig.appID, sap.hybrid.openFirstOpenStore);
sap.hybrid.kapsel.doLogonInit(context, appConfig.appID, sap.hybrid.openSecondOpenStore);
} else {
console.error(“context data for logon are not complete”);
}
},

bootStrap: function () {
if (sap.hybrid.loadCordova) {
// bind to Cordova event
document.addEventListener(“deviceready”, function () {
// check if app configuration is available
if (fiori_client_appConfig && fiori_client_appConfig.appID && fiori_client_appConfig.fioriURL) {
sap.hybrid.appLogon(fiori_client_appConfig);
} else {
console.error(“Can’t find app configuration probably due to a missing appConfig.js in the app binary.”);
}
}, false);
} else {
console.error(“cordova is not loaded”);
}
},

loadComponent: function (componentName) {
sap.ui.getCore().attachInit(function () {
// not support sap.ushell navigation
sap.ui.require([
“sap/m/Shell”,
“sap/ui/core/ComponentContainer”
], function (Shell, ComponentContainer) {
// initialize the UI component
new Shell({
app: new ComponentContainer({
height: “100%”,
name: componentName
})
}).placeAt(“content”);
});
});
},

openFirstOpenStore: function () {
jQuery.sap.require(“sap.ui.thirdparty.datajs”); //Required when using SAPUI5 and the Kapsel Offline Store
var properties = {
“name”: “store_first”,
“host”: sap.hybrid.kapsel.appContext.registrationContext.serverHost,
“port”: sap.hybrid.kapsel.appContext.registrationContext.serverPort,
“https”: sap.hybrid.kapsel.appContext.registrationContext.https,
“serviceRoot”: fiori_client_appConfig.appID + “_” + mobile_appRoutes[0].destination +
“/sap/opu/odata/sap/it_was_our_first_service_url/”,

“definingRequests”: {
“ItWasOurFirstEntitySet”: “/ItWasOurFirstEntitySet”
}
};

store = sap.OData.createOfflineStore(properties);

var openStoreSuccessCallback = function () {
sap.OData.applyHttpClient(); //Offline OData calls can now be made against datajs.
// sap.hybrid.startApp();
};

var openStoreErrorCallback = function (error) {
sap.m.MessageToast.show(“An error occurred” + JSON.stringify(error));
};

store.open(openStoreSuccessCallback, openStoreErrorCallback);
},

openSecondOpenStore: function () {
jQuery.sap.require(“sap.ui.thirdparty.datajs”); //Required when using SAPUI5 and the Kapsel Offline Store

var properties = {
“name”: “store_second”,
“host”: sap.hybrid.kapsel.appContext.registrationContext.serverHost,
“port”: sap.hybrid.kapsel.appContext.registrationContext.serverPort,
“https”: sap.hybrid.kapsel.appContext.registrationContext.https,
“serviceRoot”: fiori_client_appConfig.appID + “_” + mobile_appRoutes[0].destination +
“/sap/opu/odata/sap/it_was_our_first_service_url/”, // we are using the same route from the appRoutes.js file, but it can change!

“definingRequests”: {
“ItWasOurSecondEntitySet”: “/ItWasOurSecondEntitySet”
}
};
store2 = sap.OData.createOfflineStore(properties);

var openStoreSuccessCallback = function () {
sap.OData.applyHttpClient(); //Offline OData calls can now be made against datajs.
sap.hybrid.startApp();
};

var openStoreErrorCallback = function (error) {
sap.m.MessageToast.show(“An error occurred” + JSON.stringify(error));
};

store2.open(openStoreSuccessCallback, openStoreErrorCallback);
},

refreshStore1: function () {
if (!store) {
sap.m.MessageToast.show(“The store must be open before it can be refreshed”);
return;
}
store.refresh(sap.hybrid.refreshStoreCallback, sap.hybrid.errorCallback, null, sap.hybrid.progressCallback);
},

refreshStore2: function () {
if (!store2) {
sap.m.MessageToast.show(“The store must be open before it can be refreshed”);
return;
}
store2.refresh(sap.hybrid.refreshStoreCallback, sap.hybrid.errorCallback, null, sap.hybrid.progressCallback);
},

refreshStoreCallback: function () {
sap.m.MessageToast.show(“Offline events: refreshStoreCallback”);
},

clearStore1: function () {
store.close(sap.hybrid.closeStoreCallback1, sap.hybrid.errorCallback);
},

clearStore2: function () {
store2.close(sap.hybrid.closeStoreCallback2, sap.hybrid.errorCallback);
},

closeStoreCallback1: function () {
store.clear(function () {
sap.m.MessageToast.show(“Clear1 Success”);
}, sap.hybrid.errorCallback);
},

closeStoreCallback2: function () {
store2.clear(function () {
sap.m.MessageToast.show(“Clear2 Success”);
}, sap.hybrid.errorCallback);
},

flushStore1: function () {
if (!store) {
sap.m.MessageToast.show(“The store must be open before it can be flushed”);
return;
}
store.flush(sap.hybrid.flushStoreCallback, sap.hybrid.errorCallback, null, sap.hybrid.progressCallback);
},

flushStore2: function () {
if (!store2) {
sap.m.MessageToast.show(“The store must be open before it can be flushed”);
return;
}
store2.flush(sap.hybrid.flushStoreCallback, sap.hybrid.errorCallback, null, sap.hybrid.progressCallback);
},

flushStoreCallback: function () {
sap.m.MessageToast.show(“Offline events: flushStoreCallback”);
},

errorCallback: function (error) {
sap.m.MessageToast.show(“An error occurred: ” + JSON.stringify(error));
},

progressCallback: function (progressStatus) {
var status = progressStatus.progressState;
var lead = “unknown”;
if (status === sap.OfflineStore.ProgressState.STORE_DOWNLOADING) {
lead = “Downloading “;
} else if (status === sap.OfflineStore.ProgressState.REFRESH) {
lead = “Refreshing “;
} else if (status === sap.OfflineStore.ProgressState.FLUSH_REQUEST_QUEUE) {
lead = “Flushing “;
} else if (status === sap.OfflineStore.ProgressState.DONE) {
lead = “Complete “;
} else {
sap.m.MessageToast.show(“Unknown status in progressCallback”);
}
sap.m.MessageToast.show(lead + “Sent: ” + progressStatus.bytesSent + ” Received: ” + progressStatus.bytesRecv + ” File Size: ” +
progressStatus.fileSize);
}
};

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Atul Salgare
      Atul Salgare

      Hi Jay,

       

      It's really very helpful ?.

      Thanks

      Author's profile photo prabhu teja
      prabhu teja

      I don't have a launchpad I am still working on WEBIDE can I navigate from one app to another app by pressing button. Is it possible .can u explain .

      Author's profile photo JaiR S
      JaiR S
      Blog Post Author

      Hi

      launchpad is require for this because this is not working locally.
      regard
      jai sharma
      Author's profile photo Vinothkumar T
      Vinothkumar T

      Hi Jai Sharma,

       

      Nice blog..!!

      I have one query, in this did you handled the launchpad back button.

      am facing some issues on that.

      Thanks,