Web application developers have a smooth transition to widget development because most of the development involves by using the same techniques. Widgets have specific requirements for deployment and localization, and details are given in this section.
Creating the User Interface
Widgets are full-screen applications, but since the user interface is provided through HTML, widgets can use HTML layout to accommodate the form factor of the Windows Mobile device. In addition, the developer can use the document body object to access the screen dimensions and orientation of the device. The widget API also provides notifications for the change in screen orientation (for example, if the device is rotated), and the developer can use this notification to alter the user interface.
Similar to AJAX application development, widget developers can respond to events from controls and other elements on the Web page. A particularly useful feature of Windows Mobile is the support for localization.
Localizing Widgets
Application resources are often specific to a locale. In particular, text should be localized to reflect the language and dialect of the user’s device. When designing an application, you should identify the resources that will be localized and create a separate file for each locale that is supported. For example, a widget that displays currency exchange rates and stock quotes should obtain this information from localized Web sites so that, for example, a user in the United States will see the value of the Dow Jones Index and a user in Great Britain will see the value of the FTSE index.
The following code fragments show excerpts from two files, both called directoryUrls.js. The first file is the default file for the widget. The resource indicates that the http://mny.mobile.msn.com/en-us/default.aspx? Web site should be used for stock quotes. This file is stored in the scripts folder called js in the deployment file. The second code fragment is the localized resource for the en-UK locale (British English). In this case, the stock quotes are obtained from the http://mobile.uk.msn.com/device/mny/default.aspx? Web site. This file has the same name as the default resource, but it is within the localized script folder called en-UK/js. It is important to note that the src attribute of the <script> element in the HTML for the widget is not localized; the src attribute only references the default file in the js folder and Windows Mobile 6.5 will load the appropriate file.
// Default locale, js/directoryUrls.js
var MSN_OCID_PARAM = "ocid=widget_mny_1";
var DirectoryUrls = {
MSNMoney: "http://mny.mobile.msn.com/en-us/default.aspx?"
+ MSN_OCID_PARAM
}
// UK locale, en-UK/js/directoryUrls.js
var MSN_OCID_PARAM = "ocid=widget_mny_1";
var DirectoryUrls = {
MSNMoney: "http://mobile.uk.msn.com/device/mny/default.aspx?"
+ MSN_OCID_PARAM
}
At run time, Windows Mobile 6.5 checks the locale of the device (for example, en-US or en-UK), and if there is a folder with the name of this locale it will use the localized folder as the base folder for the script files. If the localized folder does not exist, Windows Mobile searches for a folder with the language name (for example, en).
If the device cannot find any localized files, it will load the default files. The widget code is contained in locale-neutral script files. To obtain the URL to use for stock quotes, this code accesses the DirectoryUrls.MSNMoney variable from the localized directoryUrls.js file loaded by Windows Mobile, where it gets a URL appropriate to the locale.
It is important that if you provide localized files you also provide default files. All the widget files can be localized. However, to minimize the size of the deployment package, it is better to localize individual items, as shown above, rather than simply providing a localized copy of each HTML and JavaScript file.
Using the Widget JavaScript Objects
A widget is a stand-alone, locally executed AJAX application, written in JavaScript. The widget can be as simple as a single HTML file with a <script> element or it can be composed of one or more JavaScript files. The HTML file can contain <object> elements and this also means that the widgets can display Flash files. The JavaScript code is subject to the widget security model.
Windows Mobile provides a JavaScript object called widget that gives access to some device system state information and to widget-specific features. The widget object provides some information through properties, and it can also be used to create a state object to provide access to other features. The widget manifest file is an XML file deployed with the widget. It is covered later in this article.
|
Property
|
Description
|
|---|
|
authorEmail
|
The e-mail address of the widget author. This is the email attribute on the <author> element in the widget manifest file.
|
|
authorName
|
The name of the widget author. This is the value of the <author> element in the widget manifest file.
|
|
authorURL
|
The Web site address of the widget author. This is the href attribute on the <author> element in the widget manifest file.
|
|
currentIcon
|
The icon used by the widget. This is an object of type WidgetIcon.
|
|
description
|
The description string for the widget. This is the value of the <description> element in the widget manifest file.
|
|
height
|
The height, in pixels, of the widget.
|
|
identifier
|
The unique identifier for the widget. This is the uid attribute on the <widget> element in the widget manifest file.
|
|
locale
|
The locale of the widget. This reflects the setting selected in the Regional Settings dialog box on the device.
|
|
menu
|
The menu object for the widget. This is an object of type Menu.
|
|
name
|
The user-friendly name of the widget. This is the value of the <name> element in the widget manifest file.
|
|
version
|
The version of the widget. This is the version attribute on the <widget> element in the widget manifest file.
|
|
width
|
The width, in pixels, of the widget.
|
The following code example shows how to use the widget properties.
<div id="divData"></div>
<script type="text/javascript">
divData.innerHTML = "The " + widget.name + " widget is localized to "
+ widget.locale;
</script>
Further system information is obtained through the SystemState object. This object has the following properties.
|
Property
|
Description
|
|---|
|
CradlePresent
|
A Boolean value indicating whether the device is cradled.
|
|
DisplayRotation
|
An integer between 0 and 360 indicating the rotation of the display in degrees.
|
|
PhoneHomeService
|
A Boolean value indicating whether the device is presently registered on its home network.
|
|
PhoneOperatorName
|
A string indicating the name of the device’s mobile operator.
|
|
PhoneRoaming
|
A Boolean value indicating whether the device is currently roaming.
|
|
PhoneSignalStrength
|
An integer indicating the phone signal strength, expressed as a percentage of full strength.
|
|
PowerBatteryState
|
An integer indicating the current state of the battery, such as whether the battery level is critically low or if the battery is charging.
|
|
PowerBatteryStrength
|
An integer indicating the current battery strength, expressed as a percentage of full strength.
|
The following code shows how to access information about the device.
<div id="divData"></div>
<script type="text/javascript">
var systemState = widget.createObject("SystemState");
divData.innerHTML = "The phone operator name is "
+ systemState.PhoneOperatorName + " and the signal strength is "
+ systemState.PhoneSignalStrength;
</script>
You can register an event that will be called when the property changes. To do this, you call the addEventListener method to add a handler function for the changed event on the SystemState property for which you want the notification. For example, using the objects declared in the previous code, you can specify that a function called cradled is called when the device is cradled.
var cradledState = systemState.CradlePresent;
cradledState.addEventHandler("changed", cradled);
Most of the widget and SystemState properties are integer or strings, but some are new object types. For example, the widget.currentIcon property is an object of type WidgetIcon with the following properties.
|
Property
|
Description
|
|---|
|
height
|
An integer giving the height of the icon.
|
|
src
|
A string with the URL to the icon file.
|
|
width
|
An integer giving the width of the icon.
|
The widget.menu is a Menu object and will be covered in the next section.
Creating Widget Menus
A widget can have a menu and it can also define the action of the device soft keys. These tasks are performed through the Menu object.
|
Method
|
Description
|
|---|
|
append(item)
|
Appends a MenuItem object to right soft key.
|
|
clear()
|
Clears the contents of the main menu.
|
|
createMenuItem(id)
|
Creates a MenuItem object with the specified integer ID.
|
|
getMenuItemById(id)
|
Returns the MenuItem object with the specified ID.
|
|
remove(item)
|
Removes the specified MenuItem object from the menu.
|
|
setSoftKey(item, id)
|
Assigns a MenuItem object to the soft key with the specified ID.
|
The soft keys can be assigned with either a single MenuItem object, or a menu made up of one or more MenuItem objects. By default, when the widget starts, the left soft key has the single MenuItem object called Exit (which closes the widget), and the right soft key has a menu that comprises just one MenuItem object that also exits the application. The following illustration shows the right menu displayed when the right soft key is clicked.
The menu object has two properties, leftSoftKeyIndex and rightSoftKeyIndex that can be used to identify the soft key to assign a menu item using the setSoftKey method.
The following code creates a new menu item by calling createMenuItem. The numeric identifier passed to the method must be unique in this widget code. The menu item is then initialized with the display text and the click event handler function. The code then calls setSoftKey to assign the menu item to the left soft key.
function clickMeHandler() {
alert("do something");
}
var menu = widget.menu;
var menu1001 = menu.createMenuItem(1001);
menu1001.text = "Click Me";
menu1001.onSelect = clickMeHandler;
menu.setSoftKey(menu1001, menu.leftSoftKeyIndex);
The following illustration shows the results.
If you use the following line instead of the call to setSoftKey, the menu item will be appended to the right menu.
The following illustration shows the results.
The MenuItem object has a text property that gives the display text and an enabled property that determines whether the menu item can be clicked. The MenuItem object also has a read-only property called id that is assigned by the Menu.createMenuItem function. The click event handler function for a menu item is passed the id of the menu item, so you can write generic handler functions that handle more than one menu item. The MenuItem also has an append and a remove method to add child menu items.
Using the clear, append, remove and setSoftKey methods on the Menu object, and the append and remove methods on the MenuItem object, you can build up complex multilevel menus. When a menu item has child items, the menu item's click handler opens the child menu rather than calling the handler you specify.
Calling AJAX Code
The widget code can use the XMLHttpRequest object to access data asynchronously from the Internet, and can then use the XML DOM to parse the returned data. The following is a simple form to request a stock symbol and display the symbol value on the page.
<div id="divQuote">Quote</div>
<form>
Stock symbol (eg US:MSFT) <input type="text" id="iSymb" />
</form>
The onClick function is a handler for a menu item click to obtain a stock quote.
function onClick() {
var xmlhttp = null;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
if (xmlhttp) {
createRequest(xmlhttp, document.getElementById("iSymb").value);
}
}
This function creates an XMLHttpRequest object and then calls a function called createRequest passing the object and the symbol name.
function createRequest(xmlhttp, symb) {
var url = "http://blu.services.stub.msn.com/"
+ "StockQuotes.aspx?symbols=" + symb;
xmlhttp.open("GET", url);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
harvestResults(xmlhttp);
delete xmlhttp;
}
};
xmlhttp.send();
}
The call to the XMLHttpRequest.open method creates an asynchronous request to the MSN stock quote service passing the stock symbol. The actual request is made when the send method is called. The onreadystatechange event is raised when the request returns. The stock quote service returns an XML document with one or more stock quotes, and this data is parsed by the harvestResults function.
function harvestResults(xmlhttp) {
if (xmlhttp.status == 200) {
var xmldoc = xmlhttp.responseXML;
if (xmldoc) {
var quoteList = xmldoc.getElementsByTagName("ticker");
if (quoteList != null && quoteList.length > 0) {
divQuote.innerText = quoteList[0].getAttribute("name")
+ " $" + quoteList[0].getAttribute("last");
}
}
}
}
The responseXML property returns the data as an XML Document Object Model (DOM) object. The remainder of the code uses the DOM to obtain the first <ticker> element, and from this obtains the full name of the company and the last value of the stock.
A widget running this code enables the user to request individual stock quotes, and the widget will display the code onscreen.
Using Widget Persistence
Widget security denies access to common Windows Mobile persistence mechanisms (for example, the file system and Microsoft SQL Server® Compact Edition databases). Persisting information between runs of a widget is a useful feature, so the widget API provides a persistence mechanism that enables storage of simple string information. The data persistence is isolated so that a widget can only read the data that it has stored. However, it is important to point out that the storage mechanism does not encrypt the data, so another non-widget application (native or managed code) could have access to the data.
To store data, a widget calls the setPreferenceForKey method on the widget object.
var symbol = document.getElementById("iSymb").value;
widget.setPreferenceForKey(symbol, "SYMBOL");
The previous code stores the last stock symbol requested. The code can read the value with the preferenceForKey method.
var symbol = widget.preferenceForKey("SYMBOL");
The values stored with this mechanism persist until the next time that the widget runs, and it will be available after a reset. The mechanism should be used for relatively small values since there is a limit of 4000 bytes per key.
Using Widget Security
Security is vital in every application, but it has an increased significance in code that can be installed over a network and whose functionality depends on data from the Internet. Windows Mobile widgets run under Internet Explorer and are subject to the Internet Explorer Sandbox. This means that the widget cannot access personal data on the device, so information like contacts, the e-mail message store, the registry, and the file system are not accessible to widgets. Furthermore, by default, network access is denied to the widget unless the widget manifest file requests this privilege through the <access> element in the manifest file.
<access network="true" />
Internet Explorer security policy is maintained. Data maintained by Internet Explorer, like cookies, the cache, and the history list are isolated to each widget and the history and the cache are cleared every time the widget starts.
Special exceptions are made to relax the sandbox, but these still maintain widget security. Although the widget cannot access files in general, it may access files in the home folder and the folder beneath it using the src attribute of relevant HTML elements (for example, <img> for image files). The security sandbox enables navigation through some special protocols like mailto:, sms:, callto:, and tele:, but in these special cases the navigation is delegated to the device process responsible, and the user will be able to cancel any action being taken.
The device is protected from installing rogue code. First, users will only be able to install a widget from the Internet through Microsoft SkyMarket and can therefore authenticate the source of the code. Second, the user is notified during the installation process and approval is requested, so when the user installs a widget he will get a page displaying information from the widget manifest describing the widget and the page will request permission to install the code. Furthermore, some security checks are made before the widget runs. For example, if the widget manifest indicates that the widget requires network access, the device displays a warning dialog box indicating that network access could incur call plan costs. The user gets the option to continue running the widget or to exit.
Providing Widget Files
Widgets must contain one HTML file for the user interface. This start file is named in the widget manifest using the <content> element. The start file can contain style elements and scripting to support the widget functionality, but typically the start file references separate CSS files and scripts through the <style> and <script> elements. Widgets support localization of resources and code, and Windows Mobile loads the localized files if they are present. All of these additional files are provided within the widget folder. The following table summarizes the types of files within a widget folder.
|
File Type
|
Mandatory
|
Description
|
|---|
|
<widget>.html
|
Yes
|
The start file for the project. <widget> is the name of the widget as given by the widget manifest file.
|
|
config.xml
|
Yes
|
An XML file containing the metadata for the widget.
|
|
*.ico, *.png, *.jpg
|
Yes, at least one
|
The icon to be used for the widget in the Start menu of the mobile device. The icon file is mentioned in the widget manifest file. Smartphones only support .ico files, while Pocket PC files support all three formats.
|
|
*.js
|
No, but preferred
|
JavaScript files containing the code for the widget.
|
|
*.css
|
No, but preferred
|
Style sheets for the widget.
|
|
Resource files: .jpg, .png, and more
|
No
|
Additional resources.
|
Creating the Manifest File
Each widget must have a manifest file. This is an XML file called config.xml containing a root element called <widget>. The manifest file contains information about the widget including data that may be localized, so the manifest may be within the localization folders. However, even if you use localized versions of the manifest file, it is prudent to place a default copy of the manifest file in the root of the widget folder to be used as the default if the device has a locale that is not handled. The <widget> element in the manifest file must have the name of the start file; other elements are optional but recommended. The following is a minimal manifest file.
<?xml version="1.0" encoding="utf-8" ?>
<widget xmlns="http://www.w3.org/ns/widgets" version="1.0">
<content src="StartUp.htm" type="text/html" />
</widget>
This manifest indicates that the start file is called StartUp.htm. If the device Regional Settings are set to English (United States), the locale is en-US, so when the device runs the widget, it first looks for a file called StartUp.htm in the en-US folder. If the folder does not exist, or the file is not in that folder, the device looks for a file called StartUp.htm in the en folder and if that file does not exist, the device loads StartUp.htm from the root folder.
Another localized file is the icon file. Smartphone devices can only use .ico files, while other Windows Mobile devices can also use .png and .jpg files.
The following table lists the elements that can be used in the <widget> element.
|
Element
|
Description
|
|---|
|
<access>
|
This element indicates the network requirements of the widget. If the network attribute has a value of true, the widget must have permission from the user for network access before the widget is run.
|
|
<author>
|
This element contains information about the author of the widget. The optional attributes are: href, a URL to the author’s site; email, the author’s e-mail address; and img, a graphic associated with the author.
|
|
<content>
|
This element is required. The src attribute gives the path to the start file.
|
|
<description>
|
This element describes the widget; the description is displayed during installation of the widget.
|
|
<icon>
|
This element gives the name of the file to be used for the widget icon in the Start menu. The src attribute gives the name of the file.
|
|
<name>
|
This element gives a user-friendly name of the widget. This name is displayed in the Start menu and in the Remove Programs page.
|
Some of the manifest values can be accessed by the widget code using properties of the widget object.
Creating the Deployment Package
A design goal of Windows Mobile widgets is to provide a single download deployment package. The package is a standard zip file with the extension changed from .zip to .widget. You can use any name for this file, but best practice is to use the name of the widget. If you do not provide the name of the widget in the manifest file, the widget installer uses the name of the deployment file as the name of the widget on the device.
Within the zip file are all the files that the widget needs to run: Web pages, icon graphics files, style sheets, JavaScript files, and other resources. These files are stored in the zip file using the same folder structure as will be used by the widget, that is, if your widget uses localization, the zip file contains the locale folders containing the localized files and folders as explained earlier.
Deploying the Widget
The current version of Windows Mobile widgets supports two deployment modes: SkyMarket and sideload deployment. SkyMarket is an online application store intended to be a one-stop shop for purchasing Windows Mobile applications.
Developers can use sidelong deployment from the desktop development workstation. To do this, the developer copies the widget deployment file to the device and then runs the widget file on the device. This deployment method works out of the box for the emulator image, but for actual devices the developer must add the following registry keys to the registry of the device.
[HKEY_CLASSES_ROOT\riapp]
"EditFlags"=dword:00010000
[HKEY_CLASSES_ROOT\riapp\Shell\Open\Command]
@="wmwidgetinstaller.exe %1"
Without these keys, the Windows Mobile device does not recognize that there is a file association with the .widget file.
The widget installer extracts the files from the widget file and puts them in a location below \Program Files. Then the installer adds the widget icon to the device Start menu and provides uninstall information so that the widget can be removed through the Remove Programs application. After the widget is installed, the widget files are accessible through a subfolder under the \Program Files\Widgets\User folder. This means that when you develop your application, you only need to deploy the .widget file one time, and when you change files you can copy them directly from the development workstation to the device using Windows Explorer.