1 2 3 28 Previous Next

SMP Developer Center

414 Posts

Make Sure Your Offline Works Right

 

Developing an offline mobile app is not always as straightforward as initially thought. During the various stages of app development there is sometimes a time to step back and take a close look into a system behaviour. Often we call this “debugging”. Debugging code is pretty well known for all the supported platform of the SAP Mobile Platform SDK – it is just code. But in an offline application you also want to check the data transferred to your device as well as the configuration you set on the server.

The SAP Mobile Platform SDK provides a simple command line tool, which is able to simulate an offline application, perform the initial sync, refresh and flush as well as the usual data operations like POST, PUT, MERGE and so on. With the help of this tool you can easily make sure that your OData service is performing correctly, that your server settings are correct and you can simulate client data modifications without using app code to do the same.

Wow, this sounds great, but where is this tool and how can I use it?

Once you have installed the SAP Mobile Platform SDK you can find it in

 

$ ~/SAP/MobileSDK3/Tools/bin

and it is called ilodata.

If you have installed the SDK into another path, you’ll need to search accordingly. Oh, and on Windows it called ilodata.exe.

On your Mac you would first make it an executable by typing:

 

$ chmod +x ./ilodata

For your convenience I’d recommend to create a symlink in /usr/local/bin by

 

$ sudo ln -s ~/SAP/MobileSDK3/Tools/bin/ilodata /usr/local/bin/ilodata

Now navigate your user’s directory and create a new folder or create the directory wherever you think would it would be appropriate. Here create an empty working directory and navigate into it and start ilodata:

 

 

$ mkdir offlinedebug

$ cd offlinedebug

$ ilodata

Oh what was that… I can’t read that fast. So let’s scroll up again and read the text together:

 

Interactive Local OData Tool Version 17.0.3.4520

USAGE:

   ilodata.exe -?|--help|[option=name [option=name ...]]

Interactive Local OData (ILOData) lets you execute OData queries against an UL database.If the database exists, ILOData will just use it. If not, it will do a refresh to create the database. To do a refresh, at least defining_request and serviceRoot must be set. If no defining requests are specified on the command line and no store exists, the user will be prompted to enter defining requests before ILOData opens the store.

Many of the options correspond to settings in the Offline Store Options.

Please see the Offline OData SDK API documentation for additional details

Ok, now we know that ilodata stands for Interactive OData. That sounds promising, but how to get started?

In order to use ilodata you need to provide exactly the same configuration parameter we use for creating an offline store (Don’t worry if you don’t know the parameters, we’ll come to them in a minute).

But the text above holds some valuable information. First, it explains how to add options to the command line by using the option=name syntax. Second, it tells us that it is using version 17 and this has a deeper meaning, that I’ll explain later. And finally it points us to the documentation and to make it more comfortable for you here’s the direct link to SAP Help

 

Don’t click it now, just stay with me a bit longer, please.

 

Before we can use ilodata we need to have a proper server setting in place – you may know that the offline capabilities are mainly managed by the server and therefore we can’t leave him behind. A minimal App setting in your HANA Cloud Platform mobile service for development and operations should suffice. So open the mobile service Admin Cockpit and create an app config with the name OfflineApp and point its primary connection to http://services.odata.org/V2/northwind/Northwind.svc/ and set Proxy Type to Internet. It does not matter if you have chosen a native or hybrid app in this case. Please choose None as the security configuration. (ilodata works with credential-based authentication as well as with certification based security, but for debugging purposes we can often turn off the security)

 

APPID

OfflineApp

                                                      Primary Back-end URL

http://services.odata.org/V2/northwind/Northwind.svc/

Proxy Type

Internet

Security Configuration

None

 

This is how your App overview screen should look like:

Picture1.png

Now that we have a server configuration we need to create an APPCID (Application Connection) for this app. We can do this with curl (you may want to use Postman for Google Chrome or use any other tool that can create HTTP request for you)

 

$ curl -X POST https://hcpms-{SCNUSER}trial.hanatrial.ondemand.com/odata/applications/v4/OfflineApp/Connections -d '{}' -c hcpmscookie.txt -v -H "Content-Type: application/json"

You need to substitute your SCN username into {SCNUSER} above.

Once you execute this, you’ll get a lot of xml back, but for now we can just ignore this and just have a look into the hcpmscookie.txt file:

 

$ cat hcpmscookie.txt

Copy the APPCID GUID value into another text file or keep in your clipboard. Of course, if you are really really smart, you just can just memorize it. We need it now.

 

In a typical debugging situation, you don’t need to do all the steps, you would probably already have an APPCID and an app configuration on mobile services for development and operations.

 

Now, let’s use ilodata:

 

$ ilodata service_root=OfflineApp host=hcpms-{SCNUSER}trial.hanatrial.ondemand.com store_name=products defining_request=Products port=443 enable_https=yes appcid={APPCID} enable_debug_logging=true

Uh, that’s not trivial. Let’s quickly discuss all the options:

 

First, service_root should point to the OData Service Document. It does by being the APPID we defined earlier.

The host is pretty straightforward, it’s the server URL. Please make sure you substitute {SCNUSER} with you SCN username.

The store_name will reference your local UltraLite database.

You can have more than one defining_request, just use the option defining_request again to have more than one. The parameter itself refers to an OData collection name, no slashes.

Port is the server port of the host, on HCP it’s always 443.

When the port is 443, you should set enable_https to yes as seen above. Appcid defines the registration id we just found in the hcpmscookie.txt, I’m pretty sure you remember.

The last option enable_debug_logging is set to true, it’s self-explanatory.

 

If you execute the command, you’ll see a lot of things going on (well, only if you are not behind a proxy – make sure you have “unproxied” internet access to use ilodata), but the last lines should look like this:

 

 

 

Perform the reapply ...

Commit the download ...

Refresh complete.

Store state: Open

 

ILOData >

 

That’s it. Now you have created an offline store which you can query and modify.

 

Try :

 

 

ILOData > get Products

ILOData > help

ILOData > exit


Not bad, but this is not the end of the story. In your directory you’ll find to .db files:

 

  1. products.rq.udb and products.udb. The first holds all modifications from CUD operations, which you can “flush” to the server, while the later holds all the “refresh” data – everything you read from the server. Of course you can copy your devices db files into the folder and check their content with ilodata (in case of encrypted stores you need to somehow know the secret key and pass it as store_key parameter).

 

 

I hope this tool will help you in times where you really need to dig into your data and get a better understanding of what’s going on under the hood.

 

Now, it’s time to check the help document.

 

Have Fun,

Martin

Unleash the Power of Mobile with Swift and the SAP Mobile Platform SDK

 

Attention: This is not an article about the announces SAP HANA Cloud Platform SDK for iOS, which is part of the Apple SAP partnership. This article refers to the already existing SAP Mobile Platform SDK that supports SAP Mobile Platform and SAP HANA Cloud Platform mobile service for development and operations (previously: SAP HANA Cloud Platform mobile services)

 

Using Apples new and modern programming language Swift can really improve developer efficiency. SAP has the SAP Mobile Platform SDK that let you consume SAP Mobile Platform or SAP HANA Cloud Platform mobile service for development and operations features, like on-boarding, push notifications, client log upload and of course it enables you to create heavy weight offline applications.

The next steps show you how you combine Apples powerful Swift language with the SAP Mobile Platform SDK and start a blank iOS project from scratch. It’s easier than you may think.

 

Prerequisites

 

Please make sure your system mets the following requirements:

 

Getting Started

Well, I don’t think that I need to explain much about how to install Xcode.

 

To install pod use this command on your Terminal

 

$ sudo gem install cocoapods

Try

 

$ pod --version

on your Terminal to validate your installation.

 

The SAP Mobile SDK is a download on https://www.sapstore.com/solutions/701697/SAP-Mobile-Platform

Unzip the downloaded file and

 

 

$ chmod +x installSDK.command

$ ./installSDK.command

I assume that you chose the default installation path ~/SAP/MobileSDK3.

In your Terminal navigate to your folder ~/SAP/MobileSDK3/NativeSDK.

There is a file called “NativeSDK.podspec”. This file describes the Native SDK as a dependency for cocoapod. We need to modify the file and append a bit more information. Open the file in your favorite text editor and add:

 

s.authors = ['Yourname']

s.homepage = "http://www.yourwebsite.com"

s.source = { :path => '~/SAP/MobileSDK3/NativeSDK/OdataFramework/*'}


just between the lines to the other attributes.

 

Save your file.

 

Now start XCode and create a new Swift project:

 

Picture1.png

Make sure you select Swift as a Language.

Well, now close the project. Serious, just close XCode.

 

In your Terminal navigate to your freshly create XCode project. Type

 

$ pod init

 

Now you will see a file called “Podfile”, without extension.

Open it in your favorite text editor and include the following line

 

$ pod 'NativeSDK', :path => "~/SAP/MobileSDK3/NativeSDK/"

 

before the closing “end” statement. Then just close the file.

This concludes the preparations, now to the last step.

Back in your project path, just type in your Terminal:

 

 

$ pod install

 

In your project folder the you’ll find now the file {Projectname}.xcworkspace. This is the file you will now open in Xcode and use whenever you want to work on your project.

 

Your project should now look like this:

Picture2.png

Your project – in my case it’s “OfflineSwiftSDK12” and it references “Pods” which holds all your NativeSDK files.

 

You may notice the file “OfflineSwiftSDK12-Bridging-Header.h”. This is a very important file since it defines the communication between Objective-C resources and Swift. Whenever you want to reference an object that is provided by the SAP Mobile SDK you need to specify the relevant header files. You need to create the file manually. Just go to “File” > “New” > “File…”, then choose “Header File”, name it: {PROJECTNAME}-Bridging-Header.h

This is how your bridging file could look like:

//

//  OfflineSwiftSDK12-Bridging-Header.h

//  OfflineSwiftSDK12

//

//  Created by Grasshoff, Martin on 08/06/16.

//  Copyright © 2016 Grasshoff, Martin. All rights reserved.

//

 

#ifndef OfflineSwiftSDK12_Bridging_Header_h

#define OfflineSwiftSDK12_Bridging_Header_h

 

#import "SODataOfflineStore.h"

#import "SODataOfflineStoreOptions.h"

#import "HttpConversationManager.h"

#import "UsernamePasswordProviderProtocol.h"

#import "CommonAuthenticationConfigurator.h"

 

#endif /* OfflineSwiftSDK12_Bridging_Header_h */

 

You don’t need to import all header files of the SDK, only the files which references the Objects you want to use in your code.

The last step is to tell your build that it should use the bridging header. Select your project in the project inspector, select your Target and finally select your “Build Settings”. Now scroll down in the list until you find the section “Swift Compiler Code Generation”, here point your Objective-c bridging header property to ${SRCROOT}/OfflineSwiftSDK12-Bridging-Header.h

 

That’s it, now you can build your app and all the NativeSDK is at your fingertips.

 

Next action item for you is to actually use the SDK.

I’m looking forward to see your Swift-based projects.

 

 

Have Fun,

Martin Grasshoff

Hi,

I’m running late this month, but this is because we are preparing great new things for mobile at the moment. Some we small appetizers we released with 1605

 

  • Cross-origin resource sharing
  • Username propagation to back-end systems
  • Reports based on client usage data
  • Sharing of SCIM destinations

 

Cross-origin Resource Sharing

This new feature let you set CORS headers via configuration. Available settings are:

Picture1.png


Read more about CORS here:
http://www.w3.org/TR/cors

 

Username propagation to back-end systems

 

This particular feature is one of my favorites this release. It’s a pretty simple thing, once select “Propagate User Name” it means that to each back-end request there will be a “X-SMP-ENDUSERNAME” header added, which contains the username, which was retrieved by the selected authentication channel (e.g. SAML).

And what is it good for? Well, your back-end system can now add this user information to apply additional filters on the data to retrieve. The client can’t manipulate this header and impersonate another user with a valid authorization.

For instance, I could send the following request:

 

GET /userprofiles/ABC

 

even though my own user is “XYZ”. The back-end know can make sure that a use XYZ is not allowed to call resources belonging to ABC.

And you would use this features whenever, for any reason, you do not propagate the actual user context to the back-end and use a technical user.

Picture2.png

Reports Based on Client Usage Data

 

With our SDK you can measure the usage of your app, until now we just provided you the information as raw data for further processing with SAP Lumira, or other tools.

With this release we also provide five different pre-defined reports:

Picture3.png

 

Once you upload your usage data to the service, you can just navigate to “Reporting” and select “Client Log Data”, then select the timeframe and report you want to see.

And here is an example:

Picture4.png

Sharing of SCIM destinations

 

Well, that’s simple. Rather than specifying a new Connection for each app-specific SCIM destination, you simply select one of the associated Connections you already have.

The workflow is simple. Just click “Override Global HCPms SCIM Configuration”, then select one of the connections you want to reuse for SCIM.

Typically, you would just re-use your OData Service Document already defined at the top of the screen – unless you have a helpful ping-service – so, click on “Save” first, then the list is populated.

Picture5.png

That’s it for now.

 

Have fun,

Martin Grasshoff

It is possible to start/stop SMP services via Task Scheduler. I followed this discussion to try this out. Wanted to share my findings on this:


Note:

  • This was done just to test how SMP start/stop services could be planned for a given schedule.
  • If you are using a custom database with SAP Mobile Platform, starting and stopping SAP Mobile Platform Server has no effect on the database. Only the

default SAP SQL Anywhere database is automatically stopped and started in sync with SAP Mobile Platform Server (Ref. help.sap.com)

 

Pre-requisite: 1. SMP runtime should be installed on your machine (or should have remote access to the system)

                       2. Local Administrator role

                       3. SMP services should not be running and their Startup Type should be set to manual. (CTRL+R->services.msc)

 

1.png

 

Steps:

 

1. open 'Task Scheduler' (OR CTRL+R ->taskschd.msc )

     2.png

 

2. Action->Create Basic Task

3.png

 

 

3. Since i just wanted to test how this would work, i triggered it with 'One time' option

6.PNG

 

4. Here, i had to give date-time to run this task (it may vary for the options selected in step# 3)

 

7.PNG

5. No more choice here, just select first option

24.PNG

 

6. Point to go-service.bat batch command SMP installation path)

 

26.PNG

7. Make sure to select checkbox

28.PNG

 

8. As you click on 'Finish', properties dialog box appears. Make sure to select 'Run with highest privileges' option

11.PNG

 

9. I could see command window appearing on my machine on the time as set during Step# 4 . It took a while to start SMP services.

 

 

30.PNG

 

Note: verify SMP Services again in services.msc

 

21.PNG

 

Note: There is a way to delete this schedule task, search your task under 'Active Tasks' list, double click on it ->Delete

(for modify schedule timing, look under Actions)

13.PNG

10. Same way, task can be created to STOP SMP services. Point to stop.bat file.

 

14.PNG

 

 

29.PNG

 

To confirm this, open services.msc->

 

23.PNG

 

 

 

Hope this helps.

 

Thanks Wayne Smith for your inputs.

 

Regards,

JK

Are you using SAML authentication flow in your SMP 3.0 application? Is that generated certificate self-signed one (by SMP itself) ? Did you already know its expiration date? Or has it already expired? And now, user can't be on-boarded on SMP.

 

(we had same situation. So hereby, i am sharing what all we did to get rid of it)

 

There are many blogs on how SAML Flow works and how to configure it. I am not going to explain it here.

 

In order SAML flow to work, initially, metadata file of Local service provider (here its SMP) needs to be shared with Identity provider team. You provide a LSP name, Base URL (e.g. https://server:port).

Next, what about values for signing key and signing certificate?

 

Option A: Either you can go with by just clicking on 'Generate key pair' option to get these values filled automatically (SMP does this work) Not recommended for productive environment

Option B: Generate these values from a Certificate Authority (recommended for productive environment)

LSP1.png

 

Option A:

 

In this case, from where SMP takes default inputs and generate self signed certificate?

 

To check this, Go to Settings > System > scroll down > SAML SERVICE PROVIDER CERTIFICATE GENERATOR SETTINGS

 

certificatesettings.PNG

Here you can see that, there are default values for the subject, certificate is valid only for 1 year

 

(you still not sure when that generated certificate is going to be expired, here is a quick way to check. Copy the 'Signing certificate' content in a notepad and save it as .cer , double click on certificate file)

 

We were told by IdP team that they are seeing error with the SMP LSP metadata file.

 

Unable to validate SAML2 Trusted Service Provider. The trusted relationship with this entity will not be functional!
Error Validating X509 Certificate of Trusted Provider
Trusted Provider Type: SAML2 Trusted Service Provider
Trusted Provider Id: SAMLTEST
Error Validating X509 Signing Certificate
X509 Certificate Version: 3
X509 Certificate Subject: C=DE L=Walldorf O=SAP SE
X509 Certificate Issuer: C=DE L=Walldorf O=SAP SE
X509 Certificate Serial Number: xxxxx
X509 Certificate Start Date: 2015-05-20 10:18:28
X509 Certificate Expiration Date: 2016-05-20 10:18:28

X509 Certificate Validation Root Exception: com.novell.nidp.NIDPException: Certification path could not be validated. Could not validate certificate: NotAfter: Fri May 20 10:18:28 CEST 2016 Root Cause: java.security.cert.CertPathBuilderException: Certification path could not be validated.

Then we figured out the issue (already highlighted above) that generated certificate had expired.

 

How to renew it?

 

  1. Increase number of years to 1 or 2 or as much as you want
  2. Save it
  3. Generate new keypair
  4. download new metadata file
  5. share it with IdP team

 

Note: Even you can provide your company specific subject also (we went with default parameters)

certificatesettings1.png

 

Before step#4, download new metadata file, you can validate above settings:

    • Copy signing  certificate content in a notepad
    • save it with .cer extension
    • double click on it and confirm

 

     cert.PNG

Here, everything looks fine and now you can share new metadata file with IdP team.

 

Option B: Talk to your CA team.

 

Hope this helps.

 

Thanks Andreas Wegmann for your inputs.

 

Regards,

JK

Hi,

In March we present the following additions to Mobile Services

 

  • New Name!
  • New push features
  • Custom push provider
  • HANA Cloud integration services integration
  • Custom URL rewrite rules
  • Removal of inactive users – save your licenses!

New Name

Going forward you will see HANA Cloud Platform mobile services to become the umbrella term for all mobile related services on SAP HANA Cloud Platform. Therefore, HCP mobile services needs to be renamed. The new official product name is

“SAP HANA Cloud Platform mobile service for development and operations”

while the consumer edition is called:

“SAP HANA Cloud Platform mobile service for development and operations, consumer edition”.

 

We will gradually roll out this name in the product and in the documentation, so please don't be surprised. This is how it looks like now in HCP Cockpit (HCPms is now "Development & Operations"-tile:

 

HCPms_NewName.png

 

New Push Features

All native notification venders improve their services all the time and so do we.

In this release we have included support for:

Google Notifications:

  • Resend Messages – allows to automatically resend messages under certain conditions when a message could not be delivered
  • Logging GCM error codes in the event log

Apple Push Notifications:

  • Support for title, title-loc-key and other additional attributes to better control notifications on iOS devices

WNS:

  • Custom payload handling for individual WNS notifications

 

Custom Push Provider

The custom push provider substitutes the HCP mobile services implementation for push services with custom coding.

While configuring your app definition, you can multi-select your custom push provider URL for each device platform. For example, you can define a custom push provider URL for Android. Once you do this, HCP mobile services disables the the Android specific configuration for Android notifications. All Android related push events will then be forwarded to your provided URL – which is typically an HCP provided java application that handles the push for you.

This feature is very suitable, when you want to substitute the native push provides of the device venders.

This is how it looks like:


Picture1.png


HANA Cloud Integration services integration

SAP HANA Cloud integration services integration – sounds funny and is an unlucky wording, but it describes best what has happened. Last month, our colleagues of HANA Cloud Integration services have released their new feature set to allow to transform non OData services into OData feeds. In order to consume those published OData services, we have built a small, but shiny integration to your HANA Cloud Integration content:

Picture2.png

Once you have done all your integration work and published your service, just click the “Add…” button and select your service from the list. Provide the necessary authentication information and you will be able to access your service from your mobile app.

 

Custom URL Rewrite Rules

With this version we allow you to provide your own custom http payload rewrite rules. Typically, we rewrite URLs that appear in an OData service to an HCPms URL. In a given OData feed, each URL would be rewritten from “http://services.odata.org/V2/northwind/Northwind.svc/Regions(1)” to

https://hcpms-dXXXXXXtrial.hanatrial.ondemand.com/PMAPP/Regions(1)</id>”. with the new custom URL rewrite rules, you can completely control the way URLs in the payload should be rewritten.

Just select “Custom Rewrite URL” as Rewrite Mode.

Picture3.png

Then click “Configure URLs” to manage your custom rules:

Picture4.png

 

You can even provide regular expressions and test them online:

 

Picture5.png

 

This is clearly for the advanced user.

 

Removal of Inactive Users

After a period of three months, unused APPCID (registered users) will be inactivated, saving user licenses. No more to say about this feature.

 

 

Have fun,

Martin Grasshoff

The contents of this tutorial were based on another blog post: „SAP OData SDK Android for absolute beginners – Part 1” written by Peter Csontos, available on the following link: http://scn.sap.com/community/developer-center/mobility-platform/blog/2015/11/11/sap-odata-sdk-android-for-absolute-beginners-part-1

 

My post will help you to learn about the following in the least advanced way possible:

     -SAP Mobile Platform SDK for iOS

     -How to use the OData API to create an online store

     -Using Cocoapods to install dependencies for your project

 

You can think of my tutorial as an environment kickstarter for the OData SDK on iOS. If you feel like learning about the use of OData SDK itself would be more appropriate, I highly recommend you to check out the posts of Kenichi Unnai who has already written a series of posts on that topic, suitable for both beginners and more advanced. You can start with the one below:

http://scn.sap.com/community/developer-center/mobility-platform/blog/2014/09/16/smp3-odata-sdk-for-ios--tips-tricks-01

 

 

After you have finished following my instructions in this tutorial, you will end up with a project similar to a „Hello World” for OData on iOS, if there was such a thing. In order to start, you only need basic knowledge of programming in Objective-C or Swift, using Xcode, RESTful web services and the OData protocol. You also need an Xcode installed on your Mac. If I managed to keep you interested, let's start!

 

 

Step 1: Install SAP Mobile Platform SDK for iOS

In case you don't have an SMP SDK already installed on your computer, this link will give you what you need to know: https://help.sap.com/smpsdk_re . The download and install process may provide you enough time to continue with the next two steps.

 

 

Step 2: Create a new iOS project in Xcode

Fortunately, you can choose between Swift and Objective-C languages for your project, because this tutorial covers both. Since Swift language is the future and the number of developers actively using it is highly growing, so despite its early problems it should be practiced in new projects as much as possible. Of course, you may need to (or want to) write your code in Objective-C. As a template, I used a single-view application for my project, but you can choose another for yours as you prefer. In the next steps I will refer to your project location as $PROJECTLOCATION, which by default  contains the project file with extension .xcodeproj.

 

 

Step 3: Disable App Transport Security

When building iOS apps using iOS 9 SDK, App Transport Security is enabled by default. ATS uses the TLSv1.2 protocol which converts all HTTP requests to HTTPS. Any attempts to connect to a server which does not support HTTPS protocol, or only supports TLS protocol older than v1.2 will fail. Since the reference services located at odata.org (and perhaps the service you want to use) only support HTTP, you have to disable ATS.

 

In the $PROJECTLOCATION/$PROJECTNAME folder an Info.plist file was automatically generated. Open it and add a new dictionary called "App Transport Security Settings" and create a new entry with key "Allow Arbitrary Loads" and value "YES". Here's a screenshot of how it should look:

 

Screen Shot 2016-03-24 at 11.30.12 AM.png

 

Please note: disabling ATS is not recommended in most cases, so if you only connect to servers capable of using HTTPS protocol, leave it enabled.

 

Step 4: Setup project dependencies

I used Cocoapods to configure dependencies, but in case you don't want to use Cocoapods or something didn't work out with my steps, you can find another and more detailed tutorial here: http://help.sap.com/saphelp_smp3010sdk/helpdata/en/49/cc45e254f4492393801fc17391602f/content.htm

 

Here is how to do it with Cocoapods:

  -Close your project.

  -If not present, install Cocoapods by using the "gem install cocoapods" command in Terminal. Use "sudo" if needed and also note: some firewalls won't let gem to download. If you encounter any problems, connect to another network and try again.

  -In your terminal navigate to the $PROJECTLOCATION directory (or the location of your project file with extension .xcodeproj if not present by your settings) and use command "pod init". This will create a Podfile which you could have created yourself, but this way it will contain a template instead of being empty.

  -Open that Podfile in a text editor and you should create a content equivalent to the snippet below, or you can just copy-paste it. Note that $SMPSDKLOCATION is the path to your installation folder of the SAP Mobile Platform SDK and $PROJECTNAME is your project name which you should overwrite according to your environment.

 

##################################

platform :ios, "8.0"

target "$PROJECTNAME" do

inhibit_all_warnings!

pod 'NativeSDK/ODataOnline', :path => "$SMPSDKLOCATION/SAP/MobileSDK3/NativeSDK"

pod 'NativeSDK/ODataAPI', :path => "$SMPSDKLOCATION/SAP/MobileSDK3/NativeSDK"

end

##################################

 

 

  -Save the Podfile, run "pod setup" from Terminal.

  -If it succeeded, run "pod install"

 

If you encountered network related problems while executing the commands above, connect to another network and try again. If both have succeeded, the new file with the .xcworkspace extension is now your working area instead of the .xcodeproj file.

 

 

Step 5: Write your code

Now we only need some code to try if the OData SDK is working as intended. Open the .xcworkspace you have just created with Cocoapods. I suggest you to create a new file for the tester class and use a button to allocate and execute the test. In my example I pasted the code into the view controller class, which should always be avoided, but it helps to simplify my code snippet here. So let's start!

 

 

A: The Swift way

The SMP SDK for iOS was written in Objective-C which means you have to create a bridging header to import the files you need. If you are unsure how to do so, you can follow the official Apple tutorial.

Now import these headers in your new bridging header:

 

#import "SODataRequestParamSingleDefault.h"

#import "SODataResponseSingleDefault.h"

#import "SOData.h"

#import "SODataEntitySetDefault.h"

#import "SODataEntityDefault.h"

#import "SODataPropertyDefault.h"

#import "SODataOnlineStore.h"

 

 

Open the Swift file you want your OData online store to run from. For me it was ViewController.swift, but you should create your own empty class. Now start with the following definition:

 

var store : SODataOnlineStore!

 

 

Thanks to this first line, we can make sure both the pods and the bridging header were set up correctly. Jump to the definition of SODataOnlineStore (command-click by default). If you only see a big question mark, something went wrong. If it works, you can follow it with an optional UITextView object referenced from your storyboard and a String as its buffer. We will use them to inform ourselves on the screen if we managed to open the online store and it also displays the first entity to confirm our success in a more satisfying way. Error messages will also appear here if there were any. However, you can use NSLog for this purpose if you want to, but an UITextView object is easy to implement while being more elegant, plus you can drop your NSError right into it. So here go my two lines:

 

@IBOutlet var logDisplay: UITextView!

var log : String = ""


 

Our first method which opens the OData online store, needs a HttpConversationManager object in order to manage data traffic via the internet, since OData transfers data via HTTP or HTTPS as you may already know. Thanks to this manager, we don't have to worry about the details of these protocols after initializing it. Authentication is also not needed, since we will use a public reference service provided by odata.org. If you need to add authentication for services with such requirement, I suggest you to check out Kenichi Unnai's tutorials mentioned at the beginning of this post. The initialization of HttpConversationManager is as simple as this:

 

func openStore() {

     let manager = HttpConversationManager()


 

You need to specify the URL where the service is located. We will use one of the OData V4 reference services located at odata.org, but you will find other available services there, if you need to test your program with different, more advanced OData properties.

 

let url = NSURL(string: "http://services.odata.org/V4/OData/(S(readwrite))/OData.svc/")


 

Now we can initialize the online store with all its settings:

 

store = SODataOnlineStore(URL: url, httpConversationManager: manager)

 

 

The online store is initialized, it is ready to be opened. We will invoke the completion block version of the openStore method:

 

store.openStore { (store, error) -> Void in


 

Now that it's finished and we are in the completion block, we can invoke the method containing our first request in it. But before doing so, I suggest we  check if there was any error, and inform the user about it:

 

    if(error == nil){

        self.testREAD()

    } else {

        self.log = "FAILED TO OPEN STORE. ERROR: " + String(error)

        self.logDisplay.text = self.log

    }

}

}

 

 

At this point our online store is open, if there was no issue with connecting to the OData service. Let's implement the new testREAD method invoked in the code snippet above with a READ request in it.

 

func testREAD(){

 

Before executing the READ request, we have two essential arguments to set: the type of the request (READ, CREATE, etc.)  and the path of the resource we want access to:

 

let requestParam = SODataRequestParamSingleDefault(mode: SODataRequestModeRead, resourcePath: "Suppliers")


 

Thanks to the convenient interface, we only needed this line above to perform necessary initialization before actually making the request:

 

store.scheduleRequest(requestParam, completion: { (requestExecution, error) -> Void in


 

As you noticed, we use a completion block again to confirm the success of our request. Now we expect not only an error, but also a response with a payload which may or may not contain an entity set. But if an error has occurred, we may not even have a response or a payload. We should be cautious about these cases and everything should be checked in the right order. Thanks to the Swift language, setting the entity set and checking it's only one line:

 

if(error == nil){

    let responseSingle = requestExecution.response as! SODataResponseSingle

    if let entitySet = responseSingle.payload as? SODataEntitySet{

 

 

If both if-s evaluated to true, everything must be in order. But we like to see some result, so let's display what our entity set contains! The "Address" property is complex type, which needs some extra work to display properly:

 

self.log += "\nREAD SUCCEEDED.\n\nFirst entity in entityset \"Suppliers\":"

let readEntity = entitySet.entities[0] as! SODataEntityDefault

var readProperty = readEntity.properties["ID"] as! SODataPropertyDefault

self.log += "\n" + String(readProperty.name) + ": " + String(readProperty.value)

readProperty = readEntity.properties["Name"] as! SODataPropertyDefault

self.log += "\n" + String(readProperty.name) + ": " + String(readProperty.value)

readProperty = readEntity.properties["Concurrency"] as! SODataPropertyDefault

self.log += "\n" + String(readProperty.name) + ": " + String(readProperty.value)

readProperty = readEntity.properties["Address"] as! SODataPropertyDefault

self.log += "\n" + String(readProperty.name) + ": {"

let complexProperty = readProperty.value as! NSDictionary

for ( key, innerProperty ) in complexProperty {

     if let propertyValue = (innerProperty as? SODataProperty)?.value {

          self.log += "\n\t" + String(key) + ": " + String(propertyValue)}

     }

self.log += "\n}"

}

 

The buffer is now ready to be sent to display, but remember that we still have else branches left to implement for both if-s: in the inner else payload is not an entity set, in the outer one error is not nil.

 

  } else {

                    self.log = "\nERROR IN READ: RESPONSE NOT AN ENTITY SET"

                }

        } else {

            self.log = "\n\nERROR IN READ: " + String(error)

        }

        self.logDisplay.text = self.log

    } )//Completion block ends here

}//testREAD ends here

 

Finally, make sure to invoke the openStore method to start your test. I created a button and sent an action:

@IBAction func buttonPressed() {

    self.openStore()

}

 

That's all we needed to do to test the minimal OData online store. To make copy-pasting easier for you, here are the imports, declarations and the two methods without the need of formatting:

 

For your bridging header:

#import "SODataRequestParamSingleDefault.h"

#import "SODataResponseSingleDefault.h"

#import "SOData.h"

#import "SODataEntitySetDefault.h"

#import "SODataEntityDefault.h"

#import "SODataPropertyDefault.h"

#import "SODataOnlineStore.h"

 

 

For your new class or view controller:

var store : SODataOnlineStore!

@IBOutlet var logDisplay: UITextView!

var log : String = ""

 

func openStore(){

    let manager = HttpConversationManager()

    let url = NSURL(string: "http://services.odata.org/V4/OData/(S(readwrite))/OData.svc/")

    store = SODataOnlineStore(URL: url, httpConversationManager: manager)

    store.openStore { (store, error) -> Void in

        if(error == nil){

            self.testREAD()

        } else {

            self.log = "FAILED TO OPEN STORE. ERROR: " + String(error)

            self.logDisplay.text = self.log

        }

    }

}

 

func testREAD() {

    let requestParam = SODataRequestParamSingleDefault(mode: SODataRequestModeRead, resourcePath: "Suppliers")

    store.scheduleRequest(requestParam, completion: { (requestExecution, error) -> Void in

    if(error == nil) {

        let responseSingle = requestExecution.response as! SODataResponseSingle

        if let entitySet = responseSingle.payload as? SODataEntitySet {

            self.log += "\nREAD SUCCEEDED.\n\nFirst entity in entityset \"Suppliers\":"

            let readEntity = entitySet.entities[0] as! SODataEntityDefault

            var readProperty = readEntity.properties["ID"] as! SODataPropertyDefault

            self.log += "\n" + String(readProperty.name) + ": " + String(readProperty.value)

            readProperty = readEntity.properties["Name"] as! SODataPropertyDefault

            self.log += "\n" + String(readProperty.name) + ": " + String(readProperty.value)

            readProperty = readEntity.properties["Concurrency"] as! SODataPropertyDefault

            self.log += "\n" + String(readProperty.name) + ": " + String(readProperty.value)

            readProperty = readEntity.properties["Address"] as! SODataPropertyDefault

            self.log += "\n" + String(readProperty.name) + ": {"

            let complexProperty = readProperty.value as! NSDictionary

            for ( key, innerProperty ) in complexProperty {

                if let propertyValue = (innerProperty as? SODataProperty)?.value {

                    self.log += "\n\t" + String(key) + ": " + String(propertyValue)

                }

            }

            self.log += "\n}"

        } else {

            self.log = "\nERROR IN READ: RESPONSE NOT AN ENTITY SET"

        }

    } else {

        self.log = "\n\nERROR IN READ: " + String(error)

    }

        self.logDisplay.text = self.log

    } )//Completion block ends here

}//testREAD ends here

 

 

B: The Objective-C way

Open the Objective-C file you want your OData online store to run from (for me it was ViewController.m, but you should create your own empty class).

First you need to import several headers:

 

#import "SODataRequestParamSingleDefault.h"

#import "SODataResponseSingleDefault.h"

#import "SOData.h"

#import "SODataEntitySetDefault.h"

#import "SODataEntityDefault.h"

#import "SODataPropertyDefault.h"

#import "SODataOnlineStore.h"

 

 

We will also need the following properties:

 

@property (nonatomic, strong) SODataOnlineStore* store; //Online store as an object

@property (nonatomic, strong) id<SODataEntitySet> entitySet; //We will check the data we acquired by the READ request

@property (nonatomic, strong) NSMutableString *log; //We will append log messages to this object

@property (nonatomic, strong) IBOutlet UITextView *logDisplay; //Display the log (occasional refresh needed)

 

 

The UITextView object above is optional: we use it to inform us on the screen if we managed to open the online store. It also displays the first entity to confirm the success in a more satisfying way. Error messages will also appear here if there were any. However, you can use NSLog for this purpose if you want to, but an UITextView object is easy to implement while being more elegant, plus you can drop your NSError right into it. I also @synthesize-d all properties for a more pleasant code.

With the headers imported and the declarations in place, let's start implementing the first method which opens the OData online store:

 

- (void)openStore{

 

 

We need to init our log, because the first place to be accessed from is uncertain.

 

log = [[NSMutableString alloc] init];


 

Now we will use HttpConversationManager in order to manage data traffic via the internet, since OData transfers data via HTTP or HTTPS as you may already know. Thanks to this manager, we don't have to worry about the details of these protocols after initializing it. Authentication is also not needed, since we will use a public reference service provided by odata.org. If you need to add authentication for services with requirement such this, I suggest you to check out Kenichi Unnai's tutorials mentioned at the beginning of this post. The initialization of HttpConversationManager is simple as this:

 

HttpConversationManager* manager = [[HttpConversationManager alloc] init];


 

You need to specify the URL where the service is located. We will use the V4 reference service located at odata.org, but you can find several other reference services there, if you need to test your program with different, more advanced OData properties.

 

NSURL* url = [NSURL URLWithString:@"http://services.odata.org/V4/OData/(S(readwrite))/OData.svc/"];


 

Now we can initialize the online store with all its settings:

 

store = [[SODataOnlineStore alloc] initWithURL:url httpConversationManager:manager];


 

The online store is initialized, it is ready to open. We will invoke the completion block version of the openStore method:

 

[store openStore:^(id<SODataStoreAsync> store, NSError *error) {

 

 

Now that it's finished and we are in the completion block, we can invoke the method containing our first request in it. But before doing so I suggest we should check if there was any error and inform the user about it:

 

if(!error) {

  [self testREAD];

} else {

  [log appendString:[NSString stringWithFormat: @"\nFAILED TO OPEN STORE: %@",(id)error]];

  logDisplay.text = log;

}

}];

}

 

 

At this point our online store is open, if there was no issue with connecting to the OData service. Let's implement the testREAD method invoked in the code snippet above with a READ request in it:

 

- (void)testREAD {

 

Before executing the READ request, we have two essential arguments to set: the type of the request (READ, CREATE, etc.)  and the path of the resource we want access to:

 

SODataRequestParamSingleDefault *requestParam = [[SODataRequestParamSingleDefault alloc] initWithMode:SODataRequestModeRead resourcePath:@"Suppliers"];

 

Thanks to the convenient interface, we only needed this line above to initialize every essential data to actually make the request:

 

[store scheduleRequest:requestParam completion:^(id<SODataRequestExecution> requestExecution, NSError *error) {

 

 

As you noticed, we use a completion block again to confirm the success of our request. Now we expect not only an error, but also a response with a payload which may or may not contain an entity set. But if an error has occurred, we may not even have a response or a payload. We should be cautious about these cases and everything should be checked in the right order.

 

if(!error){

        id<SODataResponseSingle> responseSingle = (id<SODataResponseSingle>)requestExecution.response;

        if ([responseSingle.payload conformsToProtocol:@protocol(SODataEntitySet)]){

 

 

If both if-s evaluated to true, everything must be in order. But we like to see some result, so let's display what that entity set contains! The payload contains the entity set and we only want to see the first object in it. Here we can also inform ourselves about the success of the READ request, but for now we only need it in our buffer:

 

[log appendString:@"\nREAD SUCCEEDED.\nFirst entity in entity set \"Suppliers\":"];

entitySet = (id)responseSingle.payload;

SODataEntityDefault* readEntity = (SODataEntityDefault *)entitySet.entities[0];

 

 

Now the properties of our entity are ready to be displayed. The "Address" property is complex type, which needs some extra work to display properly:

 

SODataPropertyDefault* readProperty = (id)readEntity.properties[@"ID"];

[log appendString:[NSString stringWithFormat: @"\n%@: %@", readProperty.name, readProperty.value]];

readProperty = (id)readEntity.properties[@"Name"];

[log appendString:[NSString stringWithFormat: @"\n%@: %@", readProperty.name, readProperty.value]];

readProperty = (id)readEntity.properties[@"Concurrency"];

[log appendString:[NSString stringWithFormat: @"\n%@: %@", readProperty.name, readProperty.value]];

readProperty = (id)readEntity.properties[@"Address"];

[log appendString:[NSString stringWithFormat: @"\n%@: {", readProperty.name]];

NSDictionary *complexProperty = (id)[readProperty value];

[complexProperty enumerateKeysAndObjectsUsingBlock:^(id key, id innerProperty, BOOL *stop) {

       [log appendString:[NSString stringWithFormat: @"\n\t%@: %@", key, [[(id<SODataProperty>)innerProperty value] description]]];

}];

[log appendString:@"\n}"];

 

The buffer is now ready to be sent to display, but remember that we still have else branches left to implement for both if-s: in the inner else payload is not an entity set, in the outer one error is not nil.

 

        } else {

                [log appendString:@"\nERROR IN READ: RESPONSE NOT AN ENTITY SET"];

        }

} else {

            [log appendString:[NSString stringWithFormat: @"\nERROR IN READ: %@",(id)error]];

}

logDisplay.text = log;

}];//Completion block ends here

}//Method testREAD ends here

 

 

Finally, make sure to invoke the openStore method to start your test. I created a button and sent an action:

- (IBAction)buttonPressed{

    [self openStore];

}

 

That's all we needed to do to test the minimal OData online store. To make copy-pasting easier for you, here are the imports, declarations and the two methods:

 

#import "SODataRequestParamSingleDefault.h"

#import "SODataResponseSingleDefault.h"

#import "SOData.h"

#import "SODataEntitySetDefault.h"

#import "SODataEntityDefault.h"

#import "SODataPropertyDefault.h"

#import "SODataOnlineStore.h"

 

@property (nonatomic, strong) SODataOnlineStore* store; //Online store

@property (nonatomic, strong) id<SODataEntitySet> entitySet; //We will check the data we acquired with the response

@property (nonatomic, strong) NSMutableString *log; //We will append log messages to this object

@property (nonatomic, strong) IBOutlet UITextView *logDisplay; //Display the log (occasional refresh needed)

 

@synthesize store;

@synthesize entitySet;

@synthesize log;

@synthesize logDisplay;

 

- (void)openStore{

    log = [[NSMutableString alloc] init];

    HttpConversationManager* manager = [[HttpConversationManager alloc] init];

    NSURL* url = [NSURL URLWithString:@"http://services.odata.org/V4/OData/(S(readwrite))/OData.svc/"];

    store = [[SODataOnlineStore alloc] initWithURL:url httpConversationManager:manager];

    [store openStore:^(id<SODataStoreAsync> store, NSError *error) {

        if(!error) {

            [self testRead];

        } else {

            [log appendString:[NSString stringWithFormat: @"\nFAILED TO OPEN STORE: %@",(id)error]];

            logDisplay.text = log;

        }

    }];

}

 

- (void)testRead {

    SODataRequestParamSingleDefault *requestParam = [[SODataRequestParamSingleDefault alloc] initWithMode:SODataRequestModeRead resourcePath:@"Suppliers"];

    [store scheduleRequest:requestParam completion:^(id<SODataRequestExecution> requestExecution, NSError *error) {

        if(!error){

            id<SODataResponseSingle> responseSingle = (id<SODataResponseSingle>)requestExecution.response;

            if ([responseSingle.payload conformsToProtocol:@protocol(SODataEntitySet)]){

                entitySet = (id)responseSingle.payload;

                [log appendString:@"\nREAD SUCCEEDED.\nFirst entity in entity set \"Suppliers\":"];

                SODataEntityDefault* readEntity = (id)entitySet.entities[0];

                SODataPropertyDefault* readProperty = (id)readEntity.properties[@"ID"];

                [log appendString:[NSString stringWithFormat: @"\n%@: %@", readProperty.name, readProperty.value]];

                readProperty = (id)readEntity.properties[@"Name"];

                [log appendString:[NSString stringWithFormat: @"\n%@: %@", readProperty.name, readProperty.value]];

                readProperty = (id)readEntity.properties[@"Concurrency"];

                [log appendString:[NSString stringWithFormat: @"\n%@: %@", readProperty.name, readProperty.value]];

                readProperty = (id)readEntity.properties[@"Address"];

                [log appendString:[NSString stringWithFormat: @"\n%@: {", readProperty.name]];

                NSDictionary *complexProperty = (id)[readProperty value];

                [complexProperty enumerateKeysAndObjectsUsingBlock:^(id key, id innerProperty, BOOL *stop) {

                    [log appendString:[NSString stringWithFormat: @"\n\t%@: %@", key, [[(id<SODataProperty>)innerProperty value] description]]];

                }];

                [log appendString:@"\n}"];

            } else {

                [log appendString:@"\nERROR IN READ: RESPONSE NOT AN ENTITY SET"];

            }

        } else {

            [log appendString:[NSString stringWithFormat: @"\nERROR IN READ: %@",(id)error]];

        }

        logDisplay.text = log;

    }];//Completion block ends here

}//testREAD ends here

 

 

Step 6: Run your code

 

If you managed to build your project successfully and run it, you should see something like this:

 

Simulator Screen Shot Apr 26, 2016, 2.10.07 PM.png

 

If something didn't work, make sure you have connected to a network with your device or emulator and make sure the firewall on your network lets the service through. Either you have questions about this tutorial, or you have valuable additional information or corrections, feel free to share your thoughts in the comment section below. Thank you!

Hello SMP Developers, Administrators

 

I would like to share my experience on current requirement for my project. There was already one OData native application available on SMP (with offline functionality).

Previous requirement: one offline application (with its ini file imported in Admin cockpit) connecting to one back-end URL. Things were fine.


New requirement: For next release of this mobile app, there should be a new backend URL but old one should also be there in the same app configration. It sounded like accessing more than one OData services in one application

 

So where was the problem?

 

You might have noticed that to make your app to work in offline mode, you have to import its .ini file that has information like how OData producer should be processed by mobile platform and store the offline data, offline DB pre-population, client index, defining requests and so on.

Our first impression was, if there are 2 back-end URLs, there would be 2 .ini files to be imported. But when we try to import second file (one ini file was already there containing info regarding first back-end url) , status of first ini file changes to 'No Custom Settings'

 

1.jpg

 

Then, we realized and concluded that information from both files should be combined into a single one and that the one should be imported. Now for both connection names' status is showing 'Configured'

 

2.png

 

Tips:

 

1. Sequence in.ini file should be:

     [endpoint]  <<could be either backend connection name>>

     [defining request]

     [defining request]

     .

     .

     .

     .

      [endpoint]

     [defining request]

     [defining request]

     .

     .

     .

 

2. name=com.test.test

     name=com.secondary.endpoint

     should be the same names as connection names for backend URLs (already explained here)

3. Before importing the new .ini file, make sure you have back-up file for old ini.

4. To retrieving data from 1st back-end URL,

  • On-board user on SMP
  • GET call: http(s)://smp:port/com.test.test 

 

5. To retrieving data from 2nd back-end URL,

  • On-board user on SMP
  • GET call: http(s)://smp:port/com.secondary.endpoint

 

Regards,

Jitendra

OData Provisioning feature in HANA Cloud Integration (HCI) converts non OData protocols to OData, hence HCPMS applications can consume it. This feature is similar to what Integration Gateway do in SMP 3.

 

2016-04-15_14-08-17.jpg

 

In this blog I am explaining how to create HCPMS mobile app using OData service I created from an existing SOAP service as mentioned in my blog.

Business Scenario

Data from backend is exposed as SOAP service. It is possible to define backend of HCPMS application with SOAP service, but the application will not get all the benefits of HCPMS, ex. Offline.

So, to create a mobile app with all features of HCPMS, SOAP has to be converted into OData. To convert SOAP to OData we need to use HCI.

 

Step to Step Procedure

As mentioned in this blog OData service was created, it will be used as backend in HCPMS application.

The following steps will guide you through creating an HCPMS application, and testing it on a simulator.

 

Web IDE is used to create the hybrid app.

 

Configure app on HCPMS

  • Logon to HCPMS cockpit. Click on Applications tile.

      2016-04-17_20-25-32.jpg

  • Press the + icon to create a new application.

      2016-04-17_21-59-04.jpg

  • In the create application screen enter below details. Click Save. Note: Security configuration as Basic means it require Basic Authentication.

      2016-04-17_22-13-57.jpg

  • Click on Configure. Then click on Backend.

      2016-04-17_22-22-12.jpg

  • Fill in the details as given below. Then click Save to complete your configuration.

     2016-04-17_22-24-28.jpg2016-04-17_22-31-51.jpg

Create Mobile App using Web IDE

  • Logon to SAP Web IDE select Local root and open the context menu by right clicking.
  • Choose New > Project from Template to open the new project creation wizard.

      Untitled.png

  • On Template Selection page click on SAPUI5 Master Detail Kapsel Application. Click Next.

      2016-04-17_22-46-40.jpg

  • Enter a name for your project and click Next.

      2016-04-17_22-49-11.jpg

  • Next, choose the backend and provide details to complete the base URL as given below. Click  “Load Service Metadata” button, it will list the OData collections of the OData service. Click Next.

      2016-04-17_22-51-14.jpg

  • Note: I have configured a destination with the details of my HCI system as given below. This backend was used in the above step.

     2016-04-17_23-19-16.jpg

  • Fill out the Project Namespace, Master Section, Master Data Fields and Detail Section as displayed in the screenshot.

     2016-04-18_11-45-49.jpg2016-04-18_12-50-12.jpg

  • Click Next.
  • Click Finish to create the project.

      2016-04-18_12-54-53.jpg

  • To run this app as a hybrid app, right click on the project > Project Settings.

      2016-04-18_12-58-27.jpg

  • Under Device Configuration provide below details. Click Save. Note: I am going to test this app on iOS simulator hence chose iOS as the mobile platform. Logon plugin is used to login to HCPMS from the app.

     2016-04-18_13-03-51.jpg      2016-04-18_13-10-33.jpg

  • Finally, to test the app on a simulator right click on the project > Run > Run On > iOS Simulator. Note: To use this feature you need HAT configured.

     2016-04-18_13-13-20.jpg

  • The application will be installed on the iOS simulator. Backend credentials has to be provided to login to the app. Note: In the background Web IDE is creating a cordova project with the plugins and platforms we chose during device configuration.

      2016-04-18_13-21-57.jpg2016-04-18_13-22-36.jpg

CC:

SAP for Mobile

 

Regards, Midhun

SAP Technology RIG

Hi,

This time we have put the following features into the release:

 

  • OAuth Authentication for Back-end Connections
  • Flagging of Account Types
  • Enhanced User Registration Data
  • Application List Enhancements
  • Canonical ID support for Google Push Notifications
  • Mobile Services Preview

 

OAuth Authentication for Back-end Connections

 

By allowing OAuth authentication for back-end connections we allow for more secure connectivity towards other cloud services like SAP Jam or SAP Cloud4Customers.

Picture1.pngNow it is no longer necessary to use HTTP Basic authentication as a fallback to create integrated mobile applications. Here is how the OAuth configuration for back-end connections looks like:

 

Picture2.png

Flagging of Account Types

 

With this release we introduced the option to qualify your account as a being used for production or other purposes. This has two effects. First, when you work with multiple accounts, you now have a better visibility for what the current account is being used to. In addition, HCP mobile services DevOps team can better allocate necessary resources to your account if marked “production”.

 

Please be aware that flagging an account as “production” is a non-reversible action.

 

In the settings section, you can now find a new tile labeled “Account Type”. Here you can specify a tag to identify the purpose of your account.

Picture3.png

You can specify either “production” or “non-production” and provide a description. Possible options where e.g. “HR development” or “q-landscape”. Basically, the description is free text that should make sense to you.

 

Picture4.png

 

Once you have saved your changes, you can see the account information whenever you click on your user profile icon in the upper right corner of the Administration Cockpit:

 

Picture5.png

Enhanced User Registration Data

With this HCP mobile services 1603 we introduced a new version of our registration API.

Under

 

https://{host}/odata/applications/v4/{APPID}/Connections

 

you can now put additional attributes into the user registration context of your user’s device.

 

We added the following values:

 

Property

Description

UserLocale

users preferred language

TimeZone

users time zone

LastKnownLocation

geolocation

CreatedAt

registration time

PushGroup

custom value

Email

users email address

 

So if you create a user registration using the REST API (see Documentation)  you can easily add these attributes:

 

POST https://{HOST}/odata/applications/v4/{APPID}/Connections

Content-Type : application/json

Authorization : Basic XYZ

 

{

"DeviceType":"Windows"

}

 

 

<content type="application/xml">

      <m:properties>

     ….

<d:ApplicationConnectionId>172038f3-ccc7-4b75-830f-5ef399ee7afd</d:ApplicationConnectionId>

         <d:UserName m:null="true" />

         <d:UserLocale m:null="true" />

         <d:TimeZone m:null="true" />

         <d:LastKnownLocation m:null="true" />

         <d:CreatedAt m:type="Edm.DateTime">2016-03-18T07:42:13.166</d:CreatedAt>

         <d:PushGroup m:null="true" />

         <d:Email m:null="true" />

      </m:properties>

   </content>

 

While the application runs, you can now update the properties to update the values whenever you want.

 

POST https://{HOST}/odata/applications/v4/{APPID}/Connections(‘{APPCID}’)

X-HTTP-METHOD:MERGE

Content-Type:application/js

 

 

{

"UserLocale":"de_DE",

"PushGroup":"News",

"LastKnownLocation":"49.2936957,8.6394329",

"Email":"noone@email.com"

}

 

Canonical IDs

 

If a bug in the client app triggers multiple registrations for the same device, it can be hard to reconcile state and the client app might end up with duplicate messages.

Implementing canonical IDs can help you more easily recover from these situations. A canonical registration ID is the registration token of the last registration requested by the client app . This is the ID that the server should use when sending messages to the device.

If you try to send a message using an old registration token, GCM will process the request as usual, but it will include the canonical ID in the registration_id field of the response. Make sure to replace the registration token stored in your server with this canonical ID, as eventually the old registration token will stop working.

 

Mobile Services Preview

 

Silently we have released the option for customers (and not for trial) to subscribe a preview landscape in the HCP Cockpit (upon request).

This subscription behaves exactly like the productive version of HCP mobile services, but it runs one version ahead. The idea is, that customers can create automated regression test against this landscape and in addition developers can check how a new feature behaves. This landscape or better: additional subscription is much less resources than a productive landscape assigned and therefore it is not meant to be used for any other purposes.

 

Picture6.png

 

This is an illustration about how the Preview works from a timing perspective:

 

Picture7.png

 

Hope you will enjoy the new features. Let us know what you think about the new stuff.

 

Have Fun,

Martin

In this article, we will see how one can develop a hybrid mobile application in WebIDE using HAT and then register it with HCPMS .

 

Please note that there are certain prerequisites that need to be fulfilled before we try to create Hybrid Mobile app .These have been mentioned very nicely here -

https://open.sap.com/courses/mobile2/items/09VyUvkiTYy78ePyRLqDBp

 

 

Step 1 - Creation of Hybrid Mobile App on WebIDE



Ceate.jpg

 

Step 2 - Device Settings

 

Right Click on the project name and select Project Settings . Then select device settings to configure device properties.

Provide App Name , App ID , Description and Version . Make a note of the App ID as this will be used later in HCPMS .

Under Build Options , select Debug Mode for our purpose .

Under Platforms , select your desired platform(s) on which you intend to deploy the app .

Under Plugins , go to Kapsel Plugins and select Logon Manager . If this is not selected , the device will not register on HCPMS as this plugin contains the required code for registration .

Now save and close .


Step 3 - App Configuration on HCPMS


Open the HCPMS service from your HANA Platform cockpit . Go to Applications and Click on Create. You will see a screen similar to what is shown below -


HCPMS1.jpg

Fill in the values as above . The Application ID should be the same as the one that was entered in step 2 . Security Configuration can be set to None . After saving , the application can be seen in the list . Click the settings icon against the application and click on the Back End tab . Set the configuration as shown below . Please note that I have used Northwind for oData and hence mentioned it here against Back-End URL . You can enter your applicable back end URL here .



HCPMS2.jpg


 

Step 4 - Deploying the app to Device/Emulator

 

In the WebIDE , right click on the name of the application , click on Run -> Run On -> Device/Emulator

 

HCPMS3.jpg

 

The Hybrid App would now be created and deployed on your Device/Emulator . This generally takes around 5 -7 minutes for me and could take the same time for you as well .

 

Step 5 - Opening the app on the device

 

You will see the following once the app deploys on your device/emulator

 

Dev1.jpg

 

Once you have filled in the user name and password , click on register to see the following screen .Screenshot_20160323-211527.png

I decided to disable the passcode and then clicked on Submit to be taken to my app .Dev3.jpg


At this point of time , the Kapsel Logon plugin would have run and the device would have registered itself on HCPMS . We can see the device entry by clicking on Registration and Users in HCPMS . You might have to adjust the date filters to see all devices .


HCPMS4.jpg

I recently started working on an HCPms / Kapsel project that makes use of the Offline OData plugin. While working on the project we thought it would be useful to have the ability to open the local offline database and examine the data in it. In the following, I will share how to do just that.

 

The following steps are involved:

  1. Installing SAP SQL Anywhere 17 / SQL Central
  2. Locating the database files
  3. Opening the database files in SQL Central
  4. Viewing the content of a table

 

Installing SAP SQL Anywhere 17 / SQL Central

The first step is to install SAP SQL Anywhere 17 available from here: https://go.sap.com/cmp/syb/crm-xu15-int-sqldevft/index.html. This installation includes the database administration tool SQL Central. SQL Central will connect to UltraLite databases – the format used by the Offline plugin.

 

Note: For me using Gmail, the e-mail with the download link ended up in “Promotions”

 

I won’t cover the installation process here in details, since it is more or less next, next, next. However, I will say that during installation I tried to limit what was installed to only what I needed. I select the “Database Client” for both 32 and 64 bit as well as the Database Administration tool. Everything else (including the Database Server components) I opted not to install.

 

Locating the database files

Once installation is completed, the next step is to obtain the actual database file(s). The Offline plugin splits data into two separate databases. One database for the actual offline entity data cache where you will find tables for each entity set and one database for the request queue where you will find request waiting to be send to the server as well as the table containing the error archive.

 

The location of the files will obviously differ from platform to platform. I initially tried this on Windows 8.1. I tested the application by opening the project directly in Visual Studio and a least in that case you will find the files here: “C:\Users\<username>\AppData\Local\Packages\<app id + identifier>\LocalState”.

The database files will be named after the name you supplied when opening the offline store (calling store.open() in javascript in our case). The files will be named as follows:

 

  • Offline entity database: <store name>.udb
  • Request queue: <store name>.rq.udb

 

On iOS, as far as I remember, you will find the files in the Documents directory. If you are running on the simulator this directory can be accessed directly via the file system, but if you are using an actual iOS device you will need a file explorer utility (such as https://www.macroplant.com/iexplorer/) to browse and extract the files.

 

I do not know where the files are located on Android but I would expect it to be similar.

 

Opening the database files in SQL Central

To open one of the database files in SQL Central, go to “Connections” and select “Connect with UltraLite 17…”

 

1.png

 

Next select “Browse” and locate the file you want to open (in my case I opened the entity data cache). Next select “Open”.

 

2.png

 

After selecting the path to the database file, select “Connect” to open the connection to the database. This will take you to a view like this:

 

3.png

 

You can now inspect the metadata of the database. Double clicking “Tables” will display the tables in the database. If you scroll to the bottom of the list, you will see the tables that contain the actual entity data (names starting with a “random” character sequence in the image below).

 

4.png

 

Viewing the content of a table

To view the content of a table, right click it and select ”View Data in Interactive SQL”.

 

5.png

 

This will bring up the Interactive SQL query windows with a prepopulated SELECT statement for the selected table. The query will be executed automatically and the result will be displayed in the bottom half of the window.

 

6.png

 

So there you have it. The next time you are wondering if a particular piece of data is actually in the database (or if you just want to have a look at how the Offline plugin stores data under the hood), just open the database and have a look!

 

Hopefully someone finds this helpfull - feel free to leave comments, suggestion or corrections below!

 

Best regards,

Olav Rask

The SAP Discovery Service is documented in HCPms and SAP Mobile Secure Admin docs.  This post details using the REST API directly, how to set up your domain with the Discovery Service, and also how to prepare an iOS application to use Discovery Service.

SAP Discovery Service

One of the most basic problems in deploying an enterprise app which end-users acquire through a public app store is getting your organization's server connection & configuration settings to the app when it's installed, without forcing your end-users to jump through hoops.  SAP has delivered the SAP Discovery Service cloud solution, which allows you to publish app connection settings for end users on your email domain/sub-domains, using just their email address.  SAP Discovery Service is integrated with HCPms and SAP Mobile Secure services.

 

At a high level, the process is as follows:

  • Register with SAP Mobile Secure, receive onboarding email
  • Activate your Discovery Service provider ID
  • Update your DNS system with a TXT record that SAP can access with advanced DNS query, to verify you are the owner of the domains/subdomains for which you'll publish app configurations
  • Activate the domains with Discovery Service, for your provider ID
  • Publish your app configurations to Discovery Service, for your provider ID & domain
  • End users are prompted for their email address when they launch an app for the first time.  The app makes a request to Discovery Service, which does a lookup for configurations for the domain + application ID.
  • If the configurations are available, the application uses them to attempt to register to the SMP/HANA Cloud Platform, Mobile Services endpoints

End User Experience

The end user experience is quite simple.  When using the regular Logon component in your app, the end users may see your splash screen (1), and/or launch directly to the 'Acquire Settings' screen (2).  There, the end user is prompted for an email address on their corporate domain.  On entry, the client fetches the connection settings for that ApplicationID + Version + Domain combination.

 

If the app requires the end user's Basic credentials, the end user is prompted for credentials, and the acquired settings are pre-populated on the Login screen (3).

 

If the app uses SAML2 or Client Certificate authentication, the Login screen is not displayed, and instead, the SAML2 authentication challenge is handled in a webview.  If the app uses Client Certificate authentication, the Login screen is displayed, with the pre-populated connection settings, and end-users should click 'Login' to continue.

 

Discovery Service onboarding flow, with Basic auth

The Splash Screen may be disabled, by editing the plist property in MAFLogonUING.bundle/MAFLogonUIOptions.plist:  set keyMAFLogonUseSplashScreen = NO.

This is a one-time operation, and connection settings are persisted for the lifetime of the app.  End users can re-acquire connection settings by resetting the app, or un-registering (if supported in the app).

Adding Discovery Service to your app as a Developer

The Discovery Service UI is baked-in to the Logon component and flow, so there is very little additional work required to include it in your project.

Important:  Discovery Service features in the SDK are typically notated as Mobile Place.   So, MobilePlace == Discovery Service in the libraries and bundle names.  'Mobile Place' is actually a product codename for SAP Mobile Secure, which is the team managing the SAP Discovery Service deployment.

  1. Make sure that Logon component is added to your project, along with the required bundles

     

    The typical set of bundles to add to your project includes:

    MAFUIComponents.bundle HttpConvAuthFlows.bundle Logger.bundle MAFLogonManagerNG.bundle MAFLogonUI.bundle Settings.bundle MobilePlace.bundle 
  2. Add MobilePlace.storyboard, from MobilePlace.bundle

     

    A detail in the way xCode reads linked resources requires you to explicitly add MobilePlace_iPhone.storyboard to your project.  (This file works for iPad as well.).

     

    In your xCode Project Explorer, explode MobilePlace.bundle > Base.lproj, and then drag MobilePlace_iPhone.storyboard up into the project itself.  It will appear side-by-side with the bundles.

    Add MobilePlace_iPhone.storyboard to project

  3. Ensure that MAFLogonUING is set to show Discovery Service UI

     

    Verify that the key value in MAFLogonUING.bundle/MAFLogonUIOptions.plist: is set to keyMAFLogonUseMobilePlace = YES.

     

  4. Optional:  Disable configuration check by MAFLogonManagerNG to SAP Afaria MDM client

     

    SAP has supported distributing configurations and client certificates natively between the Logon component and SAP Afaria, and continues to do so in SAP Mobile SDK 3 SP05.  However, if the applications are configured to get configurations from Afaria, and fail to find configurations from Afaria, then they will not fall-back to try the Discovery Service.  So, if you are distributing your application through a public app store, be aware that you should either:

     

    a) Caution customers who have already deployed SAP Afaria, that they should distribute configurations via SAP Afaria

    b) (recommended):  Disable SAP Afaria feature on MAFLogonManagerNG, by setting key value keyMAFUseAfaria = NO in MAFLogonManagerNG.bundle/MAFLogonManagerOptions.plist.  Then, have your customers upload their application connection configurations to Discovery Service.  If your customers are also using SAP Afaria for distibuting client certificates, then you can enable them to continue to do so by implementing the <CertificateProvider> protocol in your application, so that the provider invokes the Afaria APIs for obtaining the client certificate.  In this way, the Discovery Service will be used to obtain the configurations, and the ClientCertificate protocol will be called by Logon, and the client certificate will be supplied by Afaria.

    Note:  It is possible for customers to adopt option (b) on net-new applications, but still support their existing configuration landscape with SAP Afaria for apps already deployed to app stores & end users.

  5. Build and run.  The 'Acquire Settings' screen should appear, and you will be able to see the request and response from the Discovery Service in the console

    2014-08-15 TravelAgency_RKT[] URL: https://discovery.sapmobilesecure.com/config-api.svc/ApplicationConfigurations/getApplicationConfiguration(AppConfigID='flight:1.0',EmailAddress='stan@sap.comEmailAddress='stan@sap.com') 2014-08-15 TravelAgency_RKT[] received response: { "host" : "smpqa12-01.sybase.com", "port" : 80, "protocol" : "http"} 

Upserting Application Configurations to Discovery Service

Upserting configurations to Discovery Service can be done natively from the Admin UI of HANA Cloud Platform Mobile Service ('HANA Mobile'), or directly, via the REST API.

Common to HANA Mobile and REST API

  1. Register with SAP Mobile Secure, to obtain a Provider ID and Activation Token

    You'll receive a welcome email, containing your keys.  This email is valid for 24 hours, so you should plan to complete the onboarding within that window.

    Discovery service welcome email

  2. Add a TXT entry to your DNS records, containing your provider ID

     

    In order to prove that you are the owner of the domains / subdomains for which you are publishing application configurations, we require that you add a text record to your DNS system.  This indicates that you do indeed have Admin rights on these domains, and prevents impersonation during this onboarding sequence.

     

    The procedure for editing TXT records on your DNS will vary from provider to provider, but the format of the record should be identical.  I'll share the steps for Network Solutions LLC, who hosts my domain, and for a personal developer setup, a simple GoDaddy domain would work similarly.

     

    This should result in a finished record like the following:

    1. In your account view, go to Advanced DNS Settings (Edit).  Skip through the add-ons splash ads.
    2. Select Edit TXT Records
    3. In the Add/Edit Text(TXT Records) - Currently Managing Domain :  form, add a new record with Host = _sap_mobsec, and Text = providerid=<My Provider ID>

 

Next, pick the instructions for HANA Cloud Platform, Mobile Services (not yet released), or for the REST client (use the REST client, if you have SMP installed on-premise).

With HANA Mobile

HANA Cloud Platform, Mobile Services is documented on help.sap.com.  Please refer to documentation there.

With REST Client

All services described here are available as a POSTMAN collection.  POSTMAN is a free REST API tool available on the Chrome Web Store, with an optional native installer.  To get the API collection, launch POSTMAN, and select Import Collection.  Paste this URL in the form:  https://www.getpostman.com/collections/51615332081eda73a86c, and you should then see a collection named SAP Discovery Service in your explorer.

Activate your Provider ID and obtain a Secret Key

Select POST activateApplicationServiceProvider API.  Insert your Provider ID in the designated query parameter, and add the ActivationToken in the POST body payload as a JSON key value

{     "ActivationToken":"<My Activation Token>" } 

The response should include your Secret Key.   Do NOT lose this key!

{     "SecretKey":"<Secret Key Response>" } 

Add an Email domain to your Provider account

Once your _sap_mobsec TXT record is deployed on your DNS, you can add the domain to your Provider account.  This (and all REST calls from here on out) are a slightly more complicated procedure, that must be completed within 5 minutes of start.  So, don't worry if you timeout the first attempt; it will soon be easy.

  1. Download Signature.htm from Github.
  2. Edit the file, and paste your Provider ID and Secret Key into the prompted variable values
  3. In POSTMAN, execute GET /date.  Switch to the Response Headers tab, and copy the Date value  (e.g.:  Fri, 15 Aug 2014 23:03:16 GMT).
  4. Paste the Date value into the time variable in Signature.htm, and load the page.  You should see a result like the following:

    Wed, 13 Aug 2014 17:40:28 GMT New Signature ProviderID=91d4167f97dd3a328cfb8098383920,Signature=lepHz71dMjqAeri322jfk39sjnl2zkM7eMOg+4l5uo= 
  5. In POSTMAN, select the POST upsertEmailDomain service.  Paste the Date value into the x-sms-date header value, and the New Signature value into the x-sms-authtoken header value

  6. Add a JSON object to your POST body, containing your ProviderID and EmailDomain

    {"ProviderID":"<My Provider ID>", "EmailDomain":"<My Email Domain"} 

    Execute Send.

     

    If you succeed, you will get a response payload containing your email domain.  If you fail, you'll the appropriate error message, and you may retry.  Some DNS providers have a waiting period for syncing the TXT records, so check to see that the _sap_mobsec TXT record is active.  Save your request, so that your JSON body is retained.  Repeat steps 3, 4, and 5, and re-send.

Upsert an application configuration for your domain

Once your email domain is active on the Provider account, you can push up application configurations.  Application configurations have the following minimum required payload:

{     "host" : <host>,            //e.g. "sapwin-643.sap.com"    

"port" : <port>,            //e.g. 80    

  "protocol" : <protocol>     //e.g. "http" }

To upsert the application configuration, use POSTMAN to open POST upsertApplicationConfiguration.  Paste the JSON payload of your configuration into the POST body.  Then, follow steps 3-5 from POST upsertEmailDomain procedure to get the current Date, generate a Signature, and set the x-sms-date and x-sms-authtoken header values.

 

The new header values that you need to set are:  X-SMS-EmailDomain = one of the email domains registered to your Provider ID, and X-SMS-AppConfigID = your application ID:version.  This application ID matches the application ID in your SMP3 or HANA Mobile system, and in the application itself (e.g. in your Logon setup, you've invoked [self.logonManager setApplicationId:@"flight"];).  The version value currently defaults to "1.0", so you should concatenate ":1.0" to your application ID to construct this value.

Don't attempt to add the version in your Application ID itself, as the client library will automatically append "1.0" anyway.

Once these are set, you can POST the service, and you should see

Authentication Types
http://scn.sap.com/#basic-authBasic Auth

If you provide only these minimum connection settings, then the Logon client will assume that the authentication expects Basic auth, and will prompt end users for Basic credentials.

Client Certificates

If deploying for use with Client Certificates, then you should add an Auth Type value to the payload.  To instruct the client to invoke a <CertificateProvider> before attempting to register with the server (to obtain the certificate), expand the structure to include the following values:

{     ...    

"protocol" : <protocol>,    

  "auth" : [         {            

  "type" : certificate.sdkprovider         }

]

}

http://scn.sap.com/#saml2-identity-providerSAML2 Identity Provider

If deploying for use with SAML2 Identity Provider, you need to specify both that SAML is the auth type, as well as a set of configurations.   These are discussed in more detail here.

{    

...    

  "protocol" : <protocol>,

    "auth" : [        

  {        

  "type" : saml2.web.post,        

  "config" : {            

  "saml2.web.post.authchallengeheader.name" :"com.sap.cloud.security.login",            

  "saml2.web.post.finish.endpoint.uri" : "/SAMLAuthLauncher",            

  "saml2.web.post.finish.endpoint.redirectparam" : "finishEndpointParam",            

  }        

  }],

}

Hi,

This time we have put the following features into the release:

 

  • EDIT: HCP Subscription hidden
  • New Version Schema
  • Enhanced Data on Application Overview Screen
  • Capability based Push Enhancements
  • One Time Passcodes
  • Active User GLAS reporting

 

HCP Subscription hidden

This is just a configurational change in the trial landscape and not really a feature. As of now, the HCPms Admin Cockpit (HTML5 App) and the HCPms core (JAVA App) is not longer visible in the HCP Cockpit under "Subscriptions", this is to prevent accidentally changes on the trial subscription for HCPms. You can manage and access HCPms subscription under "Services".

 

New Version Schema

As of today we use a new versioning schema to label our releases. While the "16" indicates the year, "02" indicates the month of the release. This is inline with the SAP cloud versioning.

 

Enhanced Data on Application Overview Screen

Sometimes small improvements take a long time to mature. As a product manger I was trying to put these “feature” in for a real long time, but due to it’s minor priority it was constantly shifted from one release to another. At some point in time you have to really push the small things as well – otherwise they will contaminate your backlog. And finally, we have enriched the information on the Application Overview screen to show the URLs that the developers want to know, like Onboarding URL, Application URL that is the result of your configuration, push API URLs and more:

 

Property

Description

Server URL

used to configure your app

Mobile App URL

endpoint created by this App configuration, used within the App to access the Primary Back-End URL

Push URL

Subscription based Push API (NetWeaver/OData feed subscription callback URL)

Enhanced Push API URL

Push API that let’s you send notifications too e.g. all users of an App

Registration URL

URL where you send your POST request to get an APPCID

 

 

And this is how it looks like:

AppOverview.png

Capability based Push Enhancements

Maybe you already have seen the Capability based push scenario that mainly applies to Fiori Launchpad based applications. You can read more about that here: help.hana.ondemand.com


With this release of SAP HANA Cloud Platform mobile services we have extended the flexibility to handle the badge numbers you want to send to your mobile app that is comprising multiple push notification receiving apps. If you have such an application the back-end system typically has no clue about this and can only see the “capability”, which serves as an abstraction layer to the one-to-one push. This layer is entirely located on HCPms.

 

So with this release the back-end can attach a badge number per capability, which results in better and more accurate badge numbers on the mobile device, since HCPms will calculate the correct badge number for your app.

 

Example:

 

Let’s assume you send:


"badges": {

"capability1": 2,

"capability2": 4,

"capability3": 8

}


to the user “Peter”. Now, HCPms examines the capabilities for Peter that are registered. Currently Peter has an App that is registered for “capability2” and “capability3”, so HCPms send a notification to Peters device A with a badge count of 2. On Peters tables (device B) there is an App that is registered for “capability1” so another notification is send to device B with a badge count of 2.


One Time Passcodes

If you want to use one time passcodes to let your users enter your app, you can easily enable OTP in the Admin UI:

OTP.png


Unfortunately, that is only half of the story. There are some prerequisites to match before you activate this configuration.

 

This whole scenario is based on the assumption that you have configured your HCP account to use the SAP Cloud Identity Service to authenticate your mobile users. In addition, you need to use the SAP Authenticator App. So in order to use OTP you need:

 

  • SAP HANA Cloud Platform mobile services
  • SAP Cloud Identity Service
  • SAP Authenticator
  • A Mobile App using the Logon Component of the SAP Mobile SDK (SP11 PL01)

 

Then you need to establish trust between all parties according to the various guides.

 

Once you have setup all the prerequisites, your users will be challenged with an OTP whenever the users’ session need to be renewed.

 

Please make sure that the tradeoff between security and usability fits to your use case. For example, it would make no sense to use OTP in a B2C like application displaying public available product information. If you have a high security mobile app with sensitive data that then this feature is a perfect fit to your use case.


Active User GLAS Reporting

For all customer who are interested in a B2C license for HANA Cloud Platform mobile services, we have introduced the licensing audit for our B2C license, based on “active users” as part of the GLAS auditing report.



Have Fun,

Martin

Hi All,

 

The objective of this post is to explain all the methods that are available for registering a device in the SAP Mobile Platform using android programming.

I thought this was an important topic since there are many possible approachs to perform the registration, and it is difficult to get an insight in each of them when you are just giving your first steps using the SAP Mobile Platform and all the tools that it provides.

 

First of all, let's give a little definition of what is the On-boarding.

User on-boarding is the process of registering a user and giving them appropriate access to data and applications. Without being onboarded, a device is not available to use any of the functionalities provided by the SAP Mobile Platform, as Push Notifications, using authentication, etc.


There are three methods available for registering a device into the SMP for Android Native programming:

1) Calling the registration Endpoint provided by SMP


Request:

URL:

https://<SMP Server address>:<SMP Port>/odata/applications/latest/<appId>/Connections


METHOD:

POST


Header:

Content-Type: application/xml


Payload:

<?xml version="1.0" encoding="UTF-8"?>

<entry xmlns="http://www.w3.org/2005/Atom"

xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"

xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">

<content type="application/xml">

<m:properties>

<d:DeviceModel>Samsung Galaxy S2</d:DeviceModel>

<d:DeviceType>Android</d:DeviceType>

<d:DeviceSubType>Smartphone</d:DeviceSubType>

<d:DevicePhoneNumber>555-555-1212</d:DevicePhoneNumber>

<d:DeviceIMSI>123456</d:DeviceIMSI>

</m:properties>

</content>

</entry>

 

Response:

<entry xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"xml:base="http://<host>:<port>/odata/applications/latest/<appId>/">

<id>

http://<host>:<port>/odata/applications/latest/<appId>/Connections('e6b41263-9d9d-4152-b148-34b95ae01a97')

</id>

<title type="text" />

<updated>

2016-02-24T20:23:38Z

</updated>

<author>

<name />

</author>

<link rel="edit" title="Connection" href="Connections('e6b41263-9d9d-4152-b148-34b95ae01a97')" />

<category term="applications.Connection" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />

<content type="application/xml">

<m:properties>

<d:ETag>

2016-02-24 17:23:38.0

</d:ETag>

<d:ApplicationConnectionId>

e6b41263-9d9d-4152-b148-34b95ae01a97

</d:ApplicationConnectionId>

<d:AndroidGcmPushEnabled m:type="Edm.Boolean">

true

</d:AndroidGcmPushEnabled>

<d:AndroidGcmRegistrationId m:null="true" />

<d:AndroidGcmSenderId>

333666698688

</d:AndroidGcmSenderId>

<d:ApnsPushEnable m:type="Edm.Boolean">

true

</d:ApnsPushEnable>

<d:ApnsDeviceToken m:null="true" />

<d:ApplicationVersion>

  1. 1.0

</d:ApplicationVersion>

<d:BlackberryPushEnabled m:type="Edm.Boolean">

false

</d:BlackberryPushEnabled>

<d:BlackberryDevicePin m:null="true" />

<d:BlackberryBESListenerPort m:type="Edm.Int32">

0

</d:BlackberryBESListenerPort>

<d:BlackberryPushAppID m:null="true" />

<d:BlackberryPushBaseURL m:null="true" />

<d:BlackberryPushListenerPort m:type="Edm.Int32">

0

</d:BlackberryPushListenerPort>

<d:BlackberryListenerType m:type="Edm.Int32">

0

</d:BlackberryListenerType>

<d:CollectClientUsageReports m:type="Edm.Boolean">

false

</d:CollectClientUsageReports>

<d:ConnectionLogLevel>

NONE

</d:ConnectionLogLevel>

<d:CustomizationBundleId m:null="true" />

<d:CustomCustom1 />

<d:CustomCustom2 />

<d:CustomCustom3 />

<d:CustomCustom4 />

<d:DeviceModel>

Samsung Galaxy S2

</d:DeviceModel>

<d:DeviceType>

Android

</d:DeviceType>

<d:DeviceSubType>

Smartphone

</d:DeviceSubType>

<d:DevicePhoneNumber>

555-5525-1212

</d:DevicePhoneNumber>

<d:DeviceIMSI>

123456

</d:DeviceIMSI>

<d:E2ETraceLevel>

Low

</d:E2ETraceLevel>

<d:EnableAppSpecificClientUsageKeys m:type="Edm.Boolean">

false

</d:EnableAppSpecificClientUsageKeys>

<d:FeatureVectorPolicyAllEnabled m:type="Edm.Boolean">

true

</d:FeatureVectorPolicyAllEnabled>

<d:LogEntryExpiry m:type="Edm.Int32">

7

</d:LogEntryExpiry>

<d:MaxConnectionWaitTimeForClientUsage m:null="true" />

<d:MpnsChannelURI m:null="true" />

<d:MpnsPushEnable m:type="Edm.Boolean">

false

</d:MpnsPushEnable>

<d:PasswordPolicyEnabled m:type="Edm.Boolean">

false

</d:PasswordPolicyEnabled>

<d:PasswordPolicyDefaultPasswordAllowed m:type="Edm.Boolean">

false

</d:PasswordPolicyDefaultPasswordAllowed>

<d:PasswordPolicyMinLength m:type="Edm.Int32">

8

</d:PasswordPolicyMinLength>

<d:PasswordPolicyDigitRequired m:type="Edm.Boolean">

false

</d:PasswordPolicyDigitRequired>

<d:PasswordPolicyUpperRequired m:type="Edm.Boolean">

false

</d:PasswordPolicyUpperRequired>

<d:PasswordPolicyLowerRequired m:type="Edm.Boolean">

false

</d:PasswordPolicyLowerRequired>

<d:PasswordPolicySpecialRequired m:type="Edm.Boolean">

false

</d:PasswordPolicySpecialRequired>

<d:PasswordPolicyExpiresInNDays m:type="Edm.Int32">

0

</d:PasswordPolicyExpiresInNDays>

<d:PasswordPolicyMinUniqueChars m:type="Edm.Int32">

0

</d:PasswordPolicyMinUniqueChars>

<d:PasswordPolicyLockTimeout m:type="Edm.Int32">

0

</d:PasswordPolicyLockTimeout>

<d:PasswordPolicyRetryLimit m:type="Edm.Int32">

20

</d:PasswordPolicyRetryLimit>

<d:ProxyApplicationEndpoint>

http://ema.dummy.com

</d:ProxyApplicationEndpoint>

<d:ProxyPushEndpoint>

http://localhost:8080/Notification

</d:ProxyPushEndpoint>

<d:PublishedToMobilePlace m:type="Edm.Boolean">

false

</d:PublishedToMobilePlace>

<d:UploadLogs m:type="Edm.Boolean">

false

</d:UploadLogs>

<d:WnsChannelURI m:null="true" />

<d:WnsPushEnable m:type="Edm.Boolean">

true

</d:WnsPushEnable>

<d:InAppMessaging m:type="Edm.Boolean">

false

</d:InAppMessaging>

<d:FeatureVectorPolicy m:type="Bag(applications.FeatureVectorPolicy)" />

</m:properties>

</content>

  </

entry>


If you want to investigate more in detail this method, please refer to the following URL:

http://help.sap.com/saphelp_smp307sdk/helpdata/en/8a/251b61893340c6ad2ba418679a19d1/content.htm


2) Using the MAF Logon Component


The MAF Logon component is one of the most common reusable components of the Mobile Application Framework (MAF) and it provides easy integration for applications that use logon UI behavior. It is a key component, because before any communication can take place with a backend OData producer, the app needs to on-board users onto the SAP Mobile Platform.

This component can be very useful if you are looking for a quick win, but in the case you want to developer an application that provides a personalized experience, I would recommend to go for the method 3.

This component is perfect if you are doing some test, or if you are building a PoC.


If you want to get more details from this component, check the following post:

http://a248.g.akamai.net/n/248/420835/5df1fcfbdd794e073a8acd0f584ac9fd679f1b00fe2ee8a7b95788cd6d17c49b/sapasset.download…


It is important to clear out, that there is a way to customize a little bit this screen, and this is explained in the following blog:

Customizing MAF Logon Component in Android


Below some screens on how this component looks like:

 

 



Img01.png



img02.png


img03.png


3) Using the oData SDK


This is the best method if you are looking for a personalized experience, where you can define the screen with all the fields you want to show, and whatever look & feel you want to use.

For instance, below you can see an example of a custom screen design, different to the one provided by the MAF Logon Component.


img05.png


If you are interested in this approach, I encourage you to take a look at the following post:

http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/30304722-614d-3210-65a6-faf86a032319?QuickLink=index&…


See you in the next post!

Emanuel

 






Actions

Filter Blog

By author:
By date:
By tag: