You are on page 1of 90

OpenMobster - Mobile Cloud Platform

App Developer Guide
openmobster at gmail.com

OpenMobster - Mobile Cloud Platform: App Developer Guide
openmobster at gmail.com 2.4

Table of Contents
1. Introduction to OpenMobster - Mobile Cloud Platform .......................................................... 1 Data Synchronization .................................................................................................. 1 Real-Time Push Notifications ....................................................................................... 1 Mobile RPC (Remote Procedure Call) ............................................................................ 1 Management Console .................................................................................................. 1 2. Mobile Programmer's Dilemma ......................................................................................... 2 ............................................................................................................................... 2 WebApp ("Browser based") Development ....................................................................... 2 Advantages ........................................................................................................ 2 Disadvantages .................................................................................................... 2 App ("Native") Development ........................................................................................ 3 Advantages ........................................................................................................ 3 Disadvantages .................................................................................................... 3 Popular Mobile Platforms (in no particular order of preference or market share) ..................... 3 Blackberry ......................................................................................................... 3 Google Android ................................................................................................. 3 iPhone .............................................................................................................. 3 Symbian ............................................................................................................ 4 Windows Mobile ................................................................................................ 4 ............................................................................................................................... 4 Back to the Future ...................................................................................................... 4 3. Programming Concepts .................................................................................................... 5 Cloud Server ............................................................................................................. 5 Channel ............................................................................................................ 5 MobileServiceBean ............................................................................................. 5 Mobile App Frameworks ............................................................................................. 5 Mobile Data Framework ...................................................................................... 5 Mobile MVC Framework ..................................................................................... 6 Mobile Cloud .................................................................................................... 6 4. Architecture ................................................................................................................... 7 OpenMobster Architecture ........................................................................................... 7 Mobile Cloud Stack .................................................................................................... 8 Sync ................................................................................................................. 8 Push ................................................................................................................. 8 OfflineApp ........................................................................................................ 8 Mobile RPC ...................................................................................................... 9 Network ............................................................................................................ 9 Database ........................................................................................................... 9 Inter-App Bus .................................................................................................... 9 Cloud Server Stack ................................................................................................... 10 5. Get Started: Hello Mobster ............................................................................................. 12 .............................................................................................................................. 12 System Requirements ........................................................................................ 12 Create your first Mobile Cloud App ............................................................................. 12 Developing the Channel ............................................................................................. 12 Step 1: Write the HelloSyncBean ......................................................................... 12 Step 2: Write the HelloSyncChannel .................................................................... 13 Step 3: Configuration ........................................................................................ 15 Developing the Android App ...................................................................................... 16 Step 1: Write the HomeScreen ............................................................................ 16 Step 2: Configuration ........................................................................................ 16

iii

.................................................................................................. 34 Integrating the CloudManager .................................................................................................................................................................................................. 29 OpenMobster Provisioning ........... 19 7.................................................................................................................................................................................................. 19 CloudManager App Installation ............................................................... 32 Add the libraries and Frameworks .................................................................................................................................................................................................................... 20 Cloud-Side: Channel Development ................................................................................................. 29 10.......................................................................................... Production Mode Installation .................................................................................................................................... 39 Cloud Activation .. 38 12............... 20 App/Device-Side: MobileBean component ................................................................................. iOS + OpenMobster Sample App ........................................................................................................................ 26 Cloud-Side ..... 24 8................................................................................................ 18 6.......................................... 26 Accessing a Nested Property .................................................................................. 38 Run the SampleApp ............................... 28 Push Setup on an iOS App ............................ 17 JBoss Deployment ...................... 33 The bootstrapping functions ................................................................ 27 Iterating through an Indexed Property (One-Dimensional Array or a java..................................... 26 Specification .............................. 39 Running the Cloud Server ......................... 32 Introduction ..util........................ 40 Load Synchronized Beans .................................................... 32 Start a View-based App ........................................... 26 Device-Side ................................................................List) ................. 39 Offline App Usage ................. 37 Sample App ................................................................................................................................util... 32 Prepare the mobilecloudlib static library ....................................... 20 Tutorial ................................................................................................ 32 Create a Group called OpenMobster ................................................................................ 19 Cloud-Side: Installation ............................................................................. 26 Accessing an Indexed Property (One-Dimensional Array or a java............................... 37 11......................................................................................................................................... 38 Prepare the mobilecloudlib static library ..............................................................................................................................................Mobile Cloud Platform Running the App ................................................... 39 Installing the Offline App ................................................................................................................. 28 Sending a Push Notification ..........................................................List) ............................................................... Push Programming ................................................................................................................... 27 9............... 26 Accessing a Simple Property ............................................................................................................................................ 29 Apple Provisioning ................................................................................................................................................................................... 26 MobileBean ....................................... iOS + OpenMobster integration ....................... 38 Run the Cloud Server ................................................ 20 ............................................. 39 Introduction ................................................................................................... 36 Implement the action behind the button ............................................ 36 Integrate the CloudManager button on the View .............................................................. 32 Add OpenMobster bootstrap code ...........................................................................................................................................................................................................................................OpenMobster ............................................................................................ 41 iv ...................................................................................................................................................... 40 Add a New Bean to the Sync Channel ... MobileBean ................. PhoneGap: Offline Web Apps using the Sync Plugin ... 19 Device-Side: Installation .......... 38 Introduction ............................... 39 Dissecting the JQuery Offline App ............................................... Sync App Development ............................................................. 19 Install Cloud Server ..................................... 33 Integrating the bootstrapping function with the App Delegate ......................................................................... 28 Push Setup on an Android App ...........................................

....................................................... 59 Add a New Bean into the Sync Channel ...........queryByNotMatchAll ..............................................................sync................... 64 Clear the entries inside an Array/List property .................................plugins................................................................sync....................value .......... 73 Management Console ............. 70 Cloud-Side: Configuration ..............................plugins.... 45 The Channel ..............queryByMatchAll ........................ 62 Commit the operations with the Sync Channel ..........................................plugins.......................OpenMobster .............................................................................window..........................................................................................................................................plugins.....window. 44 Dissecting the Cloud ..............plugins..................................insertIntoArray ....................................plugins.................. 66 Location Aware Apps .......window.......................................................................... 74 13...............window..................sync................................................ 45 The MobileBean ............................................................................ 72 Setup ..............Mobile Cloud Platform Update an existing Bean in the Sync Channel ......................................................................... 55 Execute Query Match All ............................................................................................. 57 Execute Query Do Not Match Even One ............................................................................................. 72 Load Balancing ....... 72 Starting the Cluster ......................................plugins.................queryByMatchOne ..........................plugins.... 54 Introduction ................. 72 Clustering the Cloud Server ................. 18......... 55 Execute Query Match Atleast One .....................sync....... 66 LocationServiceBean ..............window.......................................queryByContainsAll ................................................................. 72 Configuration ................................................ 74 ........readall .. 49 Introduction .................................window......................................................................................plugins...................................... 60 Update a Bean in the Sync Channel ..........window..............................................sync...............................plugins.................sync.............................clearArray .sync.............................................. 66 The App Side Logic ................................................. 63 Get the Length of an Array/List property ........................queryByNotMatchOne ....................... 49 Add OpenMobster bootstrap code ............. 47 PhoneGap + iOS + OpenMobster integration ... 72 High Availability .. 49 Prepare the mobilecloudlib static library ..............................sync............................................................................................. 49 Add the libraries and Frameworks ......................................... 16......................................................................................plugins.............................. 17.............. 65 Location Aware Apps ......... 54 ReadAll .. 51 PhoneGapSync App ................... 57 Execute Query Match Contains All ........................................................................ 67 Processing the Response .....window....sync............................................ 14..... 15.....................................................................................queryByContainsOne...................commit ........window.......................................... 56 Execute Query Do Not Match All .....................................................................................window...... 71 Putting it altogether ......arrayLength ........................deleteBean ........... 74 GUI Functionality ...................plugins.. 63 Insert an object into an Array/List property .......................................sync................... 53 PhoneGap: Sync Plugin Reference .......sync..........plugins.......................sync............................................ 49 Copy JSON components to the App .............................................................................window..............sync..................................................................window....................................................................................... 49 Start a Cordova-based App ....................plugins.........................................................................................addNewBean .updateBean .............. 43 Delete a Bean from the Sync Channel ............plugins...... v ....... 49 Create a Group called OpenMobster .............sync........................ 54 Get a Property Value ....... 70 Cloud-Side: MobileServiceBean implementation . 69 Mobile RPC (Remote Procedure Call) Development .................................................................... 50 Integrating the bootstrapping function with the App Delegate ............................................................ 50 The bootstrapping functions ..................window.. 61 Delete a Bean from the Sync Channel ............................................................. 58 Execute Query Match Contains Atleast One ................................................... 71 Cloud-Side: Packaging and Deployment .....................................................window........................................................................... 71 Clustering ........................ 71 App/Device-Side: Invoking the MobileServiceBean ......................................window.........sync................................

........................................................................................ 75 Services . 74 19......................................... Mobile MVC Framework ...................................................................... 74 Administrators ................. 80 vi ............................................. 75 Components .....................................................................................................................Mobile Cloud Platform Create Account ...................................................... 75 ............................................................................................................................................................................................... 80 Tutorial ............................................................................................................ 74 Push Setup . 74 Devices ..................................................................................OpenMobster ..............................................................................................................................

The Push notifications happen inside the App's execution environment. It does not require any special device-side sync-related programming on the part of the developer. These services are invoked via a simple RPC mechanism without any low-level programming like http-client code.com> OpenMobster is an open source platform for integrating native Mobile Apps with "Cloud" services It provides the following features: Data Synchronization Cloud data is made available to an App's local storage.Mobile Cloud Platform openmobster at gmail. There is a simple RPC API that is used for making these calls. Push notifications are sent via a simple API. It provides security. The Push mechanism uses pure network/socket based approach instead of clunky methodologies like sending sms alerts or email alerts. These state changes are auto detected and synchronized with the Cloud.Chapter 1. etc on the part of the App developer. Introduction to OpenMobster . client side REST library. and account provisioning features. remote tracking. remote lock-down. The data is automatically synchronized with the Cloud service based on local state changes. 1 . It does not require the developer to learn any low-level platform specific services. Real-Time Push Notifications Changes on the Cloud are automatically pushed to the Apps in real time. This allows the App to function seamlessly in both online as well as offline modes. Over time the console will carry device management features like remote wipe. Mobile RPC (Remote Procedure Call) Provides a simple way of exposing your server-side coarse grained business services. It is available via a simple API.com <openmobster@gmail. etc. Management Console A Management Console is provided to administrate the Cloud Server.

each browser renders its content differently depending on the device. Apple with their iPhone release in 2006. Disadvantages • Not a very good user experience.com <openmobster@gmail. Mobile Programmer's Dilemma openmobster at gmail.com> The Mobile Platform is a relatively new beast in the world of computer programming. but for the most part the App is fully reliant on the server and an active network connection. For the longest time (atleast since 1996 that I know of). CSS. After many stop and go linear approaches. The Mobile Computer is turning out to be the next step in evolution of the Personal Computer. Even a delay of a few milliseconds can result in frustration. Run Anywhere flexibility for the developer. A whole new Computer with different architectural rules. WebApp ("Browser based") Development Web App Development involves accessing the Mobile App via a native browser located on the device. Companies lazily expecting their users to adopt "The Browser" on the mobile phone without realizing this is a completely different beast. Advantages • No need to maintain a different codebase for each native mobile platform.Chapter 2. • No App approval process needed. while the mobile browser serves as a dumb terminal rendering just the UI. • Some access via javascript and/or browser plugin is available. the same rule does not translate naturally to the mobile environment. one company changed the game. Plus. • Write Once. Some Javascript/Ajax approaches try to add some thickness to the architecture. In fact that was the very reason why Mobile Internet has been the next big thing atleast for the last 15 yrs. • Uses the same serverside infrastructure as traditional web applications. Even though "The Browser" is a perfectly mainstream gateway to the Internet on a desktop. Same pause on a desktop goes completely ignored. the App executes completely on the server. which can further add to frustration. The network latency on a desktop does not map equally to a mobile device. and user expectations was born. Its ability to feed context sensitive information back into the system unlocks the potential for a whole new world of computing. Just like the PC world. • Does not allow access to all the low level services of the mobile platform that can deliver true innovation. Accessing remote data on the go is not the only real advantage of this new computer. Its a paradigm shift in computer programming. • Web apps don't have the native look and feel which makes the user experience un-intuitive. Users need information quick. but it can never replicate the natural feel of accessing the low level platform API. The notion of native Apps was created. 2 . and Javascript>. companies have tried to come up with ways to squeeze the power of the Internet into a device that conveniently sits in your pocket. Programming can be done using standard web technologies like HTML.

Mobile Programmer's Dilemma • Too much dependence on a network connection. License: Apache 2. and sensors to truly take advantage of a mobile computer that is aware of its surroundings • Offline access to critical data even in the event of network failure • Provide intuitive push based notifications as the state of an App changes remotely Disadvantages • Managing an App codebase across multiple programming languages and platform APIs • No write once. Here are some of the advantages of developing a native app. run everywhere convenience for programmers • Some platforms may require a slightly tedious approval process before installation on an actual device Popular Mobile Platforms (in no particular order of preference or market share) Here is a list of some of the popular smartphone platforms available in the market Blackberry • Programming Language: Java • Operating System: RIMOS (Proprietary/Open API) Google Android • Programming Language: Java • Operating System: Android (Open Source. Advantages • Best user experience with respect to response times and intuitive user interaction • Accessiblity to low level hardware. No offline access to critical data in the event of a network outage.0) iPhone • Programming Language: Objective-C • Operating System: Mac OSX (Proprietary/Open API) 3 . It provides the most flexible approach to implementing complicated functionality and provide the best user experience possible. App ("Native") Development Native App Development involves developing the App using the programming language and APIs provided by the native platform.

Here are some of the ways. HTML5 based native apps are probably a couple of years away from fruition. Only thing that requires porting are the Screen and Command components that are implemented using the native programming language/API. Blackberry OS and Google Android are based on the same 'Java' programming language. this is still an on-going effort at the spec level. a native app is the best route. This makes the API features lot more consistent and only thing that varies across platform code is the syntax of the programming languge. whether to use the native approach or the web based approach is purely a business decision. It takes away the hardwork of writing middleware infrastructure.Mobile Programmer's Dilemma Symbian • Programming Language: C++ • Operating System: Symbian (Open Source. For simple apps that only need to access data via a dumb terminal. innovative native apps. but it can be language-portable.0) Windows Mobile • Programming Language: C#. with all the features and services that are desirable for a native app. The OpenMobster Mobile Cloud Platform aims to deliver the low level infrastructure that provides services needed to build easy to use.Net Programming Languages • Operating System: Windows Mobile (Proprietary/Open API) In other words. and Javascript for event handling code. Most of the GUI level plumbing is provided by the Mobile Cloud runtime. License: Eclipse Public License 1. and CSS for the GUI presentation layer. The code cannot be platform independent. This is in fact possible in theory with HTML5. OpenMobster tries to alleviate some of the disadvantages of native app development • The pluggable nature of the Mobile MVC framework makes it easier to port an app across multiple platforms. However. For instance. • Provide the same exact framework API in case where the programming languages are the same. . so that the app developer can focus their development effort on implementing their business requirements. • Having a consistent messaging spec across all the device level components. HTML5 aims at providing a standard for developing cross platform native apps. This cuts down the porting effort dramatically. native approach is overkill. 4 . and a mobile computer has many differentiating factors that prevent this from happening. This is highly impractical considering we still have not achieved this in a desktop environment. Back to the Future The ideal scenario would be to have a standard API/programming language across all platform for native apps. Only code that would require porting is the code that uses the low level platform API. For complex apps that fully utilize the power of the underlying platform. However. In that case the API of the various frameworks have the same exact syntax. what is possible are native apps that use HTML.

Read. content repositories. receiving push notifications related to state changes on the server. or other mobile-oriented issues. and Delete) interface to expose the backend data. It provides a very simple request/response based synchronous invocation mechanism.com> Cloud Server A Cloud Server is the server-side component of the infrastructure that is located in the 'Cloud'. MobileBean MobileBean is a managed Mobile Component which carries the state of the domain object that it represents on the Cloud. Update. and simple RPC (Remote Procedure Call) mechanism. The Channel is specifically designed such that the Developer does not have to worry about any low-level state management. ERPs etc. Here are its programming concepts: Channel A Channel serves as a gateway for integrating on-device model/data objects with the server-side backend storage systems such as relational databases. The Cloud Server provides a Java based Developer API to expose your data services. MobileServiceBean A MobileServiceBean exposes some coarse grained business process to the on-device Mobile App. It provides a simple CRUD (Create. 5 . synchronizing locally modified beans back with the server. synchronization. the Developer will still be shielded from the low-level programming details regardless of what higher-level services will be supported. security. sync concepts like two-way sync. Programming Concepts openmobster at gmail. real-time push. real-time push notifications. Mobile App Frameworks Mobile Data Framework The Mobile Data Framework provides Cloud data-oriented services like data synchronization. marshalling/unmarshalling payloads etc. or Enterprise systems like CRMs. The Mobile Data Framework shields the App developer from state management issues like. In any case. It is propagated from the Cloud Server to the mobile device via its corresponding "Channel" on the server. The native runtime smartly tracks the changes to the local state of the MobileBean and decides which type of sync is needed. It frees up the developer from all low-level (Remote Procedure Call) concerns like making network connections. offline access. Eventually it will provide more robust REST-based functionality.Chapter 3. From an architecture standpoint it sits between the mobile device and the actual cloud data services being mobilized. and mobile rpc. one-way sync etc.com <openmobster@gmail. Note: This component is quite simple at the time of the milestone M1 release. The system provides mobile-oriented features like data synchronization. The idea is to keep a Channel a purely data-oriented component.

The framework abstracts out some of the low level services into the container such as App bootstrapping. etc. graceful error handling. The Mobile MVC Framework is extensible to support various GUI frameworks. At this point in time of evolution of the mobile space. REST invocations etc. etc.Programming Concepts MobileService MobileService facilitates making RPC (Remote Procedure Call) invocations from the device to the server side 'MobileServiceBean' components. background services. The Cloud Manager App provides configuration functions such as secure Device Activation. there isn't a commonly adopted GUI development standard across various mobile platforms. This helps make better use of device resources like storage. push sockets. It hosts the runtime that is used by the above mentioned App Frameworks.org/wiki/Rich_Internet_application] design principle. This does open the door for integrating cross platform GUI frameworks like standard widgets.wikipedia. Channel Management. going back to the previous screen. network management. an instance of the Mobile Cloud runtime must be installed by bundling it with each App. Mobile MVC Framework This is a thick client MVC (Model-View-Controller) framework. On platforms that support inter-application communication such as Android. Although this framework is not designed for (Write Once. Push Management. Run Anywhere) approach. HTML5 based GUI. ported and maintained by the developer. The Mobile Cloud also comes with a Cloud Manager App. Command Command is an abstraction for an instance of a GUI Event Handler which receives various callbacks based on the screen's lifecycle A command typically puts a business process into motion via accessing various other services like the Mobile Cloud Framework components and/or native platform services. it abstracts out a lot of the UI Framework plumbing that would otherwise need to be written. It presents a simple API to the developer and shields them from low-level networking details. etc. there is a single instance of a Mobile Cloud which is shared by all the Apps installed on the device. Mobile Cloud Mobile Cloud is an on-device native system service. Besides the actual implementation of a "Screen" all services related to a "Screen" are portable across mobile platforms. http libraries. It is based on a Rich Internet Application [http://en. On platforms that do not support inter-application communication. screen navigation. These components are: Screen Screen is an abstraction for an instance of the App screen that must be made visible to the user at a particular moment in time The low level Navigation Manager keeps track of the various screens of an App and provides services such as navigating to a specified screen. Discovering/Installing new Apps. and internationalization. 6 . and going to the home screen. This results in a lot of App porting activity across platforms. There are two types of components in this framework that use a plugin mechanism and receive call backs to perform activities implemented using native platform API.

Chapter 4. Architecture openmobster at gmail.com> OpenMobster Architecture 7 .com <openmobster@gmail.

one way device sync. Push Push service manages state updates being sent as notifications from the Cloud Server. Sync Sync service auto-synchronizes all state changes to App/Moblet Data back with the Cloud Server. Clarification: The Push service is a real time comet based service. one way server sync. When relevant information becomes available on the server. The notifications are received within the context of the App and not as SMS alerts or some other non-intuitive experience. Inter-App Bus. OfflineApp OfflineApp service provided is designed to be an App Developer's best friend. slow sync. Because of the 8 . OfflineApp. vibration. This improves the mobile user's experience as they do not have to pro-actively check for new information. the user is automatically notified via system notifications like a beep. The experience is just like the Blackberry email experience. It provides the following services to Mobile Apps: Sync. Mobile RPC. Network.Architecture Mobile Cloud Stack This is a software stack that is installed on the mobile device. Push. The Cloud Server does not require any special infrastructure like the Blackberry Enterprise Server to make this happen. Database. Its carries the management capabilities to create smart coordination between low-level services like Sync and Push. and boot sync. It supports various synchronization modes such as two way sync. etc.

It carries the smartness to track the type of data being pushed along with which installed App on the device needs the notification. It provides thread-safe concurrent access to the Apps. Depending on the platform in question it uses the corresponding storage facilities. one way device sync. Inter-App Bus Inter-App Bus service provides low-level coordination/communication between the suite of Apps/Moblets installed on the device. etc. This is a very low-level service and an App developer never has to deal with using it directly. Synchronization is something that is managed by the OfflineApp service and it decides which mode of synchronization is the best for the current runtime state of the App. all synchronizations and push notifications are automatically handled by the OfflineApp service. The App developer is shielded from any low level connection establishment. etc by using the higher level Mobile Data Framework components. The App developer does not have to write any special code to receive notifications. Database Database service manages local data storage details for Apps. security. 9 . protocol details. its a low-level service used by the Mobile Data Framework components. The moment the data channel for the App is established. The App developer is never exposed to low level synchronization details like two way sync. It coordinates managing the Push service.Architecture OfflineApp service. It carries the smartness to track coverage and establishes proper connections automatically. It manages the communication channel needed to receive Push notifications from the server. Network Network service manages establishing a network connection with the Cloud Server. Just like the Network service. It is designed to coordinate storage among the suite of Apps/ Moblets installed on the device. the programmer never has to write any code to actually perform any synchronization. Mobile RPC Mobile RPC facilitates making synchronous RPC (Remote Procedure Call) invocations from the device to the server side 'MobileServiceBean' components.

and a SSL-based socket server. Management Console Sync Sync service synchronizes device side App state changes with the backend services where the data actually originates. Secure Socket-Based Data Service Secure Socket-Based Data Service is a high performance socket server based on Java NIO. It provides a plugin framework to mobilize the backend data.apache. Clarification: The push service does not depend on any special infrastructure like a Blackberry Enterprise Server to achieve its functionality. a plain socket server . it waits in a queue. It provides the following services to Mobile Apps: Sync. 10 .Architecture Cloud Server Stack This is a software stack that is installed on the server-side. The service uses the Apache MINA [http://mina. depending on the security requirements of the Apps.org/] network application framework. and delivers the push the moment the device connects back to the network. Push Push service monitors data "Channels" for updates. It uses the concept of a data "Channel" which mobilizes the data in the form of "MobileBean" instances. It provides both. Secure Socket-Based Data Service. corresponding Comet-based notifications are sent back to the device. Its a pure Comet-based approach via a socket channel with the device. The moment updates are detected. Security. Mobile RPC. If the device is out of coverage or disconnected for some reason. Push.

After the device is registered. it is challenged for proper credentials when the device itself needs to be activated. Once the device is activated. remote tracking. 11 . all Cloud requests are properly authenticated/authorized going forward. remote locking. The console provides user and device provisioning functionalities. The components are plugged in as MobileService Beans and the device-side Mobile RPC service invokes them via a simple synchronous request/response based approach. Every device must be first securely provisioned with the system before it can be used. Security Security component provides authentication and authorization services to make sure mobile devices connecting to the Cloud Server are in fact allowed to access the system. Management Console Every instance of a Cloud Server ships with a Command Line application called the Management Console.Architecture Mobile RPC Mobile RPC service on the server-side provides a Remote Procedure Call framework for invoking coarse grained business services of an App. this same component will have more device management features like remote data wipe. etc. In the future.

This information is encapsulated inside a MobileBean instance. lets start with a simple app.google. package com.sync. In your distribution. Configuration is located under src/main/resources/moblet-app.api.hello.bat This will generate a Maven-based skeleton for the Mobile App. Each generated project has the following maven modules: • cloud: Contains the src for the Cloud-side Channel component. and res directory • moblet: This is an assembly component that packages this App into a jar file ready for deployment in a JBoss AS based OpenMobster instance.com> In the spirit of confidence building when using a new technology.sh' (Linux and Mac) to generate a skeleton project appcreator. the Android SDK specific setup is located under AndroidManifest. We will call it the HelloSync app. It does not require any methods to be implemented. System Requirements Cloud Server • Java SE JDK v6. Inside the directory.openmobster. Java code is located under src/main/ java.MobileBean interface. Java code is located under src/main/java. This bean implements the org. 'appcreator.bat' (Windows).Chapter 5. Get Started: Hello Mobster openmobster at gmail. It will be used by the native App on the device side.com <openmobster@gmail.xml.cloud.com/p/openmobster/ downloads/list] .sync. • app-android: Contains the src for the Android App. and configuration is located under src/main/resources.0 Create your first Mobile Cloud App Download an OpenMobster distribution from here: Downloads [http://code. This is a simple marker interface. use a tool called the 'appcreator. Besides the OpenMobster component setup. 12 . go to the directory AppCreator. Developing the Channel Step 1: Write the HelloSyncBean The HelloSyncBean is a simple annotated MobileBean that carries the domain level information that will be synchronized with the device.

@MobileBeanId private String oid. and synchronization issues.message = message. For sake of simplicity. import org.cloud. It provides a simple CRUD (Create.api.Channel interface. implement a small portion of the Implement the org.sync.cloud.MobileBean.openmobster. } public void setOid(String oid) { this. Read. The Channel is specifically designed such that the Developer does not have to worry about any low-level state management. private String message.MobileBeanId.cloud. public HelloSyncBean() { } public String getOid() { return oid. and Delete) interface to expose the backend data.cloud. } public void setMessage(String message) { this. or Enterprise systems like CRMs.openmobster.api.oid = oid. public class HelloSyncBean implements MobileBean { private static final long serialVersionUID = 1L.sync.Get Started: Hello Mobster import org.openmobster.sync.sync. content repositories.api. Update.api.Channel interface 13 . } public String getMessage() { return message. } } Step 2: Write the HelloSyncChannel A Channel serves as a gateway for integrating on-device model/data objects with the server-side backend storage systems such as relational databases. we will only org.openmobster. ERPs etc. email servers.

openmobster.setOid(""+i).util..Get Started: Hello Mobster package com. } return bootupBeans. import org.util. syncBean. import java. syncBean.List. The rest of the beans are synchronized silently in the background without requiring any manual intervention or docking the device to a desktop.sync.openmobster.Usually this will extract the information from a backend for(int i=0.cloud.openmobster.core. Implement scanForNew method @Override 14 . import java.sync.openmobster. • mobileBeanClass: Class of the MobileBean that will be managed via this channel.security. • uri: Unique value for registering the channel with the Channel Framework.Channel. import java.cloud. i++) { HelloSyncBean syncBean = new HelloSyncBean().cloud.sync.ChannelInfo annotation.util..sync. @ChannelInfo(uri="hellosync". This allows instant usage of the App without having to wait a few hours for all the required data to be loaded. } This method only returns the essential beans needed to make the App functional.Date.api. //Just using mock data.openmobster.api.api.hello.device.cloud.setMessage("hello from "+syncBean. import org.sync. bootupBeans.MobileBean. Implement bootup method @Override public List<? extends MobileBean> bootup() { List<HelloSyncBean> bootupBeans = new ArrayList<HelloSyncBean>(). i<5.ArrayList.getOid()).add(syncBean). import org.Device.sync. mobileBeanClass="com. It can be thought of as providing enough information for booting up the App. import org.ChannelInfo.api. etc.hello.HelloSyncBean") public class HelloSyncChannel implements Channel Annotate the channel class with org.

syncBean. return syncBean. "push:2"}... } This method provides a fully loaded MobileBean instance associated with the supplied id.setOid(id). it pushes something every scan. syncBean. Based on that it would send the just new bean ids back.xml file.Just for push demo return new String[]{"push:1". Step 3: Configuration Register this channel using the cloud/src/resources/META-INF/openmobster-config.0"> <bean name="hellosync" class="com.getOid()). Date lastScanTimestamp) { //In this example.0" encoding="UTF-8"?> <deployment xmlns="urn:jboss:bean-deployer:2. This way developer knows to only include beans that may have been created in the backend since this period in time. If not.Get Started: Hello Mobster public String[] scanForNew(Device device.Usually the bean //would be constructed using the data //from a backend service or database HelloSyncBean syncBean = new HelloSyncBean().sync. Implement read method @Override public MobileBean read(String id) { //Just mock data..HelloSyncChannel"> <depends>services://MobileObjectMonitor</depends> <depends>services://MobileServiceMonitor</depends> </bean> </deployment> 15 .. nothing happens on the device side.setMessage("hello from "+syncBean. <?xml version="1. Backend information is linked via the user identity associated with the device • lastScanTimestamp: provides when the last scan occurred.hello. or return null. if nothing new is available. If something new is available. this information is automatically synced and notified on the user's mobile device. } This method checks with the backend service if a new MobileBean instance has been created on the backend connected to by the channel. • device: provides the context around which device should this call apply to.

in the message field String[] ui = new String[helloBeans..i<size... ... android.googlecode... //Show the List of the "HelloSyncBeans" automatically synced and stored on the dev //As a developer you only deal with the MobileBean component...readAll("hellosync").length....i++) { ui[i] = helloBeans[i]. } //Showing the data in the list listApp..getActiveInstance().... In order to keep the tutorial clean.. we will only highlight the aspect that deals with displaying the HelloSyncBeans that are synchronized between the Cloud and the device....simple_list_item_1.Get Started: Hello Mobster Developing the Android App Step 1: Write the HomeScreen Using the OpenMobster MVC Framework requires at the very least a very basic understanding of Android Application Fundamentals [http://developer.java]. This is accomplished using the following snippet of code: @Override public void postRender() { ListActivity listApp = (ListActivity)Registry. A high level understanding of the concept of Activities is a bonus. //No low-level sync stuff to worry about if(MobileBean. The HomeScreen component represents the main/ home screen that is launched when the Android App is launched. ui)).android.... getContext(). The full src code of the HomeScreen component can be found here [http://openmobster..length].getValue("message")...com/guide/topics/fundamentals.layout.R.html]. //Preparing the ui with data stored in the beans. for(int i=0.size=ui. } Step 2: Configuration Configure the Sync and Push systems using app-android/src/resources/openmobster-app.xml <app-conf> <encryption>false</encryption> 16 . } .setListAdapter(new ArrayAdapter(listApp.isBooted("hellosync")) { MobileBean[] helloBeans = MobileBean.com/svn/samples/hellosync/app-android/ src/main/java/com/hello/sync/app/HomeScreen.

install the HelloSync App.sync. Here [http://developer.xml.hello.HomeScreen</screen> </bootstrap> <!-. App Command are fired in response to events generated by user interactions --> <commands> <command id='/hellosync/reset'>com. Under the HelloSync project. androidapp/res/layout/home. <icon-name>push</icon-name> </push> <!-.Get Started: Hello Mobster <push> <launch-activity-class>org.sync.core.xml <moblet-app> <!-.html] are more details about using the Android Emulator emulator -avd droid and ddms • Once the emulator is started and ddms is connected.xml Running the App • Build the whole HelloSync project mvn clean install • Start the Cloud Server.xml. and android-app/res/strings.mobileCloud.Registers the Cloud channels used by the App --> <channels> <channel name='hellosync'/> </channels> </app-conf> Configure the OpenMobster MVC Framework used by this App using app-android/src/resources/ moblet-app/moblet-app. go to the cloud directory. Go to the app-android directory and type in: 17 .android_native.Registers the home/main screen of the app --> <bootstrap> <screen>com.framework.ResetChannel</command> </commands> </moblet-app> Android platform specific configuration can be found under: android-app/AndroidManifest.Registers App Commands with the OpenMobster Command Framework.hello.openmobster.app.app. and type in: mvn -PrunCloud integration-test • Start the Android emulator.com/guide/developing/tools/emulator.android.

Get Started: Hello Mobster mvn -Papp-hot-deploy install • Launch the HelloSync App. You can change this value in the moblet/ pom.GA AS. you can aggregate all these artifacts into a single jar ready for deployment into a JBoss AS based Cloud Server. This is a security measure to make sure only securely authenticated users are allowed to access the data in the Cloud.com/ svn/samples/hellosync-2. • You can download the entire HelloSync App here: HelloSyncApp [http://openmobster.0.zip] JBoss Deployment Once the App and its corresponding Cloud artifacts are developed and tested end-to-end. For instructions on setting up your JBoss instance please see JBoss Setup. • Go to the moblet module: cd moblet • Generate the app and deploy into the JBoss AS instance: mvn -Pjboss-install install Note: Before executing this deployment command you will need to make sure that the jboss.googlecode.xml file 18 .4. This single artifact when deployed into the JBoss AS based Cloud Server performs all necessary registrations with the system and is ready for deploying the app onto a real device via the Internet. • At first launch you will be guided through an Activation process of the App with the Cloud Server.1.home property is properly set to your location of the JBoss 5.

0.xml according to your own MySql5 instance • Step 4: Start the JBoss AS instance with the OpenMobster binary installed using: run -c openmobster -b "a real IP address" Note: A real IP address like "192.org/jbossas/downloads/] • Step 2: Copy openmobster to the JBoss AS server directory.0.1" or something like that is needed for the mobile device to be able to connect to the server.com> Cloud-Side: Installation Install Cloud Server • Step 1: Download and install JBoss-5. there is no requirement to install the CloudManager App on the device. The main purpose is to activate device management features such as: Remote Wipe and Remote Lock. modify openmobster-ds.1" • Step 5: Verify the Cloud Server installation by typing in: http://{cloudserverIp}:{port}/o Device-Side: Installation Starting with OpenMobster 2.0. you can simply download CloudManager App from the built-in browser of the device.1.4.com <openmobster@gmail. Download the following and follow the instructions provided by the device: • http://{cloudServer IP}:{cloudServer port}/o/android/cloudmanager Installing the Sample Offline App Using your CloudManager App . the device's browser does not connect to a loopback address like "localhost" or "127.0. install the deployed Apps using the Corporate App Store option 19 . Even in the case of a simulation environment. Production Mode Installation openmobster at gmail. openmobster is a pre-configured/optimized instance for the OpenMobster Cloud Server • Step 3: In the case of using MySQL5 as the database.GA from here [http://www.jboss.168. The CloudManager App does still serve a purpose. You also get access to the Corporate App Store functionality which makes it easy to download/install apps from the OpenMobster App Store. CloudManager App Installation If you have a Cloud Server running and accessible from the Internet. All you need to do is install your App and it will automatically take care of the Activation process.Chapter 6.

• This data is available to the mobile App even in the event the Cloud is unavailable.MobileBeanId. private String demoString. //used to demonstrate mobilizing a simple property of t private String[] demoArray. and synchronization issues. The closer this data is stored. This MobileBean should adhere to the MobileBean specification covered here: Specification import java. ERPs etc. A major advantage of this environment is access to local storage for data associated with the App.api.openmobster. content repositories.sync. and Delete) interface to expose the backend data.openmobster. Without the data. If logic is the nervous system of an App.util. Step 1: Define a simple MobileBean to represent a data entity being mobilized. • App related data is synchronized from the Cloud with the local storage over a network connection. • Any data state changes (add/update/delete) on the Cloud are pushed/synchronized with the device.cloud. //used to demonstrate mobilizing of an indexed propert 20 .api. or Enterprise systems like CRMs. • Any data state changes (add/update/delete) via the App are synchronized with the Cloud.cloud. The OpenMobster Cloud Platform uses a "Channel" component on the Cloud-side and a MobileBean component on the Device-side to provide the above mentioned offline capabilities to an App Tutorial Cloud-Side: Channel Development A Channel serves as a gateway for integrating on-device model/data objects with the server-side backend storage systems such as relational databases. Sync App Development openmobster at gmail. Read.com <openmobster@gmail. The Channel is specifically designed such that the Developer does not have to worry about any low-level state management. A typical Mobile App has the following data-oriented requirements • Data originates in the Cloud.Chapter 7. an App is lifeless. import org.sync. Update.MobileBean. data is its life blood.List. import org. the faster and better is the performance of the App.com> A native Mobile App runs within the constraints of its local runtime. It provides a simple CRUD (Create. public class DemoBean implements MobileBean { @MobileBeanId private String beanId. Local Storage brings an App to life instantaneously.

@ChannelInfo(uri="/offlineapp/demochannel". } public void setBeanId(String beanId) { this. 21 .beanId = beanId. } } Step 2: Provide a Channel implementation that exposes this MobileBean via a CRUD interface.demoArray = demoArray. } public List<String> getDemoList() { return demoList. } public void setDemoArray(String[] demoArray) { this.demoList = demoList. } public void setDemoString(String demoString) { this. //used to demonstrate mobilizing an indexed propert public DemoBean() { } public String getBeanId() { return beanId.Sync App Development private List<String> demoList. } public void setDemoList(List<String> demoList) { this. } public String[] getDemoArray() { return demoArray. } public String getDemoString() { return demoString.demoString = demoString.

getData().getData(). They provide just enough information for an App to be functional.DemoBean") public class DemoChannel implements Channel bootup This method provides a subset of the "MobileBean" instances associated with the said device.core. } read This method loads the particular "MobileBean" instance in question. public List<? extends MobileBean> readAll() { List<MobileBean> list = new ArrayList<MobileBean>().demoRepository.add(bean).get(beanId)). //Just get only the top 5 beans to bootup the service on device side //This decision is App-specific for(int i=0. i++) { DemoBean bean = this. list. This helps with avoiding very long synchronization sessions.Sync App Development mobileBeanClass="org.demoRepository.demoRepository. The other beans are loaded on-demand from there on public List<? extends MobileBean> bootup() { List<MobileBean> list = new ArrayList<MobileBean>(). for(String beanId: beanIds) { list.keySet(). i<5.openmobster.get(""+i).add(this. } return list.offlineapp.demoRepository.examples. 22 .getData().getData(). } readAll This method provides all the "MobileBean" instances associated with the said device. //Get All the Beans associated with this Channel for this Device Set<String> beanIds = this.get(id). public MobileBean read(String id) { return this. } return list.

getData().xml that will deploy the "Channel" into the Cloud Server. It returns the unique id generated by the server and associated with this bean.put(updatedBean. public void delete(MobileBean mobileBean) { DemoBean deletedBean = (DemoBean)mobileBean. } delete Deletes a bean instance that is user confirmed to be deleted from the device.getData(). 23 .getBeanId(). } Step 3: Provide the META-INF/openmobster-config.demoRepository. return newBeanId. This bean was created on the Device and is being //synchronized with the backend cloud service String newBeanId = String.remove(deletedBean.getDemoRepository(). //Generate a new unique bean Id.put(newBeanId. public String create(MobileBean mobileBean) { DemoBean newBean = (DemoBean)mobileBean. newBean.setBeanId(newBeanId).getData(). public void update(MobileBean mobileBean) { DemoBean updatedBean = (DemoBean)mobileBean. } update Synchronizes the updated state of a bean from the device with the state on the Cloud. this.getData(). this.size()).demoRepository.demoRepository.valueOf(this. updatedBean).getBeanId()). This happens when a new instance is created on the device and synchronized back with the Cloud.Sync App Development } create Creates a new instance of a "MobileBean" within the backend data service. newBean). this.

Chances are some of the instances are only proxies that will be loaded seamlessly when they are really needed on-demand.MobileBean component. Device-side MobileBean component semantic are covered here:Specification Here are some simple methods to access a MobileBean on the device • readAll: Returns all MobileBean instances associated with a channel. for(int i=0.examples.readAll("/offlineapp/demochannel").core. The device-side MobileBean is a generic component which exposes a Cloud-side MobileBean information through a robust interface.offlineap <bean name="/offlineapp/demochannel" class="org. this data is accessible via the org. i<size. This process happens behind the scenes and there is nothing special a programmer needs to do.isProxy()) { actions. i++) { if(!demoBeans[i]. } else { actions.android.xml into a simple jar file. actions = new Vector().api.0"> <bean name="/offlineapp/demorepo" class="org.length.0" encoding="UTF-8"?> <deployment xmlns="urn:jboss:bean-deployer:2.offlin <property name="demoRepository"><inject bean="/offlineapp/demorepo"/></propert </bean> </deployment> Step 4: Package the the above classes and the corresponding META-INF/openmobster-config.sync.openmobster.Sync App Development <?xml version="1.addElement(demoBeans[i]. MobileBean[] demoBeans = MobileBean.getId()+": proxyState").addElement(demoBeans[i].examples.getValue("demoString")). } } 24 . Step 5: Deploy this jar file into the "deploy" directory of your JBoss AS instance Putting it all together The end-to-end Channel Example is located in the binary distribution at: Samples/offlineapp/cloud App/Device-Side: MobileBean component On the device side.openmobster.core. int size = demoBeans.openmobster.

demoBeans[i]. • setValue: Updates the field/property of an instance of a bean.setValue("demoString".Sync App Development • getValue: Reads the value associated with a field/property of an instance of a bean. A property expression and its value are provided.getValue("demoString"). A property expression is provided to access this information. This particular method call reads the "demoString" property of the corresponding Cloud-Side MobileBean instance covered earlier. For a more detailed coverage of the MobileBean usage. "new updated value"). demoBeans[i]. please see some example code in the binary distribution located at: Samples/offlineapp/app-android 25 .

api. MobileBean openmobster at gmail.myStreet on a bean. the following expression is used: MobileBean.sync. The Mobile Data Framework shields the App developer from state management issues like. offline access. The individual properties of a bean are accessed using simple and intuitive expressions. Accessing a Simple Property For a simple property myName on a bean.Chapter 8.List properties of Concrete Types. etc.api. Through the channel instances of these beans are serialized into wire format and propagated to their respective devices. It provides various state-oriented operations. Cloud-Side On the Cloud-Side the MobileBean is a simple Java Object that implements the org. One-Dimensional Array property. In order to be successfully serialized/deserialized.sync. Specification • The system successfully processes the following properties of a bean: Simple Property.com> MobileBean MobileBean is a managed Mobile Component which carries the state of the domain object that it represents on the server. and Parameterized java. The concept of a MobileBean applies to both sides of the world.com <openmobster@gmail.MobileBean component is used to extract the state associated with each instance. the following expression is used: 26 . Cloud-Side as well as Device-Side. • MUST contain an empty constructor • MUST contain provide public get and set methods for each one of its properties Device-Side On the Device-Side the MobileBeans from a channel are made accessible via the Mobile Data Framework. • Array PropertiesMUST NOT contain Null elements.getValue("myName"). Nested Property. they should follow the proper specification.openmobster. The generic org.android. synchronizing locally modified beans back with the server.cloud.util.openmobster. It is propagated from the Cloud Server to the mobile device via its corresponding Channel on the server. The MobileBean is processed by its corresponding Channel. Accessing a Nested Property For a nested property myAddress.MobileBean interface. receiving push notifications related to state changes on the server.

MobileBean

MobileBean.getValue("myAddress.myStreet");

Accessing an Indexed Property (One-Dimensional Array or a java.util.List)
For an indexed property "myName" on the "third element" of an Array or List named "users" on a bean, the following expression is used:

MobileBean.getValue("users[2].myName");

Iterating through an Indexed Property (One-Dimensional Array or a java.util.List)
private void iterateEmails(MobileBean mobileBean) { BeanList emails = mobileBean.readList("emails"); for(int index=0; index<emails.size(); index++) { BeanListEntry email = emails.getEntryAt(index); System.out.println(email.getProperty("from")); System.out.println(email.getProperty("to")); System.out.println(email.getProperty("subject")); System.out.println(email.getProperty("message")); } }

In the background, the state of all device-side MobileBean instances is tracked by the OfflineApp service. Any state updates are automatically synchronized back with its Cloud-Side channel using the appropriate synchronization mode. As far as the App developer is concerned, they just update this state locally and go about their business.

27

Chapter 9. Push Programming
openmobster at gmail.com <openmobster@gmail.com>

Sending a Push Notification
You can send a push notification from the cloud using the Push API. This API is located on the org.openmobster.cloud.api.push.PushService object. On this object you use the following method

/**

* A device agnostic Push method. Push is associated with the user and not * * @param identity user that must receive this message * @param appId unique application id this push is associated with * @param message message to be sent * @param title title of the message * @param details any other details associated with the message */ public void push(String identity, String appId, String message, String titl

Push Setup on an Android App
You can setup Push Notification support in your app via two configuration files. Before we go into those details you must understand that there are two types of push notifications. User Initiated Push notification using the PushService API, and Sync Initiated Push Notification which is generated by the Sync Engine. Configuration:AndroidManifest.xml

<receiver android:name="org.openmobster.core.mobileCloud.api.ui.framework.push <intent-filter> <action android:name="org.crud.android.app"/> </intent-filter> </receiver>

<receiver android:name="org.openmobster.core.mobileCloud.api.ui.framework.p <intent-filter> <action android:name="org.openmobster.sync.push"/> </intent-filter> </receiver>

First you setup the user initiated push notification receiver. In the action value you have to make sure its the same as the name of the unique package that identifies this application. Next, you will setup sync initiated push notifications. There is no extra configuration to keep in mind here.

28

Push Programming

openmobster-app.xml

<push>

<launch-activity-class>org.openmobster.core.mobileCloud.android_nat <icon-name>push</icon-name> </push>

Here, launch-activity-class indicates the activity that must be launched when the user clicks on the notification from the notification bar icon-name points to a drawable image that should be displayed as an icon with the notification.

Push Setup on an iOS App
This is a guide to integrate the iPhone Apple Push Notification (APN) based system with the OpenMobster? Push Service. It consists of several provisioning steps from the Apple side and integration via the Management Console on the OpenMobster? Side.

Apple Provisioning
Step 1: Obtain the Application Certificate
In order to push via the APN service, the provider side (OpenMobster?->APN connection) requires a certificate for each App registered for Push Notifications. The best instructions for doing the proper provisioning and obtaining a certificate is explained at : http://mobiforge.com/developing/story/ programming-apple-push-notification-services.

Step 2: Getting an aps_production_identity.p12 certificate
Once you have downloaded the aps_production_identity.cer file from the Apple Provisioning Portal • Import the aps_production_identity.cer into the KeyChain?. Double-clicking the file will do it • Select both certificate and private key (associated to the application you wish to use to send notifications) • Right click, and select Export 2 elements, give a name (for example : aps_production_identity.p12) and password (for example : p@ssw0rd) and then export as p12.

OpenMobster Provisioning
• Step 1: Register the App and the Device Token On the OpenMobster? side, Apps that want Push notifications must be registered with the OpenMobster? system. The Device Token is also needed to be registered as it is a requirement for the Apple Push Notification Service. This registration is as follows:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWith // Override point for customization after application launch.

29

Push Programming

// Add the view controller's view to the window and display. [self.window addSubview:viewController.view]; [self.window makeKeyAndVisible]; //Bootstrap the Cloud services [self startCloudService]; //This registers the App for Push Notifications [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)]; return YES; }

If the registation is successful a callback is invoked on the delegate. It goes as follows:

- (void)application:(UIApplication *)app didRegisterForRemoteNotificatio {

NSString *deviceTokenStr = [NSString stringWithFormat:@"%@",deviceToken]; deviceTokenStr = [StringUtil replaceAll:deviceTokenStr :@"<" :@""]; deviceTokenStr = [StringUtil replaceAll:deviceTokenStr :@">" :@""]; NSLog(@"DeviceToken: %@",deviceTokenStr); @try { SubmitDeviceToken *submit = [SubmitDeviceToken withInit]; [submit submit:deviceTokenStr]; } @catch (SystemException * syse) { UIAlertView *dialog = [[UIAlertView alloc]

initWithTitle:@"Token message:@"Device Token delegate:nil cancelButtonTitle:@"OK dialog = [dialog autorelease]; [dialog show]; } }

These two operations registers the Application for Push notifications both on the device and on the OpenMobster? Push Service.

30

Push Programming

• Step 2: Upload the certificate .p12 file • Login to the Management Console: http://cloud-server-address/console • Select Push Setup • Find the App associated with this certificate • Upload the certificate and supply its password • If successfull, the icon next to the App will turn green • Step 3: Send a Test Push • Click on the App • Click the 'Test Push' button • Select the 'Device' where it should be sent • You should receive a Push alert on your phone

31

You must change this option to "Location Specified By Targets". Please take a look at this thread for details: https://groups.framework • CFNetwork.framework • CoreGraphics.xcodeproj • Build the project in XCode For some reason.com> Introduction As of version 2.com/forum/#!searchin/openmobsterusers/mobilecloudlib/openmobster-users/zJhJKbFekLs/WiNWtKfG_RcJ XCode project by opening: iPhone/mobilecloudlib/ Start a View-based App • Go to File>New Project. Here are some tips related to iOS and OpenMobster integration Prepare the mobilecloudlib static library • Open the mobilecloudlib mobilecloudlib. building the mobilecloudlib fail to compile if your XCode code location is set to the recommended setting of "Derived Data".a .framework 32 .google. iOS + OpenMobster integration openmobster at gmail.com <openmobster@gmail.framework • UIKit. DragnDrop/Copy all the resources located under the app-bundle group Add the libraries and Frameworks In the Frameworks group add the following library and Frameworks • libmobilecloudlib. iOS is fully supported by OpenMobster.Chapter 10.2-M1. In the displayed project templates select the View-based Application and follow the wizard Create a Group called OpenMobster • Create a New group named OpenMobster • From the mobilecloudlibproject.OpenMobster static library • CoreData.

} @catch (NSException * e) { //something caused the kernel to crash //stop the kernel [self stopCloudService]. The following code shows how this bootstrapping process works. It must be bootstrapped and started. } } Stop Cloud Service -(void)stopCloudService { @try { CloudService *cloudService = [CloudService getInstance]. The bootstrapping functions Start Cloud Service -(void)startCloudService { @try { CloudService *cloudService = [CloudService getInstance].iOS + OpenMobster integration Add OpenMobster bootstrap code Before OpenMobster runtime can be used within an App. [cloudService shutdown]. } @catch (NSException *e) { } } Start Device Activation if it is not activated with the Cloud already -(void)startActivation 33 . [cloudService startup].

(BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions .window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] // Override point for customization after application launch. [cloudService forceActivation:self.viewController]. CommandService *service = [CommandService getInstance]. self.(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSD { //OpenMobster bootstrapping [self startCloudService].window. BackgroundSyncCommand *syncCommand = [BackgroundSyncCommand withInit]. } } Do a Sync at Startup -(void)sync { CommandContext *commandContext = [CommandContext withInit:self.rootViewController].viewController = [[[ViewController alloc] initWithNibName:@"ViewContro 34 . [commandContext setTarget:syncCommand]. } @catch (NSException * e) { //something caused the kernel to crash //stop the kernel [self stopCloudService]. [self sync]. if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { self.iOS + OpenMobster integration { @try { CloudService *cloudService = [CloudService getInstance]. } Integrating the bootstrapping function with the App Delegate . [service execute:commandContext].

leftBarButtonItem = but [button release].topViewController.iOS + OpenMobster integration } else { } self.navigationItem. //Register the App for Push notifications [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)]. he */ //OpenMobster bootstrapping [self sync]. self.topViewController.navigationItem. //Add the Create button to the nav bar UIBarButtonItem *create = [[UIBarButtonItem alloc] initWithTitle:@"Create" styl self.navigationController.rootViewController = self.rightBarButtonItem = cr [create release]. } -(void)applicationWillEnterForeground:(UIApplication *)application .window makeKeyAndVisible].navigationController.navigationController. [self.navigationController = [[UINavigationController alloc] initWithRootViewCon //Add the CloudManager button to the navbar UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Cloud Manager" self. return YES. //OpenMobster bootstrapping [self startActivation].viewController = [[[ViewController alloc] initWithNibName:@"ViewContro //setup the NavigationController self. 35 .window.(void)applicationWillEnterForeground:(UIApplication *)application { /* Called as part of the transition from the background to the inactive state.

navigationItem. See also applicationDidEnterBackground:.(void)applicationWillTerminate:(UIApplication *)application { /* Called when the application is about to terminate.View. This can come in handy when you want to do some Manual Syncing in case there are issues happening with the automatic Sync process.leftBarButtonItem = butt [button release].navigationController = [[UINavigationController alloc] initWithRootViewControl //Add the CloudManager button to the navbar UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Cloud Manager" s self. You can activate your device with the Cloud and you can manage the Sync Channels used by your App. Save data if appropriate.pushRegistered) { [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)].iOS + OpenMobster integration if(!self.topViewController. The CloudManager is an administrative GUI tool that allows some provisioning functions. } Integrating the CloudManager As an App Developer you can integrate the CloudManager functionality within your App. Here are the integration steps Integrate the CloudManager button on the View //setup the NavigationController self. */ //OpenMobster bootstrapping [self stopCloudService]. This GUI layer integration is done by activating the Modal. 36 .navigationController.Controller CloudManager component. } } -(void)applicationWillTerminate:(UIApplication *)application .

the App to run is located under iphone/showcase/cloud. You run the Cloud Server using the command mvn -PrunCloud integration-test 37 . you can find an iOS/OpenMobster Sync App under iphone/SampleApp. } Sample App In the OpenMobster distribution. On the Cloud Side.iOS + OpenMobster integration Implement the action behind the button -(IBAction)launchCloudManager:(id)sender { //Launch the CloudManager App [CloudManager modalCloudManager:self].

Once the Build is successful.xcodeproj • Build the project in XCode For some reason.com <openmobster@gmail.Chapter 11. building the mobilecloudlib fail to compile if your XCode code location is set to the recommended setting of "Derived Data". Under this directory issue the following command to start the Cloud Server required by the sample app mvn -PrunCloud integration-test Run the SampleApp Open the XCode project located under iphone/SampleApp. Build the project to make sure there are no errors. If this is the first time running the App. This is to securely setup your Cloud account so that you can acess the Enterprise resources in the Cloud. iOS + OpenMobster Sample App openmobster at gmail. it will present a device activation screen. You must change this option to "Location Specified By Targets".google.com> Introduction This chapter covers the steps involved in running the iOS + OpenMobster based Sample App Prepare the mobilecloudlib static library • Open the mobilecloudlib mobilecloudlib. by default) Email Address: Your email address to uniquely identify you with the Cloud Password: Your password to authenticate with the Cloud This is a one time activation across all your apps. It asks the following information Cloud IP: The IP address of the Cloud Server Port: The port that the Cloud Server is running on (1502.com/forum/#!searchin/openmobsterusers/mobilecloudlib/openmobster-users/zJhJKbFekLs/WiNWtKfG_RcJ XCode project by opening: iPhone/mobilecloudlib/ Run the Cloud Server Go to iphone/showcase/cloud. Please take a look at this thread for details: https://groups. Run the project. 38 .

Installing the Offline App 39 . The Sync Plugin exposes the native Sync service to the JavaScript layer using the PhoneGap bridge technology. PhoneGap leverages web technologies developers already know best. HTML and JavaScript.phonegap.2-M8. This is done using a CloudManager App that comes with the OpenMobster distribution. Cloud Activation For security reasons. before apps can use the OpenMobster Cloud. you can write offline web apps with synchronization of data using the OpenMobster Sync Plugin for PhoneGap. The rest of this chapter will discuss how to use the Sync Plugin using a JQuery based sample offline application. Starting with OpenMobster 2. You can install this App on the Android device or emulator using the following command: adb install -r CloudManager.com <openmobster@gmail..apk.com] is an HTML5 app platform that allows you to author native applications with web technologies and get access to APIs and app stores.com> Introduction PhoneGap [http://www. the device must be registered with the cloud. Offline App Usage Running the Cloud Server cd PhoneGap/plugin-jquery-cloud mvn -PrunCloud integration-test This should make the OpenMobster Cloud Server up and running for the Offline App.Chapter 12. PhoneGap: Offline Web Apps using the Sync Plugin openmobster at gmail. You can locate this App in the distribution under Android/core-runtime/CloudManager.apk Once installed you can use the Activate function to register with the Cloud..

apk Dissecting the JQuery Offline App Load Synchronized Beans //read the oids of the tickets stored in the sync channel window. function(oids) { if(oids == '0') { return. } }. //read the value of the 'title' property of the synchronized bean window. function(value) { var encodedOid = encodeURIComponent(oid). function(error) { } ).plugins.'title'. function(error) { alert('Sync Plugin:'+error).sync. i++) { var oid = oids[i].oid.length. } oids = JSON.readall(channel. //create a list item corresponding to the ticket in question html += '<li><a href="#read_ticket?oid='+encodedOid+'" data-rel="dialog" }.parse(oids). var length = oids. 40 . This function reads the oids of the beans and then iterates through each bean and extracts the title property. window. for(var i=0.sync.plugins.sync.readall(channel. i<length.PhoneGap: Offline Web Apps using the Sync Plugin adb install -r JQueryOfflineApp. } ).plugins.value(channel.

} oids = JSON. function(error) { } ).'customer'.sync.title. oids are then parse into a JavaScript object using the JSON.tempoid.updateBean(channel.value(channel.customer.updateBean(channel. //read the value of the 'title' property of the synchronized bean window.sync. function(success) { 41 .parse function.plugins.'title'.'title'.tempoid.sync. If the function is successful it returns an array of oids in JSON format. window.sync.oid. It takes the channel name and the oid of the bean as arguments to locate the bean whose property is to be read.parse(oids).plugins. function(tempoid) { window. function(value) { var encodedOid = encodeURIComponent(oid).plugins. //create a list item corresponding to the ticket in question html += '<li><a href="#read_ticket?oid='+encodedOid+'" data-rel="dialog" }.plugins. window.addNewBean(channel. Add a New Bean to the Sync Channel window. Invokes the readall function and reads the oids of all the beans stored in the sync channel. function(error) { }). function(success) { }.sync.value reads the value of the specified title property.PhoneGap: Offline Web Apps using the Sync Plugin function(oids) { if(oids == '0') { return.plugins.

sync.updateBean(channel. function(success) { }.tempoid.sync. The method returns a temporary oid used to refer to this newly added bean.specialist.plugins. function(error) { }).updateBean(channel. //Commit here window.plugins. }). its properties are updated and committed to the Sync Engine for synchronization window. function(error){ alert("Ticket Add Error:"+error).plugins.sync. window.addNewBean creates a new bean into the Sync Channel.plugins. window.PhoneGap: Offline Web Apps using the Sync Plugin }. Once the bean is created. }.'specialist'. function(error) { }). window. function(tempoid) { window.sync.title.updateBean(channel. function(success) 42 . The above code creates a new bean in the Sync Channel. function(error) { }).comments.plugins.sync. function(success) { }. }.'comments'.commit(function(success) { alert("Ticket was successfully added").plugins.tempoid.'title'.sync. }).addNewBean(channel. function(error) { alert("Sync Plugin:"+error).tempoid.

val().title. //update the 'customer' property on the ticket bean window.PhoneGap: Offline Web Apps using the Sync Plugin { }. function(error) { }).plugins.sync. function(error) { }).oid. function(error){ alert("Ticket Add Error:"+error).sync.commit(function(success) { alert("Ticket was successfully added").customer.tempoid.plugins.sync.updateBean(channel.sync. window.plugins.commit commits the beans into the Sync Channel for synchronization Update an existing Bean in the Sync Channel var oid = $('#update_ticket_oid').customer. window.updateBean(channel. In this case it modifies the title property on the newly added bean referred to by tempoid. //update the 'title' property on the ticket bean window. function(success) { }.'customer'. }.plugins.updateBean updates the specified property on the bean referred to by its oid.plugins.sync.updateBean(channel. function(success) { }.oid.sync.'title'. }).plugins. function(success) { 43 . //Commit here window.'customer'. window. function(error) { }).

updateBean(channel.sync. function(error) { }).oid.plugins. function(success) { }.plugins.commit(function(success) 44 . //commit window.sync.plugins. function(success) { //commit window. //update the 'comments' property on the ticket bean window. This is very similar to the add new bean explanation above. }).commit(function(success) { alert("The Ticket was successfully saved").sync. }.'comments'.specialist. function(error) { }).sync.val().PhoneGap: Offline Web Apps using the Sync Plugin }.deleteBean(channel. //delete this bean window.sync.plugins. It updates each property of the bean and then calls commit to get the bean synchronized with the Cloud. function(success) { }.comments.oid.plugins.updateBean(channel.oid.'specialist'. Delete a Bean from the Sync Channel function deleteTicket() { var oid = $('#read_ticket_oid'). //update the 'specialist' property on the ticket bean window. function(error) { }). function(error){ alert('Ticket Update Failed: '+error).

false).'slide'.sync.}). comments.commit commits this change into the Sync Channel and prepares for synchronization with the Cloud. Dissecting the Cloud The MobileBean public class JQueryBean implements MobileBean. }. } window.Serializable { @MobileBeanId private String oid.plugins.mobile. function(error){alert("Ticket Delete Failed: "+error). } ).PhoneGap: Offline Web Apps using the Sync Plugin { alert("The Ticket was successfully deleted"). This is the component which will be injected into the Sync Channel.changePage('#tickets'. function(error) { alert("Ticket Delete Failed: "+error). window.plugins. Full Source of the MobileBean implementation public class JQueryBean implements MobileBean. The MobileBeanId annotation specified that the oid field will serve as the unique object identifier for these beans. $.true. }. private private private private String String String String title. Creates a MobileBean by implementing the MobileBean interface. It will then be accesssed on the device via the Sync Plugin API. specialist.deleteBean deletes the bean referred to by the oid on the specified channel.Serializable { @MobileBeanId private String oid.sync. public JQueryBean() { 45 . customer.

oid = oid. } public String getCustomer() { return customer.comments = comments.title = title.customer = customer.specialist = specialist. } } 46 . } public void setOid(String oid) { this. } public String getComments() { return comments. } public void setSpecialist(String specialist) { this. } public void setTitle(String title) { this. } public void setComments(String comments) { this. } public String getTitle() { return title. } public String getSpecialist() { return specialist.PhoneGap: Offline Web Apps using the Sync Plugin } public String getOid() { return oid. } public void setCustomer(String customer) { this.

read(id). The MobileBean instances used by the Channel implementation must be instances of this specified class. Update.core.mobileBeanClass specifies the class of the MobileBean instance that the channel will be dealing with. @ChannelInfo(uri="plugin_jquery_channel".pho public class PluginJQueryChannel implements Channel The ChannelInfo. } @Override public List<? extends MobileBean> bootup() { return this.isEmpty()) { for(Object bean:all) { beans. Delete) interface.readAll(). List<JQueryBean> beans = new ArrayList<JQueryBean>().objectStore. If this rule is not followed there will be unexpected errors during the synchronization process.readAll().objectStore. } } return beans. } Create the MobileBean 47 .add((JQueryBean)bean). } @Override public MobileBean read(String id) { return (JQueryBean)this. Read the MobileBeans @Override public List<? extends MobileBean> readAll() { Collection<Object> all = this.openmobster. Read. if(all != null && !all.uri specifies the name of the Sync Channel and ChannelInfo. mobileBeanClass="org.PhoneGap: Offline Web Apps using the Sync Plugin The Channel The Channel is the component that exposes the MobileBeans to the Sync Engine via a CRUD (Create.

objectStore.objectStore. } Update the MobileBean @Override public void update(MobileBean mobileBean) { JQueryBean toUpdate = (JQueryBean)mobileBean. toCreate).save(toCreate.delete(toDelete. return this.objectStore.PhoneGap: Offline Web Apps using the Sync Plugin @Override public String create(MobileBean mobileBean) { JQueryBean toCreate = (JQueryBean)mobileBean. } Delete the MobileBean @Override public void delete(MobileBean mobileBean) { JQueryBean toDelete = (JQueryBean)mobileBean.getOid(). this. } 48 .getOid(). toUpdate).getOid()).save(toUpdate. this.

The Sync Plugin exposes the native Sync service to the JavaScript layer using the PhoneGap bridge technology. The rest of this chapter will discuss how to setup an iOS app for development using the SyncPlugin for iOS.m files in the JSON folder to the JSON folder in your PhoneGap app Create a Group called OpenMobster • Create a New group named OpenMobster • From the mobilecloudlibproject.2-M8.. You must change this option to "Location Specified By Targets". Starting with OpenMobster 2. Please take a look at this thread for details: https://groups. PhoneGap leverages web technologies developers already know best. DragnDrop/Copy all the resources located under the app-bundle group Add the libraries and Frameworks In the Frameworks group add the following library and Frameworks 49 .Chapter 13. HTML and JavaScript.phonegap.. you can write offline web apps with synchronization of data using the OpenMobster Sync Plugin for PhoneGap.xcodeproj • Build the project in XCode For some reason. Prepare the mobilecloudlib static library • Open the mobilecloudlib mobilecloudlib.com] is an HTML5 app platform that allows you to author native applications with web technologies and get access to APIs and app stores.com/forum/#!searchin/openmobsterusers/mobilecloudlib/openmobster-users/zJhJKbFekLs/WiNWtKfG_RcJ XCode project by opening: iPhone/mobilecloudlib/ Start a Cordova-based App • Go to File>New Project.com> Introduction PhoneGap [http://www.google. In the displayed project templates select the Cordova-based Application and follow the wizard Copy JSON components to the App • Create a New Folder called JSON • Go to the mobilecloudlib project and Drag n Drop/Copy all the .h and .com <openmobster@gmail. PhoneGap + iOS + OpenMobster integration openmobster at gmail. building the mobilecloudlib fail to compile if your XCode code location is set to the recommended setting of "Derived Data".

It must be bootstrapped and started. [cloudService shutdown].framework • UIKit.framework • CFNetwork.a . [cloudService startup].OpenMobster static library • CoreData.framework Add OpenMobster bootstrap code Before OpenMobster runtime can be used within an App.framework • CoreGraphics. } } Stop Cloud Service -(void)stopCloudService { @try { CloudService *cloudService = [CloudService getInstance].PhoneGap + iOS + OpenMobster integration • libmobilecloudlib. } @catch (NSException * e) { //something caused the kernel to crash //stop the kernel [self stopCloudService]. The bootstrapping functions Start Cloud Service -(void)startCloudService { @try { CloudService *cloudService = [CloudService getInstance]. The following code shows how this bootstrapping process works. } @catch (NSException *e) { } 50 .

PhoneGap + iOS + OpenMobster integration } Start Device Activation if it is not activated with the Cloud already -(void)startActivation { @try { CloudService *cloudService = [CloudService getInstance]. [service execute:commandContext].(BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions . } } Do a Sync at Startup -(void)sync { CommandContext *commandContext = [CommandContext withInit:self.(BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSD { //OpenMobster bootstrapping [self startCloudService].viewController]. [commandContext setTarget:syncCommand]. [cloudService forceActivation:self. } @catch (NSException * e) { //something caused the kernel to crash //stop the kernel [self stopCloudService]. } Integrating the bootstrapping function with the App Delegate . CommandService *service = [CommandService getInstance]. 51 .viewController]. BackgroundSyncCommand *syncCommand = [BackgroundSyncCommand withInit].

useSplashScreen = YES. self. if (UIDeviceOrientationUnknown == curDevOrientation) { // UIDevice isn't firing orientation notifications yet… go look at the stat curDevOrientation = (UIDeviceOrientation)[[UIApplication sharedApplication] } if (UIDeviceOrientationIsValidInterfaceOrientation(curDevOrientation)) { for (NSNumber *orient in self. self. } [self. self. newOrient.webView.supportedOrientations) { if ([orient intValue] == curDevOrientation) { forceStartupRotation = NO.supportedOrientatio // The first item in the supportedOrientations array is the start orientati UIInterfaceOrientation newOrient = [[self. // check whether the current orientation is supported: if it is. UIDeviceOrientation curDevOrientation = [[UIDevice currentDevice] orientation].viewController. } CGRect screenBounds = [[UIScreen mainScreen] bounds].invokeString = [url absoluteString].viewController.viewController.startPage = @"index. NSURL* url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey]. 52 . // over-ride delegates self. CGRect viewBounds = [[UIScreen mainScreen] applicationFrame]. self. url).view]. rathe BOOL forceStartupRotation = YES.view.viewController. if (url && [url isKindOfClass:[NSURL class]]) { self.wwwFolderName = @"www". self.viewController.delegate = self. } } } if (forceStartupRotation) { NSLog(@"supportedOrientations: %@".window addSubview:self. curDevO [[UIApplication sharedApplication] setStatusBarOrientation:newOrient]. [self. self.viewController.viewController.supportedOrientati NSLog(@"AppDelegate forcing status bar to: %d from: %d".viewController.window makeKeyAndVisible].frame = viewBounds.window.window = [[[UIWindow alloc] initWithFrame:screenBounds] autorelease].html". self.viewController. self. break.viewController = [[[MainViewController alloc] init] autorelease]. NSLog(@"PhoneGapSyncApp launchOptions = %@".autoresizesSubviews = YES. keep it.commandDelegate = self. self.PhoneGap + iOS + OpenMobster integration [self sync].viewController.

the App to run is located under iphone/showcase/cloud.PhoneGap + iOS + OpenMobster integration //OpenMobster bootstrapping [self startActivation]. See also applicationDidEnterBackground:. On the Cloud Side. } -(void)applicationWillEnterForeground:(UIApplication *)application -(void)applicationWillEnterForeground:(UIApplication *)application { /* Called as part of transition from the background to the inactive state: here */ [self sync]. you can find an iOS/PhoneGap Sync App under iphone/ PhoneGapSyncApp. You run the Cloud Server using the command mvn -PrunCloud integration-test 53 . } PhoneGapSync App In the OpenMobster distribution. } -(void)applicationWillTerminate:(UIApplication *)application -(void)applicationWillTerminate:(UIApplication *)application { /* Called when the application is about to terminate. */ [self stopCloudService]. return YES.

2-M8.Chapter 14. Starting with OpenMobster 2.plugins.com> Introduction PhoneGap [http://www.com] is an HTML5 app platform that allows you to author native applications with web technologies and get access to APIs and app stores. }.phonegap.plugins. PhoneGap: Sync Plugin Reference openmobster at gmail. 54 .parse(jsonArray). } ).readall(channel.readall Reads all the beans stored in the sync channel Returns a JSON array of oids associated with the beans Parameters: • channel: The Sync Channel name where the beans are stored • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: window.com <openmobster@gmail. } var oids = JSON. The Sync Plugin exposes the native Sync service to the JavaScript layer using the PhoneGap bridge technology. The rest of this chapter will provide a reference guide to the Sync Plugin and how to use it ReadAll .window. you can write offline web apps with synchronization of data using the OpenMobster Sync Plugin for PhoneGap.sync.. function(error) { alert(error). HTML and JavaScript..sync. PhoneGap leverages web technologies developers already know best. function(jsonArray) { if(jsonArray == '0') { return.

} ). function(value) { console.'property'. }.queryByMatchAll Queries the Sync Channel for beans such that all name/value pairs from the search criteria have to match Returns a JSON Array of oids of beans that match the criteria Parameters: • channel: The Sync Channel name where the beans are stored • criteria: JSON name/value pairs to match against • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: 55 . Execute Query Match All window.plugins.plugins.log(value).value(channel.PhoneGap: Sync Plugin Reference Get a Property Value window.oid.plugins. function(error) { alert(error).sync.sync.value Reads the value of a property of a bean Returns the value of the property Parameters: • channel: The Sync Channel name where the beans are stored • oid: unique oid of the targeted bean • property: The property of the bean • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: window.sync.

Execute Query Match Atleast One window.{'title':'titleValue'. function(error) { } ).sync.'comments': function(matchedOids) { if(matchedOids == '0') { alert('No Records Found!!!').sync.sync.{'title':'titleValue'.plugins.queryByMatchAll(channel.plugins. }. 56 .parse(matchedOids).plugins.parse(matchedOids). } var oids = JSON. }.PhoneGap: Sync Plugin Reference window.'comments': function(matchedOids) { if(matchedOids == '0') { alert('No Records Found!!!'). return.queryByMatchOne Queries the Sync Channel for beans such that atleast one of the name/value pairs from the search criteria have to match Returns a JSON Array of oids of beans that match the criteria Parameters: • channel: The Sync Channel name where the beans are stored • criteria: JSON name/value pairs to match against • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: window. } var oids = JSON. return.queryByMatchOne(channel.

function(error) { } ).plugins.queryByNotMatchAll Queries the Sync Channel for beans such that instances that do not match all the name/value pairs of the criteria are returned Returns a JSON Array of oids of beans that do not match the criteria Parameters: • channel: The Sync Channel name where the beans are stored • criteria: JSON name/value pairs to match against • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: window.sync. } var oids = JSON.queryByNotMatchOne Queries the Sync Channel for beans such that instances that do not match even one of the name/value pairs of the criteria are returned 57 .{'title':'titleValue'.plugins.PhoneGap: Sync Plugin Reference function(error) { } ).sync.'comment function(matchedOids) { if(matchedOids == '0') { alert('No Records Found!!!'). }.plugins.queryByNotMatchAll(channel. Execute Query Do Not Match Even One window.parse(matchedOids). Execute Query Do Not Match All window. return.sync.

PhoneGap: Sync Plugin Reference Returns a JSON Array of oids of beans that do not match the criteria Parameters: • channel: The Sync Channel name where the beans are stored • criteria: JSON name/value pairs to match against • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: window.queryByContainsAll Queries the Sync Channel for beans such that all of the name/value pairs from the search criteria have to match.queryByNotMatchOne(channel. }.plugins. return.{'title':'titleValue'.sync.plugins. function(error) { } ).sync. The comparison is made such that the criteria value is contained within the property being matched against.parse(matchedOids). Returns a JSON Array of oids of beans that match the criteria Parameters: • channel: The Sync Channel name where the beans are stored • criteria: JSON name/value pairs to match against • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: 58 . Execute Query Match Contains All window. } var oids = JSON.'comment function(matchedOids) { if(matchedOids == '0') { alert('No Records Found!!!').

'comments':'c function(matchedOids) { if(matchedOids == '0') { alert('No Records Found!!!').parse(matchedOids).plugins.queryByContainsOne(channel. } var oids = JSON.queryByContainsAll(channel. The comparison is made such that the criteria value is contained within the property being matched against.'comments':'c function(matchedOids) { if(matchedOids == '0') { alert('No Records Found!!!'). } var oids = JSON.sync. Returns a JSON Array of oids of beans that match the criteria Parameters: • channel: The Sync Channel name where the beans are stored • criteria: JSON name/value pairs to match against • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: window.{'title':'title'.sync. Execute Query Match Contains Atleast One window. }. return.{'title':'title'.sync.parse(matchedOids).plugins.queryByContainsOne Queries the Sync Channel for beans such that atleast one of the name/value pairs from the search criteria have to match.plugins.PhoneGap: Sync Plugin Reference window. 59 . return. function(error) { } ).

plugins.sync. function(error) { } ).'title'. The method returns with a temporary oid to reference this bean by.tempOid. A permanent oid is assigned to the bean once it is synchronized with the Cloud Returns a temporary oid to work with this bean before commit/synchronization Parameters: • channel: The Sync Channel name where the beans are stored • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: window.plugins.tempOid. Add a New Bean into the Sync Channel window.sync.sync. } ). function(error){ alert('Setting the Title: '+error). } ).PhoneGap: Sync Plugin Reference }.plugins. 60 .'/test/newbean'. function(success) { }. function(tempOid) { console.{'string':'/test function(success) { }.addNewBean Adds a New Bean into the Sync Channel.plugins. //set the title window.sync.'customers'.addNewBean(channel.insertIntoArray(channel.updateBean(channel. //insert into a string array window. function(error) { alert('InsertIntoStringArray: '+error).log('Temporary Oid: '+tempOid).

'title://updated'. //Commit here window.plugins.sync.sync.'messages'.plugins. }.sync. function(success){ window. 61 .updateBean Updates the specified property of a bean in the Sync Channel Returns nothing Parameters: • channel: The Sync Channel name where the beans are stored • oid: The unique identifier of the bean • property: The property of the bean to be updated • value: The new value of the property • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: window. Update a Bean in the Sync Channel window.plugins.updateBean(channel.plugins.insertIntoArray(channel. function(error){}). function(error) { alert(error).'title'. }.oid.commit(function(success) { alert('Commit successful').plugins.tempOid.PhoneGap: Sync Plugin Reference //insert into an object array window.oid.sync. function(error) { alert('InsertIntoObjectArray: '+error).sync. }).value(channel.{'from':'from@tes function(success) { }.'title'. } ).

commit(function(success) { alert('Commit successful').log(value). } ). function(error){ alert(error). } ). } ).oid. function(success){ }.PhoneGap: Sync Plugin Reference function(value) { console. function(error){}).deleteBean Deletes the specified bean from the Sync Channel Returns nothing Parameters: • channel: The Sync Channel name where the beans are stored • oid: The unique identifier of the bean • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: //delete this bean window. function(error){ alert('Updating Title: '+error).sync.plugins.sync. //Commit here window.plugins. }. 62 .plugins. }.sync. Delete a Bean from the Sync Channel window. function(error) { alert('Reading the Title:'+error).deleteBean(channel. }.

sync. Commit the operations with the Sync Channel window.plugins.commit(function(success) { alert('Commit successful'). } ).plugins.PhoneGap: Sync Plugin Reference //Commit here window.commit(function(success) { alert('Commit successful').plugins.sync. Get the Length of an Array/List property window. function(error) { alert(error).commit Commits the operation to the Sync Channel. Upon commit the Sync Engine synchronizes the Channel with the Cloud Returns nothing Parameters: • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: //commit window.arrayLength Retrieves the length/size of an Array/List property of the specified bean Returns the array length Parameters: • channel: The Sync Channel name where the beans are stored • oid: The unique identifier of the bean 63 . function(error){}). }.sync. }.sync.plugins.

oid.'customers'. function(arrayLength) { console.insertIntoArray Inserts an object into the array Returns the new array length after adding the object to the Array/List Parameters: • channel: The Sync Channel name where the beans are stored • oid: The unique identifier of the bean • property: The property of the bean • value: The object in JSON format • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: window. } ).arrayLength(channel.PhoneGap: Sync Plugin Reference • property: The property of the bean • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: window. }.plugins. Insert an object into an Array/List property window.{'string':'insert function(arrayLength) { }.oid.sync.plugins.sync.insertIntoArray(channel.sync.log('ArrayLength: '+arrayLength). function(error) { alert('InsertIntoArray: '+error).plugins. 64 . function(error) { alert(error).'customers'.

plugins. Clear the entries inside an Array/List property window.sync. function(success) { }.PhoneGap: Sync Plugin Reference } ). } ).oid. function(error) { alert(error).sync.clearArray(channel.'customers'. 65 .clearArray Clears all the entries inside the Array/List property Returns nothing Parameters: • channel: The Sync Channel name where the beans are stored • oid: The unique identifier of the bean • property: The property of the bean • successCallback:function that will be invoked if this call is successful • errorCallback:function that will be invoked if this call fails Usage Example: //clear this array window.plugins.

util. One is the LocationContext and the other is a Request object which carries the business data associated with the invocation.com */ @BeanURI(uri="restaurants") public class RestaurantBean implements LocationServiceBean BeanURI registers this component with the kernel.openmobster.location.location.cloud.openmobster.openmobster. @Override public Response invoke(LocationContext locationContext. 66 .cloud. import import import import import import import import import import java.BeanURI.api. java. org. Location Aware Apps openmobster at gmail.openmobster.location.openmobster.api.location.LocationServiceBean.List.location. LocationServiceBean components are encapsulated by Location Data carried inside an object called the LocationContext. java. Request request) { Response response = new Response().util. In OpenMobster.Random.LocationContext.api.util.cloud.openmobster.Request.cloud. java. org.cloud.Map.Chapter 15. Invocation of these components involves two paramaters.location.com> Location Aware Apps This tutorial covers developing Location Aware Apps using the new Location Module of the OpenMobster platform.HashMap. org.util.api.api. /** * * @author openmobster@gmail.cloud.Response. the business components are encapsulated with this Location information.Place. LocationServiceBean On the Cloud-side.com <openmobster@gmail. The components then have easy access to the Location data and can easily integrate it with the business data.api. The following is a RestaurantBean which provides coupon data associated with restaurants that are close to a certain user provided location. org. org. Location Awareness means writing your business logic by taking Location information into account. org.

if(nearbyPlaces != null && !nearbyPlaces.getAttribute("zip"). and zip code.getNearbyPlaces(). } return response.setRequest(request).add("food"). } It takes a list of nearby restaurants from the LocationContext and then associates coupons from a database with each. address. placeTypes. city. coupons.getAttribute("city").setAddress(address). //Narrow search to restaurants List<String> placeTypes = new ArrayList<String>(). This business data married with location data is then sent back as a Response object. //Add the Address around which the restaurants must be looked up Address address = new Address(). the location data is provided by the user in terms of street.put(placeId. address. an invocation is made from the device to the cloud to get nearby restaurants to this location.setCity(city).String> coupons = new HashMap<String. //Construct a request for the RestaurantBean Request request = new Request("restaurants"). locationContext. String coupon = coupondb[couponIndex]. coupon).abs(couponIndex).getAttribute("street").setZipCode(zip).String>(). you can lookup the coupon in the database based on int couponIndex = (this.isEmpty()) { Map<String.setStreet(street).random.getId(). String street = (String)commandContext.nextInt())%7. //In a real implementation. } response. String city = (String)commandContext. couponIndex = Math. 67 . String zip = (String)commandContext. LocationContext locationContext = new LocationContext(). The App Side Logic In this app. Once this data is available. for(Place place:nearbyPlaces) { String placeId = place. address. locationContext. coupons).Location Aware Apps //Get coupons associated with each place List<Place> nearbyPlaces = locationContext.setMapAttribute("coupons".

address. A LocationContext is also initialized which will carry the location data associated with the invocation //Add the Address around which the restaurants must be looked up Address address = new Address(). locationContext. //Make the invocation to the Cloud to make a Location Aware search 68 . LocationContext locationContext = new LocationContext(). locationContext.setStreet(street). //Set the search radius locationContext. //1000 meters Narrow the search to only restaurants over a 1000 meter search radius. placeTypes. Create an Address object and assign it to the LocationContext. //Narrow search to restaurants List<String> placeTypes = new ArrayList<String>().invoke(request. //Construct a request for the RestaurantBean Request request = new Request("restaurants").setRadius(1000).setPlaceTypes(placeTypes).add("food"). address. responseContext).setZipCode(zip).setRequest(request).setPlaceTypes(placeTypes). A Request object is created and its given the name of the component to invoke which is restaurants in this case.setCity(city). address. //1000 meters //Make the invocation to the Cloud to make a Location Aware search LocationContext responseContext = LocationService. locationContex commandContext.setRadius(1000). //Set the search radius locationContext.setAddress(address).setAttribute("locationContext". locationContext.Location Aware Apps locationContext.

Processing the Response Map<String.getLatitude()). GeoPoint point = new GeoPoint((int)(latitude * 1E6).getLongitude()).parseDouble(restaurant.coupons. OverlayItem item = new OverlayItem(point. //Add restaurant markers and corresponding coupon information MyItemizedOverlay restaurantMarkers = new MyItemizedOverlay(marker. List<Place> restaurants = locationContext. double longitude = Double.getMapAttribute("coupons"). for(Place restaurant:restaurants) { double latitude = Double. (int)(longitude * 1E6)).restaurant.addOverlay(item).get(resta restaurantMarkers.invoke(re Invoke the RestaurantBean providing the location data in the LocationContext and business data inside the Request object.String> coupons = response.getNearbyPlaces(). while the nearby restaurants being location data are read from the LocationContext.getName().Location Aware Apps LocationContext responseContext = LocationService.parseDouble(restaurant. } The coupons being business data are read from the Response object as a Map<String.String>.map). 69 .

cloud.class). Cloud-Side: MobileServiceBean implementation MobileServiceBean is a simple interface org.info("-------------------------------------------------"). log..rpc.getNames(). Mobile RPC (Remote Procedure Call) Development openmobster at gmail. marshalling/unmarshalling payload. public DemoMobileBeanService() { } public Response invoke(Request request) { log. At this time.Chapter 16.MobileServiceBean with a single "invoke" method. } 70 . security.getAttribute(name). log. response.info("-------------------------------------------------").getLogger(DemoMobileBeanService.getClass(). "response://"+value). Value="+value).info(this.api. } log.openmobster. etc.info("Name="+name+". String[] names = request.com <openmobster@gmail. return response. resolving remote services. for(String name: names) { String value = request.getName()+" successfully invoked."). @ServiceInfo(uri="/demo/mobile-rpc") public class DemoMobileBeanService implements MobileServiceBean { private static Logger log = Logger. The next iteration of this component will involve introducing more robust features based on a REST-based architecture. This implementation should carry coarse grained business process logic.com> The MobileService component on the Device-side is used to make synchronous remote service invocations on registered MobileServerBean instances on the Cloud Server.setAttribute(name. protocol details.. this is a very simple request/response based system whose main design goal is to shield the App developer from any low level details like making network connections. Response response = new Response().

DemoMobileB </deployment> Cloud-Side: Packaging and Deployment • Packaging: Package the the above classes and the corresponding META-INF/openmobster-config.xml into a simple jar file.rpc.invoke(request). request.xml that will deploy the "MobileServiceBean" instance into the Cloud Server.MobileService component Request request = new Request("/demo/mobile-rpc").0"> <bean name="/demo/mobile-rpc" class="org.rpc. <?xml version="1.android. 71 .core.openmobster.setAttribute("param1". "paramValue2").0" encoding="UTF-8"?> <deployment xmlns="urn:jboss:bean-deployer:2. Putting it altogether Entire MobileServiceBean Example is located at: src/dev-tools/sampleApps/rpcdemo/cloud and AppCreator/sampleApps/rpcdemo/cloud App/Device-Side: Invoking the MobileServiceBean On the device side inside a Moblet. the remote "MobileServiceBean" instance can be invoked using the org.examples. MobileService service = new MobileService().openmobster.api. Response response = service. request. "paramValue1"). • Deployment: Deploy this jar file into the "deploy" directory of your JBoss AS instance.Mobile RPC (Remote Procedure Call) Development } Cloud-Side: Configuration Provide the META-INF/openmobster-config.setAttribute("param2".

4-SNAPSHOT. one of the other nodes immediately becomes a Master node. This is how you can get a highly available cluster running since at any given time there is always one master node processing requests from the mobile devices. This feature will be supported in a future release. all new services developed will support load balancing to get the best out of a clustered setup. the Sync service does not support this replication except data sharing via the shared database. At this point.Make this value true to activate this node as a Cluster node --> <property name="active">true</property> </bean> </deployment> 72 .Clu <!-.0" encoding="UTF-8"?> <deployment xmlns="urn:jboss:bean-deployer:2. Load Balancing At this point in time the Master node processes all the incoming requests. All the incoming traffic is directed to this Master node.openmobster. Out of these nodes there is a single node that serves as the Master node. This process keeps going till all the nodes are used up. Make sure the file looks as the following to activate the node as a Cluster node <?xml version="1.core. High Availability The high availability cluster consists of multiple JBoss nodes of the OpenMobster Cloud Server.xml.Chapter 17. This is a challenge because it needs to replicate local state among the cluster members. Setup This will cover the steps for setting up an OpenMobster Cloud in a clustered environment Configuration In your JBoss server open the following file: deploy/openmobster.0"> <bean name="clustering://ClusterService" class="org.cluster. The Master node is not a single point of failure because if the Master node goes down. It does not delegate any requests to its other nodes to balance the load.last/clustering-2.com> Clustering the Cloud Server You can setup the OpenMobster Cloud as a highly available Clustered environment. From here on out.jar/ META-INF/openmobster-config. Clustering openmobster at gmail. This is not enough and will require some re-architecting to make the service truly stateless.com <openmobster@gmail.

The other nodes remain in standby to become the Master node when/if it goes down.sh -c {server-name} -b {node-ipaddress} 73 ./run.Clustering Starting the Cluster To start the cluster you start one node at a time. The first started node starts off as the Master node. You start the node using the standard JBoss command: .

This is where your certificate can be uploaded and assigned to an App. This tool will evolve over time to include some management functionality like remote wipe. remote lockdown. Management Console openmobster at gmail. Push Setup This is used to configure the Apple Push Notification service. Administrators Used for managing the 'Admin' accounts. As the software matures it may add more system level functions like remote wipe.Chapter 18. If de-activated. remote lock down. As part of the system. his device can be re-assigned to another user. Activate/De-Activate Activates or Deactivates the 'Device' account. 74 . devices. This Console can be used to administrate users. etc. comes with a GWT/SmartGWT based GUI Management Console.com> OpenMobster. deactivation. This is so that when a user leaves. etc GUI Functionality Create Account This lets you create an 'Admin' account.com <openmobster@gmail. They will be available as soon as the account is activated. Re-assign De-activates the 'Device' account and makes it available to be assigned to another user. etc. and push services. This creation has to be approved by another administrator before you can login. Devices This lets you manage your devices such activation. Activate/De-Activate Activates and De-Activates the 'Admin' account. you can send a test push to your iPhone. a security certificate has to be assigned to an application before messages can be pushed to it. Once this is successful. none of the Cloud services will be available to the device.

} public abstract void render(). • A context oriented "State Management" system used to handle View level state. The low level Navigation service keeps track of the various screens of an App and provides services such as navigating to a specified screen. At this moment in the evolution of the mobile space. This results in a lot of App porting activity across platforms. there isn't a commonly adopted GUI development standard across various mobile platforms. etc. The MVC Framework provides the following features/benefit to an App developer: • An abstraction from the different bootstrapping behavior associated with each native phone platform.Chapter 19. • A Navigation framework used to help with screen navigation needs. background processing.id = id. The framework abstracts out some of the low level services into the container such as App bootstrapping.com> This is a thick client MVC (Model-View-Controller) framework.com <openmobster@gmail. 75 . Although this framework is not designed for (Write Once. public abstract Object getContentPane(). Components Screen Screen is an abstraction for an instance of the App screen that must be made visible to the user at a particular moment in time. and going to the home screen.org/wiki/Rich_Internet_application] design principle. Abstracts platform-level details related to Event Dispatch Thread. it abstracts out a lot of the UI Framework plumbing that would otherwise need to be written. graceful error handling. public String getId() { return this. Besides the actual implementation of a "Screen" all services related to a "Screen" are portable across mobile platforms public abstract class Screen { private String id. • A Command framework used for Event Handling. • A portable way to do "Internationalization". going back to the previous screen.wikipedia. Mobile MVC Framework openmobster at gmail. and internationalization. ported and maintained by the developer.id. Run Anywhere) approach. } void setId(String id) { this. screen navigation. It is based on a Rich Internet Application [http://en.

. System.Mobile MVC Framework public abstract void postRender().. • doAction: This method is invoked when the actual business logic associated with the command should be executed. System.getAppContext(). The MVC Framework provides two builtin Commands..println("-------------------------------------------------------")."... • doViewError: This method is invoked if an App-level exception is encountered during the execution of this command. A command typically puts a business process into motion via accessing various other services like the Mobile Data Framework components. This frees the App Developer to focus on the App behavior.. "LocalCommand about to execute. } public void doAction(CommandContext commandContext) { try { System. } Command Command is an abstraction for an instance of a GUI Event Handler which receives various callbacks based on the screen's lifecycle.. this component will probably be renamed to: FastCommand public class DemoLocalCommand implements LocalCommand { public void doViewBefore(CommandContext commandContext) { Toast. may be draw a status bar. Some examples would be putting up a simple alert dialog. } catch(Exception e) { 76 .. LocalCommand This tells the system that the business logic executes quickly and will not freeze the UI... In the next iteration of the system.. • doViewBefore: This method is invoked prior to doAction. Being executed within the context of an Event Dispatch thread... it provides the opportunity to make appropriate GUI changes to robustly handle the error condition..show().out. and/or native platform services.. Its executed within an active Event Dispatch Thread and allows making any visual GUI changes to the screen.println("-------------------------------------------------------").."). and allows for making visual GUI changes to the screen. etc • doViewAfter: This method is invoked after doAction is executed. This is also executed within the context of an Event Dispatch Thread... Toast... A Command has the following life cycle which is managed by the event bus.. It provides standard behavior associated with these commands.makeText((Activity)commandContext.LENGTH_SHORT). Command instances are managed by the built-in EventBus of the MVC framework.out.out.println("Demo Local Command successfully executed.

. System..out.show().. This approach is synonymous to the Ajax [http://en.makeText((Activity)commandContext.getInstance(). Any UI changes associated with the execution of this command are then displayed to the user's screen.".")..getAppContext().getNavigationContext().LENGTH_SHORT).org/wiki/Ajax_%28programming%29] approach in the Web Development realm. Below are some of many mobile scenarios where an AsyncCommand can come in handy: • Show validation errors inline with user input • Update the current screen with data fetched from the Cloud without showing a busy dialog or freezing the UI public final class DemoAsyncCommand implements AsyncCommand { public void doViewBefore(CommandContext commandContext) { Toast. } } public void doViewAfter(CommandContext commandContext) { Services. The RemoteCommand freezes the UI but shows an in progress dialog.currentThread(). This is used to make the mobile application more responsive and at the same time accomplish some critical task of interacting with the remote cloud..println("Demo Async Command successfully executed. System.. } catch(Exception e) 77 . "Error".println("-------------------------------------------------------")..getOkModal((Activity)commandContext.sleep(10000).out.wikipedia.. "DemoLocalCommand had an error!!"). this command immediately frees up the UI for other interactions.Mobile MVC Framework throw new RuntimeException(e.out. } } AsyncCommand This tells the system that the associated business logic executes in the background...navigate("local")... it re-establises the view cycle. Once the action associated with this command finishes execution outside the UI thread.println("-------------------------------------------------------").... } public void doAction(CommandContext commandContext) { try { //Simulate network latency Thread... } public void doViewError(CommandContext commandContext) { ViewHelper.getAppContext(). Toast...toString()). "AsyncCommand about to execute.show().. The difference between this and the RemoteCommand is that. System..

"Async Command success. System. "RemoteCommand about to execute. this component will probably be renamed to: BusyCommand public final class DemoRemoteCommand implements RemoteCommand { public void doViewBefore(CommandContext commandContext) { Toast. It will put up appropriate status indicators to keep the UI fluid...LENGTH_SHORT).getInstance(). } public void doViewError(CommandContext commandContext) { ViewHelper.. "Success".. or may be other scenarios where there is some form of waiting involved. Toast..show().out.out. } } RemoteCommand This tells the system that the associated business logic executes slowly and must execute in the background.show(). "Error".". Usually a RemoteCommand is used when making network calls for data located in the cloud..show(). System.. The system wants to provide the appropriate user experience/feedback so that the user does not think the device is frozen..currentThread()..getOkModal((Activity)commandContext.navigate("async"). System..sleep(10000).toString()).. } catch(Exception e) { 78 .getAppContext().... In the next iteration of the system...getAppContext().getAppContext()..it c //Services. } } public void doViewAfter(CommandContext commandContext) { ViewHelper.out..Mobile MVC Framework { throw new RuntimeException(e.getNavigationContext().getOkModal((Activity)commandContext. //An Async Command should not navigate away from the screen that launch it..").println("-------------------------------------------------------").println("Demo Remote Command successfully executed.. } public void doAction(CommandContext commandContext) { try { //Simulate network latency Thread.println("-------------------------------------------------------")....makeText((Activity)commandContext.")... "DemoAsyncCommand had an error!!").

System.out. An App's PushCommand (if specified) is invoked so that the App can take necessary action such as showing a dialog box.println("----------------------------------------").getOkModal((Activity)commandContext.getPush(). updating the app's icon with an alert.getId()). } } System.println("Handling Push----------------------------------------"). } public void doViewError(CommandContext commandContext) { ViewHelper.out. } } PushCommand A PushCommand allows the developer to handle Cloud Push at the App level.toString()). etc.out. MobileBeanMetaData[] updates = push.Mobile MVC Framework throw new RuntimeException(e. The Mobile Cloud runtime automatically takes care of system level notifications like blinking LED.getPushData().println("Push Updates: "+push. When the Mobile Cloud runtime synchronizes the App state with the Cloud in the background. } catch(Exception e) { 79 .getNumberOfUpdates()).out. if(updates != null) { for(MobileBeanMetaData update:updates) { System. System. showing some global screen.getNavigationContext(). Note: PushCommand should only be used to perform an App-specific action. "Error".getInstance(). it decides how to route the push notifications to the respective Apps on the device.navigate("remote"). public final class PushHandler implements PushCommand { public void doViewBefore(CommandContext commandContext) { } public void doAction(CommandContext commandContext) { try { MobilePush push = commandContext. etc.show(). "DemoRemoteCommand had an error!!").getAppContext().println("Bean: "+update. } } public void doViewAfter(CommandContext commandContext) { Services.

makeText(context.reflect. } } public void doViewAfter(CommandContext commandContext) { MobilePush push = commandContext. The EventBus frees up the App Developer to develop high-level App specific components like Screen and Commands. Internationalization The Internationalization service abstracts low-level details about localizing an App. Navigation The Navigation service abstracts low-level details about navigating through the various App screens that will be presented to the user.Mobile MVC Framework e. This will be the first screen that will be displayed upon launching an App.toString()). Tutorial Simple Home Screen Create a simple Home Screen component. Toast.getActiveInstance().getContext().getClass().getName()+" had an error!!". import java. this.makeText(context.getPush(). Context context = Registry. The API is language-portable. } public void doViewError(CommandContext commandContext) { Context context = Registry.printStackTrace(System.getActiveInstance().show().getContext().LENGTH_SHORT). Toast.show(). } } Services EventBus The EventBus shields the App Developer from learning the low-level GUI Event Management details. Typically this revolves around using the Event Dispatch Thread most efficiently and providing a fluid user experience. throw new RuntimeException(e. It provides a platform independent way to package the resource bundles. push.out).Field.lang.LENGTH_SHORT). and a standard API to access the information. Users are far more sensitive to GUI pauses on a mobile device compared to their traditional desktop. and lets the EventBus worry about the low-level details. Toast. 80 . Each mobile platform has its own methodology for handling GUI events.getNumberOfUpdates()+" Updates successfully received Toast.

getContext(). "render". android.Configuration.handle(se). ErrorHandler.android_native.ListActivity. } } 81 .core. org.mobileCloud.events.ui.api.Mobile MVC Framework import import import import import import import import import import import import import import import import import import import org.api. ne "Message:"+e.android.openmobster.core.mobileCloud. android.openmobster.getPackageName()+".Activity.api.AppResources.core.CommandContext.ui.openmobster.android_native. } catch(Exception e) { SystemException se = new SystemException(this.framework. String home = "home".view. android.ArrayAdapter.core.configuration.getActiveInstance().openmobster.openmobster.openmobster. org.getName().mobileCloud.R$layout".OnMenuItemClickListener. throw se.core.MenuItem.events.mobileCloud.MenuItem. @Override public void render() { try { final Activity currentActivity = (Activity)Registry.ListItemCli org.getInstance().ErrorHandler.openmobster.android.toString() }).framework. org.core.SystemException.api.forName(layoutClass).core.framework. org.android.openmobster.mobileCloud.getInt(clazz).errors.navigation. org.Services.widget.core.ListItemCli org.openmobster.screenId = field. android.mobileCloud.mobileCloud.api.resources.framework. Class clazz = Class.com */ public class HomeScreen extends Screen { private Integer screenId.mobileCloud. android. org.ui.mobileCloud.openmobster. Field field = clazz.android.mobileCloud.openmobster.core.core.mobileCloud.api.framework.ViewHelper.NavigationConte org.android_native.mobileCloud.getClass().openmobster.ui.getField(home).framework.service.app.view.framework.Screen.model.core.navigation.Registry. String layoutClass = currentActivity.framework.command.core.Menu.errors.core.openmobster. "Exception:"+e.app. org. org. android.ui. this.getMessage().mobileCloud. /** * @author openmobster@gmail.view.MobileBean. org.

isBooted("offlineapp_demochannel")) { MobileBean[] demoBeans = MobileBean.size=ui.R. } //Setup the App Menu this. getContext().getOkModalWithCloseApp(listApp. AppResources res = Services. Menu. for(int i=0. } private void setMenuItems() { Menu menu = (Menu)NavigationContext.setListAdapter(new ArrayAdapter(listApp. } @Override public void postRender() { ListActivity listApp = (ListActivity)Registry. res.getValue("demoString").i<size.getActiveInstance().add(Menu.layout.localize("inactive_m show().i++) { ui[i] = demoBeans[i]. if(menu != null) { MenuItem resetChannel = menu. ui)).NONE. Configuration configuration = Configuration. 0. "Reset Channel"). android.readAll("offlineapp_demochannel").screenId.simple_list_item_1. return.addClickListener(clickListener).getInstance(listApp).setMenuItems(). "App Error".getInstance(). } listApp.Mobile MVC Framework @Override public Object getContentPane() { return this.NONE. //List Listener ListItemClickListener clickListener = new ClickListener(demoBeans). getAttribute("options-menu").length. String[] ui = new String[demoBeans. } //Show the List of the "Demo Beans" stored on the device if(MobileBean.getResources().getInstance(). if(!configuration.length].getInstance(). NavigationContext.isActive()) { ViewHelper. 82 .

commandContext. pushTrigger.activeBeans = activeBeans.. return true. Services. } }). MobileBean selectedBean = activeBeans[selectedIndex].NONE. return true. commandContext.execute(commandContext).execute(commandContext).NONE.setTarget("/offlineapp/reset").Mobile MVC Framework resetChannel.this is where the Commands can be execute CommandContext commandContext = new CommandContext(). "Make RPC Invocation"). } } private static class ClickListener implements ListItemClickListener { private MobileBean[] activeBeans.add(Menu. 0.getInstance().setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem clickedItem) { //UserInteraction/Event Processing. Services.setTarget("/offlineapp/rpc").getCommandService(). return true. Menu.NONE.getInstance(). MenuItem pushTrigger = menu.setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem clickedItem) { //UserInteraction/Event Processing.getCommandService().getCommandService()...getInstance().this is where the Commands can be execute CommandContext commandContext = new CommandContext(). MenuItem rpc = menu.setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem clickedItem) { //UserInteraction/Event Processing. 83 .this is where the Commands can be execute CommandContext commandContext = new CommandContext(). rpc.execute(commandContext). commandContext.setTarget("/offlineapp/pushtrigger"). private ClickListener(MobileBean[] activeBeans) { this..getPosition(). 1. } }).. Menu..NONE. } }). Services.add(Menu. } public void onClick(ListItemClickEvent clickEvent) { int selectedIndex = clickEvent. "Push Trigger").

. and src/mobileCloud/android/2_0/test-suite/nativeframeworktestdrive/src/main 84 . commandContext.command.android.ResetChannel</ <command id="/offlineapp/rpc">com.The Android core + OpenM I stand corrected.offlineApp.getInstance().app.getCommandService(). src/devtools/sampleApps/rpcdemo/app-android.command.xml <moblet-app> <bootstrap> <screen>com.command..app.openmobster.setAttribute("selectedBean".examples.. commandContext.android.android.android.screen.execute(commandContext).offline.app. The configuration is located at: /moblet-app/mobletapp.getValue("demoString")) Services. selectedBean.core.Android is actually superior to BlackBerry Platform (atl <push> <command>org.offlineApp.DemoMobileRPC</c </commands> <channels> <channel>offlineapp_demochannel</channel> </channels> </moblet-app> Putting it all together Detailed Examples located at: src/dev-tools/sampleApps/offlineapp/app-android.Mobile MVC Framework CommandContext commandContext = new CommandContext().DemoDetails</comma <command id="/offlineapp/pushtrigger">com.app.command.offlineApp.HomeScreen</screen> </bootstrap> <!-In Android's case this is not needed for this App.PushHandler</command> </push> --> <commands> <command id="/demo/details">com..offlineApp.command.offlineApp.app.setTarget("/demo/details"). } } } Configuration The Moblet code is packaged in a simple jar file.android.PushTrig <command id="/offlineapp/reset">com.