Skip to Content
Technical Articles
Author's profile photo Ludo Noens

Creating an Offline CRUD hybrid mobile app in SAP Web IDE Full-Stack with Hybrid Application Toolkit

Updated 3 March 2021: added steps to avoid CORS issues on iOS

Updated 5 January 2021: updated as the Neo trial landscape is no longer available

Updated 24 March 2020: added information regarding multiple offline stores

Updated 21 February 2020: as the old Mobile Services sample OData service has been deprecated, I’ve updated the destination configuration.

 

Important note: although hybrid apps are a valid way to implement offline apps, we strongly recommend using more modern mobile technologies instead. 

When you start developing a new mobile app, we strongly recommend that you consider developing this with either MDK (Mobile Development Kit) for cross platform applications, or our native SDKs (SAP Cloud Platform SDK for iOS or SAP Cloud Platform SDK for Android).

 

A new milestone and a bit of background

As a Product Owner, it is always good to see your product reach a new milestone. Last week, you’ve seen the announcement of Hybrid Application Toolkit release 1805 in Britt’s blog. In this release, we’ve made some fundamental changes in the way we build hybrid apps in the cloud from SAP Web IDE.

It is not my intention to repeat Britt’s blog; but let me just highlight the most important part of this release: Developers have a lot more control on what is packaged into a hybrid app. This opens the door to more possibilities and allows developers to more easily resolve challenges by themselves.

One of the hot topics we did not completely cover in this release is the ability to create offline apps. Many developers have been asking for this. In December 2017, I’ve announced our plans to ‘end-of-maintenance’ the HAT local add-on. We have provided you one offline specific template in SAP Web IDE (with that I mean the Eclipse Orion based version) that could only be used in conjunction with the HAT local add-on. The template is not available in SAP Web IDE Full-Stack. Meanwhile, our colleagues from SAP Web IDE have shut down the old SAP Web IDE and you are advised to migrate projects to the Full-Stack version. So how do you build offline hybrid apps in SAP Web IDE Full-Stack, if we don’t provide the template anymore?

Before answering, let’s look back into the history of this toolkit. When we started, we had no cloud build feature. Instead, we were relying on the locally installed tools for developing Cordova apps. There were templates in Web IDE that kept evolving over time. At some point we’ve decided to grab a snapshot of a UI5 Master Detail template and adapt it to support offline. This template was shipped with HAT, the Web IDE plugin. We then tried to keep up with changes in the original template. At some point, the original template was replaced with a Fiori Master-Detail Application template. We did not further update our offline template, unless really needed.

Although we could have created new mobile specific templates in HAT, we actually wanted the opposite: any template should by default support mobile; hence there should not be mobile variants at all. The functionality we’ve provided last year was actually doing this. When the HAT plugin in Web IDE was active, a newly created project was automatically enabled for mobile. We were adding some magic in the background to make this happen. However, although we’ve tried to make it easier, in reality things got a lot more difficult (especially troubleshooting).

We do not plan to provide you an offline template in SAP Web IDE Full-Stack. The main reason is that every app is unique and requires specific customization around the topic of offline. It is very difficult to provide you this as part of a one-fits-all template. Instead, we will give you guidelines on how to implement offline functionality in your app and provide you with an example below.

Creating an offline app based on the Fiori CRUD Master-Detail template

Prerequisites

Before we start creating the example app, let us first ensure we can access the Mobile Service Sample Service from SAP Web IDE. In your SAP Cloud Platform cockpit, go to Connectivity > Destinations and create a new destination as shown below. Make sure you add the additional properties as indicated. The url is not completely visible is the screenshot. Please enter https://hcpms-<your account number>trial.hanatrial.ondemand.com/mobileservices/origin/hcpms/ESPM.svc/v2. I was using a trial account for this blog post. However, the Neo trial landscape is no longer available. Please adapt the url for your productive environment.

After saving the destination settings, it can take up to a few minutes to have the new destination active.

Update 21/02/2020: for Authentication, please use App2AppSSO.

Now let’s start creating the app from scratch in SAP Web IDE Full-Stack. You can find this version of SAP Web IDE in your SAP Cloud Platform cockpit’s services list:

Although not required at this point, please make sure you have activated Hybrid Application Toolkit. Once you are in SAP Web IDE Full-Stack, go to the preferences and ensure the feature Hybrid App Toolkit is activated. Don’t forget to save your selection and reload SAP Web IDE.

You will use the Cloud Build feature based on Mobile Services. Customers who have access a productive environment could see the following in the Hybrid Application Toolkit preferences (depending on your subscription):

If you don’t see the Cloud Build Service mentioned in the preference, you will be using Mobile Services by default. If you do see the radio buttons, please ensure the radio button regarding Cloud Build Service is enabled for Mobile Services (not the deprecated one for SAP Fiori).

Creating a new project from a template

In SAP Web IDE, please select File > New > Project from Template. To avoid possible issues with the latest innovation version, I have selected a CRUD Master-Detail template based on SAPUI5 version 1.52. Feel free to use a different version.

In the next step, fill in the details.

In this example I am using the Mobile Service Sample Service to consume OData from a Service URL. We have exposed this service to SAP Web IDE through the destination we have created earlier.

In the Template Customization step, I have selected the following:

Once finished, you can run the application from SAP Web IDE in your web browser. It will show you the data from the data source (read) and you can create new entries (create), change it (update) and remove entries (delete). Also referred to as “CRUD”.

Mobile enable the project

Right-click on your project to bring up the context menu and select Mobile > Enable as Hybrid Mobile Project.

This step will add a ‘mobile’ folder to your project, containing some source files only relevant for when your app runs on a device or emulator (as Packaged app, or Developer Companion app).

Take note that during the cloud build process, the contents of the webapp folder and the mobile folder will be merged into the www folder of your Cordova project. The index.html file in the mobile folder will replace the one in your webapp project (if your project has one).

We’ve decided to use this approach, so you can still deploy the webapp to SAP Cloud Platform.

Creating a hybrid app from this project

You can create a Packaged app based on this project by selecting in the context menu: Mobile > Build Packaged App.

In the first step of the build wizard, you can change the app’s name as visible on your device’s home page. You can also select an app icon and images for the splash screen.

In the next step, you indicate for which platform you want to build your app. You’ll need to provide a valid the signing profile. For Android devices, you can simply generate one on our service. The provisioning profile for iOS is a bit more tricky. I recommend creating a wildcard App ID on developer.apple.com and include that in the profile which allows you to install the application on your device. Note that this is wildcard App ID is only for development; not for production. You’ll then need to export your certificate and provisioning profile and import it here.

Currently, we only have two UI5 versions to select from. We will gradually add more versions.

At this point you can hit the Build button. Once the Cloud Build Service is finished generating your app, a QR code and hyperlink will be displayed, so you can download the app onto your device.

During this build process, Hybrid Application Toolkit will automatically create a new application on Mobile Service, and also create the related Cloud Platform destination for you.

Adding Cordova plugins (optional)

Although not related to the offline topic, I have received several queries on how to add Cordova plugins. So let’s quickly discuss this.

In case you want to make use of one or more of the more than 2300 publicly available Cordova plugins in your project, open the context menu and choose Mobile > Select Cordova plugins. You can browse and search for plugins. Once you are done, make sure to save your selection.

When you trigger a new build, the plugins will automatically be added in your Cordova app.

Note that there is a tab called “Default (34)”, which does not allow you to make a selection. It merely lists down the plugins we add to your app by default. You’ll notice most of the Kapsel plugins are listed there. You don’t need to select them. They will be part of your app by default.

Adding the offline capabilities

Before we discuss the offline capabilities, I want to highlight one thing regarding Developer Companion: since this type of app is typically an online app, we cannot use Developer Companion for developing offline apps. Offline will only work for Packaged Apps.

Users who have already created offline apps before using our cloud build service are probably familiar with the way to add the Kapsel Offline OData plugin to the project. This is actually triggered by adding a “sap.mobile” section that defines ‘stores’ in the project’s manifest.json. We have kept this in the new delivery, so that existing projects can more easily transition. The content of this section is actually not important anymore. What matters is that this section is there. Before the HAT 1805 release, the content was used in the build process. As long as you specify the bare minimum, you are fine:

	},
	"sap.mobile": {
		"definingRequests": {},
		"stores": [
		]

As a result, your Packaged app built with Cloud Build Service includes the SAP Kapsel Offline OData plugin. Now we need to add some more code to make use of this.

Initializing the offline store

The file mobile/hybrid/sap-mobile-hybrid.js contains most of the bootstrap code for the hybrid app. You are free to make changes here. We are going to add a function to create and open the offline store that will be used to store the data relevant for the app on the device.

    openStore: function() {
        console.log("In openStore");
        jQuery.sap.require("sap.ui.thirdparty.datajs");  //Required when using SAPUI5 and the Kapsel Offline Store
        var properties = {
            "name": "store_mainService",
            "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,

		"definingRequests": {
			"supplierset": "/Suppliers?$expand=Products"
		}
        };
    
        store = sap.OData.createOfflineStore(properties);
    
        var openStoreSuccessCallback = function() {
            console.log("In openStoreSuccessCallback");
            sap.OData.applyHttpClient();  //Offline OData calls can now be made against datajs.
            sap.Xhook.disable(); // temporary workaround to ensure the offline app can work in WKWebView
            sap.hybrid.startApp();
        }
    
        var openStoreErrorCallback = function(error) {
            console.log("In openStoreErrorCallback");
            alert("An error occurred" + JSON.stringify(error));
        }
    
        store.open(openStoreSuccessCallback, openStoreErrorCallback);
    },  

An important piece to mention here is the serviceRoot specified in the properties. The serviceRoot is basically the location where the offline store will fetch its data, indirectly through Mobile Service. In this particular example I am using the Mobile Service Sample Service; but I could easily change this to use a different destination. The Cloud Platform destination used here was automatically generated by HAT, after triggering the build previously. Also note that the above code assumes one single data source and hence, one single offline store. If your app needs to consume data from multiple sources, you’ll need to open multiple offline stores here.

Updated 19 March 2020: the switch to WKWebView as mentioned in this blog post requires an additional temporary workaround. This is the call to disable Xhook.

In the same file, the appLogon function needs to be adjusted a little bit. Once the logon is done, we call the newly added openStore function, instead of the startApp function.

		if ('serverHost' in context && 'serverPort' in context && 'https' in context) {
			// start SCPms logon
			sap.hybrid.kapsel.doLogonInit(context, appConfig.appID, sap.hybrid.openStore);

Modification of the datasource uri in the manifest file is no longer required. You can use the same project for running it as online as well as standalone offline app. For existing projects that were mobile enabled, it is advised to remove the ‘mobile’ folder from the project (you might want to save a copy) and re-enable for mobile. New projects will automatically get the latest code needed when the project is enabled for mobile.

Avoid cross origin (CORS) issues on iOS

With the introduction of iOS 14, the security aspects were further enhanced. To avoid having your application running into cross origin issues, we need to change the settings in the SAP Mobile Services cockpit for Cross Domain Access. This is especially relevant if your app is using the User API (we had a few users facing this).

Please refer to the screenshot below. Please open the SAP BTP Mobile Services Admin Cockpit. Go to Settings -> Security -> Cross Domain Access. Set Origin field to “<AdminAPI>,null”.

Read-only offline app.

Trigger a new cloud build and download your app on your device. After the authentication screen and passcode screen, the screen will go blank for a while. We should actually show something here, so the end-user knows what is happening. This is an improvement to be added later. At this point, the offline store is being synchronised with the backend database. Once this is done, the UI will show up and display the data (this can take around 15 seconds).

You can put your device into airplane mode and continue accessing the data.

Congrats! You’ve built an offline app.

It is nice to be able to Read data when offline, but how about Create, Update and Delete?

The application template is actually already allowing modifications, removal and adding new data entries. But how do we handle this when the device is not connected to the network? The data is simply stored in the on-device offline store. When network connectivity returns, we can synchronise the changes between backend database and on-device store.

To get the latest changes from the backend, we use the refresh function. To upload locally made changes to the backend, we use the flush function.

For the refresh, the most obvious way of implementing this, is as part of the pull-to-refresh. The flush should be triggered once the network connection is back. But for the sake of this demo and making it easier to test, I’ll just add two buttons to the footer bar: a Refresh and a Flush button.

Let’s open the file webapp/view/Master.view.xml and add the following buttons in the customFooterContent.

	<semantic:customFooterContent>
	    <Button text="Refresh" width="80px" id="__button1" press="onRefreshButton"/>
	    <Button text="Flush" width="70px" id="__button0" press="onFlushButton"/>
	</semantic:customFooterContent>

Now open the file webapp/controller/Master.controller.js and add the following code for handling the button press:

		onRefreshButton: function() {
			if (typeof sap.hybrid !== 'undefined') {
				sap.hybrid.refreshStore();
			}
		},
		
		onFlushButton: function() {
			if (typeof sap.hybrid !== 'undefined') {
				sap.hybrid.flushStore();
			}
		},

I have added the type check to make sure these calls are only done for a hybrid app. The web app should not call these functions.

We will add the functions called in the file mobile/hybrid/sap-mobile-hybrid.js

	refreshStore: function() {
		console.log("Offline events: refreshStore");
		if (!store) {
			console.log("The store must be open before it can be refreshed");
			return;
		}
		store.refresh(sap.hybrid.refreshStoreCallback, sap.hybrid.errorCallback, null, sap.hybrid.progressCallback);
	},

	refreshStoreCallback: function() {
		console.log("Offline events: refreshStoreCallback");
	},

	flushStore: function() {
		console.log("Offline events: flushStore");
		if (!store) {
			console.log("The store must be open before it can be flushed");
			return;
		}
		store.flush(sap.hybrid.flushStoreCallback, sap.hybrid.errorCallback, null, sap.hybrid.progressCallback);
	},

	flushStoreCallback: function() {
		console.log("Offline events: flushStoreCallback");
	},

	errorCallback: function(error) {
		console.log("Offline events: errorCallback");
		alert("An error occurred: " + JSON.stringify(error));
	},

	progressCallback: function(progressStatus) {
		// console.log("Offline events: progressCallback");

		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 {
			alert("Unknown status in progressCallback");
		}
		console.log(lead + "Sent: " + progressStatus.bytesSent + "  Received: " + progressStatus.bytesRecv + "   File Size: " +
			progressStatus.fileSize );
	},

The refresh and flush functions are asynchronous and will take some time. For demo purposes, I’ve kept the implementation rather simple and added some console logging to have an idea of what is going on. For your enterprise mobile applications, you should implement a way to inform the user about progress and update the UI when needed.

After saving all your code changes, please trigger another cloud build. The result will be an app that allows you to work with your data in online, as well as offline mode. You trigger a refresh to update the on-device store. You can flush the changes made in the on-device store to the data service.

What about data conflicts?

There is one important aspect that I will not discuss in this blog: data conflicts. How do you handle errors when data on the service has changed, while your device was offline, and your user also made changes on the same data?

I think this topic is worth a separate blog post.

Using multiple stores or multiple data sources

Over the past months we have received queries from several users asking about the use of multiple data sources. Customers can have heterogeneous landscapes where data is stored in various systems. When you are building a mobile app that is supposed to work in all kinds of network conditions, you have to use an offline store. Your app might need data from multiple systems. Every data source requires its own offline store. So if you are using data from ‘X’ number of data sources in your app, you’ll need to initialise and open ‘X’ number of offline stores.

I have seen customers using one single offline store, while their application needs data from multiple sources. To prevent errors in retrieving data, there were various checks in the code to ensure the device was having a network connection. This approach is not recommended. Instead, you should add additional stores. This could require a different way of exposing the data as well.

You might be asking, “Is there a limit to the size or amount of stores ?”. The answer simply depends on the amount of storage available on the device. You can have ‘N’ number of stores, as long as the size of the total storage space required doesn’t exceed the storage space on device. The question will be: how much storage space do my target devices have available at a minimum, so my app can work well on all those devices ? In other words and as a practical example: I can have 64GB available on my device, but my colleague has only 2GB free. The answer will be ‘less than 2GB’ in that case.

In the example code shown above, I’ve created one ‘openStore’ function, with a specific serviceRoot and definingRequests, and callback functions for success and failure. You can add more ‘openStore’ functions where needed. You will also need to implement flush (if required) and refresh functions for each of the stores created. The key will be the serviceRoot and definingRequests. This is where most developers struggle. If the path doesn’t match, the initialisation will fail. Please check the troubleshooting section below to resolve this.

Take note that once you add the additional data source to the manifest.json file, the UI5 application will try to fetch metadata from this source when the app initialises; no matter whether there is a network or not; and this could trigger an authentication flow, which you might want to avoid under bad network conditions.

Conclusion

With this blog post I’ve shown you how to create an offline app in SAP Web IDE Full-Stack. The example code provided is very basic. There is surely room for improvement to get this to production level apps. My goal was to show you the basics here, to get you started quickly. I hope this blog post is useful to you and I encourage you to try it out yourself.

Our online documentation is here.

Troubleshooting

After providing support to several users, I’m adding this section to help you in resolving issues you might be facing.

  • You can test the URL used for OData access in the Mobile Service admin cockpit. Select the application and go to Connectivity. Make sure you can Ping the destination. Use the OData application destination test (the icon on the left side of Ping). Specify the relative path as used by your app and click next. You should be able to view data available in the service. If this is not working, then your app will not be able to retrieve data either. Resolve this first before continuing to debug your app.
  • When the offline store is initialised on your device, it will be based on the serviceRoot provided. If you want to make changes to the serviceRoot, you have to delete the existing offline store from your device. Otherwise it will still exist when you restart the app, using the serviceRoot it was initialised with. On iOS, you can remove the store by deleting the app. On Android, removing the app is not sufficient. You also need to clear the app data and cache.
  • A common issue for several users is that the initialisation of the offline store fails. In the example code I am using an alert to indicate this. In case of doubts, you can put a breakpoint on the success callback and error callback to see what is happening.
  • In the file mobile/index.html there is some code to adjust your app’s XMLHttpRequests to use URLs that work locally. Please check whether the URL used matches with the serviceRoot you’ve defined. If the path doesn’t match, the app will not use the on-device store.
  • The offline store communicates with Mobile Service over a dedicated channel called Mobilink. You won’t be seeing data exchange in the (web) app’s logs, as this is handled via native code. Using the Trace functionality in Mobile Service admin cockpit (see Analytics), you will be able to generate a HAR file and get detailed information about the communication between the client app and Mobile Service AND ALSO between Mobile Service and your backend. Check for error messages in the traces to understand why there are failures happening.

Reporting issues

Although I have verified and tested the above flow several times and received confirmation from several users that this works, the results for you might be different. This might be due to interruptions in service availability or changes on the various systems involved. Also take note that I have not tested other scenarios (e.g. on-premise, with Cloud Connector) myself.

For users who are trying to add offline capability to their own app and it fails: please try reproducing exactly the same as described above. Once you have this working, it will be a good reference for your  own application. Adding offline capabilities to a hybrid app is not trivial.

In case you are running into issues, please raise a (BCP) ticket for component CA-WDE-MOB. You can also comment down below, but take note that I will not be monitoring this blog very frequently.

Also, please check my latest blog post “What’s new with Hybrid Application Toolkit in 2019” for the latest updates, tips and tricks, ways to resolve issues.

If you found this posting useful, please let me know by hitting the like button.

Thank you!

Assigned Tags

      426 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo SHADAAN QUAISER
      SHADAAN QUAISER

      Hi Ludo,

      I am trying to add my gateway box to SCPms via cloud connector. I am able to register the backend via cloud connector. I have a couple of question here.

      1. While registering backend via HCC on SCPms what would be the the SSO mechanism.
      2. While creating mobile destination in SCPms with proxy type Cloud connector the url would be virtual IP and port that we have created in HCC while adding gateway. right?
      3. On testing destination always its give me below message.

      4. Then i am using this as a destination to SCP with appending the service url i.e; "/sap/opu/odata/sap/service_name"

      5. Here in the user i tried adding backend user and Pxxxxxxx user also every time i am getting 403 forbidden error.

       

      Am i missing anything or any roles.Please suggest me the solution, i am stuck here for a week.

       

       

      Regards

      Shadan

      Author's profile photo Venkatesh Hulekal
      Venkatesh Hulekal

      Hi
      did you find any solution? I'm stuck with same

       

      Author's profile photo jai sharma
      jai sharma

      hie

      please remove after .com/
      exp:sap/opu/odata
      WebIDESystem = True
       try once .
      regard
      jai sharma
      Author's profile photo R AVINASH KUMAR
      R AVINASH KUMAR

      hi ludo,

       

      i followed you steps , but  while assessing the mobile service , i am getting forbidden error 403. Actually i was able to replicate your application , Now i am trying with my own service .Are there any user roles or permission that has to be provide to assess the mobile service in destinations.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      If you were able to replicate my app, then you have all the user roles and permissions you need.

      It is more likely that you have not configured the destination properly. You can test the connection from the Mobile Services admin cockpit. If the 'ping' works and you are able to get some (meta)data, then this part is fine.

      If this doesn't help, you have two features in Mobile Services that can help identify the problem. In the Analytics tab, check the logs. If this doesn’t tell you enough, you can use the trace function to record the network activity related to your app. Take note that when debugging your app through Chrome (Android) or Safari (iOS), you will not be able to see the exchange done over mobilink, which is the protocol used by the offline store. But you can see it in the traces.

      Hope this helps.

      Author's profile photo R AVINASH KUMAR
      R AVINASH KUMAR

      Hi ludo

      the steps that i follwed where

      1. first i created a service in Destination with the backend system. I am passing just the bankend system general url .(everything is fine here).
      2. the i created a mobile destination using this cloud destination (ping is succesfull here).
      3. while accessing the api for destination of that particular application i am getting
        HTTP Status 403 – Neither Application connection id nor Application id is provided.

        4. then i am trying to use this mobile service in my cloud destination there i am getting 403 forbidden error.

      Questions:

      1. should i pass full service url in the cloud destination including my oadta service name?

      2.while creating the mobile destination is  there a requirement of header that should be passed ?.

       

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      I suspect there is a problem with the destination you've configured. Although you can ping it successfully, you are getting a 403 at step 3. Try to resolve this first, before trying to consume it through mobile services.

       

      Author's profile photo R AVINASH KUMAR
      R AVINASH KUMAR

      Can youhelp with the steps if I create using my own odata service.

      If I create mobile destination and use it in for webide destination , I don't get the link between the application I'd  and destination before application is even created . I am new to this . Am I missing some step?

       

       

      Author's profile photo Edgar Chavez
      Edgar Chavez

      Hi Ludo,

       

      I am have a problems.

      when build package app and install in my phone, this imagen is show.

      could you  help me? please.

       

      Author's profile photo JaiR S
      JaiR S

      Hi

      Please change the following area
      cloud platform mobile service ==> nattive/Hybrid == > select the project ==> security
      security configuration Basic to SAML 
      and check once thank you.
      regard
      Jai sharma
      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Hi Ludo.

       

      I'm using template sapui5. I've a problem with sap.odata is undefined.

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Angel,

      I recommend using the CRUD or Master-Detail template as your starting point. The SAPUI5 template is rather barebones and you will need to add a bunch of libraries yourself.

      Cheers,
      Ludo

       

      Author's profile photo E V LINGA REDDY
      E V LINGA REDDY

      Hi Angel,

      Even I'm also facing the same issue. How did you resolve the above issue?

       

      Regards,

      Linga

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Hi E V,

      you need to change in file manifest.js your templateid to CRUD or Master-Detail

      Author's profile photo Vineet Safaya
      Vineet Safaya

      Hi Angel,

      I have the same CRUD template but still I am facing the undefined error. Please suggest any other alternative ?

      "sourceTemplate": {
      "id": "html5projecttemplates.2masterdetailcrud",
      "version": "1.40.12"
      }

      --

      Vineet

      Author's profile photo Vineet Safaya
      Vineet Safaya

      Hi All,

      I resolved the issue. Basically this error can be removed by adding the kapsel plugin of odata.

      --

      Regards,

      Vineet

      Author's profile photo E V LINGA REDDY
      E V LINGA REDDY

      Thanks for the reply, Angel. will try to change the manifest.

      Author's profile photo T. Fincham
      T. Fincham

      Hi,

      How did you manage to put a breakpoint in the sap-mobile-hybrid.js ? If I put a breakpoint there nothing happens because my code doesn't reach it.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Tyler,

      When you initially start the app, you will probably not be able to trigger a breakpoint as the code execution has already happened before you are able to do so. Reloading the web app in Safari (or Chrome in case of Android) will allow you to break in this code.

      Regards,
      Ludo

      Author's profile photo Luis Cortez
      Luis Cortez

      Hi Ludo,

       

      Great blog ! I was able to replicate your example. In a separate app I was also able to use my own OData (using my on premise DEV system). I have a question:

      When I am offline, let's say I want to validate one input field , for example customer. How can I do a look up to a master table for validation? Should the master table be part of the OData?  Do you have any suggestions on how to do a look up?

      Louis

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Luis,

      How would you do this for an online app? If you are using an OData source for the master table look up, then it makes sense to offline that table as well. The way to implement it is just like when your source is online.

      You can create multiple offline stores if needed.

      Cheers,
      Ludo

       

      Author's profile photo Luis Cortez
      Luis Cortez

      Hi Ludo,

       

      Thanks for the info. I will try that.

      Luis

      Author's profile photo R AVINASH KUMAR
      R AVINASH KUMAR

      Hi louis

      Can you help me with the steps if I am consuming my odata services.

      Actually the steps before consuming mobile destination in web ide.that ludo has described.

      Author's profile photo Luis Cortez
      Luis Cortez

      Hi Ravinash,

       

      What are the steps that you are referring to ? I will try to help if I can.

      Author's profile photo R AVINASH KUMAR
      R AVINASH KUMAR

      Hi Luis ,

      • I created cloud destination for webIde basic application .
      • I created a simple list application where i binded the data from the service.
      • And i added a button on the screen on click of which i can add random data to the list  , through create service.
      • This application is fully functional in chrome.  

      Now for the mobile application part .

      1. I enabled the hybrid toolkit feature and , i right clicked on the application and enabled for the application .
      2. Then i build the companion application.
      3. Mobile folder got generated in my application.
      4. I went to mobile services and check if my application is generated . There my application was generated and connection was generated .
      5. Now i tried to open the application in my mobile .
      6. Application gets opened but i don't receive the data .
      7. when i try to create the data it gets created .In the error log it shows application is in offline mode.

      If I create a app and add service to that , and try to use that in Scp destination. it gives 443 forbidden error .

      If i use the sample mobile service as mentioned by ludo ,read service on offline works fine .

      Can you please guide me through end to end steps . I am working on hybrid application for first time.

       

      Thanks i advance .

      Author's profile photo Satya Kodati
      Satya Kodati

      Hi Luis,

      I was also able to replicate the example given by Ludo. But while i am trying to use my own oData i am facing issue like my destination with own oData is not displaying in the Service URL list.

      Can you help me on this how you created destination for your own oData ? This will be very helpful to me.

      Thank you,

      Satya

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Hi Ludo.

      Could you help me, please? I’ve got a problem in my application.

      Regards

      Angel.

      Author's profile photo Vineet Safaya
      Vineet Safaya

      Hi Angel,

       

      How did you resolve this issue ? Facing the same problem.

       

      --

       

      Regards,

      Vineet Safaya

      Author's profile photo Venkatesh Hulekal
      Venkatesh Hulekal

      any solution for above?

       

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Hi Ludo.

      My application request certificate. When download and install app in my mobile phone. How can i resolve that a problem.

      Regards

      Angel.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      This can be avoided by setting the following value in config.xml:

      <preference name="SAPKapselHandleX509Challenges" value="false" />

      However, currently there is no way for you to change this value from SAP Web IDE. We are planning an enhancement for this.

      Meanwhile, if really needed, you can change this by downloading the Android project, modifying the file and rebuilding the project locally.

       

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Where could i find the file config.xml. Tell me Please.

      this structure from my project.

      .

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      config.xml is added by Cordova during a Cloud Build. It is currently not available in the SAP Web IDE project.

      As indicated earlier, you won't be able to modify this file now. We are working on an enhancement for this.

      Author's profile photo Arne Bücker
      Arne Bücker

      Is there now any solution or work around for this problem without the need of a local build?

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Arne, we are planning a new release around early May that will allow you to edit the config.xml file in SAP Web IDE. You will also be able to remove plugins currently added by default, which should allow you to optimise the footprint a bit.

      Thanks,
      Ludo

       

      Author's profile photo Mathias Ingemann Mortensen
      Mathias Ingemann Mortensen

      Hi Ludo,
      As far as I know, we should be able to see the config.xml file in the SAP Web IDE by now. Unfortunately it is still not visible in my project. Could this be because I am using a trial account?

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Mathias,

      Please check the HAT extension version available in SAP Web IDE on your trial account. It should be version 1.32.1. If not, then try to clear your browser's cache and reload.

      See my recent blog for more details.

      Thanks,
      Ludo

      Author's profile photo Kunj Bihari Shukla
      Kunj Bihari Shukla

      Hi Ludo,

      Nice blog, very informative and helpful. Though While following the blog and trying to explore more on offline functionality I faced some issues, will really appreciate your comments on the below points.

      I have followed all the steps as mentioned while using a simple custom service (entity1: parent, entity2: child association 1:n from parent to child) custom odata service. Overall it works fine but with some issues (all issues faced are with the mobile device):

      1. Create an entry -> flush -> refresh -> refresh the list -> leads to duplicate entries in the mobile one local and the other from the server.
      2. Delete operation fails with the message "cannot delete this entity instance. Another entity instance depends on it", and I did put a breakpoint in the backend dpc_ext class method but its not hitting it and also it works fine in desktop. (I want to debug this scenario but not sure how we can debug, please suggest if possible)
      3. Also please suggest if there is any way to debug the file sap-mobile-hybrid.js file(or any other way to debug and understand the offline functionality better like can we play around with the offline store at the client) . I did import the project in android studio but was unable to put a breakpoint at any of the relevant code.

      Thank you again!

      Warm Regards,

      KBS

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi KBS,

      Are you facing these issues also when using the Mobile Services sample data service, or only when using your own service?

      Debugging sap-mobile-hybrid.js is possible by setting breakpoints using the Safari (in case of iOS) or Chrome (in case of Android) browser. Once set, hit the reload button in the browser.

       

      Regards,

      Ludo

      Author's profile photo Kunj Bihari Shukla
      Kunj Bihari Shukla

      Hi Ludo,

      Thank you for your help on Debugging sap-mobile-hybrid.js by setting breakpoints. Took me some time but figured it out now.

      Regarding the below issue of dual records, this issue exist only with my custom oData service.

      Create an entry -> flush -> refresh -> refresh the list -> leads to duplicate entries in the mobile one local and the other from the server.

      Comment Update on 29th October - the above issue has been resolved

      Warm Regards,

      KBS

      Author's profile photo Ankit Agarwal
      Ankit Agarwal

      Hi KBS,

       

      Could you help me with the Create operation in offline app. I followed the steps but some how its not working.

       

       

      Regards

      Shadan

      Author's profile photo Kunj Bihari Shukla
      Kunj Bihari Shukla

      Hi Shadan,

      Are you using the SampleService or your own custom service. Please provide some specific details.

      Thanks,

      KBS

      Author's profile photo Harsha Jalakam
      Harsha Jalakam

      Kunj Bihari Shukla ,

      How did you manage to resolve this issue. We are facing similar more or less the same, wherein the successfully flushed entries do not get deleted from the store, thereby creating a pile of records which is preventing some of our validations and requirement  achievement.
      Thanks in advance.

      Regards,
      Harsha

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Hi Ludo.

      I’ve got a problem in my application. I don´t understand.

      Regards

      Angel.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Angel,

      It looks like you data model has issues for which an entity is defined too large. Please check your data model and refine the properties.

       

      Author's profile photo Mikael THEPAULT
      Mikael THEPAULT

      Hi Ludo,

      Thank you for your blog.

      I have a question, how can we add custom plugins with cloud build ?

      Thank you for your help.

      Best regards,

      Mikaël.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Mikaël,

      With custom plugins, you mean plugins you have created yourself, which are not part of a public repository ? If the answer is positive, then I can tell you that we currently do not plan to support this. The alternative is to download the complete project from our cloud build service and continue app development on a local system.

      Thanks,
      Ludo

      Author's profile photo Mikael THEPAULT
      Mikael THEPAULT

      Hi Ludo,

      Thank you for your reply.

      Yes I want to add a plugin created by myself in the project. Do you know if in the next upgrade of Web IDE we will have this functionnality ?

      As a workaround do you know if I can use HAT version 1.29.7 with SAP Web IDE ? (I have some problems to install it).

       

      Thank you for your help.

      Regards,

      Mikaël.

      Author's profile photo Brendan Farthing
      Brendan Farthing

      Hi Ludo Noens,

      I’d just like to check if it’s still the case that SAP do not plan to support the ability to add custom Cordova plugins (those not available in the official Cordova public repository)? We use Fiori Mobile, where this is obviously possible, and this is the key thing stopping our company from moving from Fiori Mobile to Mobile Services.

      Some companies will not put their Cordova plugins in the public repository but instead wish to provide them directly to paying customers only. In our case we have Cordova plugins for specialised mobile device hardware that is connected to mobile devices running our Fiori apps via custom Fiori Clients.

      I understand that we could achieve this by then using a local development environment on our developers PC’s, but this then defeats the key benefit of SAP Cloud mobile build functionality, especially where we have developers who we dont want or need to be deeply skilled Cordova developers (big additional cost to our company). It’s disappointing to us that you offered this in Fiori Mobile, but take it away when enhancing Mobile Services and pointing customers in the direction of using Mobile Services.

      One other question, as Fiori Mobile is now deprecated, can you let me know how long this will continue to be fully supported by SAP? Because it does not suit our company to move away from Fiori Mobile (due to lack of custom Cordova plugins and lack of “Mobile Place” functionality in Mobile Services), we need to stay on it, as long as we are fully supported.

      Thank you,

      Brendan Farthing

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Brendan,

      Thanks for bringing this up. We are taking this request into consideration and discussing an approach that would allow you to add custom plugins with minimal effort from our side.

      I cannot comment on the timeline for Fiori Mobile at this point. For now, you will continue to receive support.

      Thanks,
      Ludo

      Author's profile photo Harsha Jalakam
      Harsha Jalakam

      Hi Ludo,

      We have followed the same steps as in your system and have tried configuring offline code. As soon as we add offline code we are getting the error, as shown in the error screenshot, Please could you help on this. The pain part is that the error message doesn’t give much information nor it has much logs in the mobile services.

      Below is the code we added for offline configuration.( It was working fine, before the below code was added).

      "sap.mobile": {
      "_version": "1.1.0",
      "definingRequests": {},
      "stores": [{
      "name": "ODATA",
      "serviceRoot": "/sap/opu/odata/sap/ZTEST/",
      "definingRequests": {
      "ValueList": "/List"
      }
      }]
      }

       

      We are trying this on the productive account( not on trail account).

      Regards,
      Harsha

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Harsha,

      I recommend creating a trace of this in Mobile Services cockpit and check the log for details on why you are receiving a 403.

      Also, besides the configuration you mentioned, did you implement the offline initialisation code accordingly ? The details in the manifest.json will be ignored; it has to be part of the openStore() function.

      Thanks,
      Ludo

      Author's profile photo Venkatesh Hulekal
      Venkatesh Hulekal

      Getting stuck with same issue ? any solutions please?

      Author's profile photo Andre Julius
      Andre Julius

      Hi Ludo Noens

       

      Thanks for this comprehensive blog, I was trying a different approach but somehow I am lost, can you advise? Please pardon me since I’m really new at UI5, but I’ve been reading all the post and comments and still can’t be sure I’m doing it right

       

      Context:

      • I want to build a Hybrid UI5 to be deployed in Android
      • I built a destination in SCP named [D17], where the URL is referring to the SAP Cloud Connector to SAP backend which I named as https://virtual:8080
      • [D17] works fine with regular CRUD app which I named [CRUD] that I built from scratch (because I want to figure out how exactly the code works without getting mislead by generated codes
      • I am using service Catalog instead of service URL
      • I was using New->OData menu, which got reflected in manifest.json
        "dataSources": 
        {
           "ZMM_EMP_SRV": {
              "uri": "/sap/opu/odata/sap/ZMM_EMP_SRV/",
              "type": "OData",
              "settings": {
        	 "odataVersion": "2.0",
        	 "localUri": "localService/metadata.xml"
              }
           }
        }
        ...........
        "models": {
           "EmpData": {
              "uri": "/sap/opu/odata/sap/ZMM_EMP_SRV/",
              "type": "sap.ui.model.odata.v2.ODataModel",
              "settings": {
        	"defaultOperationMode": "Server",
        	"defaultBindingMode": "OneWay",
        	"defaultCountMode": "Request"
              },
              "dataSource": "ZMM_EMP_SRV",
              "preload": true
           }
        }
        ...........​
      • FYI the particular set that I am working on is called EmployeeSet
      • As I don’t want to spoil a working prototype, exported [CRUD] and imported back as [CRUDOffline] to prepare setup

      My Walkthrough with Your Guide:

      • Adding offline capabilities (Doubts: I Just need to add blank segment in manifest.json as below?)
        "sap.mobile": 
        {
           "definingRequests": {},
           "stores": []
        }​
      • Initializing the offline store (Doubts: Do I need to change only the defining request portion as below?)
        var properties = { 
           "name": "store_mainService", 
           "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,
           "definingRequests": 
              { "EmployeeSet": "/EmployeeSet" } 
        };​
      • Replace call to startApp in appLogon() with openStore
      • If I read the comments above, since I do not create the project from template, I have to create destination in
        https://hcpmsadmin-pXXXtrial.dispatcher.hanatrial.ondemand.com/sap/mobile/admin/ui/index.html
      • So I tried creating them to mimic  generated destination from CRUD Template
        URL: https://XXX/sap/opu/odata/sap/ZMM_EMP_SRV/
        Proxy Type Internet
        Basic Authentication
      • https://XXX/sap/opu/odata/sap/ZMM_EMP_SRV/$metadata works fine on chrome.
      • When I Ping, I get error “Failed to execute ping” (Doubts: Please advise where I went wrong?)

       

      Best Regards

       

      Andre Julius

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      I would take a different approach and start with using the CRUD template available in SAP Web IDE.

      You can use the OData source from the service catalog as well; no problem. Make sure the app works as online web app (if it runs fine in SAP Web IDE preview, you are good).

      To trigger the cloud build to include the offline plugin, a blank mobile segment is sufficient. We’ll ignore the content.

      When you trigger a cloud build, Hybrid App Toolkit will create a new app on Mobile Services and a corresponding destination.

      The defining request you specified should be sufficient.

      Once you have this working, you have a reference that will help to figure out what is missing in your approach.

      I suspect there is some issue with the destination you’ve created. But it is difficult to tell. At first glance, it should work…

       

      Author's profile photo Andre Julius
      Andre Julius

      Hi Ludo Noens

       

      Following your advice, so far I seem to be able to make it work for service URL based app. Service URL / Service Catalog, both would generate [MS Destination] URL according to URL in [SCP Destination]

      Since in my Service URL SCP destination config [SURL] I already have the full path...my app is working

      https://S17:80/sap/opu/odata/sap/ZMM_EMP_SRV/

      However....in the case of service catalog config [SCAT]...I am pointing to the system as a whole

      https://S17:80

       

      Thus, when the service catalog based app is trying to read metadata it returns a fail, as they are trying to read

      https://S17:80/$metadata
      
      instead of the supposed
      
      https://S17:80/sap/opu/odata/sap/ZMM_EMP_SRV/$metadata

      I played around tried the rewrite URL, adding relative path "sap/opu/odata/sap/ZMM_EMP_SRV/" on the [SCAT] but it seems it still try to read  "https://S17:80/$metadata"

      I wonder, whether I am supposed to tamper with the code below in order to make it work for service catalog scenario? i.e.: by adding a hardcoded "sap/opu/odata/sap/ZMM_EMP_SRV/" behind the serviceRoot? Doubts: is this the right way to go?

      var properties = {
         "name": "store_mainService",
         "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, 
         "definingRequests": {
      	"EmployeeSet": "/EmployeeSet"
         }
      };

       

      Best Regards

       

      Andre Julius

      Author's profile photo Ganesh Babu
      Ganesh Babu

      Hi Andre,

      Change your code to the following :

      "serviceRoot": fiori_client_appConfig.appID + "_" + mobile_appRoutes[0].destination + "/sap/opu/odata/sap/ZMM_EMP_SRV/",
      Author's profile photo Andre Julius
      Andre Julius

      Hi Ganesh Babu ,

       

      Thanks for the recommendation, it did work out as you suggested. Initially I had Error Code 500, then I realize something wrong with the GW Model, as I need to regenerate it.

       

      Best Regards

       

      Andre Julius

      Author's profile photo Venkatesh Hulekal
      Venkatesh Hulekal

      Hi Andre,

      I'm stuck with the same issue. It would be great help if you could help me with what you had to change with the model.

       

      Author's profile photo Ganesh Babu
      Ganesh Babu

      Hi Ludo Noens

      Thank a lot for a very detailed and comprehensive blog. We could achieve Offline CRUD on Mobile Sample services.

      To point out, I believe the following defining requests should be?

      "supplierset": "/Suppliers/?$expand=Products"  ->  "/Suppliers?$expand=Products" .

      Now I am trying out the same thing but on our ECC backend. I am trying to make a sample Work Order CRUD app with offline and have some questions on that.

      1. Why is sap.OData.applyHttpClient()used regardless of whether the device is offline or not? Is it not expected from the app to query the backend directly when a network connection is present?
      2. Will Offline oData CRUD queries work the same way even in custom ui5 applications?
      3. Am using the below code in defining requests. It is working as intended on GW Client, but when the app goes in offline mode it only fetches the WorkOrdersSet  i.e the list and not the items. I created Association and Navigation property as usual for both entities. It seems it cannot fetch Operations from the offline store.
      /WorkOrdersSet?$expand=Operations

       

      Thanks for your help.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Ganesh,

      Thanks for point out that the defining request is actually wrong and should not have a slash at the end of the entity name. The app did still work fine though, so our solution is having some tolerance there ? .

      As for your questions:

      1. The offline plugin will overload the relevant functions and divert the calls to the on-device offline store. As an app developer, you don’t need to change a single line of code for this in your UI5 app.
      2. Yes, it will work the same. The only reason for choosing the CRUD template as a starting point here, is that it contains most of the CRUD code out-of-the-box. In other templates (or when working from scratch) you’ll have to implement it yourself.
      3. Please use the logs and network trace features in Mobile Services cockpit to find out why the Operations cannot be fetched. I suspect there is something fishy in your data model.

      Thanks,
      Ludo

      Author's profile photo Ganesh Babu
      Ganesh Babu

      Hi Ludo,

      Thanks for your reply.

      I guess it didn’t tolerate for me then since when I followed the same code it gave server error with “suppliersSet” due to which I had to fix the slash.

      Anyway,

      1. I did some changes where after the store is created, the Http Client is applied only if the device is offline. As long as there is a network connection app runs Online as usual and right as it loses connection the Http Client is applied and thereafter it runs offline.

      Is that not a preferred way?

      On the third point,

      As soon as the app runs online am getting the Details from ?$expand query as expected. Once the app runs offline, the Details screen is empty.

      How can I check logs and traces for this app since my Application is not there in Mobile services’ List of applications?

       

      Edit2: I have fixed the above issue. The OperationsSet Entityset had empty Orderid field. This won't be a problem in the Online Query. In Offline though it searches for OperationsSet based on the OrderID from ListSet. So even if Operations exists in the store it will just not fetch. Hope it's understandable, its hard to say in a few lines.

       

      Edit:

      Also is there an issue with downloading APK? Tried with different networks at different times, sometimes it downloads successfully but most of the times it just bottlenecks and stops at around ~10mb constantly. Having to do small changes and redownload every time only to face this stops the development process. I had expected a “Run on a device” feature(for Offline too) instead of Build and Download every time.

       

      Thanks,

      Ganesh

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Ganesh,

      Regarding the download issues... What is your location, and which landscape are you using ? Is it a Trial or production account?

      Thanks,
      Ludo

       

      Author's profile photo Adam Harkus
      Adam Harkus

      Hi Ludo

      Regarding this:

      "After the authentication screen and passcode screen, the screen will go blank for a while. We should actually show something here, so the end-user knows what is happening. This is an improvement to be added later. At this point, the offline store is being synchronised with the backend database. Once this is done, the UI will show up and display the data (this can take around 15 seconds)."

       

      Is this change imminent?

      Can you advise on a workaround until it becomes available?

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Adam,

      There are no plans to provide further improvements at this point. With all the code available in SAP Web IDE, I would assume that this is customisation that can be added by users.

      Regards,
      Ludo

      Author's profile photo Adam Harkus
      Adam Harkus

      Hi Ludo.

       

      It may be possible but in the Index.html this calls sap.hybrid.bootStrap() in sap-mobile-hybrid.js.

      We could wrap this in a promise etc but it would vastly overcomplicate the codebase as we'd need to combine the callbacks of the flush, refresh requests within a promise.

       

      E.g we could show a SAPUI5 Progress Indicator.

       

      call sap.hybrid.bootStrap();

       

      Then. (when all Promises have been fulfilled) hide the Progress Indicator.

       

      Wrapping all of the offline calls with Promises etc is a lot easier said than done though and would mean quite a lot of extra development.

       

      Hopefully, a progress indicator will be added as standard at some point.

      Author's profile photo Andre Julius
      Andre Julius

      Hi Ludo Noens

       

      I managed to simulate my case using service catalog until the flush part...however, the refresh callback does not seem to work for me. as per guide I do:

      Add in view controller

      onRefreshButton: function() {
      ....
      }

      Add in Hybrid.js as per guide also

      refreshStore: function() {
      ....
      },
      
      refreshStoreCallback: function() {
      ....
      },
      
      flushStore: function() {
      ....
      },
      
      flushStoreCallback: function() {
      ....
      },
      
      errorCallback: function(error) {
      ....
      },
      
      progressCallback: function(progressStatus) {
      ....
      },

      But apparently, the "Refresh" did not seem to detect the record that I already deleted from Online UI5 on the web. It did detect that I have additional.

       

      Am I missing something?

       

      Best Regards

       

      Andre Julius

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Andre,

      After the refresh callback is triggered, we should actually refresh the list displayed. This is currently missing in the example. If you use pull-to-refresh (after the refresh is finished, which takes a bit of time) it should reflect the changes.

      Cheers,
      Ludo

       

      Author's profile photo Andre Julius
      Andre Julius

      Hi Ludo Noens

       

      Thanks, it does work...BTW, does it make any difference when I put these functions in Master.js (View Controller) instead of in sap-mobile-hybrid.js?

       

      Best Regards

       

      Andre Julius

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Andre,

      It doesn't really matter. You can put this anywhere. I would keep the hybrid app code as much as possible in the mobile folder; just to keep your web app code as clean as possible.

      Cheers,
      Ludo

       

      Author's profile photo Ferry Djaja
      Ferry Djaja

      Hi Ludo Noens

      I have issue with using cordova geolocation plugin for iOS11. I am using SAP Web IDE Full Stack, it seems the Web IDE didn't add the NSLocationWhenInUseUsageDescription into  info.plist.

      I am using this plugin: https://github.com/slkerndnme/cordova-plugin-geolocation-ios-fixed

      What's the setting in Web IDE to ensure this parameter is included so the location service is working properly in iOS11 ?

      Thanks.

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Ferry,

      In the plugin selection dialog, you can add a usage description for this plugin. Did you provide an entry there?  (see screenshot)

       

      Thanks,
      Ludo

      Author's profile photo Ferry Djaja
      Ferry Djaja

      Hi Ludo,

      I have done that as well. But the Web IDE console gives me an error message

      (hat) There were errors (see browser console for details) when setting the selected plugins

      From the browser' console:

      HTTP/1.1 500 Internal Server Error
      Content-Type: application/json

      {"error":{"code":"0","message":"com.sap.xscript.json.JsonException"}}

       

      This is also happens with all other plugins with usage description. I am wondering why.

      Cheers,

      Ferry

       

      Author's profile photo Ramzi Abdallah
      Ramzi Abdallah

      Hi Ludo Noens,

       

      I want to thank you for this blog, it's really helpful.

       

      I was just wondering, Is it possible to create the Crud operations with Hat but with online mode ( like a simple sapui5 application but with android version) ?

       

      Should I do same steps you've mentioned but without creating a store in manifest.json?

       

      Thanks in advance,

      Ramzi

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Ramzi,

      If you create a new project from CRUD template in SAP Web IDE, it will be an online app out-of-the-box. You can build that into a hybrid app using HAT, simply by hitting the build. No code changes required.

      This blog is specifically describing the offline scenario, which does require some coding.

      Hope this answers your question.

      Cheers,
      Ludo

       

      Author's profile photo Rakesh Narayan
      Rakesh Narayan

      Hello Ludo –

      Thanks for the blog.

      One Question : Why does the build fail (Build Packaged App) with Error: Build Failed as the CBS build job id was not found for this Application.

      ~ Rakesh Narayan.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Rakesh,

      Is this issue persistent ? Or does it go away when you trigger the build again ?

      Also, can you tell us which landscape you are using ? Is this on trial or a production landscape?

      Thanks,
      Ludo

       

      Author's profile photo Rakesh Narayan
      Rakesh Narayan

      Hello Ludo -

      Yesterday, it worked fine for me and I was able to build the project and generate apk.

      Today, I have tried several times (recreating, rebuilding) but the build is not going through and I get the same error.

      Regarding Landscape - I am using Trail Account for now.

      Regards,

      Rakesh Narayan.

      Author's profile photo Rakesh Narayan
      Rakesh Narayan

      ++ build error in WebIDE

      The mobile build failed at step “POST/ startBuild” (scpms_api)

      (The error is coming for every project, even an empty random project  shows this error when I try to build)

      Regards,

      Rakesh Narayan.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Rakesh,

      We are currently facing issues on the trial landscape. Our engineering team is looking into this. The issue is only affecting trial users.

      Thanks,
      Ludo

      Author's profile photo Rakesh Narayan
      Rakesh Narayan

      Thanks for the confirmation Ludo.

      I hope this to get resolved soon.

      Regards,

      Rakesh Narayan.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Rakesh,

      The issues on Trial landscape have been resolved.

      Thanks for your patience.

      Cheers,
      Ludo

      Author's profile photo Rakesh Narayan
      Rakesh Narayan

      Thanks a lot Ludo. I have tried and it looks all fine now.

      Besides, I would like to ask about the size of the file (apk); its 90-100 MB files in most of the cases.

      Do we have any compression in place to reduce the size?

      Regards,

      Rakesh Narayan.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Rakesh,

      The reason for the large footprint is that we include a relatively large set of UI5 libraries. Our current Cloud Build Service is not able to strip down this set to the bare minimum for your app.

      It might be possible to optimise this using UI5 Evolution. However, we don't have any plans to support this with Cloud Build Service.

      Thanks,
      Ludo

      Author's profile photo Deborshi De Sarkar
      Deborshi De Sarkar

      Hello Rakesh,

      Can you please share me with the details how you solved the issue.

      I am facing same issue.

       

      Thanks

      Deborshi

      Author's profile photo ivan harb
      ivan harb

      Hello! Great post thank you!

      I am currently facing an issue when trying to build packaged App, it says (hat) the CSFR token has expired.

      I am not using a trial account.

      Maybe is an easy fix but i have no experience in this topic. Do you have any suggestion? thank you!

      Ivan

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Ivan,

      Are you still facing this issue ?

      Thanks,
      Ludo

       

      Author's profile photo Wlliam Wrigley
      Wlliam Wrigley

      Hi Ludo,

       

      Thanks for your informative blog. I am currently attempting to implement downloading of offline attachments with my app.

      I have configured a defining request pointing to my attachments entity with retrieveStreams = true

      "Attachments" : {"url" : "/zdod_i_attachments", "retrieveStreams" : "true"}

      However, on initial opening of the store I receive a sync error. Checking mobile services, I can see that the app attempted to call:

      <service_root> + ZDOD_DEF_APP_SRV/file_name
      

      The app appears to be attempting to download all attachments on store open. I assume I need to use the function registerStreamRequest, however I am unsure where in the application lifecycle this needs to be called and if I need to make the function call for each individual attachment

       

      Below is a sample call:

       

      sap.hybrid.store.registerStreamRequest("stream",
      "/zdod_i_attachments(incidentId=guid'" + incidentId + "',attachmentId=guid'" +attachmentId + "')", this._onRegisterStreamSuccess.bind(this), this._onRegisterStreamError.bind(this));

       

      Thanks,

      William

       

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Hi Ludo.

      How can i deploy app in SAP Fiori Mobile Place. Thanks

      Regards,

      Angel

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      This would be via a manual step in Mobile Place; if you have access to this. As Mobile Place is being phased out, we no longer provide this integration.

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Could you give me the manual steps, please?

      Regards,

      Angel

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      I don't have details, but you should still be able to do this using Mobile Secure, if you have access to this.

       

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      I do not find the option to import APK or app in Mobile Secure.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      This product is out of my scope. Please open a support case against mob-fm asking how to distribute mobile service built apps via mobile place.

      Author's profile photo Andre Julius
      Andre Julius

      Hi Ludo Noens

       

      I find that recently there is a change in behaviour? With the code in this blog now even when I am online, I need to flush in order to get the result pushed to the back. Is it just my imagination? I'm pretty sure last time when I am online I don't have to flush.

       

       

      Best Regards

       

      Andre Julius

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Andre,

      Once you make use of an offline store, your app will be working against the local store only. You'll need to flush in order to update the online database. I don't think anything changed recently regarding this behaviour.

      When using the web app (deployed to SAP Cloud Platform), you will be working online, with the online database.

      Thanks,
      Ludo

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Hi Ludo.

      Could you help me, please?.

      I have a problem in defining requests, because i need filter data before download to local storage offline. I have used $filter, but it is not work.

      regards.

      Angel

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Angel,

      Looking at the strings used, I am seeing:

      • UserStatuSet             (you probably meant UserStatusSet)
      • WOSystemStatuss    (you probably meant WOSystemStatus)
      • SystemStatus   (you are trying to filter based on a substring of this)

      Please review and adjust accordingly.

      Thanks,
      Ludo

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      when i use $filter in defining requests (WorkOrderSet), this no work. I need data without TECO and CLSD, SystemStatus  is field to WorkOrderSet. Could i use odata syntax.

      Author's profile photo Mehmet kaya
      Mehmet kaya

      Hi Ludo, thank you for your great blog.
      Nowadays, I am realy focusing on offline topic and when I saw your blog I immediately tried to implement offline application.
      When my application run as a web application on browser, it works fine on pc without any errors (but I am not sure about of offline part is ok or not). Also, the apk file works fine on phone when online.
      But I need your support for mobile offline scenerio. I try to test applicaiton on phone via apk file when switch off internet, it gives error for every process. It shows just error thus, I couldn't try offline scenerio.
      Although, I tried different many kind of path for solving error. it unfourtunetly did not work on phone.
      Colud you tell me, where and how should I check in the project?

      Also, I couldn't open Android Studio Project via Android Studio. The project has so different structure than native Android applications.
      How can I open and modify it?

      Could you help me, please?

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Mehmet,

      If the app works as online app, then the issue is most likely related to the offline store initialisation. I have recently added a troubleshooting section to this blog. Please ensure the offline store get initialised.

      Loading the Android Studio project is detailed in this blog: https://blogs.sap.com/2018/07/02/whats-new-in-hybrid-app-toolkit-release-1807-custom-fiori-client/

      Hope this helps.

      Regards,
      Ludo

      Author's profile photo Mehmet kaya
      Mehmet kaya

      Thank you for your supporting.

      Now, I can open custom fiori client project via Android studio and I understand the concept.

      I have one more question, can I use on-premise SAP Mobile Platform in this offline architecture and how?

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Mehmet,

      On-premise SAP Mobile Platform is not supported in the scenario described. This only works with Mobile Services, available on SAP Cloud Platform.

      Using SAP Cloud Connector, you could expose your OData sources to SAP Cloud Platform.

      Thanks,
      Ludo

      Author's profile photo Deborshi De Sarkar
      Deborshi De Sarkar

      Hi Ludo,

      Thanks for this great blog.

      I am just doing the same thing what you have done, but i have stuck in the App Build step.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Deborshi,

      Is your app using Push notifications?

      Regards,
      Ludo

       

      Author's profile photo Deborshi De Sarkar
      Deborshi De Sarkar

      Hello Ludo,

      Thanks for this information. I have unchecked the Push notification check box and i have generated the QR code.

      But my question is why that error was coming when i was using Push notification ?

      and another question is how i scan qr code from mobile device?

       

      Thanks

      Deborshi

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Deborshi,

      There is a known issue with Push notifications that will be fixed in a patch we have planned to release by end of this week.

      Scanning QR codes is standard built into the iOS camera function. For Android, there should be a large amount of options out there (apps, built in).

      Cheers,
      Ludo

      Author's profile photo Deborshi De Sarkar
      Deborshi De Sarkar

      Thanks Ludo.

      I have SAP Cloud Platform license. with that license can i access Mobile Service license version or should i need another license for this?

       

      Thanks

      Deborshi

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      If you've managed to build the app using cloud build service and the result is a QR code, then you have Mobile Services in your subscription.

       

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Hi Ludo.

       

      Is possible filter data from a entity before what data is to download in local storage. I use $filter in defining requests but this action no function.
      Have you got any idea?.

       

      Author's profile photo VIKAS TRIVEDI
      VIKAS TRIVEDI

      Hi Ludo,

      Thanks for the blog.

      I am able to create an offline app and it works perfectly.

      I still have a few questions which are not clear for me. Would be really great if you can help.

      1. Whenever we do changes in our app, we have to build it again which leads to reinstalling the app on our devices again. How can we use AppUpdate plugin with cloud build?
      2. How to customize the login screen similar to what we can do using HAT?
      3. Can we remove the unwanted Kapsel plugins from the app as it increases the application size?

      Regards,

      Vikas

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Vikas,

      1. AppUpdate is not supported from SAP Web IDE Full-Stack.
      2. This will be some manual coding work. In the file mobile/hybrid/sap-mobile-hybrid.js , we pass a context to the Kapsel logon plugin. You can modify the code as described in the Kapsel logon documentation
      3. Currently, the only way to do this is by downloading the complete Xcode / Android Studio project from the cloud build service and manually stripping out the plugins not required. We are working on an update planned for end of April 2019, where you can select/deselect plugins from within SAP Web IDE.

      Hope this helps,
      Ludo

      Author's profile photo VIKAS TRIVEDI
      VIKAS TRIVEDI

      Thanks, Ludo.

      Is there any update planned for supporting AppUpdate plugin?

      Regards,
      Vikas

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Vikas,

      It is not on our roadmap. 

      Meanwhile, try to keep your app working in both online and offline cases. This way you can keep your main app development web based.

      Regards, Ludo

       

       

      Author's profile photo Sushant Nath
      Sushant Nath

      Hello Ludo,

      Hope you are doing good!

      • I have followed, all the steps, given above to generate/package the application.
      • However,I am getting, error as mentioned below(unable to attach an image/screenshot here.), while trying to access the app, from android mobile.
      • I am able to ping, the destination successfully from destinations tab, in SCPMS.

       

      • The error is "Retrieve metadata failed because the OData server returned HTTP code, 404, with message: null".

      Can you please, help me out, on this?

       

      BR,

      Sushant

       

       

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      You are able to ping the destination in Mobile Services, but are you able to perform the OData application destination test (the icon on the left side of Ping) ?

      Checking the logs and traces in Mobile Services will provide you more details on this 404.

      Which OData source are you using ?

      Thanks,
      Ludo

      Author's profile photo Sushant Nath
      Sushant Nath

      Hello Ludo,

      Thanks for looking into,this issue.

      I am using northwind odata services.

      Yes, am able to perform Odata application destination test, after setting the relative path to "/v2/northwind/northwind.svc".

       

      BR,

      Sushant

      Author's profile photo Former Member
      Former Member

      Hey!

      I could recreate your sample with no problems, but if I try to do it with my own Odata Service it doesn’t work.

      The Odata does work, as long as the store function isn’t implemented.

      I did use the Odata from the Service Catalog:

       

      with this Destination:

       

      I tried it with this 3 methods for the serviceRoot, getting either 401 or 403 errors.

       

       

      With the first Method I get: As I tried to recreate it, I did just get a blank screen where nothing happens. Not even the login Prompt for SAP.

       

      With the second Method I get: [-100010] Retrieve metadata failed because the OData server returned HTTP code, 401, with message: null.

       

      With the third Method I get: [-100010] Retrieve metadata failed because the OData server returned HTTP code, 403, with message: Backend connection sap is not mapped for this application configuration.

       

      Manifest is just :

      	"sap.mobile": {
      		"definingRequests": {},
      		"stores": []
      	}

       

      If you could help me, that would be awesome!

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Dominik,

      The manifest part is correct. This is can be left empty is shown, because this structure is only needed to trigger the cloud build service to add the Kapsel offline plugin. The contents are ignored.

      Unfortunately, I have not created an example that involves on-premise OData sources.

      Please check in the Mobile Services admin Cockpit which (mobile) destination is used for the mobile app and see whether you can Ping this destination. Use the OData application destination test (the icon on the left side of Ping). Specify the relative path as used by your app and click next. You should be able to view data available in the service.

      You might want to experiment with the URI in the manifest file. There are other users who reported fixing issues by changing this. Please check previous comments on this. Given the large amount of comments on this blog, you might have to click on the "Older Comments" button to see all of them.

       

      Thanks,
      Ludo

      Author's profile photo Vineet Safaya
      Vineet Safaya

      Hi Dominik,

      Try to use 2nd scenario. In your frontend system, open the odata service in SICF. Under the logon data tab, mark the checkbox - Use all logon procedures. Clear data of your app on device & check again. You should be able to resolve the error.

      I used this way to solve mine.

      --

      Vineet

      Author's profile photo Sumanth Thunga
      Sumanth Thunga

      Hi Ludo,

      Are there any issues with iOS Cloud Build. I am getting below error fir iOS version. It was working before.

      [2019-03-11 03:02:58.13739] [IT] [LogToken] [Command Return Value: 0] [] [CBS\Utils\Utility::execCommand]

      [2019-03-11 03:02:58.13763] [IT] [LogToken] [Finished Executing Command: prepare_sign.sh] [] [CBS\Utils\Utility::execCommand]

      [2019-03-11 03:02:58.14033] [ET] [LogToken] [[Build Failed For [ios][ErrorCode :PREPARING]][[ErrorStatus:DEPLOY_STATE_FAILED][Invalid appId - less than 3 segments: .x9fda02d1cd9a403b81a90535cbeb0a99][CBS\BuildEntities\CordovaIosBuildEntity::adjustIosBuildFile]] [] [CBS\BuildEntities\CordovaIosBuildEntity::adjustIosBuildFile]

      [2019-03-11 03:02:58.14070] [ET] [LogToken] [Exception occurred at Build Phase: 1  Exception Message:

      Error Message:: Invalid appId - less than 3 segments: .x9fda02d1cd9a403b81a90535cbeb0a99

      ErrorCode::PREPARIN0

      ErrorState::2] [] [BUILD]

      This is both on Trial and regular SCP Mobile services. Please suggest.

      Thanks
      Sumanth

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Sumanth,

      This is related to a change we did in November last year. You should update your signing profile to the new appId, which is now based on 3 segments   (e.g. com.sap.x9fda02d1cd9a403b81a90535cbeb0a99).

      Regards,
      Ludo

      Author's profile photo Sumanth Thunga
      Sumanth Thunga

      Hi Ludo,

      Thanks for info and reply. I will try change my certificate to include app id as com.sap.*

      Is there an option to use customer name space in to app Id instead of com.sap

      I did not find any option to enter different id while cloud build. All apps are being created as com.sap.webide.xxxxxxx

      Thanks

      Sumanth

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Actually, yes, you can use other combinations as well.

      Take note that we used to combine the AppId (as used on Mobile Services), with the Bundle ID used for the signing profile. However, these can now be defined independently.

      So, your Bundle Id used for the signing profile can be for example com.yourcompany.myapp

      Cheers,
      Ludo

       

      Author's profile photo Sumanth Thunga
      Sumanth Thunga

      Hi Ludo,

      Thanks for the help. That worked after adding a Bundle ID with three segments. Is oAuth Security supported for Hybrid Offline Applications?

      I tried to enable oAuth at app level in mobile services cockpit and build the app. Got 403 Error at ODATA Service call as there was no SAML Token passed to backend service. Will look further in the documentation. Any pointers in using oAuth would be helpful.

      Thanks
      Sumanth

       

      Author's profile photo Dominic Keller
      Dominic Keller

      Hi Sumanth,

      Could you please describe how you have changed your Bundle ID? Do we have to change it in the config.xml file?

      Thanks for your help.

      Dominic

      Author's profile photo Adam Harkus
      Adam Harkus

      Hi Ludo.

      By default, requests are 'batched' which is causing memory errors on the Samsung Galaxy J5 (and J3) Android phones.

      Turning off batching ("useBatch": false in Manifest.json) causes other issues with speed and oData call execution, so this isn't an option.

      End result is we really need to get this working using batching.  Can you recommend any optimisation? I have setup the Client Indexes.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Adam,

      I would consider the devices you've mentioned as low end. Memory resources are pretty limited on these devices.

      Only other thing we can think of is to optimise the app to deal with paging if it’s not already.  If it does do paging then you'll need to make it more aggressive.

      You can create the offline store with the pageSize option.  This should restrict the max entities that can be returned in a single read request.

      https://help.sap.com/doc/acbf025f18854e63a7f3bf20038356c8/3.1/en-US/api/sap.OfflineStore.html

       

      Also on individual requests you can use $top and $skip

      https://www.odata.org/documentation/odata-version-2-0/uri-conventions/

       

      Hope this helps.

      Regards,
      Ludo

      Author's profile photo Adam Harkus
      Adam Harkus

      Thanks Ludo.

       

      There isn't a huge volume of data so I don't think it's data related., Basically, we have 48 'questions' with 3-5 'answers' for each.

       

       

       

      Author's profile photo Adam Harkus
      Adam Harkus

      Hi Ludo. A PageSize of 10 did indeed resolve the issue of speed/crashing. However, we can't use this as we need all of the data.

       

      Do you have any other suggestions?

      Author's profile photo JITHIN VS
      JITHIN VS

      Hi Ludo,

       

      After building the app, why it is having file size around 100 MP. iIt's just the template I'm having in the project(I don't have any additional code)?

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Jithin,

      This is because we need to package a large amount of UI5 libraries into the packaged app.

      Regards,
      Ludo

      Author's profile photo JITHIN VS
      JITHIN VS

      Hi Ludo,

      Is there any way, we can reduce the app size? (Only build the required libraries instead of bundling all)

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Jithin,

      Unfortunately, we don't provide a way to limit the amount of libraries included in the cloud build service. What is included is already a subset tailored for mobile.

      You could manually strip out the libraries you deem not required by downloading the Xcode/Android Project locally. But this is tricky, because you might not know the dependencies. If you leave out too much, the mobile app will fail at runtime (and this can be very hard to debug).

      Regards,
      Ludo

      Author's profile photo Jay Malla
      Jay Malla

      Hi Ludo,

      Nice blog.  I went though this and did the build for Android.

      However, for our client, we are trying to build offline Hybrid applications for Windows platform.  I am able to get some of the offline examples working for Windows and debug them through Visual Studio 2017.  I am working on the offline example - Getting Started with Kapsel – Part 10 — Offline OData(SP13+)

      From your example, since we do not have the Windows build service available through cloud build, do you have the steps on how I can bring this project into a Cordova windows project and run this.  I am able to create the Cordova windows project, add Cordova and Kapsel plugins, and debug.  In Daniel's blog, i just need to add the corresponding plug-ins and then replace the default Cordova generated index.html with the one he had written.

      With your example, if I just export the project from WebIDE and then bring this folders and files into the Cordova Windows project, I am not sure exactly how this will work.  Do I keep the mobile/hybrid folders as you have in the project or do I need to blend them with the web app folder?

      In your article, you state:

      Take note that during the cloud build process, the contents of the webapp folder and the mobile folder will be merged into the www folder of your Cordova project. The index.html file in the mobile folder will replace the one in your webapp project (if your project has one).

      Can you please provide some guidance on the steps to go from your example to doing a build on Visual Studio 2017 for Windows?

      Thanks,

      Jay

       

       

       

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Jay,

      We will basically merge the mobile folder into the webapp folder during the build process. This will obviously not happen when you export the project from SAP Web IDE. If you want to do this manually:

      1. copy webapp folder contents into Cordova www folder.
      2. copy mobile folder contents into Cordova www folder, overwriting existing files from step 1.

      I think the easiest way to get what you need, is to perform a cloud build for Android, with the build option "Save Xcode/Android Studio project". Once this is done, you will be able to download the complete project onto your windows machine. This project will contain the merged folders.

      I am not sure whether you could add the Windows platform directly in the Cordova project by using the Cordova CLI tools, but it is worth a try.

      You might need to adapt the index.html and other files for the Windows target. I don't have instructions for that.

      Hope this helps,
      Ludo

      Author's profile photo Jay Malla
      Jay Malla

      Hi Ludo - I just saw your comment after I posted a comment below.  I will try the steps you have mentioned.  I will take the Android studio project and then download that and then see how that has been done.

      What I had done is merge the contents manually and then point the start to be the index.html from the mobile folder which now is under the www folder.  I also brought in the resources folder that has the SAP UI5 sap m and ui folders.

      I am not sure where fiori_client_appConfig is defined.  I do not have the appConfig.js and appRoutes.js in the exported WebIDE project.

      Thanks,

      Jay

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Yes, that is another reason for advising you to download the complete project from our build service. Those missing files are generated and will be part of the final project.

      Cheers,
      Ludo

      Author's profile photo Jay Malla
      Jay Malla

      Hi Ludo,

      I downloaded the project from WebIDE and trying to bring the files into the Cordova project.

      But I am not sure where to get these files you have referenced - appConfig.js and appRoutes.js - since I am not using the Cloud Build serve.

       

      	<!-- initialize bootstrap -->
      	<script type="text/javascript" src="hybrid/sap-mobile-hybrid.js"></script>
      	<script type="text/javascript" src="hybrid/logon.js"></script>
      	
      	<!-- app configuration info files are added during cloud build -->
      	<script type="text/javascript" src="appConfig.js"></script>
      	<script type="text/javascript" src="appRoutes.js"></script>
      	
      	<script type="text/javascript" src="cordova.js" onload="sap.hybrid.setCordova();"></script>
      
      	<script type="text/javascript">
      	(function() {
      		var remoteBase = fiori_client_appConfig.fioriURL;	// not use fioriclient plugin but borrow some of its configuration format
      		if (remoteBase.charAt(remoteBase.length - 1) === '/') {
      			remoteBase = remoteBase.substring(0, remoteBase.length - 1);	// remove trailing slash
      			fiori_client_appConfig.fioriURL = remoteBase;
      		}
      

       

      I am getting the error:

      SCRIPT5009: Unhandled exception at line 42, column 3 in ms-appx-web://com.sap.webide.x30eab3620cc54629bd808de0ffd6e721/www/index.html 0x800a1391 - JavaScript runtime error: 'fiori_client_appConfig' is not defined

      Where does this variable get referenced?

       

      Thanks,

      Jay

       

       

       

      Author's profile photo Jay Malla
      Jay Malla

      Hi Ludo,

      I downloaded the Android build project and copied the files over.  What is strange is that I am now getting an error:

      SCRIPT5022: Unhandled exception at line 1360, column 9 in ms-appx-web://com.sap.webide.x30eab3620cc54629bd808de0ffd6e721/www/cordova.js 0x800a139e - JavaScript runtime error: Module cordova-plugin-network-information.network does not exist. cordova.js (1360,9)

       

      I had already added the cordova-plugin-network-information.network in the project using the cordova CLI:

      cordova plugin add cordova-plugin-network-information

      So I am not sure why it's erroring out.  Should I just copy all of the plugins from the SAP Built project into my Cordova project or should I add them one by one with the CLI.

       

       

      I am not sure why the code is not finding this plugin.

      Regards,

      Jay

       

       

      Author's profile photo Jay Malla
      Jay Malla

      Hi Ludo,

      I copied the resources folder from platforms\android\app\src\main\assets\www\resources which has all of the sap ui5 libraries and also the plugins from platforms\android\app\src\main\assets\www\plugins so I am no longer getting the issues with missing js files and plugins.

      I can step through the call to sap.hybrid.bootStrap();  But the application just exits without going into the first page of the application.  I am not sure why.  I do see an error - "Can’t load the ActiveX plug-in that has the class ID '{D27CDB6E-AE6D-11CF-96B8-444553540000}'. Apps can't load ActiveX controls." that happens before.

      So the sap-mobile-hybrid.js never goes into the actual application.

       

      Regards,

      Jay

       

      Author's profile photo Shree Krishna
      Shree Krishna

      Hi Ludo,

      store.open() function control enters success callback function, but the store is not getting created, the app opens  fine, but the busy dialog keeps running with user interface opened  ( tried keeping it for more than 20 minutes, no help  ) . And major doubt is with "store" variable, you have not declared "store" variable, I declared it just as a local variable, does that have anything to do here? Because rest of the lines of code remain the same as yours.

       

      Thank you,

      Shree Krishna

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Shree,

      This sample code is not perfect, but I did validate this multiple times and various users have confirmed this was working fine.

      Please see the troubleshooting sections for directions on how to analyse potential issues. I suggest capturing a trace at Mobile Services cockpit to see why the store is not getting created.

      Thanks,
      Ludo

      Author's profile photo Shree Krishna
      Shree Krishna

      Hi Ludo,

      I figured out the problem, the problem is with the Regular Expressions within startApp() function, like you mentioned in the blog

      "In the file mobile/index.html there is some code to adjust your app’s XMLHttpRequests to use URLs that work locally. Please check whether the URL used matches with the serviceRoot you’ve defined. If the path doesn’t match, the app will not use the on-device store."

      can you please help me out what is happening in the regular expressions out there in that function.

      Regular expression will not match my appId.

      My appId looks like this : com.sap.webide.x4b530a7020154b4ea11037a6c5416c69

       

      Thank you,

      Shree Krishna

      Author's profile photo Manjula Gupta
      Manjula Gupta

      Hi Ludo,

      Thanks for the wonderful blog.I was able to successfully build an offline application. However, what I have noticed is that some entities in the metadata are not loaded when opening the app first time.As a result, create and read are not working for those missing entities while it works fine for the ones which gets loaded. The application works fine on web browser however not working on mobile both in online and offline mode.

      Could you please help and suggest what could be the issue possibly.Have a demo lined up this week.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      I think we handled most queries via email.

      Thanks,
      Ludo

      Author's profile photo Martin Koch
      Martin Koch

      Dear Ludo

      thanks for the great post!

      We got everything working, but when trying to connect to an OnPremise ABAP System we get an error:

      Failed to load resource: net::ERR_FILE_NOT_FOUND

      logger.js:775 error sending ping request{"errorCode":-121,"description":"ERROR whitelist rejection: url='https://mobile-xxx.hana.ondemand.com:443/odata/applications/v1/com.sap.webide.xxxxxxyyyyyy"}

       

      We also tried to change the projects config.xml

      <access origin="*"/> to the SCPms URL.

       

      Thanks fpr your help!

      BR,

      Martin

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Martin,

      I suspect a wrong configuration somewhere...

      Are you able to access your on-premise data in Mobile Services admin cockpit?

      First of all, try to ping the destination. If that works, try testing the OData source to see whether you can pull information.

      Thanks,
      Ludo

      Author's profile photo Martin Koch
      Martin Koch

      Hi Ludo

      the problem was solved by a new build of the application.

      Thanks for your help!

      Best Regards,

      Martin

      Author's profile photo Nicole Weth
      Nicole Weth

      Dear Ludo,

      I followed your tutorial exactly. But when I tried to change the sap-mobile-hybrid.js I got problems with already existing variables....

      For example fiori_client_appConfig and console are not defined. Do I have to define them or was there an error with generation of the file?

      Greetings Nicole

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Nicole,

      I believe you can ignore those errors.

      Cheers,
      Ludo

      Author's profile photo Nicole Weth
      Nicole Weth

      Thank you very much. It worked indeed. This is a really very helpful blog.

      Author's profile photo Daniel Krancz
      Daniel Krancz

      Hi Ludo!

      Great blog, your app works fine, but I have a question.

      In your app you also get an error called “[ODataMetadata] initial load of metadata failed -“. Why does this error occur and why are we able to work with the app, if the metadata couldn’t be loaded?

      Regards,

      Daniel

      Author's profile photo Satya Kodati
      Satya Kodati

      Hi Ludo,

      Nice blog.

      I was also able to replicate the example given by you. But while i am trying to use my own oData service, i am facing issue like my destination with own oData is not displaying in the Service URL list.

      Can you help me on this how you created destination for your own oData ? This will be very helpful to me.

      Thank you,

      Satya

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Satya,

      This tutorial https://developers.sap.com/tutorials/cp-webide-create-crud-app-template.html should help.

      Cheers,
      Ludo

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Hi Ludo,

       

      I am having a problem.  When i start my app in mode offline. Which shows a screen in blank.

      Could you help me with this problem, please?

      Regards,

      Angel

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Angel,

      Please raise a support ticket for component CA-WDE-MOB.

      Include in the ticket:

      • do you see this behaviour only in offline mode?
      • which version of Ui5 are you using?
      • iOS and/or Android

      Thanks,
      Ludo

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Hi Ludo,

       

      My app is in productive environment. When I execute method refresh. That returns error.

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Angel,

      Please raise a support ticket for component CA-WDE-MOB.

      Offline functionality spans a wide range of SAP SDKs and services, created by various teams within SAP. I cannot answer you based on the error in the screenshot. What I do advise is to make use of the logs and tracing features in SAP Mobile Services (see Analytics) to identify the cause of the error.

      Thanks,
      Ludo

      Author's profile photo Shanir Tvaija
      Shanir Tvaija

      Hi Ludo Noens!

      I got transferred to your blog from another blog on building UI5 offline apps.  But I see an update, that you suggest using Mobile Kit or native CP SDKs. The first question here is:

      Are there some LH courses or any other guides on that?

      the second question is, or more like a precision information - the HAT toolkit in webIDE and subsequent packaging is currently the only option if OS (desktop-Windows and mobile devices - iOS&Android) wide application needed, right? or is there something new as well?

       

      Thanks a million,

      Shanir

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Shanir,

      For Mobile Development Kit and other options, there is currently a free to access openSAP course running: https://open.sap.com/courses/mobile3

      Hope this helps and sorry for the late response.

      Cheers,
      Ludo

      Author's profile photo Hari krishna Chevvakula
      Hari krishna Chevvakula

      Hi Ludo Noens

      Good Day..!

      This Blog is Really Helpful. Thanks for your Quick & Exact Solutions.

      Colud you Please Suggest me. how to add Cordova plugin  for native dialer plugin my native/hybrad Mobile app.Plugin also seclected before buld. i don't know how to use/any code need to be keep in our files. Please Guide me.

       

      Thanks In Advance

      Hari.

       

       

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Hari,

      How to use a plugin is not in the scope of Hybrid Application Toolkit. For any public plugin selected through the plugin dialog, please refer to the documentation of the plugin to learn how to use it. This is the same challenge you'll face when building Cordova apps using command line tools.

      In general, look for the documentation of the plugin. Sometimes we offer a direct link from the "View Details" option in our dialog. In other cases search for it.

      An example of a plugin you could use is cordova-plugin-os-call-number (note: this is a not a recommendation, as I have no idea whether this plugin is suitable for your needs). You can call this using window.plugin.CallNumber.callNumber(onSuccess, onError, number, bypassAppChooser).

      Obviously you'll need to add a function that gets called when the 'call' button is pressed.

      Regards,
      Ludo

      Author's profile photo Tjarliman Rusadi
      Tjarliman Rusadi

      Hi Ludo,

      If I created FIORI apps using ABAP for FIORI or ABAP Restfull programming, can I create off line apps based on those?

      If it can be done, could you pls. share on how to do it? because seems the structure of app project is different in SAP WEB IDE, and it is using different template of project as well.

      Thanks in advance.

      TJ

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi TJ,

      In general, the answer is no. Our tooling does not support ABAP. But you can develop the server side of the application in ABAP. It just won’t run as mobile app. For the front end part, it has to be a UI5 based app, which can be developed as offline mobile app.

      You would have think about a separate app for the front end. Don’t try to solve the whole problem in ABAP. Split it into a server side ABAP implementation that provides an OData source, and a UI5 based front end that consumes that OData source. You can also build the mobile apps with our native SDKs or MDK, consuming the same OData source.

      Hope this helps.

      Ludo

       

       

      Author's profile photo Tjarliman Rusadi
      Tjarliman Rusadi

      Ok Got it. Thanks Ludo.

      Author's profile photo Dominik Steinrücken
      Dominik Steinrücken

      Hi Ludo,

      I converted a customer project from the old local HAT to a cloud build project.

      Opening an and initializing the store works well using the folling code:

      var mobile_appRoutes = [{
      	"path": "/gw_sso",
      	"manual": true,
      	"target": {
      		"type": "destination",
      		"name": "gw_sso",
      		"entryPath": "/"
      	},
      	"description": "Gateway"
      } //...
      }
      
      		init: function () {
      			if (sap && sap.hybrid && sap.hybrid.kapsel) {
      				jQuery.sap.require("sap.ui.thirdparty.datajs"); //Required when using SAPUI5 and the Kapsel Offline Store
      				this.properties = {
      					"name": "mainServiceV2",
      					"host": sap.hybrid.kapsel.appContext.registrationContext.serverHost,
      					"port": sap.hybrid.kapsel.appContext.registrationContext.serverPort,
      					"https": sap.hybrid.kapsel.appContext.registrationContext.https,
      					"serviceRoot": this.serviceUrl, // is: "/gw_sso/sap/opu/odata..
      					"definingRequests": {
      						"TourHeaderSet": "/TourHeaderSet?$top=10",
      						"PlantSet": "/PlantSet",
      						"ShippingPointSet": "/ShippingPointSet"
      					}
      				};
      
      				var sAppCID = sap.hybrid.kapsel.appContext.applicationConnectionId;
      				var sAuth = "Basic " + btoa(sap.hybrid.kapsel.appContext.registrationContext.user + ":" + sap.hybrid.kapsel.appContext.registrationContext
      					.password);
      
      				this.properties["streamParams"] = "custom_header=Authorization:" + sAuth + ";custom_header=X-SMP-APPCID:" + sAppCID + ";";
      
      			}
      
      		openStore: function () {
      			console.log("In openStore");
      			this.store = sap.OData.createOfflineStore(this.properties);
      			this.store.open(this.openStoreSuccessCallback, this.openStoreErrorCallback);
      		}

       

      But - the offine-store is not used after applying the http-client.

      I think the reason is the following coding from OData.js (kapsel-plugin-odata):

      var url = request.requestUri;
              var requestUrlInfo = getURLInfo(url);
      
              if (requestUrlInfo) {
                  for (var i = 0; i < openStores.length; i++) {
                      var storeUrlInfo = getURLInfo(openStores[i].serviceUri);
      
                      if (requestUrlInfo.scheme === storeUrlInfo.scheme &&
                          requestUrlInfo.host === storeUrlInfo.host &&
                          requestUrlInfo.port === storeUrlInfo.port &&
                          pathWithSlashes(requestUrlInfo.path).indexOf(pathWithSlashes(storeUrlInfo.path)) === 0)
                      {
                          handle = true;
                          break;
                      }
                  }
              }

       

      The endpoint of the Odata-Model is /destination/servicepath , the endpoint of the offline-store is https://mobile-<account>.hana.ondemand.com/destination/servicepath. So the request ist not handled by the offline-plugin.

      I could change the odata service url in the ui5-manifest to the mobile service url, but the app is not hybrid anymore (because the mobile service url cannot be used in the browser).

      How can I "force" the app to read the data from the offline store?

       

      Best regards

      Dominik

       

       

       

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Dominik,

      Sorry for the late response. I am not monitoring this blog post regularly.

      There is some code in the index.html file handling this path. This file can be found in the mobile folder after mobile enablement. If the url used in the request to fetch data doesn't match the url specified during initialisation of the offline store, then the offline store will not be used. You'll probably need to tweak the service root.

      Note: once the offline store is initialised, the service root is fixed. You'll have to completely remove the app (and data on Android) to be able to use a different configuration (re-initialise).

      Regards,
      Ludo

      Author's profile photo Krisztian Szabo
      Krisztian Szabo

      Hi Ludo,

      In the openStore function how we can add more than one serviceRoot?

      How we can open multiple offline stores?

      Could you give me an example, please?

      Thanks and regards,

      Krisztian

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Krisztian,

      It is possible to open multiple offline stores. But you'll have to initialise them individually; not by adding multiple serviceRoots in a single openStore function.

      Unfortunately, the example code provided in this blog post does not handle multiple stores and I don't have examples for this. Besides multiple openStore functions, there is other code to be adapted as well to ensure those online service calls are translated/intercepted into local store calls.

      Thanks,
      Ludo

       

      Author's profile photo Gergely Varga
      Gergely Varga

      Hi Ludo,

      You helped me a lot!

      Now it works! 🙂

      Thanks,

      Krisztian

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Krisztian,

      Glad to hear ! Did you need to make changes besides the additional openStore function to get it working ?

      Thanks,
      Ludo

      Author's profile photo Krisztian Szabo
      Krisztian Szabo

      Hi Ludo,

      My short answer is: Yes, I made some small changes.

      These were my steps:

      • I removed the mobile folder and added a new oData service to the application.
      • I enabled again the HAT plugin (in this case the HAT will fill the appConfig.js automatically and I don’t have to touch it).
      • In the sap-mobile-hybrid.js file I created 2 different openStore functions (*Note: I commented out the startApp() in the first openStore function).
      • In the second openStore function I renamed the store to store2
      • In the appLogon() I had to call the doLogonInit() twice:
        • sap.hybrid.kapsel.doLogonInit(context, appConfig.appID, sap.hybrid.openStore); 
        • sap.hybrid.kapsel.doLogonInit(context, appConfig.appID, sap.hybrid.openStore2);
      • I created a copy from these functions for the store2:
        • refreshStore, clearStore, closeStoreCallback, flushStore and I renamed the store to store2 in these functions.

      Do you know what is the size limitation of the offline store?

      How many offline store do we have?

      Thanks and regards,

      Krisztian

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Krisztian,

      Happy to hear it works for you and good to know it can be done with minimal changes.

      I was expecting additional changes in handling the data calls, but it looks like this is not needed.

      As for the limits: the only size limit is your device's storage space. For the amount of stores, I think there is no limit either, as long as they fit in the storage space.

      Regards,
      Ludo

      Author's profile photo Angel Gutierrez Bellido
      Angel Gutierrez Bellido

      Hello Ludo,

      I'm have a problem when i try to build APK but cloud build service hasn't finished to build.

      Could you give me any solution.

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Angel,

      This behaviour is a bit odd. First of all, could you try the following:

      1. Log out of SAP Web IDE
      2. clear browser cache
      3. Reload SAP Web IDE
      4. Log in
      5. Trigger another build.

      If you still encounter the same behaviour, please open the browser developer tools and check the console log and network trace to have some more information on why the creation of the mobile services application fails.

      Also, please do not hesitate to raise a support ticket on component CA-WDE-MOB.

      Regards,

      Ludo

      Author's profile photo rihab ouaslati
      rihab ouaslati

      Hi Ludo,

      i’m relativly new to offline hybrid apps , i’ve followed your blog before using web ide trial version and managed to build various hybrid apps.

      However now that i’m using web ide full stack version, each time i rey building the packaged app i always get this message :

      i have the administrator role for all the mobile services in scp.

      If i uncheck and check Android again i get a different error message :

      Do you have any suggestion on how to fix this ? thank you! 

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Rihab,

      In both cases, you are using SAP Web IDE Full-Stack. The difference is that on the trial account, some settings were already preconfigured for you. On a production landscape, these settings need to be configured.

      You can find the prerequisites here: https://help.sap.com/viewer/8e5c63b6470a4255861c259f3b2d9b41/Cloud/en-US/aa8715ac0a914f12b90fbb8865612c71.html

      You basically need to go the SAP Cloud Platform cockpit, go to services, find Mobile Services. Select Configure Mobile Services and configure the roles 'Administrator' and 'Notification User'. Select Configure Mobile Services cockpit and configure the role 'HanaMobileAdmin' for your user.

      Hope this helps.

      Regards,
      Ludo

      Author's profile photo rihab ouaslati
      rihab ouaslati

      Hello Ludo,

      Thank you for your quick response, i do have all the needed roles and did a retake to check,

      I don't get the unauthorized error anymore , however i do still get this error conserning the signing profiles:

      thank you,

       

      Author's profile photo Ludo Noens
      Ludo Noens
      Blog Post Author

      Hi Rihab,

      Can you check the network tab in Chrome DevTools (or other browser) for the GET /ApplicationSigningProfileSet response. Is the response empty?

      Regards,
      Ludo