SAP Fiori Mobile (v2.6.x)
Transcript of SAP Fiori Mobile (v2.6.x)
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 1/22
SAPFioriMobile(v2.6.x)
Introduct ion
Whatarehybridmobileapps?
Hybridmobileappsarewebapplicationswrappeduptheirownbrowserwhichcanrunonanyofthemobileplatforms(Android,iOS,Windowsetc.).Thebigadvantageofahybridappisthatithasasinglecodebase,whereasanativeappmustbere-writtenforeachplatform.
ApacheCordovaisanopen-sourceframeworkfordevelopinghybridapps.Tousenativefeatures(beyondthosealreadyavailableviahmtl5,)appscanmakeuseofplugins.Thesepluginshandletheplatform-specificcodeandareavailableforsingleormultipleplatforms.PluginsareavailabletoaccesstheGPS,accelerometerorcamera,forexample.
SAPhavewrittentheirownplugins,brandedasKapsel,tohandlethingslikelogonandofflineOData.Thesebringanenterpriseflavourtohybridapps.
WhatisFioriMobile?
UntilrecentlySAP’srecommendedapproachwastousetheHybridApplicationToolkit(orHAT)inordertobuildhybridapps.Theappbuildtookplaceonthedeveloper’sPCorMac.TheHATgainedareputationforbeingtrickytosetupandthathinderedtheuseofhybridappswithintheSAPecosystem.
FioriMobilehasat it scoreacloud-buildservice,sothereisnoneedtoinstalltheHAT.WecantriggerthebuildfromWebIDE.Wespecifythe(alreadydeployed)Fioriapp(s)thatwewanttopackageandafterafewminuteswecandownloadthe.apk(forAndroid)and.ipa(foriOS)filesreadytobeinstalledonmobiledevices.
Doesit work?
Thecloudbuildserviceworkswell.Ittypicallybuildforbothplatformsinabout8minuteswithoutissueas.Therehaveonlybeenacoupleofoccasionswhenbuildsfailedduetotechnicalproblems.
Therearesomefacetstothetechnologywhichdon’tfeelmatureyet.OneareaistheofflineODatafeatures.WhenusingFioriMobilethingsworkdifferentlytothemoreconventionalhybridandnativeapps.Oneexamplewouldbethedestinations,becauseFioriMobileappsuseagenerateddestinationwhichreferencetheSAPCloudPlatform(CP)portalservice.
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 2/22
MypointisnotthatofflineODataseemsimmature,ratherthattheofflinefeaturescanbetrickywhenusedwithFioriMobileapps.WearestillreceivingassistancefromSAPtogettheofflinefeaturesofourappoptimised.Thisisashame,becauseshareddataandthehandlingofdeltarequests,forexample,aretwofeatureswhichjustifythe‘middleware’approachtoofflinethatSAPhavetaken.
Authenticationhasalsobeenachallenge.OnapreviousprojectIusedtheFioriClientinconjunctionwithSAPCloudIdentity(nowofficiallySAPCloudPlatformIdentityAuthentication).TheFioriClientstoredtheusernameandpasswordonthedevicesothattheuserdidn’tneedtoenterthemeverytimetheirsessiontimedout.Wehaven’tachievedthatyetwithourFioriMobileapp.
Account andServices
SignupforafreeaccountfortheSAPHanaCloudPlatform,andactivateyouaccountfromyourmailactivationlinkthatyoureceive.OnceyouhaveactivatedyouraccountbrowseonHCPCockpit.ChooseTrialRegionandopenyourPersonalTrialAccount.
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 3/22
TocreateFioriMobileApplicationyouwillneedtousePortal,SAPWebIDEandFioriMobileservices.
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 4/22
GoinServicestabfindtheseservicesandenablethemiftheyaredisabled.
CreateFioriLaunchpad
TocreateFioriApplicationweneedtocreateandpublishtheSitewhereapplicationwillbedeployed.
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 5/22
GotoPortalServiceandclickGotoService.
Inyourbrowseranewtabwillbeopened.InthisnewwindowgototheSiteDirectorytab,andclickonCreateSite.
Apopupwillbedisplayed.EnteryourSiteName,chooseSAPFioriLaunchpadasTemplateSourceandclickCreate
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 6/22
FollowingthisyouwillberedirectedtoSAPFioriConfigurationCockpit.ClosethetabandgobacktoAdminSpaceforPortalService.
NowweneedtoPublishthisSiteandSetasdefault.
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 7/22
CreateFioriProject
OncewecreateandpublishtheSitewecancreateourFioriproject.
GotoServicestabagain,openSAPWebIDEservice,andclickonGotoService
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 8/22
Anewtabwillbeopened.FromherewewillstarttocreateourFioriproject.
ClickonNewProjectfromTemplate
ChooseSAPUI5ApplicationfromTemplateSelection
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 9/22
SetyourProjectName
ChoosetheViewTypeandsettheViewName.InoursamplewewilluseXMLView.ClickFinishandyourFioriprojectiscreated.
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 10/22
HowtousecmbSDKcordovaplugin
IntheSAPWebIDEWorkspacewecanseeallfilesthatourFioriprojectinludes.
OpenComponent.jsfile .
Component.jsisthefirstpointofourapplication,wecansaythatitservesasindexwhichencapsulatesallourapplicationsdetails,i.e .viewnames,routingdetails,mainview,applicationstype(FullScreenorSplitApp),applicationserviceconfigurationetc..
Hereininit functionwewillconfigureourplugin.Setpropertiesthatweneed,setcallbackfunctions,callsomemethods,etc..
sap.ui.define(["sap/ui/core/UIComponent","sap/ui/Device","MyFristFioriApp/model/models"],function(UIComponent,Device,models){"usestrict";
varoEventBus=sap.ui.getCore().getEventBus();varscannerIsInitialized=false;
returnUIComponent.extend("MyFristFioriApp.Component",{
metadata:{manifest:"json"},
/***ThecomponentisinitializedbyUI5automaticallyduringthestartupoftheappandcallstheinitmethodonce.*@public*@override*/init:function(){//callthebasecomponent'sinitfunctionUIComponent.prototype.init.apply(this,arguments);
//setthedevicemodelthis.setModel(models.createDeviceModel(),"device");
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 11/22
if(!scannerIsInitialized){
scannerIsInitialized=true;
window.readerConnected=0;window.scannerActive=false;
cmbScanner.addOnResume(function(result){
cmbScanner.setAvailabilityCallback((readerAvailability)=>{if(readerAvailability===cmbScanner.CONSTANTS.AVAILABILITY_AVAILABLE){oEventBus.publish("ScanView","SetConnectionStatus",{statusText:"AVAILABLE"});
cmbScanner.connect((result)=>{
});
}else{oEventBus.publish("ScanView","SetConnectionStatus",{statusText:"NOTAVAILABLE"});}});
if(Device.os.android){cmbScanner.connect((result)=>{
});}});
cmbScanner.addOnPause(function(result){
if(Device.os.android){cmbScanner.disconnect();}cmbScanner.setAvailabilityCallback();});
cmbScanner.setPreviewContainerPositionAndSize(0,0,100,50);
cmbScanner.setConnectionStateDidChangeOfReaderCallback((connectionState)=>{
if(connectionState===cmbScanner.CONSTANTS.CONNECTION_STATE_CONNECTED){
oEventBus.publish("ScanView","SetConnectionStatus",{statusText:"CONNECTED"});
if(window.readerConnected!=connectionState){cmbScanner.setSymbologyEnabled("SYMBOL.DATAMATRIX",true);cmbScanner.setSymbologyEnabled("SYMBOL.C128",true);cmbScanner.sendCommand("SETTRIGGER.TYPE2");}
varsdkKEY="";if(Device.os.android)sdkKEY=this.getModel("i18n").getProperty("MX_MOBILE_LICENSE_ANDROID");else
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 12/22
sdkKEY=this.getModel("i18n").getProperty("MX_MOBILE_LICENSE_iOS");
cmbScanner.registerSDK(sdkKEY,(res)=>{switch(res){casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_OK:
break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_INVALID_KEY:
break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_INVALID_CHECKSUM:
break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_INVALID_APPLICATION:
break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_INVALID_SDK_VERSION:
break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_INVALID_KEY_VERSION:
break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_INVALID_PLATFORM:
break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_KEY_EXPIRED:
break;default:break;}});
}elseif(connectionState==cmbScanner.CONSTANTS.CONNECTION_STATE_DISCONNECTED){oEventBus.publish("ScanView","SetConnectionStatus",{statusText:"DISCONNECTED"});}elseif(connectionState==cmbScanner.CONSTANTS.CONNECTION_STATE_CONNECTING){oEventBus.publish("ScanView","SetConnectionStatus",{statusText:"CONNECTING"});}elseif(connectionState==cmbScanner.CONSTANTS.CONNECTION_STATE_DISCONNECTING){oEventBus.publish("ScanView","SetConnectionStatus",{statusText:"DISCONNECTING"});}
window.readerConnected=connectionState;});
cmbScanner.setAvailabilityCallback((readerAvailability)=>{if(readerAvailability===cmbScanner.CONSTANTS.AVAILABILITY_AVAILABLE){oEventBus.publish("ScanView","SetConnectionStatus",{statusText:"AVAILABLE"});
cmbScanner.connect((result)=>{
});
}else{
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 13/22
oEventBus.publish("ScanView","SetConnectionStatus",{statusText:"NOTAVAILABLE"});}});
cmbScanner.setActiveStartScanningCallback((result)=>{window.scannerActive=result;});
cmbScanner.setPreviewOptions(cmbScanner.CONSTANTS.PREVIEW_OPTIONS.DEFAULTS|cmbScanner.CONSTANTS.PREVIEW_OPTIONS.HARDWARE_TRIGGER);cmbScanner.setCameraMode(cmbScanner.CONSTANTS.CAMERA_MODES.NO_AIMER);
cmbScanner.loadScanner(0,(result)=>{cmbScanner.connect((result)=>{
});});
oEventBus.subscribe("Component","LoadScanner",this.loadScanner,this);}},
loadScanner:function(sChanel,sEvent,oData){
cmbScanner.disconnect((result)=>{cmbScanner.loadScanner(oData.selectedDevice,(result)=>{cmbScanner.connect((result)=>{
});});});},
onExit:function(){
oEventBus.unsubscribe("Component","LoadScanner",this.loadScanner,this);
cmbScanner.disconnect();cmbScanner.setAvailabilityCallback();}});});
cmbScannerisanobjectthatrepresentsourplugin.WiththisobjectwecanaccessallAPImethodsandConstantsfromourplugin.
scannerIsInit ialized-variabletomakesurethatwesetsomefunctionsforinitializationonlyonetimewindow.readerConnected-globalvariablethatischangedeverytimewhenthereaderconnectionstateischangedwindow.scannerAct ive-globalvariablethatshowsusifscanningisactiveornotcmbScanner.addOnPause-inthismethodwedisconnectionfromreaderdeviceonAndroid(oniOSthisishandledautomatically),andstoplisteningtoavailabilitychanging
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 14/22
cmbScanner.addOnResume-inthismethodwetrytoconnectwithreaderdeviceagainandsetcallbackforavailabilitychangingcmbScanner.setPreviewContainerPosit ionAndSize-tosetthesizeandpositionofthepreviewcontainer.Learnmorehere.cmbScanner.setConnect ionStateDidChangeOfReaderCallback-allconnect /disconnect eventsshouldbehandledwithinthecallbackfunctionsetwiththisAPImethod.IfconnectionstateisconnectedwesetsomereaderdevicesettingswithAPImethodsordirectlywithsendCommand()method.Hereinthisexampleweenablesymbologiesandsettriggertype.AlsohereweshouldLicensingtheSDK.WewillspeakaboutthislaterinthissectioncmbScanner.setAvailabilit yCallback-tomonitorforavailabilityoftheMXdevice.IfMXdeviceisavailablewetrytoconnect.Learnmorehere.cmbScanner.setAct iveStartScanningCallback-tomonitorthestateofthescanner.Learnmorehere.cmbScanner.loadScanner-togetascannerupandrunning.Learnmorehere.
Hereweareonlyconfiguringreaderdevice,handlingconnections,availability,etc..Wewilldoscanningandgettingresultsinotherviews.IfwewanttonotifyusersabouteveryconnectionstatechangedorotherinfoaboutreaderdevicewewillbeusingEventBussapobject.Withthisobjectwecanpublishfunctionandcallthemfromanyviewintheapplication.InthisexampleonconnectionstatechangedwithEventBuswearecallingSetConnect ionStatusfunctionthatisimplementedinviewwherescanningisperformedandsetlabeltexttoshowusercurrentconnectionstate.
NowopenScanView.view.xmlandaddthiscode:
<mvc:Viewxmlns:mvc="sap.ui.core.mvc"xmlns:html="http://www.w3.org/1999/xhtml"xmlns:core="sap.ui.core"controllerName="MyFristFioriApp.controller.ScanView"displayBlock="true"><Appxmlns="sap.m"><pages><Pagetitle="MWBCameraDemo"showHeader="false"><subHeader><Toolbarid="__toolbar2"width="100%"><content><FlexBoxid="__box0"width="100%"alignContent="Center"alignItems="Start"direction="Column"fitContainer="true"justifyContent="Center"><items><Selectid="selectActiveDevice"items="{/Devices}"textAlign="Center"selectedKey="0"change="activeDeviceChanged"><core:Itemtext="{text}"key="{key}"/></Select></items></FlexBox><Labelid="lblStatus"text="DISCONNECTED"width="100%"textAlign="End"design="Bold"/></content></Toolbar></subHeader><content><FlexBoxid="flexBoxContainer"width="100%"alignContent="Start"alignItems="Start"direction="Column"fitContainer="true"/></content><footer><Toolbarid="__toolbar1"width="100%">
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 15/22
<content><Buttonid="btnScan"press="btnScanPress"text="Scan"width="100%"/></content></Toolbar></footer></Page></pages></App></mvc:View>
YoucandesignviewwithCodeEditororwithLayoutEditor.
AfterthatopenScanView.cont roller.jsandaddthiscode
sap.ui.define(["sap/ui/core/mvc/Controller"],function(Controller){"usestrict";
varoEventBus=sap.ui.getCore().getEventBus();
varoModel=newsap.ui.model.json.JSONModel();
oModel.setData({Devices:[{key:"0",text:"MXDevice"
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 16/22
},{key:"1",text:"MobileCamera"}]});
returnController.extend("MyFristFioriApp.controller.ScanView",{
onInit:function(){
this.getView().setModel(oModel);},
onAfterRendering:function(){
window.scannerActive=false;
switch(window.readerConnected){casecmbScanner.CONSTANTS.CONNECTION_STATE_CONNECTED:this.getView().byId("lblStatus").setText("CONNECTED");break;casecmbScanner.CONSTANTS.CONNECTION_STATE_DISCONNECTED:this.getView().byId("lblStatus").setText("DISCONNECTED");break;casecmbScanner.CONSTANTS.CONNECTION_STATE_CONNECTING:this.getView().byId("lblStatus").setText("CONNECTING");break;casecmbScanner.CONSTANTS.CONNECTION_STATE_DISCONNECTING:this.getView().byId("lblStatus").setText("DISCONNECTING");breakdefault:this.getView().byId("lblStatus").setText("UNKNOWN");break;}
oEventBus.subscribe("ScanView","SetConnectionStatus",this.setConnectionStatus,this);
cmbScanner.setResultCallback((result)=>{if(result&&result.readString){
varverticalLayoutContainer=newsap.ui.layout.VerticalLayout(null,{width:"100%"}).addStyleClass("sapUiSmallMarginTop");
verticalLayoutContainer.addContent(newsap.m.Label({text:result.symbologyString+":",textAlign:"Begin",design:"Bold"}).addStyleClass("sapUiSmallMarginBegin"));verticalLayoutContainer.addContent(newsap.m.Text({text:result.readString,textAlign:"Begin"}).addStyleClass("sapUiSmallMarginBegin"));
this.getView().byId("flexBoxContainer").addItem(verticalLayoutContainer);}});},
btnScanPress:function(){
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 17/22
if(window.readerConnected===cmbScanner.CONSTANTS.CONNECTION_STATE_CONNECTED){if(window.scannerActive===true){cmbScanner.stopScanning();}else{cmbScanner.startScanning();}}},
setConnectionStatus:function(sChanel,sEvent,oData){this.getView().byId("lblStatus").setText(oData.statusText);},
activeDeviceChanged:function(){cmbScanner.disconnect((result)=>{oEventBus.publish("Component","LoadScanner",{selectedDevice:parseInt(this.getView().byId("selectActiveDevice").getSelectedKey())});});},
onExit:function(){
oEventBus.unsubscribe("ScanView","SetConnectionStatus",this.setConnectionStatus,this);
if(window.readerConnected===cmbScanner.CONSTANTS.CONNECTION_STATE_CONNECTED){if(window.scannerActive===true){cmbScanner.stopScanning();}}
cmbScanner.setResultCallback((result)=>{returnfalse;});}
});});
InthisviewwehaveaScanbuttontostartScanning()/stopScanning()andcmbScanner.setResultCallbacktohandlesuccessfulscanresults.
DeployapptoHCP
AfterwefinishcreatinganddevelopingourFioriprojectweneedtoprepareformobiledeployment.
FirstweneedtodeployourprojectonSAPHANACloudPlatform.
RightclickonprojectfolderthenselectDeployandchooseDeploytoSAPHANACloudPlatform
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 18/22
SetapplicationdetailsandclickDeploy
Afterasuccessfuldeploy,thenextstepistoRegistertoSAPFiorilaunchpadthatwe'vecreatedintheprevioussection.
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 19/22
Chooseaccountandsetapplicationname.
SetType(Staticbydefault),setTitle,andSubtitle.
ChooseSitethatwecreatebefore,catalog,andgroup(samplecatalogandgroupiscreatedbydefault).
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 20/22
ClickfinishonConfirmationtabandifeverythingisfinethepopupbelowwillbeshown.ClickOKtoclosethispopup.
BuildFioriMobileApplicat ion
A
LicensingtheSDK
IfyouplantousethecmbSDKtodomobilescanningwithasmartphoneoratablet
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 21/22
(withouttheMXmobileterminal),theSDKrequirestheinstallationofalicensekey.Withoutalicensekey,theSDKwillstilloperate,althoughscannedresultswillbeblurred(theSDKwillrandomlyreplacecharactersinthescanresultwithanasteriskcharacter).
ContactyourCognexSalesRepresentativeforinformationonhowtoobtainalicensekeyincludingtriallicenseswhichcanbeusedfor30daystoevaluatetheSDK.
Afterobtainingyourlicensekeyopeni18n.propertiesfile inyourprojectonSAPWEBIDEservice,andsetyourobtainedkeys.
ThengobacktotheComponent.jsfile andcheckthiscode:
cmbScanner.setConnectionStateDidChangeOfReaderCallback((connectionState)=>{
if(connectionState===cmbScanner.CONSTANTS.CONNECTION_STATE_CONNECTED){
oEventBus.publish("ScanView","SetConnectionStatus",{statusText:"CONNECTED"});
if(window.readerConnected!=connectionState){cmbScanner.setSymbologyEnabled("SYMBOL.DATAMATRIX",true);cmbScanner.setSymbologyEnabled("SYMBOL.C128",true);cmbScanner.sendCommand("SETTRIGGER.TYPE2");}
varsdkKEY="";if(Device.os.android)sdkKEY=this.getModel("i18n").getProperty("MX_MOBILE_LICENSE_ANDROID");elsesdkKEY=this.getModel("i18n").getProperty("MX_MOBILE_LICENSE_iOS");
cmbScanner.registerSDK(sdkKEY,(res)=>{switch(res){casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_OK:break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_INVALID_KEY:break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_INVALID_CHECKSUM:break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_INVALID_APPLICATION:break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_INVALID_SDK_VERSION:
t it le:SAPFioriMobile(v2.6.x);ver:2.6.x 22/22
break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_INVALID_KEY_VERSION:break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_INVALID_PLATFORM:break;casecmbScanner.CONSTANTS.REGISTER_RESULTS.REGISTRATION_KEY_EXPIRED:break;default:break;}});
...........
Youcanseethataftersuccessfulconnectionyoureadthiskeyfromi18n.propertiesandcallcmbScanner.registerSDKmethodtoregisterSDKwithyourlicensekey.
Checkingresultobjectwhichissentbackincallbackfunctioncantellusifregistrationissuccessfulorwhatistheproblem.