Palm Synergy integrates personal information from various sources on the Web and presents it in a single view so that users can see all in one place. Yet the information is maintained in such a way that users can keep things separate when they have to. The integration is at the visual or presentation layer, while the separation is maintained at the data layer.
The core Synergy applications are Contacts, Calendar, Email, and Messaging, but the concept is general enough that you can expect other applications to be supported over time. All Synergy applications can be launched through the Application Manager service, and Email and Messaging can be used to send messages with the user’s approval, similar to the way the Phone application is used.
The Contacts and Calendar application service interfaces can do a bit more, allowing applications to add contacts or calendar events, distinguished by their own data sources. These features are designed for occasional use, serving the needs of applications that want to add single records rather than fully scaled sync solutions.
All Synergy applications require an established account before any other operations can take place. There is an implicit “Palm” account that all information created and stored on the device belongs to, but any other information must be provided by an application with an explicit account ID. The account determines all access permissions; data belonging to an account can only be accessed by the application that owns that account.
The Account Manager includes methods to create, update, delete, or read accounts, as well as a method to list accounts. Here is an account create example:
this.controller.serviceRequest("palm://com.palm.accounts/crud", { method: "createAccount", parameters: { account: { username: "myusername", domain: "mydomain", displayName: "My Name", icons: { "32x32": Mojo.appPath + "images/accountIcon.png", "48x48": Mojo.appPath + "images/stampIcon.png" }, dataTypes: ["CONTACTS", "CALENDAR"], isDataReadOnly: false } }, onSuccess: this.accountCreated.bind(this); onFailure: function(response) { Mojo.Log.info("Account create failed; ", response.errorText} } });
This method uses the service name palm://com.palm.accounts/crud
, and has
parameters that specify account properties. The dataTypes
object declares the Synergy data
sets used by the account: CONTACTS
and/or CALENDAR
. The domain
property allows
a single account to have different data sources within it. Domains are
useful in limited cases, such as when a single application wants to
maintain multiple sync sources.
Accounts may be a lot of overhead if your application has only an occasional need to add a contact or calendar event. In that case, you might choose to simply launch Contacts or Calendar and have the user enter the data directly. Plus both Contacts and Calendar support launch points to add or update individual records without creating a new account.
The accountId
is used for
subsequent Account Manager methods, and for access methods in Contacts
and Calendar. It’s also used in the other Account Manager
methods.
Both Contacts and Calendar will allow applications to add information that will be merged into an integrated view. They don’t allow applications to read, delete, or update any data that wasn’t created by the same application.
The Contacts application has methods to create, read, update, and delete contacts, along with listing all contacts. In addition, there are methods to track changes to contacts to support applications that wish to optimize updating their data sources with changes made by the user on the device.
The following is an example of creating a contact entry:
this.controller.serviceRequest("palm://com.palm.contacts/crud", { method: "createContact", parameters: { accountId: this.accountId, contact: { firstName: "Harry", lastName: "Truman", companyName: "US Government", nickname: "POTUS 33" } }, onSuccess: this.successEvent.bind(this), onFailure: this.failureHandler.bind(this) });
Notice the use of this.accountId
. This is returned when you
create the account and is used for most of these Contacts or Calendar
functions. The contact
object defines
the contents of the contact entry, and has many more property options
than the few that are shown in the example.
Calendar requires that a new calendar is first created, and then entries for that calendar are created within it. This example creates a calendar in the first function and then, on success, creates an entry using the current date and time:
CalendarAssistant.prototype.createCalendar = function() { this.currentMethod = "Calendar - Create"; this.controller.serviceRequest('palm://com.palm.calendar/crud', { method: 'createCalendar', parameters: { accountId: this.accountId, calendar: { calendarId: "", name: "My Events" } }, onSuccess: this.createEvent.bind(this), onFailure: this.failureHandler.bind(this) }); }; CalendarAssistant.prototype.createEvent = function(response) { if (response) { Mojo.Log.info("Calendar Create ", Object.toJSON(response)); this.calendarId = response.calendarId; } this.currentMethod = "Event - Create"; var currentTime = new Date(); var startTime = currentTime.getTime(); this.controller.serviceRequest('palm://com.palm.calendar/crud', { method: 'createEvent', parameters: { calendarId: this.calendarId, event: { calendarId: this.calendarId, subject: "Forecast", startTimestamp: startTime, endTimestamp: startTime + 3600000, allDay: false, note: "Cliff Notes", location: "Bluff", attendees: [], alarm: "none" } }, onSuccess: this.successEvent.bind(this), onFailure: this.failureHandler.bind(this) }); };
As with Contacts, there are methods to track changes to calendar events or event deletions.
The People Picker is a special Contacts function that lets applications retrieve information from any Contacts entry. It won’t allow direct access, but it will allow the user to select a specific contact and approve the transfer of that contact’s details to the requesting application.
The People Picker is called through a Cross-App launch. As
mentioned earlier, this technique pushes a scene from another
application on your application’s scene stack. This keeps your
application context, meaning that the user won’t see any card switch. To
call the People Picker, use pushScene()
:
PeoplePickerAssistant.prototype.getContact = function(event){ this.contactRequest = true; this.controller.stageController.pushScene( { appId : "com.palm.app.contacts", name: "list" }, { mode: "picker", message: "headerMessage" } ); };
People Picker presents the Contacts list scene with the filter
field activated. Just as in the Contact’s details scene, typing will
filter down the list and eventually the user would either select a
contact or cancel with a back gesture. After the user selects a contact,
the details are returned as an argument to calling the scene’s activate
method:
PeoplePickerAssistant.prototype.activate = function(response){ if (response) { if (response.personId) { this.showDialogBox("Contact Received", response.personId); } else { this.showDialogBox("Contact Request Failed", ""); } } else { Mojo.Log.info("No Contact Requested"); } };
An application might use this to get a contact’s address for use
in planning a trip, for example, or an IM address, or some other
personal information; contact details are returned in
response.details
. You can optionally exclude contacts
from the list by enumerating their contact IDs.
You can launch the Email and Messaging applications to their main views using the Application Manager launch method, but most applications will generally use these applications to send a message. For that, you will use the launch method to launch either of these applications to a Compose view and optionally populate some or all of the compose fields.
News will be extended to share a story by either email or messaging to
illustrate these service calls. This is best hooked into the
storyView
scene, but we’ll start with the service
calls before looking at how they are integrated into the scene.
Email is called with a prepopulated subject field using the
params.summary
property, and the shared URL in the message body, using params.text
. You can also include one or
more email addresses for any of the address fields (To, CC, and BCC),
but in this example, the user would need to address the mail using the
addressing widget in the email application:
// shareHandler - choose function for share submenu StoryViewAssistant.prototype.shareHandler = function(command) { switch(command) { case "do-emailStory": this.controller.serviceRequest("palm://com.palm.applicationManager", { method: "open", parameters: { id: "com.palm.app.email", params: { summary: "Check out this News story...", text: this.storyFeed.stories[this.storyIndex].url } } }); break;
Messaging is very similar; for this example, the entire message
is provided in params.messageText
:
case "do-messageStory": this.controller.serviceRequest("palm://com.palm.applicationManager", { method: "open", parameters: { id: "com.palm.app.messaging", params: { // ** These next two lines are wrapped for book formatting only ** messageText: "Check this out: " +this.storyFeed.stories[this.storyIndex].url } } }); break; } };
As with email, you can specify the recipient(s) as part of the call. See Appendix B for a complete list of the calling arguments.
To hook these calls into the scene, add a Command menu button to
the bottom of the storyView
scene, which creates a
scene like that shown in Figure 8-2.
This sample code is used to generate the view shown in Figure 8-2:
// setup - set up menus StoryViewAssistant.prototype.setup = function() { this.storyMenuModel = { items: [ {iconPath: "images/url-icon.png", command: "do-webStory"}, {}, {items: []}, {}, {icon: "send", command: "do-shareStory"} ]}; if (this.storyIndex > 0) { this.storyMenuModel.items[2].items.push({ icon: "back", command: "do-viewPrevious" }); } else { this.storyMenuModel.items[2].items.push({ icon: "", command: "", label: " " }); } if (this.storyIndex < this.storyFeed.stories.length-1) { this.storyMenuModel.items[2].items.push({ icon: "forward", command: "do-viewNext" }); } else { this.storyMenuModel.items[2].items.push({ icon: "", command: "", label: " " }); } this.controller.setupWidget(Mojo.Menu.commandMenu, undefined, this.storyMenuModel);
The Share button is the rightmost button and will present a pop-up when tapped. The Next/Previous button group in the center was covered in Chapter 4; they are used to navigate to the next and previous stories.
There is already a command handler included in this scene, so just add handlers for the new button and add a submenu to present the email and messaging options:
// --------------------------------------------------------------------- // Handlers to go to next and previous stories, display web view // or share via messaging or email. StoryViewAssistant.prototype.handleCommand = function(event) { if(event.type == Mojo.Event.command) { switch(event.command) { case "do-viewNext": Mojo.Controller.stageController.swapScene( { transition: Mojo.Transition.crossFade, name: "storyView" }, this.storyFeed, this.storyIndex+1); break; case "do-viewPrevious": Mojo.Controller.stageController.swapScene( { transition: Mojo.Transition.crossFade, name: "storyView" }, this.storyFeed, this.storyIndex-1); break; case "do-shareStory": var myEvent = event; var findPlace = myEvent.originalEvent.target; this.controller.popupSubmenu({ onChoose: this.shareHandler, placeNear: findPlace, items: [ {label: "Email", command: "do-emailStory"}, {label: "SMS/IM", command: "do-messageStory"} ] }); break; case "do-webStory": this.controller.serviceRequest("palm://com.palm.applicationManager", { method: "open", parameters: { id: "com.palm.app.browser", params: { scene: "page", target: this.storyFeed.stories[this.storyIndex].url } } }); break; } } };
The browser launch is handled directly in the command handler
above. The service calls for email and messaging are in shareHandler
, the submenu’s callback, which
is where this section started.
3.141.42.5