September 19th Update: New Screenshots and some minor wording changes based on additional functionality added during the Early Adopter Care phase!
I start this blog with a confession to you, the loyal reader. It’s been a long time since I’ve done any “real” programming. While some of my colleagues might question whether I’ve ever done any real software development, I stipulate that at one point I was at least halfway decent. I’ve always enjoyed creating software, and though I’ve coded with a variety of languages, Java has always been favorite. So when the opportunity came up to joint the SAP Cloud Platform SDK for Android team, I jumped at the chance. After all, I have always been impressed with the power of Android and was happy to get back into some more technical aspects of Product Management. But being the impatient person that I am, I also wanted to be able to contribute quickly, and was worried that it would take me a long time to create anything of any value.
It turns out that I shouldn’t have been, thanks to the SAP Cloud Platform SDK for Android wizard, an Android Studio plugin provided as part of the SDK. Let’s take a closer look.
As one of my colleagues Michael Jess pointed out in his Mobile Services Debugging and Root Cause Analysis Walkthrough blog, a mobile app can be thought of as a distributed system. At a minimum it can be thought of as tiered. Different aspects of the end-to-end solution (since enterprise mobile apps rarely act as a standalone entity) come together when needed to solve a business or technical problem. The SAP Cloud Platform SDK for Android lives in at least two tiers, on the client and on the server. By having SDK components have peers on both tiers, certain things become easier. For example, with a push notification, the backend doesn’t have to know anything about the device the message is being sent to. The backend tells Mobile Services to send a business message to a user, Mobile Services receives the message, knows how and to whom the message should go, and delivers the message. The client layer knows what kinds of messages it receives and from whom should receive them and acts accordingly. Much of this is handled by the SDK automatically. But the developer does need to know how to implement the API to make sure that the app registers for push messaging, listens for and consumes incoming messages. Apply this pattern over multiple areas (authentication, system-of-record access via OData, UI data binding, client usage reporting, logging upload, etc) and there’s quite a bit of code to be written, hundreds if not thousands of lines. Here again the wizard can help.
The purpose of the SDK wizard is to jumpstart your project by creating a large portion of the framework code required to successfully implement your app. Code for basic connectivity, registration, authentication, OData access, Logging, Push….can be created automatically by the wizard. And while a developer will almost certainly implement their own views on top of the SAP Fiori for Android design, we can even create a shell UI so that you understand how everything comes together – the SDK, Mobile Services, the various “backends” and user experience. The developer can then focus on implementing business logic, and if he / she wants to make changes to the code we generate, it’s all right there in a standard Android project.
Let’s walk through the wizard workflow, starting at the very beginning, and describe in some level of detail what comes out of the process.
This screen is presented to the developer any time there is no project open. Using the wizard to create your app is not a requirement, it just makes things much easier! Developers can feel free to create a standard Android project then reference the SDK via making standard changes to the Gradle scripts. But let’s use the wizard, that’s why we’re here!
As I mentioned before, Android SDK apps are built to leverage SAP Cloud Platform Mobile Services. Many client side SDK components have a peer in the platform. In this step you specify the cloud account that your app will connect to. This information is also used by the wizard to read information to be used in later steps in the flow (and can be used to create or manage settings in the cloud account if required). As a developer, you can type the information in ad-hoc, but more likely you’ll want to save this information so that it can simply be re-used later on. Account information is stored on the local machine, since it may contain sensitive information, we encourage you to create a passcode.
The next step might take a little getting used to if you’re just starting as a Mobile Services developer. If you go back to the “distributed system” concept, having cloud and client peers in the SDK, it should make sense to you that a mobile app exists partly on the device and partly in the cloud. On the device side we have the mobile app, on the cloud side we have a mobile application. The client app speaks to a specific Mobile Services application to provide the end-to-end solution. Mobile Services as a whole exposes backend services, we call them features. A particular Mobile Services application is a collection of features that the client app uses. For example, offline data is a feature. Not all apps require offline support, so a particular Mobile Services application may not include the offline feature. The client app would also not leverage the OfflineDataProvider, which is the client side implementation of offline. This is an important concept so I hope it makes sense.
In the wizard, you can re-use an existing Mobile Services application, create a brand new application, or simply use a reference Sample application. If you’re doing this for the first time, the Sample might be a good place to start. It’s a real Mobile Services application, just one that’s pre-defined for your convenience. Why might you choose to use a pre-existing Mobile Services application? Let’s say you are building an app to support Android and iOS. You probably want both apps to have the same basic behaviors, so you might want to re-use an existing Mobile Services application if one was already there.
In my scenario I chose to Create a new one, calling it Manage Products. I also gave it the identifier of com.demo.app.products, and set the Authentication type to Basic. The previous step creates the code to connect the app to the right account, this step creates the code to connect the app to the right Mobile Services application. The wizard will also create all the necessary authentication logic based on the Authentication Type I selected.
Next we specify what backend the mobile app is going to communicate with. Enterprise mobile apps rarely exist standalone, they generally read or write to at least one (possibly many) backend systems of record. In Mobile Services we call backends destinations. If you already have a destination defined, you can select it here. You can pick multiple destinations if the app needs to talk to multiple backend systems. You can even choose to create the destination here if one doesn’t already exist. I chose to use our sample OData service. Using the sample service lets you get an understanding of the process in advance of having an actual backend becoming available.
This is a really important step in the process, so let’s devote at least a little time to it. SAP Cloud Platform Mobile Services apps built on the SDK rely on OData. OData V4 in fact. We provide a set of java packages that then let the developer interact with the OData model as exposed by the service’s metadata. A developer could use this API exclusively to write his application. We call this the Dynamic API (it works with the Metadata API provided in a separate package). This code could in theory be somewhat generic as it relies on standard OData classes like EntitySet, EntityType, EntityValue, EntityContainer, etc. It’s very loosely coupled to the OData service itself. Some developers will prefer that model. But in all likelihood, the mobile app is probably pretty tightly coupled to the OData service, and sometimes supporting loosely typed code can be challenging. And since we’re using OData, we know alot about the data model. For that reason during this step the wizard takes things to the next level by generating proxy classes. Proxy classes encapsulate the Dynamic API and produce strongly typed classes.
Let’s say we have an entity set called Categories with the following EntityType information:
<EntityType Name="Category"> <Key> <PropertyRef Name="ID"/> </Key> <Property Name="ID" Type="Edm.Int32" Nullable="false"/> <Property Name="Name" Type="Edm.String" Nullable="true" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="true"/> <NavigationProperty Name="Products" Relationship="ODataDemo.Product_Category_Category_Products" FromRole="Category_Products" ToRole="Product_Category"/> </EntityType>
Let’s wrap it up shall we? We’re almost done, but there are still some important options here. The first 3 items are some pretty standard stuff related to the Android project itself. But we also have the opportunity here to setup some of the additional Features that the app will use during runtime – Logging (part of the Client Policy Feature) and Push. You can even create your own Firebase messaging account here. We’ll create all the code around your logging selection and around registering for and consuming FCM notifications. Last, if you want to see how it all comes together, leave the Generate UI checked. This will create a reference user experience for one of the Destinations (I only have one here, the sample service). While you probably won’t use our UI as your finished product, it’s definitely worthwhile checking it out as it’ll tell you how everything works together! Last but not least, we will leave “Use Discovery Service for Application Bootstrapping” checked, this will avoid embedding the connection information in the app, which is generally considered bad practice. Rather, the user will enter their email address and based on their email domain and the app id we will retrieve the appropriate configuration information from Mobile Services.
When you click Finish, everything you’ve specified during the wizard flow will be used to create a fully functioning Android project. The app will run right away, connecting to the right cloud account and Mobile Services application. In the reference UI we generate, we’ll present a welcome screen, then you’ll be requested to enter your email address so that Mobile Services can provision the rest of the app settings. Finally you’ll see a EULA (if specified) and prompt you to create a passcode (if a passcode policy was set on the server):
Once your (optional) passcode has been established, the app connect to the backend (via Mobile Services) and show you data in a reference UI.
You can even use the Push Desk to send an Firebase message to your app and it’ll show up.
That, to put it mildly, is not a trivial amount of “stuff”.
Using the SAP Cloud Platform SDK for Android wizard accelerates your productivity, helping you make powerful, elegant Android apps more easily and faster than ever.
And to quote someone very famous….”That’s all folks!”