Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Jitendra_Kansal
Product and Topic Expert
Product and Topic Expert
2,275
I am happy to announce that a new release of the Mobile Development Kit is available for all Mobile Services customers and can be downloaded on the SAP Software Center (and also available on community Download page).

This release adds incremental functionality over the previous MDK Client 4.0 release.

 



 

Mobile Services Client is also available in Apple AppStore and Google Play Store.

SAP Mobile development kit (MDK) extends SAP Cloud Platform Mobile Services and SAP Web IDE to provide you with a complete set of mobile application development and management tools, onboarding, offline support, and central lifecycle management. It offers a metadata-driven approach to create native supported applications so no experience of creating iOS or Android apps is required.

The main focus of this release are:




New UI control: Profile Header


We now support Profile Header control conforming Fiori for iOS & Android guideline.

Profile header helps the user recognize and learn more about a person.



[Updated 10.01.2020] : Profile Header control is now available under available control in Section page in MDK page editor
"Sections":[ 
{
"ProfileHeader":{
"ActivityItems":[
{
"ActivityType":"Phone",
"ActivityValue":"{PhoneNumber}"
},
{
"ActivityType":"VideoCall",
"ActivityValue":"{PhoneNumber}"
},
{
"ActivityType":"Email",
"ActivityValue":"{EmailAddress}"
},
{
"ActivityType":"Detail",
"ActivityValue":"This is an alert"
}
],
"Description":"{CustomerId}",
"DetailImage":"/DemoProj/Images/contact-cell.png",
"DetailImageIsCircular":true,
"Headline":"{{#Property:FirstName}} {{#Property:LastName}}",
"Styles":{
"BackgroundColor":"ProfileHeaderBackgroundColor",
"Description":"ProfileHeaderDescription",
"Headline":"ProfileHeaderHeadline",
"Subheadline":"ProfileHeaderSubheadline"
},
"Subheadline":"{City}"
},
"Visible":true,
"_Name":"Control0",
"_Type":"Section.Type.ProfileHeader"
}
],
"_Name":"SectionedTable",
"_Type":"Control.Type.SectionedTable"
}

Check the documentation for more details.

Support rendering image via HTTPS URL


We now support rendering image via https URL for values in image properties e.g. DetailImage in ContactCell.

 






































Control Attribute in control Documentation Reference
ObjectHeader DetailImage, StatusImage, SubstatusImage Reference
ProfileHeader DetailImage Reference
ObjectCell DetailImage, Icons, StatusImage, SubstatusImage Reference
ContactCell DetailImage Reference
GridRowItem Image Row Item
ImageCell Image Reference

Here in ProfileHeader control
 "DetailImage": "https://icon-library.net/images/0234605a9c_92936.png",




We now have introduced a new property “ClearHistory” in Navigation Action to clear the history stack.  It accepts a Boolean value. Default value is false.

If set to true, the navigation back-stack should be cleared and after the navigation action is completed the back button should not be visible anymore in the target page (because the backstack is now empty).
{ 
"ClearHistory":true,
"PageToOpen":"/DemoProj/Pages/Customers/Customers_List.page",
"_Type":"Action.Type.Navigation"
}


Check the documentation for more details.

Support Stateful OData Services


You should be now able to handle and store the stateful services session so that session info can be easily retrieved and can be used.

A new property is available in Service > OnlineOptions > ServiceOptions > StatefulService (type: boolean)



If set to true, the session information returned from the CallFunction API is automatically stored in #Application/#ClientData/#Property:Session/#Property:[SessionPropertyName] for subsequent use in actions or rules.

Example:
#Application/#ClientData/#Property:Session/#Property:SessionID

 

Check the documentation (Online Service Options) for more details.

 

Support OData CreateRelatedMedia action


Create Related Media action is used to create a media enity(an OData EntityType with HasStream="true" attribute). The new media entity is linked to its parent entity(an entity has a navigation property linking to the new media entity)

 

e.g. "Image" EntityType is a Media Entity and it has an associated media stream:
<EntityType Name="Image" HasStream="true">
<Key>
<PropertyRef Name="id"/>
</Key>
<Property Name="id" Type="Edm.Int64" Nullable="false"/>
<Property Name="label" Type="Edm.String" Nullable="true"/>
<Property Name="created" Type="Edm.Date" Nullable="true"/>
<Property Name="updated" Type="Edm.Date" Nullable="true"/>
<NavigationProperty Name="artist" Type="Self.Artist"/>
</EntityType>

Parent EntityType "Artist" has a navigation property linking to "Image":
<EntityType Name="Artist">
<Key>
<PropertyRef Name="id"/>
</Key>
<Property Name="id" Type="Edm.Int64" Nullable="false"/>
<Property Name="firstName" Type="Edm.String" Nullable="false"/>
<Property Name="lastName" Type="Edm.String" Nullable="false"/>
<Property Name="dateOfBirth" Type="Edm.Date" Nullable="true"/>
<NavigationProperty Name="images" Type="Collection(Self.Image)"/>
</EntityType>



{
"_Type": "Action.Type.ODataService.CreateRelatedMedia",
"Target" : {
"EntitySet" : "Images",
"Service" : "/AssetWorkManager/Services/Amw.service"
},
"Properties" : {
"ClassName": "#CurrentPage/#Control:ClassName/#Value",
"ClassType": "#CurrentPage/#Control:ClassType/#Value",
"ObjectKey": "#CurrentPage/#Control:ObjectKey/#Value",
"FileName": "#CurrentPage/#Control:FileName/#Value"
},
"ParentLink": {
"Property": "images",
"Target": {
"EntitySet": "Artists",
"ReadLink": "{@odata.readLink}"
}
},
"Headers" : {
"slug" : {
"ClassName": "#CurrentPage/#Control:ClassName/#Value",
"ClassType": "#CurrentPage/#Control:ClassType/#Value",
"ObjectKey": "#CurrentPage/#Control:ObjectKey/#Value",
"FileName": "#CurrentPage/#Control:FileName/#Value"
}
},
"IsOnlineRequest": true,
"Media":"#CurrentPage/#Control:Attachment/#Value",
"OnSuccess" : "/AssetWorkManager/Actions/ODataCreateEntitySuccessMessage.action",
"OnFailure": "/AssetWorkManager/Actions/ODataCreateEntityFailureMessage.action"
}



 

Note:

CreateMedia action: creates a new media entity against its own entity set. This action does not support linking to another existing entity set.

CreateRelatedMedia action creates the new media entity against the navigation property of an existing entity with which the relationship is to be established.

Check the documentation for more details.

Support OData CreateRelatedEntity action


CreateRelatedEntity action is used to create an entity in the target system, related to a parent entity via a parent navigation property.


{
"_Type": "Action.Type.ODataService.CreateRelatedEntity",
"Target": {
"EntitySet": "SalesOrderHeaders",
"Service": "/MDKDevApp/Services/OnlineSampleService.service"
},
"Properties": {
"SalesOrderId": "/MDKDevApp/Rules/GetSalesOrderId.js"
},
"ParentLink": {
"Property": "SalesOrders",
"Target": {
"EntitySet": "Customers",
"ReadLink": "{@odata.readLink}"
}
},
"ActionResult": {
"_Name": "OData"
},
"OnSuccess": "/MDKDevApp/Actions/Messages/Success.action",
"OnFailure": "/MDKDevApp/Actions/Messages/Failure.action"
}



Note:

CreateEntity (with CreateLinks) action: creates the new entity against its own entity set. The entity is then linked or bound to an existing entity with which the relationship is to be established.

CreateRelatedEntity action creates the new entity against the navigation property of an existing entity with which the relationship is to be established.

Check the documentation for more details.

Add metadata function to choose between platform specific values


You can now format things like date, time, currency etc that returns the appropriate value based on the runtime platform (iOS or Android).


$(PLT, <iOS>, <Android>)


If the platform is iOS the first parameter is returned.


If the platform is Android the second parameter is returned


If the parameter is blank then the property where the function is evaluated should behave as if the property is not specified.


It supports the following value types:




  1. $(PLT, 'ABC', true) <- in iOS return string 'ABC', in Android return boolean true

  2. $(PLT, 123.4, 'false') <- in iOS return number 123.4, in Android return a string 'false'

  3. $(PLT, '123.4', null) <- in iOS return string '123.4', in Android return a null

  4. $(PLT, {MyProperty}, {\{#SomeTargetPath/#Property:SomeProperty}}) <- in iOS return string value of MyProperty binding, in Android return value of #SomeTargetPath/#Property:SomeProperty






 

Check the documentation for more details.

Support sending authenticated GET and POST request to SAP Cloud Platform Mobile Services


We already supported to get the deviceID & UserID for the registered user. Now, you can also get the SAP Cloud Platform Mobile Services AppID and server endpoint.





Once you get the Mobile Services URL and AppID, you can construct a full URL to access Mobile Services REST API/destinations via clientAPI
sendMobileServiceRequest(path: string, params?: any): Promise<any>;

 
/**
* Describe this function...
* @param {IClientAPI} context
*/
export default function DoSomePostRequest(context) {
debugger;
let userid = context.evaluateTargetPath('#Control:User/#Value');
let appId = context.evaluateTargetPath('#Application/#ClientData/#Property:MobileServiceAppId');
let uri = '/my/rest/api/v1/doSomething';
let body = {
"FirstName": "John",
"LastName": "Doe",
"Address": {
"Street": "Some Street",
"City": "AB",
"Country": "CD"
},
"UserId": userid
};
let header = {
"x-smp-appid": appId,
"Content-Type": "application/json"
};
let params = {
'method': 'POST',
'header': header,
'body': JSON.stringify(body)
};
return context.sendMobileServiceRequest(uri, params).then((result)=>{
console.log(Result: ${result});
console.log(Result Content: ${result.content});
console.log(Result statusCode: ${result.statusCode});
if (result && result.statusCode === 201 && result.content) {
//DO WHAT YOU NEED WITH THE result.content here e.g.
let data = JSON.parse({ "result": ${result.content.toString()}});
context.getPageProxy().setActionBinding(data);
return context.executeAction("/MyApp/Actions/ShowResult.action");
} else if (result) {
console.log(Failed Result: ${result.statusCode});
}
else {
console.log(Failed Result: ${result.content});
}
});
}

Check the documentation for more details.

Support Offline OData Function Imports


CallFunction action

  • supports POST, PUT, PATCH and DELETE. method on OData v2

  • Will always immediately return empty result because the request is not truly send until you sync to the server

  • Need to sync to backend to commit the transaction

  • Function Import requests cannot/will not be merged with other requests.

  • In V2, function imports can only use primitive types as parameters.


Function Import requests cannot/will not be merged with other requests. They can, however, be automatically bundled into the same ‘transaction’ if the appropriate TransactionID header is used.

In V2, function imports can only use primitive types as parameters.

 
{ 
"OnSuccess":"/DemoSampleApp/Actions/UpdateStatusSuccess.action",
"Target":{
"Function":{
"Name":"UpdateSalesOrderStatus",
"Parameters":{
"id":"{SalesOrderId}",
"newStatus":"R"
}
},
"Service":"/DemoSampleApp/Services/SampleServiceV2.service"
},
"_Type":"Action.Type.ODataService.CallFunction"
}


 

Check the documentation for more details.

 

Support multiple formats with DateFormat and TimeFormat


We have now added new customOptions parameter for formatDate, formatDateTime, formatTime function via IClientAPI to display date and time in the specified format. Supported format style: short, medium, long, full. Default for date is medium. Default for time is short (MDK default). e.g. { format: 'long' }
// Display in date format
formatDate(date: Date, customLocale?: string, customTimeZone?: string, customOptions?: any): string;
// Display in datetime format
formatDatetime(date: Date, customLocale?: string, customTimeZone?: string, customOptions?: any): string;
// Display in time format
formatTime(date: Date, customLocale?: string, customTimeZone?: string, customOptions?: any): string;

 

You can also use it via Internationalized and Localized Data.

e.g.

  • $(D,'2017-12-25T11:40:00Z',null,'Europe/Berlin',{format:'long'})

  • $(DT,'2017-12-25T11:40:00Z',null,'Europe/Berlin',{format:'long'})

  • $(T,'2017-12-25T11:40:00Z',null,'Europe/Berlin',{format:'long'})


Support Image Collection in Sectioned Table on Android


Image Collection is now fully supported in Android.

New to MDK development?


Follow these tutorials

Many thanks to our dev colleagues to share inputs in writing up this post.

Regards

Jitendra Kansal

Product Management, SAP Cloud Platform Mobile Services
SAP SE
12 Comments