Welcome to the MoSync Mobile Developer Center. The documentation for MoSync includes many guides and tutorials to give mobile developers a better start, we also have reference manuals, glossaries, and app examples. Here we provide an overview of all the documentation available for our latest feature releases, including how to install MoSync, how to start up and use the MoSync IDE, how to create mobile apps with it and how to build your mobile applications for multiple devices. Our mobile developer documentation is divided into the following sections.
Quick Links: API Reference Manual | Panics Reference | Example Applications
What is MoSync?The MoSync SDK and its main components, what you can do with it, and who uses it | Getting Started with MoSyncHow to get and install MoSync, start it, and create your first application | ||
Using the Mosync IDEHow to use the IDE and device profiles, how to build your mobile applications | Programming with MoSyncHow to use MoSync libraries to create applications in C and C++
| ||
Lessons and TutorialsStep-by-step walkthroughs of common MoSync tasks and programming activities | MoSync API Reference ManualsDetailed information about the MoSync function libraries and panics | ||
Developing MoSyncHow to build MoSync from source, coding conventions, writing extensions, and contributing to MoSync | |||
More ResourcesMore information about common issues, using MoSync, and programming with MoSync |
As you move through the documentation you will find full navigation menu in the right sidebar. You can leave comments on all pages. Please feel free to tell us about your mobile development experiences, pass on tips and code examples, and to let us know of any errors you find in the documentation.
Today's mobile device market is more fragmented than ever. New platforms are introduced every year. Dozens of new devices arrive from manufacturers every month. Sometimes it can seem that writing your application is the easy part: the real headache is tailoring it for all those different platforms and devices, and trying to keep up with the ever-changing marketplace.
| One Solution For All Platforms | We think that mobile application development is hard enough without having to worry about porting issues. That's why we've created the MoSync® Mobile SDK — a truly open-source solution for today's fragmented mobile market. The MoSync SDK is a fully-featured software development kit helps you develop anything from simple programs for basic mobile phones to advanced applications that exploit the full potential of the latest intelligent smart phones and mobile devices. And with MoSync you can adapt, build, and package your application for hundreds of different mobile devices in a few clicks - all from the same code base! That means huge savings in development costs, faster time-to-market, and wider distribution and revenue possibilities. | ||
![]() | Develop for multiple mobile platforms simultaneously | ||
![]() | Build and package for hundreds of mobile devices | ||
![]() | Gain huge savings in porting and testing costs | ||
![]() | Faster time-to-market and a quicker return on investment | ||
![]() | And it's open-source! | ||

MoSync is developed by a dedicated and enthusiastic team of developers who are committed to making the development of mobile applications faster, easier, and more cost-efficient. MoSync development is very active — check our home page at www.mosync.com and see how often we commit! We'll are adding new mobile platforms, device profiles, and library functions all the time.
MoSync is distributed under the standard GNU General Public License (GPL) version 2. That means that it is completely free for private use. You can even sell your applications commercially, as long as you make your source code available to others.
For individuals, businesses, and organizations who wish to develop MoSync-based applications but who do not wish to publish their source code, we offer a range of commercial subscriptions.
Major platforms features supported by MoSync 2.7.Pyramid
| Available in the featured release, tested | Available in the latest nightly build, may or may not be fully tested | ||
| Coming soon but not yet available | Not possible due to platform limitations |
| Feature/Platform | MoRE (MoSync emulator) | Java ME | Windows Mobile | Symbian S60 2nd, 3rd, 5th | Android 1.5-2.3.3 | iOS (iPhone, iPad, iPod Touch) | Moblin/ MeeGo | Blackberry |
|---|---|---|---|---|---|---|---|---|
| Basic graphics | ||||||||
| Basic audio | ||||||||
| Permanent storage | ||||||||
| Numeric keypad input | n/a | |||||||
| Native text box input | ||||||||
| Qwerty keypad input | ||||||||
| Stylus/touch input | 5th: |
|||||||
| Socket communication | ||||||||
| HTTP communication | ||||||||
| SSL Socket communication | ||||||||
| HTTPS communication | ||||||||
| Bluetooth discovery | 2.x: |
|||||||
| Bluetooth communication | 2.x: |
|||||||
| Bluetooth server | 2.x: | |||||||
| Location | 3rd/5th: |
|||||||
| PIM | 3rd/5th: |
|||||||
| File system access | ||||||||
| Camera access | 2.x: |
|||||||
| Locale (639-1 or 639-2) | Win32: | |||||||
| IMSI/IMEI | ||||||||
| Sending SMS | ||||||||
| Dynamic program loading | ||||||||
| Framebuffer drawing | ||||||||
| Vibration | ||||||||
| Streaming Video/Audio | ||||||||
| Sensors | | |||||||
| - Accelerometer | | | ||||||
| - Proxomity | | | ||||||
| - Gyroscope | | |||||||
| - Orientation | | |||||||
| - Magnetic field | | |||||||
Audiobuffer | ||||||||
OpenGL ES 1.0 | ||||||||
OpenGL ES 2.0 | ||||||||
NFC | ||||||||
Device Fonts | ||||||||
Native UI (Widget API) | | | | | ||||
HTML5 (Wormhole) | ||||||||
| Sound codecs (some devices may have more codecs preinstalled) | Wav, MP3, AMR | Wav, MP3, AMR | Wav | Wav, MP3, AMR | AAC, AMR, Wav, MP3, OGG, MIDI | AAC, AIFF, MP3, Audible, Apple Lossless, WAV | Wav, MP3, AMR | MP3, AAC, MIDI, AMR, WAV, WMA |
| Feature | |
| Eclipse-based IDE | |
| Advanced device emulator | |
| Resource management | |
| Device profiles database | |
| Extensive documentation | |
| Fully integrated debugger | |
| Selected standard C libraries | |
|
Custom UI (MAUI) |
|
| OOP TCP Communications | |
| OOP HTTP Communications | |
| SOAP Communications | |
| JSON/REST layers | |
| Twitter API | |
| Collection library | |
| XML parsing libraries | |
| Font libraries/converters | |
| Map rendering API | |
| On-device error reporting | |
| Batch building (finalizer) | |
| Command line packager | |
| Standard C Library | |
| STL (Standard C++ Library) |
We are constantly adding support for new platforms and new features in MoSync. Features denoted as
are to be found in the nightly builds, rather than in the current featured download.
Our nightly builds are Windows binaries and corresponding source, generated by an automatic timer-based build process. If the build fails, no files are generated. Therefore, a feature can be developed and committed to the repository several days before it shows up in the nightly builds, and longer in a featured build.
If you're really up to it, you can always pick up your MySync directly from the source, but then you need to compile it yourself. To do so you need to get the source code from our public repository:
git clone https://github.com/MoSync/MoSync.git
You can also find instructions for building MoSync on Windows here and on Mac OS X here.
The MoSync® SDK is a complete software development kit for mobile application development. It includes many tightly integrated components — compilers, runtimes, libraries, device profiles, tools, and utilities — all carefully integrated to form a most powerful open-source cross-platform mobile development SDK ever.
Mobile development with unfamiliar tools, languages, and APIs are a thing of the past. MoSync gives you standard C/C++, easy-to-use well-documented APIs, and a full-featured Eclipse-based IDE.
You'll hardly notice you're developing for mobile devices!
The MoSync SDK simplifies the development of mobile applications across multiple platforms. Our unique transformation engine, Pipe-Tool, allows your single code base to be efficiently executed on an endless variety of existing and emerging platforms.
We've developed our own GCC backend that produces MoSync Intermediate Language, which is fed into Pipe-Tool and converted to a number of platform-specific executable forms. The profile database guides the process, ensuring that the application is precisely adapted to each device. The various runtimes provide consistent behavior regarding graphics, audio, communications, input and other device features.
The MoSync IDE is based on Eclipse, allowing you to leverage its powerful editing capabilities. From main development using the PC runtime environment, through testing on a few phones to finalizing the build for hundreds of devices, the MoSync IDE provides support at every stage. Read more
MoRE is the reference implementation of MoSync. It's a PC application that executes MoSync bytecode and looks and feels like a phone. However, it is not an emulator for any particular phone. It's rather the phones that emulate MoRE (MoSync Reference Environment) - not the other way around! Read more
The device profile database contains information about hundreds of mobile devices - everything from screen sizes and memory amounts to obscure bugs and undocumented quirks. It can be used to tailor your application to different devices or create fallbacks for unsupported features. Read more
MoSync uses a custom GCC backend that outputs MoSync Intermediate Language. This is fed into Pipe-tool, our transformation engine, which builds code trees, analyzes, optimizes and finally outputs either MoSync bytecode or a generated runtime core. Read more
MoSync runtimes are libraries or programs that execute MoSync programs on a given target device. They also provide a uniform interface to low-level system APIs, including graphics, audio, event handling and communications. Read more
The MoSync IDE is based on Eclipse, allowing you to leverage its powerful editing capabilities. From main development using the PC runtime environment, through testing on a few phones to finalizing the build for hundreds of devices, the MoSync IDE provides support at every stage.
A MoSync application is built, targeting a device profile, using gcc and pipe-tool. First, pipe-tool is used to compile any resources included in the application. Subsequently gcc is called, using the settings in the application project. The path to the target device's profile is passed to gcc, which uses it to preprocess the application being built. Finally, Pipe-Tool is called to link and assemble the program.
The finalizer is a batch build system that allows you to automatically build your application for hundreds of devices. Once you've applied a number of criteria to your project, such as requiring a minimum screen resolution or the availability of a certain set of features, the finalizer automatically generates a build script for the devices that fulfil these criteria. It organizes the builds into neat, hierarchical structures that requires very little processing in order to comply with the required deployment structures.

MoSync uses a custom GCC backend that outputs MoSync Intermediate Language. This is fed into Pipe-tool, our transformation engine, which builds code trees, analyzes, optimizes and outputs bytecode or java ready for packaging with the appropriate runtime.
When you finalize your application, the MoSync IDE manages the entire build process for you, activating all the tools in the MoSync toolchain with the appropriate options and settings. The IDE uses GCC to compile your code and Pipe-Tool to link it with the MoSync libraries and your resources. The IDE then combines the resulting bytecode or java source code with the appropriate platform runtime to create the executable packages for each target device.

If needed, control over the options and settings for compilation, linking, and packaging is available through the build configurations for your project. It is also possible of course to run GCC and Pipe-Tool individually from the command line.
MoSync's implementation of GCC (the GNU Compiler Collection) compiles your program into an assembly-like format called MoSync Intermediate Language (MoSync IL).
The GCC backend defines a simple machine with a variable number of 32-bit registers and a flat memory model. Currently we are using GCC 3.4.6. For more information about GCC, see http://gcc.gnu.org/onlinedocs.
MoSync IL contains detailed metadata about your program, including symbol mappings and control flow information. MoSync IL is extremely rich, so much so in fact that you could pretty well convert it back to its source form if you wanted to.
Pipe-Tool is our transformation engine. It combines the functions of a resource compiler, linker, and code optimizer.
Pipe-Tool combines the MoSync IL output from GCC with the pre-compiled MoSync libraries into various target formats, including MoSync bytecode, Java bytecode, and C/C++ source code, ready for packaging. In the process, it also performs code verification, optimization, and dead code elimination to produce highly optimized outputs.
Pipe-Tool also compiles and indexes the external resources (images, audio files, binary files, etc.) that your application needs. For more information, see our Resource Compiler Reference.
When you finalize your application, the MoSync IDE manages the entire build process for you, activating all the tools in the MoSync toolchain with the appropriate options and settings. The IDE uses GCC to compile your code and Pipe-Tool to link it with the MoSync libraries and your resources. The IDE then combines the resulting bytecode or java source code with the appropriate platform runtime to create the executable packages for each target device.
If needed, control over the options and settings for compilation, linking, and packaging is available through the build configurations for your project. It is also possible of course to run GCC and Pipe-Tool individually from the command line.
MoSync's implementation of GCC (the GNU Compiler Collection) compiles your program into an assembly-like format called MoSync Intermediate Language (MoSync IL).
The GCC backend defines a simple machine with a variable number of 32-bit registers and a flat memory model. Currently we are using GCC 3.4.6. For more information about GCC, see http://gcc.gnu.org/onlinedocs.
MoSync IL contains detailed metadata about your program, including symbol mappings and control flow information. MoSync IL is extremely rich, so much so in fact that you could pretty well convert it back to its source form if you wanted to.
Pipe-Tool is our transformation engine. It combines the functions of a resource compiler, linker, and code optimizer.
Pipe-Tool combines the MoSync IL output from GCC with the pre-compiled MoSync libraries into various target formats, including MoSync bytecode, Java bytecode, and C/C++ source code, ready for packaging. In the process, it also performs code verification, optimization, and dead code elimination to produce highly optimized outputs.
Pipe-Tool also compiles and indexes the external resources (images, audio files, binary files, etc.) that your application needs. For more information, see our Resource Compiler Reference.
The device profile database contains information about hundreds of mobile devices - everything from screen sizes and memory amounts to obscure bugs and undocumented quirks. It can be used to tailor your application to different devices or create fallbacks for unsupported features.

Our device profile database is stored as a hierarchical filesystem structure - one directory per device vendor, each containing per-device subdirectories. Each device directory contains a C header file with information about the device formatted as C preprocessor definitions, and a textual reference to the associated runtime. The profile header file can be used in MoSync programs to automatically modify their functionality depending on the target device: Common information in profiles include vendor and device names, screen size and API availability, for example Bluetooth or Location.

The MoSync Runtime Environment (MoRE) is the reference implementation of MoSync. It’s an application that executes MoSync bytecode and looks and behaves like a phone. But it is not an emulator of any particular phone - it’s the phones that emulate MoRE, not the other way around!
Using For full instructions on using the MoSync Emulator, and for installing and using native emulators on iOS and Android, see Emulating a Device.
In traditional mobile development, being able to access an emulator that faithfully mimics the behavior of an actual devices is crucial: being able to catch bugs early before moving to testing on real physical devices significantly reduces the amount time spent porting to each device, and speeds up application development.
But at MoSync AB we don't think that's good enough. Development time shouldn't be proportional to the number of devices targeted at all. Instead, it should be related to the number of differences between the devices that really matter for your application - things like screen size, memory capacity, input methods, or API availability. You should be able to adapt your project to these variations independently, not based on arbitrary combinations of properties exhibited by actual devices.
MoRE is designed to meet these requirements. It can be configured with any combination of properties independently. Set it to any screen size you desire. Let it have Bluetooth support and 16 Mb of memory. Toggle stylus support. If you like, tell it to have the same properties as a Nokia N95 or Sony Ericsson k700i. Whatever properties you set, the MoSync SDK makes sure that the behavior you observe in MoRE regarding those properties is consistent with that of any device that exhibits them.
We're approaching the problem from the opposite direction; instead of making an emulator that faithfully reproduces the behaviour of every single device, we make sure that each MoSync implementation reproduces the behaviour of MoRE. We've developed advanced testing mechanisms that let us verify, to a very high degree, that two MoSync implementations behave the same. At any stage of an application's execution, we can accurately compare the abstract MoSync machine state between them.
Each time we develop a new MoSync runtime or update an existing one, we run comparative tests between that runtime and MoRE. We do it on the actual phones so that you do not have to. When we're done, we have a runtime that for all intents and purposes behaves just like MoRE and executes MoSync applications flawlessly. So if it runs in MoRE it will run on the device.
For more about using the MoSync Emulator, see Emulating a Device.
The MoSync runtimes consist of libraries and programs that execute your code on a given target device. They provide a uniform interface to low-level system APIs, including graphics, audio, event handling and communications.
While MoSync runtimes are tiny and efficient, they are still very sophisiticated pieces of engineering. Learn more about the architecture here.
When people hear “runtime”, they usually think of one of two things; either a lightweight support system like the C runtime library or a Java-style virtual machine. Our definition is broader.
We think of MoSync as a contract between the generators — the things that produce MoSync IL — and the runtimes, which execute it on a set of devices. In some cases, this is indeed a virtual machine, but not always. For lower-end Java phones, we don’t even have to use pre-generated runtimes — each application your write can be transformed directly to Java bytecode. We currently have a prototype implementation of this transformation. However, we still call the result a "runtime" because it essentially makes the MoSync IL executable. In the case of iPhone we convert the MoSync IL into C++ and output it in an Xcode project which includes the iPhone syscall libraries.
The MoSync runtimes that are virtual machines are not the kind of VM most people would think of. They’re register-based, generally smaller than 100k and very, very fast. Where possible, they recompile your entire program to native ARM machine code before executing it. With the tiny footprint and native recompilation, there’s never any need to worry about performance.
MoSync has two primary runtime architectures - one implemented in C++ and one in Java. However, the design is very similar in both cases.

A runtime includes a service layer providing file I/O, threading, networking, memory managment and other supporting functions.
This module holds the runtime's entrypoint. Its size and responsibilities vary across platforms. However, it typically handles platform-specific event management, initialization and destruction.
This module is responsible for implementing the basic features required for all platforms - graphics, audio, networking etc. It interprets MoSync resource files and also provides event managment, initialization and destruction.
This module provides facilities for managing resource objects, such as images, sounds and data blobs. It supports dynamic creation and destruction of resources.
Some features may not be available on all platforms. Such features are implemented as numbered functions called through a single Syscall. That Syscall returns a specific error value if the function being called is not present. This allows developers to determine whether such a non-universal API is accessible in runtime.
This module is responsible for the execution of MoSync programs. It interoperates with the syscalls and resource system. Cores come in a number of different flavors, all of which share a common interface to the above mentioned modules. These are the three main types:
| VM Core | Recompiler Core | Generated Core |
|---|---|---|
| A VM core is a virtual machine that loads, interprets and executes MoSync bytecode directly. The execution is implemented in a single, small function, allowing for efficient JIT optimization. This is the type of core we use for Java ME. |
A recompiler core loads MoSync bytecode and recompiles it into native code for the platform concerned, typically ARM machine code. The generated machine code is then executed. This is the type of core we use for Windows Mobile and Symbian. |
This type of core neither inteprets nor recompiles MoSync
bytecode - instead, it contains native code generated ahead of
time from MoSync IL, and exposes an interface consistent with
other core variants. This is the type of core we use for iPhone. |
The reason we have three types of cores is that each has its distinct advantages. VM cores are great for debugging and conformance verification and are fully dynamic, making it possible to load new code at runtime, which is useful for many types of applications. Recompiler cores are more efficient, but provide less debugging support. They are also dynamic, albeit with some recompilation overhead when loading new code. Finally, generated cores provide zero overhead for low end devices, while sacrificing dynamicite. They are not able to load code at runtime.
All three types of core share a common interface - a generated or recompiler core works as a drop-in replacement for a VM core. This allows all the other modules to be shared across runtimes without modification.
This is the roadmap for MoSync until December 2011. Some of you who may have been following the previous roadmap will notice that we've dropped the 2.8 release and moved things into the 3.0 release, but we've also added in some previously unannounced goodies!
All these things will be available in experimental form a lot earlier in our nightly builds. You can also check out our Github repository too see what we are working on at the moment.
MoSync 3.0 - December 19th 2011
The people who know the most about the challenges of mobile application development are our customers. Without them and the feedback they provide to us, development of the MoSync SDK would have been nearly impossible. We thank them all! Many of our cross-platform mobile development projects are for customers who insist on strict non-disclosure for commercial or security reasons, so of course we can't tell you about them, but here are a few of our customers who we can tell you about, and what they are doing with MoSync.
A guidance system for visually impaired pedestrians

The e-Adept system from Astando is based on a digitalized road network for pedestrians and cyclists. Combined with a precise and reliable handheld positioning system based on GPS and inertia navigation, e-Adept provides an extremely detailed route indication for its pedestrian users — much more detailed than the normal road maps for drivers. The pedestrian route network makes it possible for the user to be guided along sidewalks, pathways and pedestrian crossings.
Astando uses MoSync to build e-Adept on standard phones. In this project we supported the development of a mobile navigation service for the visually impaired involving intriguing challenges in areas such as high performance real time positioning, UI design for the visually impaired, speech synthesis, design of Web Services suited for mobile communication and more. Mosync's role in the project involves supporting development of the client software and the client-server communication solution.
A common problem with GPS positioning is that it doesn't work well indoors or when there is no clear view of the positioning satellites. To solve this problem, we first developed an indoor positioning solution based on WLAN beacons working in combination with a sophisticated triangulation software residing on the mobile phone.
The final positioning solution made use of a dead reckoning technology with circuit boards provided by Honeywell Inc — a kind of advanced step counter with compass and 3D accelerometers on-board. The goal for the project is to create seamless outdoor/indoor positioning and navigation for various groups such as the visually impaired, the elderly, tourists and other services requiring reliable, high-performance positioning. The system has been tested in full-scale in three cities, and is already in use in lesser scale, by user groups and a selected trial population. The delegates of the 2008 ITS conference in Stockholm had the opportunity to try the system during the tour day of the international conference on intelligent transport systems.
Further reading, and an introductionary movie can be found at the customer's project website at www.eadept.se (in Swedish and English).
A social networked mobile system

You’re in a pub with your friends, having a drink and chatting. You see a good looking guy with his friends a couple of tables away. Suddenly your eyes meet, and a mutual smile is exchanged. You’ld like to talk to him but you’re to shy too approach him at this time. Instead, you pick up your mobile phone and start your BlooFlirt application. Within a few seconds you see a picture list of other BlooFlirt members in the same pub, including the good looking guy who you can’t take your eyes off.
Bloo use MoSync to achieve consistent cross-plattform performance from a single code source. Instead of spending time on porting to various phone models, they can concentrate on development of the actual application.
The application uses a lot of connections, both local using bluetooth and via the cell network. This allows a user to "connect" even though a client is not in use, as long as their bluetooth connection is active another peer in the system can identify another nearby handset and register bluetooth MAC adresses in its proximity. This together with smart algoritms for roaming makes BlooFlirt as a social media system very flexible and robust. For more information on BlooFlirt and other networked social media applications, feel free to contact tommy@bloo.com.
A daily paper's local lunch guide

Dalarns Tidningar is a local daily in the mid-west of Sweden, found at www.dt.se. They run a community hub where a lot of information in the municipalty can be found, along with reviews, tips and debate on sociatal matters. All the local restaurants publish their weekly menus at the daily's website, and as an introductary step into the mobile landscape they wanted to publish information into mobile channels as well - hence they created a mab-based lunchguide for their users using MoSync.
The application is developed for the project by Lars Åke Vinberg, who normally develops software for the Windows platform and is skilled in c/c++ development. His work is then contributed to MoSync where this application is generalised into a standard map library, with the possibility to support several map formats such as Open Street Map, CloudMade and Google Maps (static).
The software is layed out in a layered structure, with a tile-based slippy map as a base layer, and with graphical elements on top which are fed into the application over HTTP using an XML-based format called geoRSS. There is also a browser supporting a small subset of HTML for viewing details about each point location on the map.
The main components are today available as libraries of the MoSync SDK, which through an open source GPL licensing is available for download at the mosync.com website.
Read more about the Maps API here
Our 2.7 release is packed with new features for cross-platform mobile application developers. We've enhanced MoSync's HTML5 and JavaScript support, created a near field communications API, and ported the C++ Standard Template Library and the C Newlib library to MoSync. There are many new code templates and example applications in the IDE, and tutorials and user guides online. Let's take a look.
iOS and Android
We're introducing Wormhole - a technology which makes it possible to build apps which seamslessly blend HTML5/JavaScript with C++ code. We've also greatly enhanced support for HTML5 applications in the IDE. That means you can bundle HTML/CSS/JavaScript/media files with your application, and edit HTML and JavaScript files right in the IDE, with syntax support. You can create native applications with rich web content, and develop advanced JavaScript applications that communicate with all the services provided by the MoSync API. You'll be up and running with a slick JavaScript app that talks to all those powerful MoSync C syscalls and C++ libraries in no time. More...
Android 2.3.3+
Our NFC API is packed with functions that allow your application to talk to the near field communication (NFC) features on the latest Android devices. That means that you can write applications that communicate with NFC tags according to the latest protocols and standards (NDEF, IsoDep, Mifare Classic/Ultralight), opening a whole range of possibilities for payment, personal identification, and similar close-proximity applications. More...
All platforms
We have ported the C++ Standard Template Library (STL) to MoSync. This feature-packed code library will already be familiar to many programmers, thanks to its all-round usefulness to computer science and industry. It provides many powerful algorithms, containers, associative arrays, and iterators, to simplify data handling within advanced applications. More...
All platforms
We have also ported the Newlib standard C library to MoSync. Newlib is particularly suited for mobile devices and embedded systems. It is a conglomeration of several library parts, all under free software licenses. It provides subroutines for handling files, environment variables, processes, output streams and memory. More...
These templates are available when creating new projects in the MoSync IDE. For an overview of all the available templates, see Creating Projects from Templates.
Documentation for all examples is available at http://www.mosync.com/content/demo-examples.
All documentation is available online at http://www.mosync.com/documentation.
Please note: MoSync 2.7 is available http://www.mosync.com/#features.
The 2.6 Pyramid release introduces many new device APIs, new libraries for Facebook and NativeUI, and many new application examples. We also now support native emulators and application profiling in the IDE.
On iPhone (iOS) and Android:
In the IDE:
Other:
The maLogWrite syscall, and also the lprintfln/printf functions, only print to the device console when the application is built in Debug mode. For example, if you use lprintfln to output log messages to the logcat console on Android, the application must be built in Debug mode for the output to appear. No output is shown in Release mode.
On iPhone (iOS) and Android:
On all platforms:
On iPhone (iOS) and Android:
On iPhone (iOS) and Android:
On iPhone (iOS) and Android:
New syscalls are documented in the reference documentation included in the package. Documentation for the OpenGL ES 1.1 and 2.0 syscalls can be found in the Open GL Reference Pages.
On Android:
All new event types are documented in the reference documentation included in the package.
On iPhone (iOS) and Android:
Documentation for all examples is available at http://www.mosync.com/content/demo-examples.
On iPhone (iOS) and Android:
All documentation is available online at http://www.mosync.com/documentation.
Our 2.5.Pyramid release introduces new APIs, runtime features, IDE improvements, application examples, and user guides. Here is a quick overview of what is new in this release.
* Not available on the MoSync emulator.
We have implemented dozens of new syscalls. A brief summary is given below. All new syscalls are documented in the reference documentation included in the package.
On iPhone (iOS) and Android:
On Android:
Support for all new syscalls will be added to the MoSync emulator in the near future.
All new event types are documented in the reference documentation included in the package.
On all platforms:
On iPhone (iOS) and Android:
On Android:
In MoSync SDK for Windows and MoSync SDK for OS X:
In MoSync SDK for Windows:
New project templates, available in both versions of MoSync:
All project templates now contain a small sample of code so that they are immediately runable on an appropriate device. All templates have been revised in line with our Coding Conventions.
Eclipse have changed the way the hover function works. See: http://www.mosync.com/content/show-source-hover.
Documentation for all examples is available at http://www.mosync.com/content/demo-examples.
We have an entirely new Developer Centre at our website from which you can access a huge range of tutorials, code examples, and resources.
Many of our existing user guides and tutorials have been updated and expanded for this release, including:
All documentation is available online at http://www.mosync.com/content/documentation.
Details about every resolved issue can be found in our issue tracker.
Our 2.4 release introduces support for Apple's popular iPhone platform (including iPad and iPod) and Android 2.2, plus many many new libraries, runtime features, IDE improvements, application examples, user guides, and tutorials. Here is a quick overview of what is new in this release.
Many of the existing example applications in the SDK package have been updated for this release, and now include touch support. Documentation for all examples is available at http://www.mosync.com/content/demo-examples.
Getting Started Guides:
User Guides:
Programmer's Guides:
Tutorials:
Developer's Guides
All of our existing user guides and tutorials have been updated and expanded for this release.
All documentation is now available online at http://www.mosync.com/content/documentation.
We have changed the default background drawing behaviour of several widgets to make them more sensible for each widget. For example, the label widget now draws its background by default. Use setDrawBackground(false) to disable background drawing.
Details about each issue can be found in our issue tracker.
The guides and tutorials in this section of the documentation cover various aspects of the MoSync integrated development environment and associated tools, including how to work with mobile device profiles, how to use the emulator, different ways to build and finalize your application, and how to send your application to a mobile device. We also provide advice here about using alternative development environments such as Visual Studio.
Here we describe the system requirements of the MoSync SDK for Windows, and how to download and install it. We also describe how to upgrade from a previous release of the MoSync SDK for Windows.
You can download the last featured release of the MoSync SDK for Windows (and its latest nightly builds) from the Download page at our website: http://www.mosync.com/download.
Important note: The MoSync SDK for Windows enables you to directly build application packages for Java ME, Symbian, Android, Windows Mobile, Smartphone, Pocket PC, and Moblin/Meego devices. You can also use it to build Xcode projects for iOS applications (i.e., for iPhone, iPad, and iPod Touch), however to finalize an Xcode project you will need to transfer it to an Apple Mac running OS X and Xcode and create the application package there. If you already have a Mac available, we recommend that you download and install our OS X development environmant, the MoSync SDK for OS X, which is available from our Download page.
MoSync is designed to run on any PC that meets the following requirements:
Install or update your Java SE Runtime Environment before installing MoSync. It can be downloaded here.
Note: we recommend the Oracle/Sun version of JRE. If you wish to use another vendor's JRE and you have set the permanent memory perm gen size to less than the default size of 82Mb, you will get warning message requesting that you increase it.
To use MoSync's device discovery and transfer features, you will also need a Bluetooth-enabled PC, a mobile device and one of the following software stacks:
To use the emulator's Bluetooth support when testing programs, you will need the Microsoft stack.
After you have downloaded the MoSync installer package, double-click the file to begin the installation. The installer will unpack the files and begin the installation process.

When the files have been unpacked, the MoSync splash-screen will appear.

The splach screen will fade and our license agreement will appear. Please take the time to read the MoSync License Agreement — it contains important information about the terms under which we supply the MoSync SDK. Agree to it if you would like to proceed with the installation.

Select the components you wish to install. Note that there isn't any options for the MoSync package, everything needs to be installed.

Select where you would like MoSync to be installed. Please note that MoSync needs to be installed to a directory which is not containing any spaces in its path.

If you have a previously uninstalled copy of MoSync you will get the following notice. Please follow the instruction and make a copy of your project files if they are inside the MoSync installation folder. Even if they shouldn't be removed it's better to be safe than sorry.

If you had a previous installation it will first be removed before the new version of the MoSync SDK is installed on your computer. Please wait for the installation to complete. The installation process may take a few minutes.

As part of the installation process, the Microsoft Visual C++ 2005 Redistributable will also be installed and some changes will be made to environment variables.
MoSync is now installed. Press Finish to end the installer and open the MoSync IDE.

MoSync includes its own powerful, cross-platform emulator, MoRE. You can also install native emulators -- particularly useful for testing native user interfaces like our Widget API and NativeUI Library, and for testing APIs and libraries that are only currently supported on a limited number of platforms. Instructions for installing native emulators can be found in our user guide Emulating a Device.
The OS X version of the MoSync SDK enables you to build applications for iOS devices (including Apple iPhones and iPads) as well as for Windows Mobile, Java ME, Symbian, Android, Smartphone, Pocket PC, and Moblin devices. Here we describe the system requirements of the MoSync SDK for OS X, and how to download and install it. We also describe how to upgrade from a previous release of the SDK.
You can download the last stable featured release of the MoSync SDK (and the latest nightly builds) from the Download page: http://www.mosync.com/download.
MoSync SDK for OS X has the following system requirements:
Apple imposes strict rules and guidelines on how applications for its App Store are to be built. To build an iOS application with the MoSync SDK, you will need to install Xcode 3.2.5 with the iOS SDK. You will also need to join Apple's Developer Program.
To use MoSync's device discovery and transfer features, you will also need a Bluetooth-enabled Mac, a mobile device and one of the following software stacks:
To use the emulator's Bluetooth support when testing programs, you will need the Microsoft stack.




Xcode can be downloaded from the Apple iOS Dev Center. Make sure that the version you download includes the iPhone OS SDK.
Advice on building iPhone applications can be found in our programmer's guide Developing iPhone Applications.
The iOS Provisioning Portal is designed to take you through the necessary steps to test your applications on iOS devices and prepare them for distribution.
MoSync includes its own powerful, cross-platform emulator, MoRE. You can also install native emulators -- particularly useful for testing native user interfaces like our Widget API and NativeUI Library, and for testing APIs and libraries that are only currently supported on a limited number of platforms. Instructions for installing native emulators can be found in our user guide Emulating a Device.
This guide shows you how to create a new application project in the MoSync IDE and describes the project templates that are available to you. It also introduces the concepts of projects and workspaces. We have templates for various types of C/C++ projects, and templates for hybrid HTML/Javascript/C/C++ projects.
The MoSync IDE is based on Eclipse. Eclipse organizes your source code using projects and workspaces. A workspace is a collection of projects. A project is a collection of a set of source files. Projects can be individual applications or modules, depending on how you choose to organize your workspaces. Each project maps to a corresponding directory in the file system.
The different projects in a workspace may map to different file system directories or drives, although, by default, all projects map to subdirectories of a single workspace directory. All files in the workspace are directly accessible to the standard programs and tools of the underlying operating system.
The Project Explorer view in the IDE shows you all the projects in the current workspace and their source files.
In the MoSync IDE, you create a new project by doing one of the following:

When the New Project window opens, expand the MoSync folder:

In the folder MoSync you will find wizards for creating MoSync projects.
Select the one called MoSync Project.
Click Next.
The project name and location screen appears:

Enter the Project name "HelloWorld". (Note: to ensure compatibility with all platforms and devices, avoid using spaces in project names; it is always safe to use the underscore character.)
Tick the Use default location box. Click Next.
A new window will open showing you the templates that are available for you new project:

Select a template and click Finish.
Your new project will now be created from the template and loaded in the MoSync IDE.
We provide you with many different project templates, adapted to meet the needs of various different application types.
All templates have:
Template | Languages | Description | Libraries | Heap size | Stack size | Data size |
HTML5 Project | HTML5, JavaScript | An HTML5 template that includes the WebAppletMoblet for pure web applications based on HTML5, CSS,and JavaScript. | mastd.lib, MAUtil.lib, NativeUI.lib, MAFS.lib, Wormhole.lib | 3072 | 512 | 4096 |
HTML5/C++ Project | HTML5, JavaScript, C/C++ | A hybrid HTML5/JavaScript and C/C++ template. Build your user interfaces in JavaScript. Do the heavy lifting in C/C++. | mastd.lib, MAUtil.lib, NativeUI.lib, MAFS.lib, Wormhole.lib | 3072 | 512 | 4096 |
MoSync C++ Project | C/C++ | A standard ANSI C++ application template consisting of a main file with a small code example. | mastd.lib, MAUtil.lib | 512 | 128 | 1024 |
MoSync C++ STL Project | C/C++ | A standard ANSI C++ application template consisting of a main file with a small code example and includes the C++ Standard Template Library. | newlib.lib, stlport.lib | 1536 | 256 | 2048 |
MoSync Moblet Project | C/C++ | A standard ANSI C++ application template that includes our Moblet event-handling framework and some simple example code. | mastd.lib, MAUtil.lib | 512 | 128 | 1024 |
MoSync MAUI Project | C/C++ | A standard ANSI C++ application template that includes the Moblet framework, MoSync’s graphical user interface library (MAUI), and some simple example code. | mastd.lib, MAUtil.lib, MAUI.lib | 1536 | 256 | 2048 |
MoSync NativeUI Project | C/C++ | A standard ANSI C application template that includes our Moblet event-handling framework and uses the Widget API. | mastd.lib, MAUtil.lib | 3072 | 512 | 4096 |
MoSync NativeUI C++ Project | C/C++ | A standard ANSI C++ application template that includes our Moblet event-handling framework and uses the NativeUI Library. | mastd.lib, MAUtil.lib, NativeUI.lib | 3072 | 512 | 4096 |
MoSync OpenGL Project | C/C++ | A standard ANSI C++ application template that includes our Moblet event-handling framework and includes some basic OpenGL code. | mastd.lib, MAUtil.lib | 3072 | 512 | 4096 |
Empty MoSync Project | C | No main file, roll your own. | mastd.lib | 512 | 128 | 1024 |
MoSync C Project | C | A standard ANSI C project template consisting of a main file with a small code example. | mastd.lib | 512 | 128 | 1024 |
MoSync C Newlib Project | C | A standard ANSI C application template using newlib. | newlib.lib | 1536 | 256 | 2048 |
The first time you start the MoSync IDE you will be offered the chance to register the product and you will also see the Welcome screen which provides helpful links to get you started. Here we look at some of the options you have when starting MoSync.
Starting the MoSync IDE on Windows:
Starting the MoSync IDE on OS X:
When you start MoSync the first thing you will see is its splash-screen:

The splash screen shows you the target platforms that this version of MoSync can build packages for. It is worth checking this screen whenever you update MoSync because we regularly add new platforms.
The splash screen also shows the version number of the MoSync SDK in the form:
<major>.<minor> <status> (<build>)
Next, the MoSync IDE will ask you which workspace you want to start working in this session:

The MoSync IDE is based on the popular development environment Eclipse, and workspaces are Eclipse's way of organizing projects. You can have several workspaces, with different projects in each. (Workspaces and projects are normal folders that you can see in the file system.)
If this is the first time you are launching MoSync, you can just accept the default workspace by clicking OK. The MoSync IDE will finish loading.
(Later you can create new workspaces and use them to orgainse your different projects. Note that workspace names cannot include spaces — only alphanumeric characters (a-z, A-Z, 0-9) and underscore (_)).
When you start the MoSync IDE, it will prompt you to register the program if you have not already done so.

MoSync registration is completely free, and it means that you can get automatic device profile updates whenever you start MoSync and full access to your website including our Developer's Forum. You also have the option of subscribing to our mailing list for news about new features.
If you have not registered with us before, simply enter your desired username and e-mail address and follow the instructions. Your e-mail address must be valid because we will send a confirmation e-mail to that address.
If you have already registered with us, follow the Already registered? Click here link and enter you username and password.
When you have completed the registration process, click Continue.
If you do not receive a confirmation email within a few minutes, it may be because your e-mail provider's spam filter has blocked it. Check in your spam or junk email folder to see if it has been put there.
If you are using Gmail and some similar email systems, and you have requested the MoSync IDE to resend your confirmation email, you may get an apparently empty email. Simply click on the "show quoted text" in this email to see the confirmation text.
If you have disabled the registration screen and want to display it later, you can find it under Help > Register in the IDE.
When you successfully registered the MoSync IDE will next display its Welcome screen:

The Welcome screen provides you with many useful links to get you started with MoSync, including links to our guides and examples:
*If the examples already exist in the current workspace they are not replaced. If you make changes to the examples, you can still import the originals at a later time (see Importing the Examples). The examples are stored in the /examples folder in your MoSync installation directory.
If you choose not to show the Welcome screen at start-up, you can always find it again under Help > Welcome in the IDE.
When you are ready to leave this screen, click the Close the welcome screen and start using MoSync link. You will now see the normal Eclipse views in the IDE.
The main screen of the MoSync IDE consists of several "views" and toolbars. If you are familiar with Eclipse, many aspects of the IDE will be familiar to you, but we have added a lot of many features to support the MoSync IDE. Some of the more important features are labelled in the diagram below.

The main views in the MoSync IDE include:
If you close a MoSync-specific view (for example the Device Profiles view or the Finalizer view you can reopen it again by selecting Window > Show View > Other > MoSync.
You can jump directly to the documentation for MoSync syscalls and other keywords by highlighting the keyword in the Editor View and pressing the F1 key. The Help View will open where you can find a link to the keyword's documentation:

Here we show you how to import the example applications in the /examples folder into MoSync. For a description of each example application, see the Example Applications overview.
There are two ways to import the example applications:
After import, the example application projects will be visible in the Project Explorer:

To build and run an example application in the MoRE emulator, open one of the examples in Project Explorer, then click the Run button
on the toolbar, or press Ctrl+F11.
Note that examples that use NativeUI and OpenGLES will not run in the MoRE emulator. They need to be transfered to a device (see Sending to a Device).
MoSync's libraries provide you with thousands of pre-written classes and functions that you can use within your application. Here we show how to connect to the libraries from your applications, and give you a brief overview of each of the main libraries.
MoSync's libraries contain both code files and matching header files. To get be able to use the syscalls, classes, and functions in the code files you need to reference the appropriate header files in your application using #include statements:

Here we are including the header file for Moblet (MoSync's event handling framework) and some header files for MAUI. That will enable us to access to the Moblet code and the MAUI screens and widgets later in our application.
You can get a list of all the header files that you can include in your application by browsing the Includes folder in your project:

As well as referencing the header files in your application code, you also need to specify the actual libraries that you want to use in the project's Build Settings (Project > Properties > MoSync Project > Build Settings):

Here we are including the mautil.lib library that contains the moblet code and the maui.lib library that contains the screen and widget code.
Note that the mastd.lib library is always included in the build — you don't need to specify it in your list of additional libraries.
When you build your application, MoSync's Pipe-Tool links the libraries that are listed in the Additional Libraries field and mastd.lib with your code:

The MoSync libraries are stored in the /lib directory in your MoSync installation. A complete description of the libraries and their contents can be found in the MoSync IDE's help system (Help > MoSync API Reference) and also in our online API Reference Guide.
| Library | Content |
| mastd.lib | The main library of MoSync system calls (syscalls). The syscalls give you access to many basic platform features, including permanent storage, graphics, sound, communications, camera, and so on. |
| mafs.lib | Virtual file system classes and functions |
| map.lib | Slippy map classes and functions |
| matest.lib | MATest test framework |
| maui.lib | MAUI graphical user interface classes and functions |
| mautil.lib | General utilities, including Moblets, event handling, framebuffer, Bluetooth discovery and connections, containers, and geometric helper structures. |
| mtxml.lib | XML SAX parser classes and functions |
| testify.lib | Testify test framework |
MoSync comes with a comprehensive set of device profiles to help you deploy your applications to the widest possible range of mobile devices. Each device profile defines the characteristics and capabilities of a single mobile device. Device profiles are used by MoSync's MoRE emulator and during the build process to dynamically tailor the application to a particular device.
MoSync comes with hundreds of device profiles, categorized by vendor. Each device profile holds important information about the characteristics of target mobile device, including information such as:
The available device profiles are shown on the Device Profiles tab in the IDE:
When you start a new project, the active device profile is always the profile for the MoSync emulator. (You can find this profile in the Device Profile view under Mobile Sorcery > Emulator.)
The current device profile is highlighted with an orange background to its icon.
To change the current device profile, right-click on the name of a device in the Device Profile view and select Set Target Phone.

If you want to see more information about a particular device, select Show Profile Info from the right-click menu. You will then see the header file that MoSync will use when it builds the application for the emulator:

You can filter the list of device profiles so that only a subset of the full device profile list is shown in the Device Profiles view so that, when you build your application, packages will only be built for the devices listed.
You can set more than one filter: setting the right combination of filters enables you to build only for the devices that meet the exact requirements of your application.
To set a filter, click the Add button beneath the Device Profiles view. The Select Filter Type window will open:

The first option is Vendor/Device. Here it's possible to choose which vendors and devices you want to include or exclude from your profiles. Use the checkboxes to select the combination of vendors and devices you require.

The second option is Feature/Bug. Here it's possible to include and exclude devices according to the features and bugs that we know exist on the various devices. It's also possible to select device operating systems through this option:

The third option is Device Constant Condition. These are constant values set in all devices. They include the screen sizes and the available heap sizes of the various devices:

By using multiple filters you can select the devices that satisfy the requirements for your application. Mutliple filters are combined using the AND operator: a device is listed only if it satisfies the conditions of all filters.
To remove or edit a currently applied filter, highlight the filter beneath the Device Profiles view, then click Remove or Edit.

To access device profile definitions in your C/C++ code, include the maprofile header file:
#include <maprofile.h>
Useful profile definitions include MA_PROF_STRING_VENDOR and MA_PROF_STRING_DEVICE, which are the names of the device and its vendor.
For writing vendor-specific or device-specific code, MA_PROF_VENDOR_* and MA_PROF_DEVICE_* definitions are also available. For example MA_PROF_VENDOR_NOKIA and MA_PROF_DEVICE_6630.
MA_PROF_SUPPORT_JAVAPACKAGE_BLUETOOTH is defined if and only if the device supports Bluetooth.
MA_PROF_CONST_SCREENSIZE_X, MA_PROF_CONST_SCREENSIZE_Y are defined as integers that describe the screen size in pixels. MA_PROF_CONST_BITSPERPIXEL describes the color depth.
If you close the Device Profiles view you can reopen it again by selecting Window > Show View > Other > MoSync > Device Profiles.
So that you can rapidly test your application from within the IDE, MoSync includes an emulator called the MoSync Runtime Environment (MoRE). MoRE can emulate any device in MoSync's device profile database. The device profile information provides all the configuration settings it needs. You can also install the native Android Emulator and iPhone/iOS Simulator and run your application in those too -- useful if you are working with OpenGL ES, NativeUI, or other APIs that are only available for Android or iOS.
All MoSync releases:
From MoSync 2.6:
The Android Emulator and iPhone/iOS Simulator can be installed and specified as the target emulator for Android or iOS applications so that you can test OpenGL ES, NativeUI Library, and Widget API-based applications. Once installed you just need to select an Android or iOS device profile before you run your application in the IDE. The appropriate native emulator will start up authomatically. For installation instructions, see Installing and Working with Native Emulators.
To start the MoSync MoRE emulator, click the
Run button on the toolbar (or press Ctrl+F11). The current project is be saved, built using the "Release" build configuration, and loaded into the emulator. A graphical phone is displayed.
(You can also start the emulator in debug mode by clicking the
Debug button on the toolbar. In this case the current project is built using the "Debug" build configuration, before being loaded into the emulator.)
The emulator is controlled either by clicking the keys on the graphical phone, or using a number of keyboard shortcuts:

The emulator communicates with the MoSync IDE, sending call stacks, panics, and other useful data to the console window.
The F4 key on the keyboard toggles the screen orientation of the emulator between portrait and landscape modes (and causes an EVENT_TYPE_SCREEN_CHANGED to be sent to the application).
MoSync 2.5+
Right-click with the mouse pointer on the emulator screen to engage multitouch simulation. Two filled circles appear, equidistant and opposite from the screen's centre point:

To emulate pinch-in, pinch-out, and rotational guestures, move the pointer in different directions while holding down the right mouse button.
The Esc key closes the emulator.
When it executes a MoSync application, the emulator uses the current device profile. For instance, the screen dimensions of the graphical phone varies according to settings in the current device profile.
When you create a new MoSync project, MoSync defaults to a generic device profile. You can find this profile in the Device Profile view under Mobile Sorcery > Emulator. The default device profile has the following characteristics:
You can use the default profile when you start to explore MoSync, and for many of our basic tutorials, but sooner or later you will want to test your application by setting up the emulator to use another device profile.
The device profile that the emulator currently uses is highlighted in the Device Profile list with an orange background. To make the emulator emulate another device, right-click on a device in the Device Profile view and select Set Target Phone.

If you want to see more information about the device, select Show Profile Info from the right-click menu. You will then see the header file that MoSync will use when it builds the application for the emulator.
Currently, the only property you can change is screen size. You can manually override the screen size setting by clicking the small down-arrow next to the Run button in the toolbar, and selecting Run Configurations:

If you debugging your application, there is a similar setting for debug mode: click the small down-arrow next to the Debug button in the toolbar, and selecting Debug Configurations to see the settings.
When a MoSync application terminates because of a panic, a call stack is transmitted to the output console in the IDE:

The call stack shows you all the stack frames that were active when the application terminated, and you can click on each line to go to the corresponding source file and line. This is the format of such lines:
IP:<instruction pointer>: <path to source file>:<line number in source file>
If the panic involved MoSync libraries that you do not have the source code to, those lines will not be clickable.
When you build your project for the emulator, the progress of the build will be displayed in the Console and includes information about the success of the invokations of GCC and Pipe-Tool, the build paths, and so on. If you build your project successfully, these results will be replaced at the end of the build process by a new Console view showing the output from your application. If you want to examine the build results, you can switch the Console view using the Display Selected Console selector on the Console toolbar:

MoSync 2.6 onwards:
If you would like to run your application
directly in the Android Emulator or iPhone/iOS Simulator you will need to install and configure them. Once you have done this, when you select an Android or iPhone/iOS device profile and start the emulator, your application will run in the appropriate emulator.
Run button.Important! Those of you who are already familiar with the Android Emulator will know that it can take a long time -- and we mean a really long time -- to start. Time enough, indeed for you to make lunch, or even dinner. Nothing to do with us. Talk to Mr Google.
In this MoSync tutorial, Miles shows you how to configure and run the Android emulator directly from the MoSync IDE.
MoSync makes it easy to scan for nearby devices and connect to them using Bluetooth. Of course, both your computer and the device must have Bluetooth installed and enabled, the device must be configured as "discoverable" so that the computer can find it. The device must also support the OBEX communications protocol. Once you have connected to your device, you will be able to send your application to it over Bluetooth.
Click the Select Target Device icon (or select Scan for Device from that icon's drop-down menu):

The transport selection dialog will appear.

Select Bluetooth. If you have correctly configured your Bluetooth stack, MoSync will start a search for all discoverable Bluetooth devices in range and display the ones that it finds:
Highlight the device that you want to send your application to and click OK.
MoSync will now check that the selected device has the OBEX service available for binary transfers:

In MoSync 2.3, when the OBEX service is detected, the Select Preferred Profile window will appear:

Select the MoSync device profile you want to associate with the target device. Usually, this will be the profile for the target device, e.g., the N95 profile for the N95 phone. However, if there is no suitable profile for your device, you can choose another compatible profile. Click OK to associate the chosen device profile with the target device.
When the OBEX service is detected, MoSync automatically completes the device selection by associating the device profile currently selected in the project with the target device. For more about this association, including how to check its current setting and how to change it, see Sending to a Device.
We have noted some issues with the pairing of Windows Mobile devices to Windows computers.
The first issue seems to happen if the device has been previously paired with the computer outside of MoSync. If you are having problems sending application packages files from the MoSync SDK to a Windows Mobile bluetooth device, try unpairing the device in the Windows Bluetooth Device Manager or its equivalent, and then searching for it again in the MoSync SDK.
The second issue relates to Windows Active Sync and/or HTC Active Sync. These applications can cause problems when trying to connect Windows Mobile devices to the computer via MoSync and Bluetooth. Try disabling Active Sync if you are experiencing connection or file transfer issues.
DocumentationInbox X | Reply![]() ![]()
Hi Chris.. I
just have found a problem and we need to document it somewhere.... its
about connecting windows mobile (the crappy one :D ) with mosync. if the
windows active sync/HTC active sync for windows mobile is installed on
the computer, one might face soooo many problems to connect it to the
computer via bluetooth in MoSync. One can find the device, associate it
with the preferred profile but can't send the application to the
device.. I also have tried to send the cab file through windows
bluetooth file wizard but it didn't work.. tried it on a couple of
fone.. then I forcefully exit the the active sync and it started working
fine... one may think its mosync problem but its not....
-- Med vänlig hälsning / Best regards, Abi Waqas Asmat (Ghuman) Test and Verification Engineer MoSync AB Cell: +46(0)760064164 Email: abi@mosync.com
|
Once you have scanned for a device and selected it (see Scanning for a Device) you can send your application package to it via Bluetooth. Alternatively, if your target device is not Bluetooth-enabled or cannot be detected, you can transfer your package to it via a cable or viaa web server. Here we describe all these methods.
Before you send your application to a device, it is always a good idea to check what target device is currently selected and which device profile is associated with it. That's because MoSync will send the package for the device profile associated with the target device.
The association is set up when you first scan for and select a target device:
Here's how to see the current associations and how to change them if necessary.
Click the small down arrow next to the Select Target Device icon. A drop-down menu will appear:

At the top of the menu you will see the names of the devices followed [in brackets] by the device profiles currently associated with them. In the example above, the phone called "Nokia 6630 demo2" is associated with MoSync "6630" device profile, while the phone called "W715" is associated with the closest match in MoSync's database, the "W710" device profile.
The current target device has a tick against it (here it's the Nokia phone).
Note: The device name is a setting in the mobile device. This name is usually set by the manufacturer, but it is often configurable, which can be helpful if you are testing your application on two otherwise identical devices.
You can change the device profile associated with a target device by selecting Edit Device List from the Select Target Device icon's drop-down menu. The Select Preferred Profile window will appear:

Select the target device you want to edit from the top list box. Double-click on a device profile in the bottom list, then click OK. The new device profile will be associated with the chosen target device.
Click the Send to Target Device icon to send the package that matches the device profile to the currently selected device:

How the actual installation on the device works is platform- and device-specific. If you are not sure how this is done or where your application is located after installation, consult the user manual for your device.
If your target device does not have Bluetooth file transfer (OBEX), you will need to transfer your package using one of the following methods:
Open MoSync, select your device profile, and build your project. You will find the executable package that MoSync has built for your application in the folder:
C:\<install-path>\<workspace>\<project>\FinalOutput\<build-config>\<vendor>\<model>\<package>
where <install-path> is the place you installed MoSync.
To install your application, copy the executable package to your device using the vendor's own file transfer solution and run it.
The MoSync IDE provides you with several ways to build your application (i.e. to compile it into a package ready for installation on a mobile device). Builds can be set to start automatically or can be started manually. The project's build configuration specifies the compiler, packager, and linker settings to use when building the project. In this guide we describe the build options available to you, and the effect of various build settings on the output packages.
When the automatic build feature is on, your application will be built whenever any file in the project is saved. By default, the automatic build feature is turned off. You can enable it by selecting Build Automatically from the Project menu.
When the automatic building feature is turned off, there are several ways to build your application manually:
to run the application in the emulator, orIn the case of both automatic and final builds done this way, the package is only built for the currently selected device profile. To build the application for all devices in the Device Profile view, you will need to Finalize Your Application.
The location where the newly built package is stored can be seen in the IDE's Console view.
If something goes wrong during the build process (or you find inconsistencies in your application when it runs), you should clean up your project files. Cleaning removes the intermediate files created during the build process.
To clean up your project files, do one of the following:
All new MoSync projects have two build configurations available by default: Release and Debug. These are the build configurations for creating standard release packages and for building a debug version of the application.
You can create more build configurations if you need them. For example, if your target platforms have different screen sizes and want to use different image files, you can create new build configurations to make sure the right images are included in each package. (Excluding files is done on a per-configuration basis, so in the above case it would be easy to have one resource list file for, say, 320x240 screens, and one for 220x176 screens, and just exclude/include the desired files.)
To see the currently available build configurations for your project, and to see which one is active:

All launch configurations as well as the Finalizer have settings that control which build configuration to use.
For example, when you press the Debug toolbar button (or select Debug from the Run menu), the build configuration is automatically set to "Debug" prior to launching your application in the MoRE emulator.
Note: if you do debug your application, the Debug profile will be set to [Active]; you will need to make the Release build configuration [Active] to launch a standard (non-debug) version of your application in the MoRE emulator.
Like the Debugger, the Finalizer has a similar setting: To see these settings, right-click the project and select Properties... > Mosync Project > Finalizer:

Note: All new MoSync projects come with build configurations activated: the Activate Configurations box is ticked by default. (The ability to inactivate build configurations is there for historical reasons as this is a fairly recent addition to the IDE.)
To add a new build configuration to a project:

| Project type | A project can be a stand-alone application or a library. Note: when building a library, make sure to check the Ignore default checkbox to the right of the Additional Libraries text box, otherwise the default set of libraries will be included during the build and you will get errors. | |
| Incremental Build Strategy | The default incremental build strategy is to compile all C files with the GCC -MF switch which generates dependency files consumed by the IDE and used for determining which files to rebuild. The other strategy is to always perform a full build. | |
| Configuration | The configuration selected in this box is the one being edited. | |
| Paths and Files |
Additional Include Paths / Library Paths / Libraries | These three options allows the user to set additional C/C++ include paths, library paths and libraries to be used during compilation and linking. The Ignore Default checkboxes is an advanced option to exclude the MoSync system libraries from the build. Note that, from MoSync 2.5 onward, there are several Path Variables you can use in paths. |
| Exclude file pattern | A space-separated list of files to not include in the build. An example could be test*.c which will exclude all C files that start with test. There is an option to explicitly include files as well, which can be useful for example if all except one file in a directory should be included. To include a file, prefix the file with a + character. So the line /images +player1.png will exclude all files in the images directory except the player1.png file. Files can also be excluded/included from a build by right clicking a file in the project explorer and selecting the Exclude From Build and Do Not Exclude From Build menu items respectively. | |
| Output File (libraries only) | The output file of the built library, relative to the project's Output directory. | |
| Output Directory (applications only) | The output directory of the built application, relative to the project's Output directory. | |
| Compiler Flags |
Activate Dead Code Elimination | This option instructs the linker to remove all redundant code from the resulting binary. (Only applicable for applications; we cannot tell which parts of a library is dead code before it has been incorporated in an application) |
| Additional GCC Switches | Allows the user to set additional GCC switches. By default an optimization level switch is set for each configuration; -O0 for the debug configuration and -O2 for other configurations. Note: that no other optimization level than -O0 should be set for debug configurations as this will confuse the debugger and trigger errors during debugging. | |
| Additional Resource Compiler Switches / Additional Linker Switches | Allows the user to set additional compiler and linker switches. To get an overview of the available options, run Pipe-Tool from the Windows command line with the -h switch (pipe-tool -h). |
|
| GCC Warnings | Compiler warning levels, corresponding to the GCC -Wall, -Wextra and -Werror switches. | |
| Memory Settings > Heap size / Stack size | Sets the amount of memory (in kilobytes) to allocate to the heap and the stack respectively. If your application runs our of memory (e.g. you get a "malloc failed" error) you can increase the amount of memory allocated for the heap. But see Memory Settings > Data size below for some limitations. |
|
| Memory Settings > Data size | Sets the total amount of memory (in kilobytes) to allocate, including the heap and stack. The size will be rounded up to the nearest power of two. Memory settings must be chosen so they conform to the following rule: Data Size > Heap Size + Stack Size + Application's static data section Since there's no easy way of knowing the exact size of the statically allocated memory, a good rule of thumb is to use the following relationship: Data Size = n Heap Size = n/2 Different devices have different amounts of memory available. If you specify a Data Size greater than the amount of available memory on the device, your program will fail to execute. |
|
| Packaging |
Use Debug Runtimes | This option instructs the packager to create packages with debug runtimes. Debug runtimes carry more information to aid the developer during application development. In particular more descriptive error messages will be shown if the debug runtimes are included. [And in the future, this is where on-device debugging support will be put.] |
| Version | Your application's version number (major.minor), used as a label in the application packages. For example "2.4". Note that the minor version number may not be supported on all platforms. Default: "1.0". | |
| Publisher | Your publisher or vendor name, used as a label in the application packages. For example: "Joe Smith Software". Default: "Built with MoSync SDK". Note that some platforms (for example Android) have no publisher identification within the package. For Windows Mobile, this value will be used for both the "provider" and "manufacturer" label within the package. | |
| Application Name | The name to be used for the application's installation package. For example, if Application Name is to "MyCoolApp_setup", the installation package created for Android devices will be MyCoolApp_setup.apk. If not set, the project's name will be used instead. Note: the name of the installed application will always be the project name, which can be changed by right-clicking on the project in Project Explorer and selecting Rename. | |
MoSync 2.5+
In Build Settings you can use the following variables in paths:
| %app-name% | Name of the application defined in "Build Settings" -> Packaging. |
| %app-vendor% | Application vendor defined in "Build Settings" -> Packaging. |
| %app-version% | Version of the application, as defined in "Build Settings" -> Packaging. |
| %compile-output-dir% | Path to the directory where the compiled source files will be stored. |
| %mosync-bin% | Path to the MoSync bin directory. |
| %mosync-home% | Path to the MoSync home defined by environment variable MOSYNCDIR. |
| %package-output-dir% | Path to the directory where the resulting package will be stored. |
| %platform% | The name of the platform in the profile being built for, e.g. android_7, wm6 etc. |
| %profile% | The device name in the profile being built for, e.g. Desire. |
| %programcomb-output% | Output directory of program.comb (combined program and resource files). |
| %program-output% | Path to the directory where the program file will be stored. |
| %project:<project>% | Path to the root of another project in the workspace, e.g. %project:3dlines%. |
| %project-name% | Name of the project. |
| %runtime-dir% | Path to the runtime directory. |
| %vendor% | The name of the vendor in the profile being built for, e.g. HTC. |
| %version-major% | Major part of the version number (see %app-version% above). |
| %version-micro% | Minor part of the version number (see %app-version% above). |
Note: If you open in MoSync 2.5 a workspace created with an earlier version of MoSync, MoSync 2.5 will automatically add the %mosync-home% variable to the Additional Include Paths and Additional Library Paths in the project's Build Settings. If you then want to go back to an earlier version of MoSync you will have to remove those variables.
This screencast shows how to build a demo application (MoTris), how to run it in the emulator, how to select a device, and how to create a package for it.
Some devices (particularly Symbian and JavaME devices) require that your application must have permission to access functions and services like Bluetooth, Calendar, Camera, Contacts, file storage, Internet, location, power management, SMS, and vibration. The MoSync SDK makes it easy to grant access to such services and functions.
An error on a device such as the Symbian OS error code "-46 KErrPermissionDenied" is a sure sign that you are trying to access a function or service without the necessary permissions. You can set the access permissions you need from the Properties menu for your project. Highlight your project in Project Explorer, then select Project > Properties > MoSync Project > Application Permissions.
Use the checkboxes to grant access to the device services that you application uses when it executes.

Click Apply to apply the changes, then rebuild your project.
You can use the Restore Defaults button to reset access permissions to their original settings.
We strongly recommend that you grant your application just enough permissions to run properly, and no more. This is not only for the sake of security, but also to avoid annoying end-users who might decide that an application that has unnecessary permissions is suspicious and is doing stuff that it shouldn't.
Pipe-Tool is MoSync's code transformation engine. It combines the functions of a resource compiler, code linker and assembler, and performs code verification, optimization and dead code elimination to produce highly optimized outputs for each of the target platforms.
Pipe-Tool is automatically invoked by the MoSync IDE during the normal build process, so in the normal case you don't need to do anything to use Pipe-Tool, just build (or rebuild) your project.
For specialist uses, Pipe-Tool can also be run on demand from the command line (see below).
When it is invoked, Pipe-Tool makes several passes through your code. It is very fast: it takes only around one second to make six passes through a 25000 line application.
Pipe-Tool compiles and indexes the external resources that your application uses when it runs. These resources include image and audio files, binary files, and namespaces.
Pipe-Tool's resource compilation function is automatically invoked as the first stage of the build process, prior to the compilation of your code by GCC. Resource compilation can also be invoked from the command line using the command:
pipe-tool -R outfile infile1 [infile2 ...]
for example:
pipe-tool -R resources audio.lst images.lst other.lst
You identify the resources that your application needs by listing them in a resource list file. In the example above, Pipe-Tool compiles all the resources that are referenced in the three resource list files called audio.lst, images.lst, and other.lst and then concatenates them into a single binary file called resources, ready for deployment to the device.
As well as outputting the binary file, Pipe-Tool also creates a header file called MAheaders.h which you need to include in your application program. This header file contains the #defines that symbolically link your application to its resources.
For more information about resource list files and their syntax, see our Resource Compiler Reference.
Pipe-Tool invokes the GCC compiler to compile your application code.
A little later in the build process, Pipe-Tool takes the output from GCC and performs code verification, code optimization, and dead code elimination. Code verification includes among other things:
Depending partly on the output required by the target platform, Pipe-Tool's code optimization features help create faster, smaller programs by:
During the dead code elimination phase, Pipe-Tool looks through the application tree, marking any nodes that are unreachable. Unlike a traditional linker that marks only whole objects or functions for elimination, Pipe-Tool eliminates dead code down to the lowest level of granularity: right down to individual instructions and bytes.
After optimization, Pipe-Tool links the MoSync IL from GCC with the pre-compiled MoSync libraries, and the compiled resource binary to create the MoSync bytecode, Java bytecode, or C/C++ source code that will be packaged with the platform runtimes.
When a program has been optimized and linked, Pipe-Tool sends the internal representation of the program to the compiler backend. The backend transforms the application into a representation that can be understood by the target architecture. Most commonly the program gets assembled into MoSync bytecode which in turn may be interpreted or recompiled by the MoSync runtimes. We also have experimental support for producing a Java bytecode representation of the application that can be executed on Java virtual machines.
pipe-tool -R options outfile infile1 [infile2 ...]
pipe-tool -L options outfile infile1 [infile2 ...]
In -L mode, Pipe-Tool combines the specifed infiles (.s files) into a single library .lib file.
pipe-tool -B options outfile infile1 [infile2 ...]
In -B mode, Pipe-Tool combines the specifed infiles to create a single output file.
The options are described in the Pipe-Tool manual page, which can displayed using:
pipe-tool -h
General options:
-h | --help show this usage info
-error-paths show file paths in errors
-xerr extra information in case of errors
-master-dump also dump the input into a single text file
-s<dir> search <dir> for input libraries
Build application (-B) options:
-entry=sym set code entry point (default 'crt0_startup')
-datasize=size set data size (default 65536)
-stacksize=size set stack size (default 2048)
-heapsize=size set heap size (default 16384)
-appcode=value set application code (default 'TEST'(0x54455354))
-p=vendor/model link with device profile
-dump-syms dump symbol tables
-dump-unref dump unreferenced symbols
-sld=file output source/line translation
-stabs=file output debug information
-elim eliminate unreferenced code/data
-no-verify prevent code verification
-java build a Java class file
-gcj=flags for -java option: set flags for GCJ
Resource compiler (-R) options:
-depend=file output dependencies in makefile syntax
MoSync's great strength is that you can use it to build your one application into the different packages you need for hundreds of mobile devices. MoSync's Finalizer will build all the executable packages, ready to be transferred to the devices you've propogated from your device profiles list.
Before you finalize your application, it is worthwhile checking that the set of devices listed on the Device Profiles tab includes all the devices you want to build the final packages for. If it doesn't, adjust the device profile filters until it does. (But don't worry if you can't get exactly the subset you want, you can adjust things later.)
When you finalize your application, the build process will use the build configuration set in the properties for your project. To see which build configuration will be used, right-click on your project in the Project Explorer view and select Properties > MoSync Project > Finalizer.
When you are ready to finalize your application, click the Finalizer tab next to the Device Profiles tab. The Finalizer view appears:

Click the Propagate button. MoSync will generate a build script based on the devices listed in the Device Profiles tab:

The script is editable so you can make changes such as adding device to it or removing devices from it.
To run the script and build all your application packages, press the Finalize button.
If you have selected many devices and you have a large project, this operation can of course take quite some time. A progress bar will indicate progress:

When you run the Finalizer, the built packages are placed in a directory called \FinalOutput in your project folder. Each device package is placed in a directory hierarchy sorted by vendor and model.
Workspaces are useful for organizing projects. For example you can use them to working with different versions of projects, or as sandboxes. Here we describe how to create workspaces and switch between them.
From the File menu, select Switch Workspace > Other.
The Workspace Launcher will open:

In the Workspace box, enter a name for your new workspace. Workspace names cannot include spaces — only alphanumeric characters (a-z, A-Z, 0-9) and the underscore character (_).
Click OK.
MoSync will restart with the new workspace loaded. (If the Welcome page opens, just close it.)
To add projects to your new workspace, see Importing Projects and Files.
To switch between your workspaces, select Switch Workspace from the File menu.
If you have already used the other workspace in this session, you can choose it directly from the pop-up menu. Otherwise, select Other to open the Workspace Launcher and browse for you workspace from there.
In the Workspace Launcher you have the option to copy the current workbench layout and working sets from the current workspace to the new one.
Here we show you how to import projects and files into MoSync. We give detailed instructions on how to import existing MoSync projects, and some information about importing other resources like archives, files systems, preference settings, breakpoints, launch configurations, and team project sets.
To see an existing MoSync project in your current workspace, you need to import it.
The Import wizard guides you through all the necesary steps of the import process and allows you to set various options.
Note: You can follow these steps to import our example applications (which of course are just another type of project). However, there is a much quicker way of importing them, which we describe in Importing the Examples.
Open the Import wizard in one of the following ways:

Choose the import source by opening the MoSync group, selecting Existing MoSync project into workspace, and clicking Next. The Import Projects dialog will open.
Select the Select root directory option and click its Browse button.
Browse for the folder where your projects are stored, highlight it, and click OK.
A list of the projects available for import will be displayed (in this case it is example application projects in our \examples folder):

You have the choice of copying the projects into the workspace or leaving them in their current location.
Make sure that the checkboxes of the projects you want to import are ticked, then click Finish to import the projects into your workspace.
The Import wizard can also be used to import other types of projects and files. Many of these import options will be familiar to Eclipse users. A brief overview of the available options is given in the table below.
| General > Archive File | Standard Eclipse import of a previously exported archive file |
| General > Existing MoSync project into workspace | see Importing Existing MoSync Projects above |
| General > Existing Project into Workspace | Standard Eclipse project import |
| General > File System | Standard Eclipse file/folder import. This option is useful for bringing legacy C/C++ files into the workspace. Create a project first, then import your files/folders into it |
| General > Preferences | Standard Eclipse import of previous exported preferences (i.e. as set in Windows > Preferences). Useful for transferring preference between Eclipse instances |
| MoSync > Existing MoSync project into workspace | see Importing Existing MoSync Projects above |
| Run/Debug > Breakpoints | Standard Eclipse import of a previously exported breakpoints file |
| Run/Debug > Launch configurations |
Standard Eclipse import of a previously exported launch configurations file. This can be very useful. When you select Run As... in MoSync, a launch configuration is created. This launch configuration contains settings like screen size, which project to run, which build configuration to use, and so on. |
| Team > Team Project Set | Standard Eclipse import of a previously exported Team Project Set. |
Use the following syntax to build MoSync projects from the Windows command line:
mosyncc.exe -application com.mobilesorcery.sdk.builder.headless -data workspacelocation -project [-f finalizerscript] projectname
Replace workspacelocation with the location of your workspace, and projectname with the name of the project to build. This will actually launch a Finalizer build with the currently set device filters.
If you wish to produce binaries for a different set of devices you will need to create a Finalizer script and use the -f switch. A finalizer script is just a text file containing lines like the ones produced when you click the Propagate button in the Finalize view in the IDE.
You can use MoSync with Microsoft Visual Studio although, of course, much of the functionality concerning building for mobile devices will be lost this way. The gain is that you will be able to use the fully-featured debugger in Visual Studio. Here we describe how to set up Visual Studio, and how to use it to build and debug an application.
It is only possible to use Microsoft® Visual Studio C++ 2005 Express Edition at this time. You will also need the Microsoft® Windows Server 2003 SP1 Platform SDK. You can download these products here:
Our win32 library for Visual Studio 2005 implements the MoSync syscall APIs. This enables developers to build MoSync projects using Visual C++ and use all of Visual Studio's features, including its debugging facilities.
You should be aware that Visual Studio produces a native windows application, which is fundamentally different from a real MoSync application. For starters, a different compiler is used, which has a number of implications, including a different layout of code and data. Furthermore, if you use the native Win32 libraries (including the Win32 API itself) the resulting source code will not work in MoSync.
(Our win32 library was originally provided because MoSync lacked a proper debugger, and although the debugging experience would be inaccurate with respect to when the application is built for the MoSync architecture, it was considered better than nothing. Today, we would encourage you to use the debugger provided in the MoSync IDE. It is still not perfect, but we are working hard to improve it and are grateful for any feedback or bug reports.)
If you haven't installed Visual Studio 2005 you will need to install it first.
Also check so that you have installed the Platform SDK.

First we need to add the correct search paths to Visual Studio. Choose Options from the Tools menu.

Expand Projects and Solutions and choose VC++ Directories. Add the search path for the MoSync library files as shown.

Choose 'Include Files' and add the path for MoSync include files.
If you use the Visual Studio 2005 Express edition you will need to follow these steps before closing the dialog
To be able to build you will also need to add the following search paths for the Windows Platform SDK:
Now you have added all the correct search paths so that Visual Studio will be able to build your applications.
Close the Options window by clicking OK.
Now you just have to make one more adjustment before you will be able to create new projects. Inside the directory C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults you will need to edit the file corewin_express.vsprops. Find the following string:
AdditionalDependencies="kernel32.lib"
You will need to change that line to:
AdditionalDependencies="kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib"
More information about this can be found at http://msdn.microsoft.com/en-us/vstudio/aa700755.aspx
Start with a Win32 project.
In the Application Wizard, in Application Settings, select Empty Project.
In Project Properties:
In General:
In C/C++, General:
In Linker, add the libraries needed (mosynclib.lib and MAStd.lib are required) Input:
In Linker, System:
If you build and run your project, the MoSync emulator will start with your project running in it. You will also be able to debug your application using the Visual Studio debugger so you are able to set breakpoints and single step through your code. Note that the program is compiled as pure x86 code, so the execution envionment may be more forgiving to badly behaved code.
You can use MoSync with Microsoft Visual Studio although much of the functionality concerning building for mobile devices will be lost this way. The gain is that you will be able to use the fully-featured debugger in Visual Studio. Here we describe how to set up Visual Studio, and how to use it to build and debug an application.
MoSync supports Microsoft® Visual Studio C++ 2010 at this time. You can download it here:
Our library for Visual Studio implements the MoSync syscall APIs. This enables developers to build MoSync projects using Visual C++ and use all of Visual Studio's features, including its debugging facilities.
You should be aware that Visual Studio produces a native windows application, which is fundamentally different from a real MoSync application. For starters, a different compiler is used, which has a number of implications, including a different layout of code and data. Furthermore, if you use any other native Win32 libraries (including the Win32 API itself) the resulting source code will not work in MoSync.
(Our win32 library was originally provided because MoSync lacked a proper debugger, and although the debugging experience would be inaccurate with respect to when the application is built for the MoSync architecture, it was considered better than nothing. Today, we would encourage you to use the debugger provided in the MoSync IDE. It is still not perfect, but we are working hard to improve it and are grateful for any feedback or bug reports.)
Start with a Win32 project.


In the Application Wizard, in Application Settings, select Empty Project.
In Project Properties:
In General:

In VC++ Directories:

In C/C++, General:
In Linker, add the libraries needed (mosynclib.lib and MAStd.lib are required) Input:

If you build and run your project, the MoSync emulator will start with your project running in it. You will also be able to debug your application using the Visual Studio debugger so you are able to set breakpoints and single step through your code. Note that the program is compiled as pure x86 code, so the execution envionment may be more forgiving to badly behaved code.

With the MoSync SDK you can develop applications in HTML5/JavaScript ... or in C/C++ ... or in HTML5/JavaScript and C/C++! Yes, that's right: you can build apps based on the latest web standards with industrial-strength foundations.

It is easy to create pure HTML5 and JavaScript applications in MoSync. We have templates in the MoSync IDE that let you define your pages, style them with CSS3, incorporate JavaScript widgets and functions, embed streaming media, and use all the other great features of HTML5.
Include the Wormhole JavaScript Library in your code and you can extend your HTML5 apps with functions that access and manage device features like sensors, contact lists, cameras, native user interface widgets, databases, and file systems, and which can react to events and notifications.
You can even also create flexible HTML5/C++ hybrid applications that combine HTML5/JavaScript with C/C++. Hybrid applications make it possible to create great-looking application interfaces and intuitive controls and make use of MoSync's extensive C++ class libraries (for example the Facebook Library and the Slippy Map Library) and C syscall functions (like the Advertising API and Database API) for fine control over all the important features supported by the mobile device.
With the MoSync Mobile SDK you can build pure applications in HTML5 and JavaScript without needing to write a single line of C/C++ code! This tutorial shows you how to create a project where you can author mobile applications using just HTML5 and JavaScript.
MoSync has a native widget system, and one of the widget types is the WebView widget. This means you can use web technologies to create your application.
New in MoSync 2.7 is full support for HTML5 applications. This means that you can create a native application with HTML, CSS, and JavaScript, and deploy it to app stores as a standalone appliction. You can use established web standards and JavaScript libraries, such as jQuery and jQTouch, and reuse your current web-based code.
You can code your entire application using HTML, CSS, and JavaScript, or you can mix web technologies with C++, using MoSync C/C++ to access device functionality not available in HTML5. Depending on which langauges and libraries you wish to use, you can write all or most of the application logic in JavaScript, or you can write the application logic in C/C++ and use HTML and CSS for the user interface of the application.
To get started, open the MoSync IDE, select File > New > Project, create an HTML5/JavaScript project, and select the HTML5 Project template as presented in the following screenshots:

This will give you an HTML5 project which is ready to build and run.
(Note: If you want to use your JavaScript to access your own C++ code or MoSync's C++ class libraries or C function APIs, use the template called HTML5/C++ Project. Unlike the HTML5 Project template, the HTML5/C++ Project template is already set up to support communication between JavaScript and C++.)
MoSync's HTML5 templates are real working applications. Here is how the HTML5 Project template application looks when you run it. In both applications the text will change when you touch the screen. (In the HTML5/C++ Project template application, the device will also vibrate.)

Note that you can manually add the code neeed for JavaScript/C++ interaction to a plain HTML5 Project, in case you wish to add functionality that requires you to code in C++ (for example, to access native device functionality not implemented by the WebView browser widget).
An HTML5 project has a directory called /LocalFiles. This is where you should put your HTML, CSS, and JavaScript media files.
Here are the technical details. The content of /LocalFiles is packaged by a build step called "Bundle", to a file called LocalFiles.bin in the /Resources directory. In /Resources, there is a file called Resources.lst, which includes LocalFiles.bin. At runtime, when the application is launched, this file is unpacked and the contents are copied to the application's local file system on the device.
This is the file system layout you will get when creating a template project (note that LocalFiles.bin won't be created until you actually build the project):

The difference between the two template projects, is that the HTML5/C++ Project template contains a file called bridge.js, which provides support for communicating between JavaScript and C++.
The main.cpp file contains code that creates a WebAppMoblet. A moblet is a class that handles events in an application. The WebAppMoblet is a moblet designed to be used for web applications. It features one WebView widget (i.e., a full-screen browser).
In the case of a plain HTML5 project, you don't need to touch anything in main.cpp.
If you want to provide functionality that invokes C++ code from JavaScript, you can edit main.cpp to add that functionality. The sample template application has code that makes the device vibrate when the screen is touched. How this is done is explained in the guide Communicating Between JavaScript and C++ in MoSync.
To run the app you need to have an Android device, or have the Android SDK or Xcode for iOS installed.
To run on an Android device, start by selecting the target device profile. This is done in Eclipse in the right-hand page labeled "Device Profiles". Double-click on the profile you wish to select. For Android, select the "Android 2.x" profile:

Then select the target device and send the app to the device. This is done using the two icons "Select Target Device" and "Send To Taget Device" in Eclipse:

Alternatively, if you have the Android SDK installed, you can select the "Run" command from the menu bar, or press the green "Run" icon, to run the app in the Android emulator. Note that you will be presented with a dialog that asks the location of the Android SDK the first time you do this. You can also use the "Run" command to run the app in the iOS simulator if you have Xcode installed.
Another option is to build the application and install the resulting package on the device. This is an alternative if the "Select/Send To Target Device" icons should not work (if you for example do not have Bluetooth).
Right-click the project in the left-hand Project Explorer and select the "Rebuild Project" command. This will produce an output package:

If the Android target profile is selected, an apk-file will be produced. The location of the file is shown in the Console output window. You can transfer this file to the device using the adb tool in the Android SDK, or publish it on a web site for download:

When building for iPhone/iPad an Xcode project file will be generated. Double-click that file to launch Xcode and run the application from Xcode. The document Developing iPhone Applications explains this in further detail.
For further details regarding Android development with MoSync, see the document Developing Android Applications.
To make your app have an nice icon, you need to have two files in your project. One XML-file with a .icon extension, for example App.icon, and one SVG file with the actual icon image. If your SVG file is named Icon.svg, this is the content of App.icon:
<?xml version="1.0" encoding="UTF-8"?>
<icon>
<instance size="default" src="Icon.svg" />
</icon>
When you rebuild the program in Eclipse, it will be added to the resulting application package.
There are several programs available for creating SVG-images, for example the open-source drawing program Inkscape.
More details can be found in the Application Icons guide.
In this MoSync tutorial, Mikael discusses how to import an example project into MoSync, and how to send it to a mobile phone.
Through MoSync's Wormhole Library you can access a wide range of device features and native user interface components from your JavaScript code. This gives you access to features that are normally not avaiable to an HTML5 application.
MoSync supports the standard smartphone implementations of HTML5. That means it is possible to create rich web applications using JavaScript and CSS over the powerful MoSync core. You can even mix HTML5 UI components and Native UI widgets.
You can edit HTML and JavaScript files directly in the MoSync IDE and get full syntax support. We provide easy-to-use project templates to get you started.
If you are a C++ developer, you can benefit from creating cool looking user interfaces in HTML and CSS. And you don't need to master all the dirty details of CCS, as you can choose from a rich selection of high-level JavaScript libraries available, such as jQTouch.
Android and iOS
It is fun to send text messages with smileys to friends and loved ones. But it is time consuming to type in lots smileys on a phone. WebViewLoveSMS is an app you can use to easily send messages with lots of heart or kiss smileys to your loved one.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
You will find the latest version of the source code of the app at the MoSync GitHub repository.
When this application starts up, the user is shown the main screen where the telephone number of the loved one can be entered.
There are just two buttons. Tapping either button send a 140-character SMS to the loved one. The Send Eternal Love button sends a repeated string of "<3" characters. The Send Warm Kisses button sends a string of ":-*" characters.
The phone number is stored on the device and will be displayed next time the application is started. (Just one phone number saved — because, after all, this is an application to be used with your loved one...)
This example application is implemented in HTML and JavaScript, and uses the MoSync Wormhole Library to access device services from JavaScript via C++. The Wormhole Library is used for sending text messages and storing data on the device, services that you normally cannot access from JavaScript.
Here is the JavaScript code used in the app for sending a text message:
bridge.messagehandler.send( { messageName: 'SendSMS', phoneNo: GetPhoneNo(), message: textMessage }, null); bridge is a JavaScript library used in the application, which enables sending messages to C++. In the above example, the message consist of a dictionary with the message names, and a callback function, which we are not using, and therefore set to null.
Here is the C++ code in file WebViewLoveSMS.cpp for SendSMS message:
void handleWebViewMessage(WebView* webView, MAHandle urlData) { WebViewMessage message(webView, urlData); if (message.is("SendSMS")) { savePhoneNoAndSendSMS( message.getParam("phoneNo"), message.getParam("message")); } ... }In file WebViewLoveSMS.cpp you find the class LoveSMSMoblet, which inherits WebAppMoblet, a central class in the Wormhole Library. The WebAppMoblet class automatically creates and configures a WebView widget (a widget in the MoSync Widget API) for the application. It listens for events from the web view and calls method handleWebViewMessage when messages are sent from JavaScript.
The file /LocalFiles/js/bridge.js is the JavaScript end of the Wormhole, and contains functions for communicating with C++. Note that WebAppMoblet is not depending on bridge.js, there could be other JavaScript libraries created to communicate with the moblet.
Class WebViewMessage is also part of the Wormhole Library and parses the data recieved from the web view. Currently the message format is based on RESTful URLs.
Support for parsing other formats, like JSON, could be added, either to class WebViewMessage, or to a subclass of it, or to an entirely new class. The idea is to provide flexibility in how to commuicate between JavaScript and C++.
A great way to learn how to author HTML5 applications in MoSync is to modify the LoveSMS app in various ways. You can easily change the background image and the color of user interface elements, to create your own personal unique look for the app. Check out this blog post for further details.
This example application is a simple Twitter client that shows tweets by selected users. Users can be added to a Favorites List stored on the device. The app uses the jQuery JavaScript library and its jQtouch plug-in, and the MoSync Wormhole C++ Library.
![]() | ![]() |
| Tweet Reader screen (Android) | User tweets screen (Android) |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When started, this example application displays the main application screen headed "Tweet Reader". On this screen the user can enter the username of a Twitter user. On tapping View Tweets by this user, a second screen is displayed showing that Twitter user's recent tweets.
On the main application screen the user can also add the Twitter user's username to a Favourites List, or tap on an entry in the Favourites List to go straight to that person's tweets.
The following technologies are used in this application:
Included in the example is a set of wrapper functions for accessing the MoSync File API from Javascript (file.js).
WebViewTwitter.cpp is the main file. It includes an implementation of WebAppMoblet. The example application uses the MessageHandler class to process and respond to messages coming from JavaScript.
All of the HTML5 and JavaScript-related files and libraries are located in the /LocalFiles directory, are included in the application when it is built in the MoSync IDE.
The /Resources.lst file has a default entry for the bundled files that should not be removed unless the user wants to remove all the HTML5 functionality.
Kindly note that this document applies to the upcoming MoSync 3.0 release.
This document outlines how to use the Wormhole communication bridge between JavaScript and C++, which is useful when you want to extend your HTML5/JS application with custom code written in C++. If you are not familiar with how to create an HTML5 project, please read the tutorial Creating an HTML5 project in MoSync.
The following example code is based on the HTML5/JS/C++ Hybrid Project template. That template program illustrates how to invoke code you have written in C++ from JavaScript, and has buttons in the HTML user interface for making the device vibrate and beep. Create an app in the Eclipse IDE, using the HTML5/JS/C++ Hybrid Project template, to get the full source code discussed below.
The example uses classes the Wormhole C++ library (WebAppMoblet, MessageStream, MessageStreamJSON) and the JavaScript libraries included in the file wormhole.js (included with the application template).
Two ways for communicating are supported by Wormhole: JSON messages and string stream messages. We will discuss both of them here.
In JavaScript, the function mosync.bridge.sendJSON() is used to send JSON messages to C++:
mosync.bridge.sendJSON(message, callbackFunction)
This function takes two parameters. The parameter "message" is a dictionary, which contains the message name and optionally other message parameters.
The parameter "callbackFunction" is an optional function that you can call from C++ to return a value to JavaScript. The communication mechanism is asynchronous, which is why a callback function is used to pass the result back from C++ to JavaScript.
Here is some JavaScript code from the file index.html that invokes C++ to make the device vibrate (here we do not need to use any callback function):
/**
* Vibrate for 1 second.
*/
function vibrate()
{
// Send message to C++ to make device vibrate.
// We use the JSON format. The message will
// be delivered to C++ in a JSON array.
mosync.bridge.sendJSON(
{
"messageName":"Custom",
"command":"vibrate",
"duration":1000
});
}
And here is the C++ code in main.cpp that handles incoming JSON messages:
void handleMessageStreamJSON(WebView* webView, MAHandle data)
{
// Create the message object. This parses the message data.
// The message object contains one or more messages.
JSONMessage message(webView, data);
// Loop through messages.
while (message.next())
{
// This detects the PhoneGap protocol.
if (message.is("PhoneGap"))
{
mPhoneGapMessageHandler.handlePhoneGapMessage(message);
}
// Here we add our own messages. See index.html for
// the JavaScript code used to send the message.
else if (message.is("Custom"))
{
String command = message.getParam("command");
if (command == "vibrate")
{
int duration = message.getParamInt("duration");
maVibrate(duration);
}
}
}
}
Wormhole comes pre-package with PhoneGap compative libraries. The messageName parameter is used to distinguish the "protocol" of the messsage. In the example, we have used "Custom" as the protocol for our own code.
To improve efficiency, the JavaScript side can send several messages to C++ in one shot. We therefore need a while-loop in the code to be able to process all incoming messages.
In the C++ code, you get the value of message parameters with the help of the methods getParam (returns a String) and getParamInt (returns an int):
String command = message.getParam("command");
if (command == "vibrate")
{
int duration = message.getParamInt("duration");
maVibrate(duration);
}String streams are an alternative way of sending messages from JavaScript to C++, which was developed to make JavaScript Native UI perform well. This method is generally faster than JSON messages (on some platforms 20x faster). Parsing on the C++ side is very efficient, and streams of string messages are concatenated before passed to C++. This makes sending large number of small messages efficient.
The JavaScript function mosync.bridge.send() is used to send string messages to C++:
mosync.bridge.send(stringArray, callbackFunction)
This function takes two parameters. The parameter "messageArray" is an array of strings, and "callbackFunction" is an optional parameter that works in the same way as with mosync.bridge.sendJSON().
Here is JavaScript code from index.html that invokes C++ to make the device beep, using a string message (again, we do not need to use a callback function):
/**
* Play one beep sound.
*/
function beep()
{
// Send to custom message beep to C++.
// Here we used the string stream format.
mosync.bridge.send(["Custom", "beep"]);
}
Here is the C++ code in main.cpp that handles incoming string messages:
void handleMessageStream(WebView* webView, MAHandle data)
{
// Create a message stream object. This parses the message data.
// The message object contains one or more strings.
MessageStream stream(webView, data);
// Pointer to a string in the message stream.
const char* p;
// Process messages while there are strings left in the stream.
while (p = stream.getNext())
{
if (0 == strcmp(p, "NativeUI"))
{
//Forward NativeUI messages to the respective message handler
mNativeUIMessageHandler.handleMessage(stream);
}
else if (0 == strcmp(p, "Resource"))
{
//Forward Resource messages to the respective message handler
mResourceMessageHandler.handleMessage(stream);
}
else if (0 == strcmp(p, "close"))
{
// Close the application (calls method in class Moblet).
close();
}
// Here we add your own messages. See index.html for
// the JavaScript code used to send the message.
else if (0 == strcmp(p, "Custom"))
{
const char* command = stream.getNext();
if (NULL != command && (0 == strcmp(command, "beep")))
{
// This is how to play the sound in the resource BEEP_WAV.
maSoundPlay(BEEP_WAV, 0, maGetDataSize(BEEP_WAV));
}
}
}
}
As with JSON messages, we use a "protocol parameter" to determine which module the message should go to. Again we use the token "Custom" to designate our own protocol.
String streams are processed by obtaining pointers to charater sequences. As long as the method stream.getNext() returns non-NULL we get a pointer to the next string parameter.
You can use standard C library functions such as strcmp to operate on string parameters, as illustrated by this code snippet:
const char* command = stream.getNext();
if (NULL != command && (0 == strcmp(command, "beep")))
{
// This is how to play the sound in the resource BEEP_WAV.
maSoundPlay(BEEP_WAV, 0, maGetDataSize(BEEP_WAV));
}Note that the code below is not part of the code you get with the template application. You can however type it in yourself, to further explore how the code works.
To evaluate JavaScript code in the WebView from C++, you can use the method WebAppMoblet::callJS(). Here is an example:
callJS("alert('Hello World')");
The following snippets illustrate how to invoke C++ from JavaScript and call a JavaScript callback function.
Here is the JavaScript part:
mosync.bridge.sendJSON(
{ "messageName":"Custom", "command":"GetScreenSize" },
function(width, height) {
alert("Screen size: " + width + " " + height);
});
And here is the C++ part:
String command = message.getParam("command");
if (command == "GetScreenSize")
{
// Call JavaScript reply handler for this message.
int callbackId = message.getParamInt("callbackId");
char script[512];
sprintf(
script,
"mosync.bridge.reply(%d, %d, %d)",
callbackId,
EXTENT_X(maGetScrSize()),
EXTENT_Y(maGetScrSize()));
getWebView()->callJS(script);
}
The JavaScript function mosync.bridge.reply always takes the callbackId as the first argument. You can then supply a variable number of arguments (zero to many) that will be passed to the callback function in JavaScript.
If you wish to dig deeper, you can explore the MoSync source code at GitHub, and you can also take a look at the example program WebViewGeoLocation, which is a low-level example that does not use the Wormhole library. Note that wormhole.js is a generated file, made up of several JavaScript source files (which means it is not found in the GitHub repository).
Items of interest:
Documentation:
Related example programs:
The WebViewGeoLocation application displays your current location, as returned by EVENT_TYPE_LOCATION events. This example is useful for understanding the basic mechanisms for communicating between JavaScript and C++.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
You will find the latest version of the source code of the app at the MoSync GitHub repository.
When this application starts up on an Android of iOS device, the main screen is displayed. Touch the Start button to start tracking the current latitude and longitude of the device. Touch the Stop button to stop tracking.
The purpose of the example is to demonstrate how to communicate between JavaScript in a WebView widget and C++ code, by using basic low-level syscalls and events.
(Other WebView examples, such as WebViewLoveSMS, demonstrate how to use the high-level MoSync Wormhole Library for such communications.)
The application is implemented in C++, HTML and JavaScript. It has an explicit event loop, rather than using a Moblet, to let you see how the basic event mechanism that handle messages from JavaScript works.
The user interface for this application is created in HTML: to keep the example code to a minimum, the example uses only very basic HTML tags and no CSS.
When the program starts, a single WebView widget is created. The HTML and JavaScript code is stored in a text file and packaged with the application as a binary resource. That resource is extracted when the program starts, and the web view is set to display that data. This is done in C++ code, in file WebViewGeoLocation.cpp.
The communication mechanism for invoking C++ code from JavaScript is based on a URL hook. In file WebViewGeoLocation.cpp, the following URL hook is installed when the web view is created:
maWidgetSetProperty(
webView,
MAW_WEB_VIEW_HARD_HOOK,
"mosync://.*");
This will cause all urls with the scheme "mosync://" to be detected by the WebView, and rather than loading a new page, a widget event of type MAW_EVENT_WEB_VIEW_HOOK_INVOKED will be sent to the MoSync event queue.
In file /Resources/GeoLocationPage.html, the following JavaScript code is evaluated when clicking the Start button:
document.location = "mosync://StartTrackingGeoLocation";
The result will be that the url is "hooked", and the following C++ code in WebViewGeoLocation.cpp is called:
case EVENT_TYPE_WIDGET:
handleWidgetEvent((MAWidgetEventData*) event.data);
break;
In the handleWidgetEvent method the following code gets called, which causes location tracking to start, and location events to be sent to the event queue:
if (0 == message.find("mosync://StartTrackingGeoLocation"))
{
maLocationStart();
}
When a location event is sent, the following code is used to communicate the location back to JavaScript to update the web page:
case EVENT_TYPE_LOCATION:
handleGeoLocationEvent((MALocation*) event.data);
break;
void handleGeoLocationEvent(MALocation* location)
{
char script[512];
sprintf(
script,
"javascript:GeoLocationUpdated('%f','%f');",
location->lat,
location->lon);
maWidgetSetProperty(mWebView, "url", script);
}
Calling maWidgetSetProperty on a WebView widget, with the property "url" set to a string that has the "javascript:" scheme will cause that JagScript code to be evaluated in the web view.
In this way, by hooking URLs in a web view and setting the "url" property of a web view, you can communicate asynchronously between JavaScript and C++ code.
It should be noted that the above code snippets use low-level mechanisms that may not be avaiable on all future platforms MoSync will run on. While they work file on Android and iOS, the facilities provided by the WebView widget varies between platforms, and some platforms may not provide url hook capabilities, for instance. If this is the case, you cannot use "document.location" to set a url with data that is hooked by the web view. You then need to use other techniques to send data between JavaScript and C++. The higher-level Wormhole library will encapsulate and abstract away these low-level details and differences between current and future platforms supported by MoSync.
MobileLua is a port of Lua to MoSync. There are two ways to author MobleLua apps:
![]() | In our screencast The JavaScript Lua Bridge Explained, Iraklis and Micki take a look at the basic architecture of JavaScript/Lua apps and show how easy it is to create them. There is also a dedicated site for MobileLua on GitHub. It provides all the information you need to get working with Lua in MoSync or LuaLive. |
In this video, Iraklis and Mikael demonstrate the JavaScript/Lua bridge. Lua, like JavaScript, is a dynamic language, which means that we can evaluate code on-the-fly. We evaluate Lua from JavaScript by sending messages with Lua scripts to the underlying Lua application hosting the WebView. View the full tutorial.
The guides and tutorials in this section of the documentation provide guidance and examples for programmers writing C/C++ applications with MoSync. We cover the three basic development models that you can follow with MoSync, and show how to use some of the many library functions.
This tutorial walks you through the creation of a simple "Hello World" application in C/C++ using the MoSync IDE and introduces you to some of the basic terminology we use throughout our guides, tutorials, and examples.
Start by Launching MoSync. MoSync prompts you to select a workspace:

Click OK to accept the default path. The MoSync IDE will open.
Register you copy of MoSync if you have not already done so. After registration, close the Welcome page if it is showing.
Create a new project by right-clicking in the Project Explorer view then choosing New > Project:

( If you have hidden the Project Explorer view, you can show it again by selecting Window > Show View > Other > General > Project Explorer and then clicking OK.)
When the New Project window opens, expand the MoSync folder and select MoSync Project:

Click Next.
The project name and location screen appears:

Enter the Project name "HelloWorld". (To ensure compatibility with all platforms and devices, avoid using spaces in project names. It is always safe to use the underscore character.)
Tick the Use default location box. Click Next.
A new window will open showing you the templates that are available for you new project:

For more information about these templates, see Creating Projects from Templates.
Select the MoSync Moblet Project template. Select it and click Finish.
Your new project will now be created from the template and loaded in the MoSync IDE:

Edit the code in the main.cpp file shown in the main window so that it looks like this:
#include <MAUtil/Moblet.h>
using namespace MAUtil;
class MyMoblet : public Moblet
{
public:
MyMoblet()
{
maSetColor(0xFFFFFF),
maDrawText(0, 32, "Hello World!");
maUpdateScreen();
}
void keyPressEvent(int keyCode, int nativeCode)
{
if(keyCode == MAK_0 || keyCode == MAK_BACK || keyCode == MAK_SOFTRIGHT)
{
close();
}
}
void keyReleaseEvent(int keyCode, int nativeCode)
{
}
};
extern "C" int MAMain()
{
MyMoblet myMoblet;
Moblet::run( &myMoblet );
return 0;
};Save your main.cpp file.
(If you would like to understand more about the code we just asked you to paste in, read our beginner's tutorial called Hello World, Deconstructed.)
Your application is now ready to be built and run.
Click on your project's name in Project Explorer view so that it is highlighted.
Now click the Run button
on the IDE's toolbar (or press Ctrl+F11). Your project will be built, and your application will run in MoRE, the MoSync emulator:

Congratulations, you have now compiled and executed your first MoSync program!
In our User Guides you will find extensive information about the MoSync IDE, including how to create projects from templates, how to use device profiles, doing bluetooth discovery and transfer, and how to use the MoRE emulator, the Debugger, the Finalizer, and MoSync's tools.
In our Programmer Guides we teach how to use MoSync's classes, functions, and syscalls in your applications, and we also provide tips for creating applications that work across multiple platforms like iPhone, Android, and Windows Mobile.
Our extensive Tutorials library covers all aspects of using the MoSync SDK to creating working applications. You will find lots of helpful code snippets here, and step-by-step instructions for common coding tasks.
We provide many Example Applications in the SDK itself, so you can see how we do it ourselves. If you are new to C/C++, we strongly recommend that you spend some time examining the code of our "Hello" series of applications: they are extremely well-commented so that you can unserstand exactly what is happening in every line of code.
At our website you can find many resources for developers, including our developer forum, and links to our code repositories and issue tracking systems.
Have fun, and good luck!
HelloWorld is a well-commented example for beginners of a very simple MoSync application that uses the Moblet framework. The application demonstrates how to structure the simplest possible application that responds to key events.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When run, the words “Hello World!” should appear on an otherwise blank screen. Examine the source code of the application (in the file helloworld.cpp) to learn how the program works. We also provide detailed documentation for this example in our Hello World, Deconstructed tutorial.
In our beginners tutorial called Creating Your First Application we skipped over many features of the "Hello World" application that we asked you to paste into the IDE. In this tutorial we are going to take a much deeper look at that code, examine the basic structure of a C++ application, and discuss some basic design decisions we have made in the MoSync approach to mobile application development.
A note to absolute beginners: C/C++ applications can be a little overwhelming at first, but with a little persistence you will soon get the hang of it. As you go through this tutorial, try typing each line into the MoSync IDE, rather than just cutting and pasting. That way you''ll get a better feel for laying out the code and getting the syntax right. As you type, you will be given interactive help by the IDE, which can be very useful. Remember to use the Moblet Project template when you create you project.
A note to experienced C++ developers: You probably know a lot of this stuff already, so feel free to skip ahead to our extensive collection of tutorials and example applications. On the other hand, if you do read on, maybe you will learn something important you didn't know about C/C++ or MoSync, like that tricky MAMain entry point....
Here is the code we asked you paste into the MoSync IDE in our Creating Your First Application tutorial:
#include <MAUtil/Moblet.h>
using namespace MAUtil;
class MyMoblet : public Moblet
{
public:
MyMoblet()
{
maSetColor(0xFFFFFF),
maDrawText(0, 32, "Hello World!");
maUpdateScreen();
}
void keyPressEvent(int keyCode, int nativeCode)
{
if(keyCode == MAK_0 || keyCode == MAK_BACK || keyCode == MAK_SOFTRIGHT)
{
close();
}
}
void keyReleaseEvent(int keyCode, int nativeCode)
{
}
};
extern "C" int MAMain()
{
MyMoblet myMoblet;
Moblet::run( &myMoblet );
return 0;
}Now let's take a close look at what is going on in each of these lines of code.
The program starts with a directive to include the contents of the Moblet.h header file from MoSync's MAUtil directory:
#include <MAUtil/Moblet.h>
In C/C++, header files are an important way to connect together the different files of a program. It is common practice to put the generic code that you might want to use in many places in a separate file and two create a header file that contains forward definitions (declarations of classes, functions, and data types) for that generic code. Then you use an #include statement to include the header file in your other code modules. The header file acts like an interface to your generic code. That way you can reuse your generic code in many places, but only have to make updates to it in one place. For information, see Working with MoSync Libraries.
Here we are using a header file to connect our main application file with the pre-compiled library file (mautil.lib) that contains the generic code for Moblets.
The "#" sign indicates that this directive is to be handled the preprocessor — a program that will be called by the compiler as the first step of translating our source code into an executable binary file. In this case the directive instructs the preprocessor to read in the declarations in Moblet.h. We will explain what a Moblet is, and how you use it, a little later on.
Our next statement specifies that we will be using the MAUtil namespace as the base reference for our objects:
using namespace MAUtil;
The effect of using this namespace is to say "look in the set of things called "MAUtil" to find the definitions of the identifiers I use in this program". By specifying the namespace here our code becomes more readable. If we didn't have this line, we would have to explicitly reference the scope of MAUtil objects, we would have to write MAUtil::Moblet every time we wanted to use the Moblet class.
The next thing we need to do in our application is define its classes. Here we define a new class, based on the Moblet class, called MyMoblet:
class MyMoblet : public Moblet {Moblet is a MoSync base class - a class which is meant to be built upon to do something useful. In the C++ world, a class is essentially a set of data and functions which manipulate that data (often referred to as instance variables and methods in other object-oriented languages). A class is a blueprint: in a running application the class is used to create actual objects (instances) as they are needed.
Usually a class represents something concrete — although it's sometimes a little hard to understand what that thing is. In the case of Moblet it represents a simplified event handler for a mobile device.
As we will see later, Moblet takes care of the application main loop for you. All you need to do is subclass it and implement functions for the events that you want to your program to respond to (such as key presses, screen touches, and new connections). A Moblet application responds to events in a consistent way regardless of the device it runs on. That means we do not need different code for an Android device, Symbian device, a Windows Mobile device, or a phone running Java ME.
To learn more about the events that Moblet can detect, and the various types of listeners you can set up, look up Moblet in the MoSync API Reference Guide in the IDE under Help > API Reference > Classes > MAUtil::Moblet.
Our new class, MyMoblet inherits all the chracteristics of the Moblet base class, and adds to it. What we will be adding are functions that will perform actions when events occur.
The keyword "public" before the Moblet identifier means that other classes and functions in our application can access all the public members of the Moblet base class when using MyMoblet. That is to say, what is defined as public in Moblet becomes public in MyMoblet, even if we don't get around to listing them in MyMoblet.
The data members (instance variables) and member functions (methods) within a class can be either public or private. If they are in the public section of the class, they can be accessed from other classes. Here we start the list of public members of our MyMoblet class:
public:
The first public member of our MyMoblet class is a method, the constructor. The constructor gets called when an instance of the class (an object) is created. In this case it is a parameterless constructor as we don't need to pass in any data:
MyMoblet() {(In the case of MyMoblet there is no destructor to clean up after the object once it has fulfilled its usefulness, simply because it would be empty. Constructors and destructors can be implicit: if you don't specify a constructor or destructor, the compiler will put it in.)
The MyMoblet constructor contains three function calls which will be executed in sequential order. (You can distinguish function calls from data members in a class because they are immediately followed by 0, 1, or more parameters in parentheses.)
These three function calls - we call them syscalls - are to low-level, device-independent functions that are defined in the main MoSync syscall header file, maapi.h. You'll be using the functions defined in maapi.h a lot in your applications, so it's worth getting to know it intimately. Read about maaip.h syscalls in the MoSync API Reference Guide in the IDE under Help > API Reference > Files > maapi.h.
The first syscall sets the colour of the output to white:
maSetColor(0xFFFFFF);
From now on, until it is explicitly changed, all output from text and drawing commands will be displayed in this colour. Note that each statement within the method is terminated by a semicolon in C/C++.
The second syscall in the MyMoblet constructor renders the text "Hello World!" to the backbuffer at the coordinates x=0 and y=32:
maDrawText(0, 32, "Hello World!");
The coordinates 0,0 are the top left corner of the screen. The y-axis increases as you head downwards, the x-axis increases as you head rightwards.
To make screen update flicker free, drawing is done to a so called backbuffer, which later, when everything is drawn, will be copied in to the display. Thus the text is not yet visible at this point in the program.
The third syscall is what updates the physical screen of the device with the contents of the backbuffer:
maUpdateScreen();
If you forget this last statement, and that's easy to do, you would just see a blank screen when you ran your application!
Curly brackets are used to group statements in C/C++. Now that we are at the end of the constructor, we close the opening curly bracket at the beginning:
}
(The bracket that marks the beginning of the class will be closed it later on, when our class is complete.)
The second public method of our MyMoblet class is keyPressEvent:
void keyPressEvent(int keyCode, int nativeCode) {Before the name of the method, we need to state the type of the data that the method returns. In this case, the method does not return anything ("void" = nothing).
The keyPressEvent method is called whenever a key is pressed on the device's keypad. It is passed two parameters by the MoSync runtime — the runtime is that part of MoSync which interfaces with the device's operating system and which handles the syscalls from your application.
The first parameter is a device-independent code representing a key, a MAK code. Regardless of the device, if the 0 key on the device's keypad is pressed, the keycode will be MAK_0, and if the device has a back key it will be MAK_BACK.
You can find all the MAK codes in the MoSync API Reference Guide in the IDE under Help > API Reference > File Members > Defines > M.
The second parameter is device-specific (native) key code. That's needed because the MoSync MAK codes are not an exhaustive list of all the buttons ever made available on a mobile device, instead they are a common subset. Your phone may have a button which is specific to that model, for instance the volume keys or the back button on an Android phone. If you know what the value of those keys, you can act on them here.
The keyPressEvent method is one of several methods we have inherited from the Moblet base class. Here we replace (override) the method with our own version. When the program runs and an instance of MyMoblet is created, the C++ runtime system will detect that the instance has a method that replaces the method in the base class. Methods that can be overridden like this are called "virtual methods" in C++.
Now we define what should happen if the zero key on the keypad has been pressed (or the back button, or the soft-right key), and in this case we are just going to exit the program using Moblet's close function:
if(keyCode == MAK_0 || keyCode == MAK_BACK || keyCode == MAK_SOFTRIGHT)
{
close();
}
}The close method releases any resources used by the object and ends the execution of the program.
The Moblet base class also includes a closeEvent method. That method can be used to detect a forced application close detected by the MoSync runtime on the device. By overriding it in your Moblet-based class, you can perform essential data-saving tasks - you only have a second or so! - before your application is forced to terminate by the devices OS.
There are many other event detection methods in the Moblet base class that you can override, including pointer movements, focus changes, Bluetooth connection, timers, and so on. The keyReleaseEvent which comes next in our example is another method that you will commonly want to implement in a Moblet-based application. It isn't actually needed for this simple application, but it works in a similar way to the keyPressEvent we used above.
void keyReleaseEvent(int keyCode, int nativeCode) {For a complete list of the events See the MoSync API Reference Guide in the SDK under Help > API Reference > Classes > MAUtil::Moblet.)
We've left a comment which you can replace with your own code for key release events:
// todo: handle key releases - put your code here.
}Single line C/C++ comments are preceded by two forward slash characters // and terminate at the line end. Anything on the right side of both forward slashes would not be read by the compiler (actually the parser).
You can also use a single forward slash followed by an asterisk to indicate the start of a comment. To end the comment, type an asterisk followed by a forward slash, for example:
/* This is a comment */
This type of comment can be spread over several lines.
There are no private data members or functions needed for the MyMoblet class, so we can just close its definition now. Note that we need to put a semicolon after bracket that closes a class.
};
Now we have completed our definition of the MyMoblet class, which is the only class we need in this simple application. If we needed more classes, we would put them here.
We move on to defining the entry point of our program. This is the place where the execution of the application starts when it is run:
extern "C" int MAMain() {In C you always have a function called main() that is called when the program execution starts. In a MoSync application, the main() function is actually implemented in the runtime. (Remember, that's the part of the application that interfaces with the device's operating system, and hides the complexity of the OS from your application.) In your application you need to use MAMain() to mark its start point. Just think of MAMain() as a synonym for main().
Because C++ is an object-oriented programming language which includes (and is built upon) the procedurally-oriented C language, C++ programs can consist of both C++ classes (like MyMoblet) and C statements like this one. Unlike our earlier methods, this one is a C function (hence the extern "C" bit). A function is like a method, but is not associated with an object, and is defined outside of the classes in the program. In C++, you can freely mix between C and C++ but you always have to start your applications in C.
There is a static method in the Moblet class called run (a static method is associated with the class, not with any instance). This is what starts your application. To call the run method you need to pass it a pointer to a new instance of our MyMoblet class, so we create one with the "new" keyword:
Moblet::run(new MyMoblet());
This constructs the MyMoblet instance and runs the code in the MyMoblet constructor.
C main methods should always return an integer (int), so we return 0, by which we indicate that the program has successfully ended:
return 0; }
And that's it. Our application is now ready to build and run.
/**
* This application provides a very basic example of how to use MoSync
* to print the text "Hello World" to a device's screen. The code is very
* well commented so that you can see exactly what's happening at each step.
* The application makes use of MoSync's Moblet framework to handle events.
*
* @file helloworld.cpp
*
* @author Chris Hughes
*/
/*Include the header files for MoSync Moblets so that we can
*access the Moblet library code from our application.
*/
#include <MAUtil/Moblet.h>
/*Declare the MAUtil namespace so that we can use the short forms of
*identifiers in our code. This allows us to write, for example, "Moblet"
*instead of "MAUtil::Moblet".
*/
using namespace MAUtil;
/*Create the wrapper for the entire application. It is here that we will manage
*the application and handle events. To create the wrapper we make our own
*implementation of the MoSync Moblet base class. There can be only one Moblet
*in an application.
*/
class MyMoblet : public Moblet
{
// Define our new class's public methods.
public:
/*First, the constructor, which we will call whenever we need an
*instance of MyMoblet. In this case, the constructor consists
*of three syscalls.
*/
MyMoblet()
{
// The first syscall sets the background colour.
maSetColor(0xFFFFFF);
// The second syscall writes the text "Hello World" to the backbuffer.
maDrawText(0, 32, "Hello World!");
// The third syscall copies the contents of the backbuffer to the
// physical screen.
maUpdateScreen();
}
/*Next, a method for detecting key presses. This is a method we have
*inherited from the Moblet base class and here we will override that
*method with some processing of our own.
*/
void keyPressEvent(int keyCode, int nativeCode)
{
//Close the application if the zero, back, or soft-right key is pressed.
if(keyCode == MAK_0 || keyCode == MAK_BACK || keyCode == MAK_SOFTRIGHT)
{
close();
}
}
// Finally, a code stub we might need to use later for another event type.
void keyReleaseEvent(int keyCode, int nativeCode)
{
// to do: handle key releases - put your code here.
}
};
/*Now we get to the entry point for the application - the place where
*processing starts.
*/
extern "C" int MAMain()
{
// Create the instance of MyMoblet
MyMoblet myMoblet;
// Run the Moblet to start the application.
Moblet::run( &myMoblet );
/*MyMoblet will run until it is closed by the user pressing key 0. When
*it's closed we end our program in a well-behaved way by returning zero.
*/
return 0;
}If you are new to C++, there are many useful references and tutorial sites on the Internet that can help you learn more. We particularly recommend the C++ language tutorials at http://www.cplusplus.com/doc/tutorial.
We have several other beginner's application examples which you can find in the MoSync IDE, for example: HelloWorld, HelloMoblet, HelloNativeUI, HelloOpenGLES.
We have a more advanced example of a Moblet application in our programmer's guide Event-Driven OO Applications, and in our tutorial Starting a New Moblet Project.
MoSync supports several application development models. We call them the "classic procedural", "event driven, object oriented" and "full GUI-based". The model that you should choose when developing an application depends both on the type of application you are developing and your personal preference.
Using the classic procedural approach means starting out with an empty main function and implementing your own main loop, including all the event handling. Examples...
| Advantages | Disadvantages | When to use |
|
|
|
This approach is embodied in the use of the MAUtil::Moblet class. Inheriting it lets you implement functions such as keyPressEvent() instead of explicitly implementing an event loop yourself while providing TimerListeners and IdleListeners to facilitate execution of code outside of responding to events. Examples...
| Advantages | Disadvantages | When to use |
|
|
|
Using the MAUI library, you gain access to a variety of ready-made widgets such as labels, list boxes, text edit boxes, images, and layouts. You add logic by registering different types of listeners with the widgets, thus responding to higher-level events than with Moblets - things like selection and slider position changes. Examples...
| Advantages | Disadvantages | When to use |
|
|
|
In this development model you have full control over (and responsibility for) how the application behaves. This model is most suited when you are porting existing C applications, or you want full control over program flow and events .
It is important to understand how to correctly implement a MoSync event loop. There three most important points to consider are:
#include <ma.h>
int MAMain() {
// Application initialization goes here
for(;;) {
MAEvent e;
// Wait until we have an event
maWait(0);
// Process all events that have occured
while(maGetEvent(&e)) {
if(e.type == EVENT_TYPE_CLOSE) {
// do cleanup
maExit(0);
}
else if(e.type == EVENT_TYPE_KEY_PRESSED) {
// It's good practise to always provide one key
// to exit the application.
if(e.key == MAK_0) {
// do cleanup
maExit(0);
}
// handle other key presses
}
}
}
return 0;
}
This example only checks for key presses, but note that results of asynchronous operations are also passed as events and should be handled similarily. See the syscall reference for more information.
Working with connections in classic applications involves responding to events whose type is EVENT_TYPE_CONN. Connection operations are executed asynchronously, and these events are the way in which your application is notified of their progress, results and termination.
#include <maapi.h>
#include <conprint.h>
int MAMain() {
char buffer[160];
// Application initialization goes here.
InitConsole();
// Create a connection.
printf("Connecting...\n");
MAHandle conn = maConnect("http://www.example.com/"); // Will cause a CONNECT event.
// The event loop.
for(;;) {
MAEvent e;
// Wait until we have an event.
maWait(0);
// Process all events that have occured.
while(maGetEvent(&e)) {
if(e.type == EVENT_TYPE_CLOSE) {
maExit(0);
}
else if(e.type == EVENT_TYPE_KEY_PRESSED) {
if(e.key == MAK_0)
maExit(0);
}
else if(e.type == EVENT_TYPE_CONN) {
if(e.conn.opType == CONNOP_CONNECT) {
// The Connect operation is complete.
if(e.conn.result < 0) {
printf("Connect error %i\n", e.conn.result);
// Close the connection, freeing resources.
maConnClose(conn);
} else {
printf("HTTP result %i\n", e.conn.result);
// Start reading data.
maConnRead(conn, buffer, sizeof(buffer) - 1); // Will cause a CONN READ event.
}
} else if(e.conn.opType == CONNOP_READ) {
// The Read operation is complete.
if(e.conn.result == CONNERR_CLOSED) {
printf("Connection closed.\n");
maConnClose(conn);
} else if(e.conn.result < 0) {
printf("Read error %i\n", e.conn.result);
maConnClose(conn);
} else {
printf("Read %i bytes:\n", e.conn.result);
// Zero-terminate buffer.
buffer[e.conn.result] = 0;
PrintConsole(buffer);
// Read more data.
maConnRead(conn, buffer, sizeof(buffer) - 1);
}
}
}
}
}
return 0;
} The MAUtil::Moblet C++ class provides boilerplate event handling and produces well-behaved, resource-efficient programs. It helps provide a higher-level abstraction of program flow.
The MAUtil::Moblet class takes care of the application main loop for you. All you need to do is subclass it and implement virtual functions to respond to the events.
#include <MAUtil/Moblet.h>
using namespace MAUtil;
class MyMoblet : public Moblet {
public:
MyMoblet() {
// Application initialization
}
void keyPressEvent(int keyCode) {
// Handle key presses here
}
void keyReleaseEvent(int keyCode) {
// Handle key releases here
}
private:
};
// Since this is a C++ program, the main function
// needs to be declared extern "C"
extern "C" int MAMain() {
Moblet::run(new MyMoblet());
}
The static function Moblet::run() implements the actual event loop. When it gets events, it distributes them to all registered listeners. The Moblet, being both a KeyListener and a CloseListener, will recieve these event types. It is recommended to handle other event types by letting your moblet inherit the corresponding listener types, such as BluetoothListener and ConnectionListener.
Working with connections in Moblet-based applications involves using the ConnectionListener interface. You inherit the class and implement the connEvent() function. You can use one listener for several connections, but each connection can only be associated with one listener. Once the events are received, you should process them in the same way as in the classic model.
#include <conprint.h>
#include <MAUtil/Moblet.h>
using namespace MAUtil;
class ConnMoblet : public Moblet, public ConnListener {
private:
// Variables survive past individual function calls.
char mBuffer[160];
Handle mConn;
public:
ConnMoblet() {
// Application initialization goes here.
InitConsole();
ConsoleDelay = 0;
ConsoleLogging = 1;
// Create a connection.
printf("Connecting...\n");
mConn = maConnect("http://www.example.com/"); // Will cause a CONNECT event.
// Register for events.
setConnListener(mConn, this);
}
void closeConn() {
maConnClose(mConn);
removeConnListener(mConn);
}
void connEvent(const CONN_EVENT_DATA& data) {
if(data.opType == CONNOP_CONNECT) {
// The Connect operation is complete.
if(data.result < 0) {
printf("Connect error %i\n", data.result);
closeConn();
} else {
printf("HTTP result %i\n", data.result);
// Start reading data.
maConnRead(mConn, mBuffer, sizeof(mBuffer) - 1);
// Will cause a CONN READ event.
}
} else if(data.opType == CONNOP_READ) {
// The Read operation is complete.
if(data.result == CONNERR_CLOSED) {
printf("Connection closed.\n");
closeConn();
} else if(data.result < 0) {
printf("Read error %i\n", data.result);
closeConn();
} else {
printf("Read %i bytes:\n", data.result);
// Zero-terminate buffer, so it can be printed.
mBuffer[data.result] = 0;
PrintConsole(mBuffer);
// Read more data.
maConnRead(mConn, mBuffer, sizeof(mBuffer) - 1);
}
}
}
void keyPressEvent(int keyCode) {
if(keyCode == MAK_0)
maExit(0);
}
};
extern "C" int MAMain() {
Moblet::run(new ConnMoblet());
} Mobile offers developers a new world, with cool devices and nice, easy, small projects compared to that monstrous and boring enterprise code you've been doing in Java or C#, right? Right! However, there are somethings I'm going to tell you to help you move your Java/C# skill to C++ in MoSync. The reality is that both Java and C# are based on syntax from C, so you are going to be able to read C++ source code without anyone having to explain how curly braces work or reminding you to put a semi-colon at the end of the line, which is cool. Java and C# both also have a runtime environment which manages memory and performs garbage collection for you, which C++ doesn't, which isn't cool. Also, it isn't too difficult, and I'm here to guide you through the processes which will save you time and effort, and when you into trouble, the answer will probably already be here.
As you are a Java or C# developer, then you've spent time gathering some fine object-oriented design skills, so we're not going to touch on C code here, this will be about C++ (mostly).
This guide is in three sections, firstly a quick reminder of how C++ works, then a section of how memory management works, and finally unlearning lots of really nice design principles which are perfect for enterprise development, but will cause you grief in mobile.
One final note: this obviously isn't an exhaustive description of how to write in C++. This is what you need to know coming from a Java or C# background to start writing C++, so don't expect this to be the definitive description. This is a quick start guide.
Ok, this isn't really everything you need to know about how C++ works, this is just a reminder about how it can be different. In C#, if you want to create a new class, you right-click and give the class a name and Visual Studio creates a new templated .cs file for you. You add in a bit of functionality, and your new class is available within its namespace. The same is nearly true in C++. Normally, in C++ you will split your class into two files, a header file and a code file. The header file will normally have a .h or occasionally a .hpp extension, whilst code files will have .c (for C code) or .cpp (for C++ code).
The header file contains the interface definition of your class, although it can contain implementation as well. In C# when you want to use a specific class you just need to simply include the namespace of the class with a using statement. In C++, you need to provide a definition of a class before you can use it. You do this by including the header file of the class in your code using #include "classname.h". The header is literally included in source code passed to the compiler. This leads to an issue which you don't get in managed environments. If you have two classes, Alpha and Beta, you can include them in your new class Gamma like this:
#include "Alpha.h"
#include "Beta.h"
However, if Beta.h itself includes Alpha.h, you will get a compilation error when you build Gamma. This will be because the compiler inserts the code from Alpha.h, then inserts the code from Beta.h, which in turn inserts the code from Alpha.h. The compiler will complain that methods of Alpha have already been defined. To prevent this, at the top of your header file, you need to add an include guard. This is a short compiler directive telling the compiler not to include the header if it has already been included. In Alpha.h you will write something like this
#ifndef __ALPHA_H
#define __ALPHA_H
When you create a new class in MoSync, the template should do this for you. You can read this as "if there isn't a token called __ALPHA_H then create a token called __ALPHA_H." At the bottom of the code there will be an #endif to round this off. You can change the naming convention if you wish, but if you write a header file from scratch, then don't forget the include guard.
So, in your class you may want to use some classes without specifying their namespace everytime. This is a very familiar command
using namespace <namespace>;
Note the semi-colon at the end; this is a C++ command and not a compiler directive.
You can create your classes in a namespace in the header file, and again it is familiar
namespace MyNamespace
{
...
};
Again note the semi-colon at the end.
Inside any optional namespace declaration, you can create one or more classes (or structs).
class MyClass
{
...
};
Once more, take notice of the semi-colon at the end of the class definition.
Inside the class, you can create methods. C++ doesn't support properties in the way you may be used to. The visibility of methods is also different, as you are able (and encouraged to) define methods in groups by visibility. A class definition in a header file might typically look like this:
class Gamma
{
public:
Gamma();
virtual ~Gamma();
void incrementCounter();
int getCounter();
protected:
int mCounter;
private:
bool isActive;
};
So there are a few things here we can see. Firstly, there is a class definition as we've seen before. Inside this are three blocks of member definitions, ordered by visibility. In the public section, we can see a constructor for Gamma and a destructor (~Gamma()). The constructor will be called when the class is instantiated and the destructor when it is destroyed. This maybe obvious, but these are going to become very important in the next two sections of this guide.
After the destructor, then there are two method declarations, incrementCounter() and getCounter(). We can see that incrementCounter() doesn't return any value and that getCounter() returns an integer. We've then got two members mCounter and isActive. You can if you really want define the visibility with each member, but this is unconventional.
Creating the code to go with the header means creating a .cpp file as well. To continue this example, we could have Gamma.h and Gamma.cpp to contain the implementation.
#include "Gamma.h"
Gamma::Gamma()
{
mCounter = 0;
}
Gamma::~Gamma()
{
}
void Gamma::incrementCounter()
{
mCounter++;
}
int Gamma::getCounter()
{
return mCounter;
}
Several things to notice here. Each method needs to start with the class scope Gamma::. This means that you can implement several classes in the same .cpp, but it isn't normally recommended. Secondly, methods in C++ generally start with a lower-case letter, unlike most Java and C# classes. Thirdly, C++ doesn't support properties directly in the same way as C#, you need to create a method for get and set. Finally, as you'd expect, when you create an instance of Gamma, mCounter is set to 0 in the constructor. There is actually another way to do this, and one which is generally preferred in C++ for two reasons. The constructor could look like this
Gamma::Gamma() : mCounter(0)
{}
mCounter will be initialised with a value of 0. This can be important in environments where it may be possible to access the class before the constructor has finished executing. With the initialisation as part of the constructor specification then you are guaranteed availability. Secondly, if your class defines references (more later), then these cannot be null. By specifying them in the constructor, then you can assign the reference and avoid this issue. More on objects, pointers and references soon!
So, if my class Gamma requires other objects or functions, then the include file can be added in the C++ file, and not in the header. It is a very good rule to only have the includes you need in the header, and if the class is used entirely internally, then #include it in the cpp file.
It is possible to have objects as public members in a C++ class, for instance
class Delta
{
public:
int counter;
};
This is as bad an idea in C++ as it is in Java and C#. There is nothing intrinsically wrong with it, but you don't get any opportunity to clean input into mCounter, or to check that its value is only changed when it is safe to do so.
C++ supports multiple inheritance, that is actual base classes with actual implementation and not just interfaces. When you specify your class, you can specify which classes to inherit from, as well as the visibility of the inheritance
class Delta : public Alpha, public Beta, private Gamma
So there are two things to say about multiple inheritance in a MoSync context. Firstly, be careful. We're sure that you regularly observe SOLID design principles and the Liskov Subsitution Principle, but C++ can be a handgun. It's an incredibly powerful piece of technology, but easy to abuse. Don't get lost in inheritance. Secondly, lots of casting of your classes between interfaces and classes is slow. The device has to do looks ups to get the correct addresses to access the object according to the interface or inherited class. We'll come back to this later.
So, those are the warnings, and here is the good news: inheritance is cool, it makes your coding easier if you've thought it through properly. Multiple inheritance means that you can use classes which in C++ are called mix-ins. You can have a little utility class which you may want to access in a variety of contexts. In C++, you can mix in this functionality directly into your class, without having the overhead of instantiating a new class to do it. Your class may be a little larger, but there are benefits in not having to create a new instance of the utility whenever you want to use it. You can also then cast classes as these mix-ins if you need to, as long as you are prepared to change your mind about this if it gets too slow.
Interfaces in C++ are just classes, there is no 'interface' declaration. You create a class to inherit from with virtual methods. It is unusual to prefix interface classes in C++ with the letter I.
In C#
public interface Alpha
{
public abstract void doSomething();
}
In C++
class Alpha
{
public:
virtual void doSomething() = 0;
};
Virtual methods can be overridden, but there is no need for an 'override' command.
class Beta : public Alpha
{
public:
void doSomething();
};
The implementation of doSomething will be the one used, as there is no implementation in Alpha. This is called pure virtual method and it can be identified by the = 0.
This is what makes it a true interface. Any class which inherits from Alpha must implement doSomething(). Alternatively, you can provide an empty method
class Beta
{
public:
virtual void performOperation() {}
};
This method provides an empty implementation, which means that you don't have to implement the method performOperation().
One of the great advantages of memory-managed environments like .net and Java is that you don't have to worry about whether objects are created in the heap or on the stack. You can go through an entire career in managed programming without ever having to worry about it. C++ is more complicated, but instead of 'complicated' most people use the word 'powerful'.
Just to remind you, stack memory is local to the scope of the code where it was created. Heap memory is shared across the entire scope of the application. You need to consider when you create an object whether it is on the stack or in the heap. Objects on the heap need to be explicitly destroyed with the command delete. Objects on the stack will be deleted when they go out of scope. The rule with C++ generally is to only create objects on the heap when you absolutely need to. Creating objects on the heap can be much slower than creating them on the stack. When you've been working in managed environments for a while, you forget that searching for free memory in the heap is an expensive operation. Every time you use new then it has to do that search. Creating objects on the heap is necessary though when you want to be able to control their lifespan, for instance in factory classes which may create objects which have a lifespan greater than that of the factory itself.
To create an object on the stack, simply declare it.
String myString;
To create an object on the heap, you need to use new
String* myString = new String();
The asterisk (*) here means that you have created a pointer to a String object. This is the address a particular object or interface starts. The actual position of the asterisk can vary, so you may read
String *myString = new String();
or
String * myString = new String();
The first form, with type*, is preferred and recommended for two reasons. Firstly, the command is in the format <type> <name>. The type is String pointer, and it is called myString. If you don't put the asterisk next to the type, then you are saying that myString is a String, which it isn't. Secondly the asterisk has some other meanings in other contexts. *myString means something else, so its use is ambiguous if you declare as <type> *<name>.
There is another type called a reference. A reference is an address like a pointer, but unlike a pointer it cannot have a null value. References are declared with an ampersand (&).
String* myString = NULL; //Is OK
String& myString; //Will cause a compiler error
References are particularly valuable as a way to pass stack objects.
String& Gamma::getHeadline()
{
return myString;
}
In this example, myString has previously been created as an object on the stack. getHeadine() will return a reference to myString and not pass the entire object back as a return value.
String& headline = gamma.getHeadline();
Shows how you can create a reference with an assignment.
When you access methods on an object, you need to know whether it is an object or a reference, or a pointer. Members are accessed in objects and references using a period (.) e.g.
myString.clear();
When you have a pointer, you access members using -> e.g.
myString->clear();
You can covert between pointers and reference using an asterisk. Firstly, you can dereference a pointer and treat it as an object.
String* myString = new String();
myString->append("hello world", 11);
String& strref = *myString;
strref.clear();
Interesting. The asterisk is used to say "the object that this pointer points to".
You can create pointers to objects, even if they are on the stack. This also means that having a pointer to an object is not the same as knowing that the object on the heap. This is useful when you want to use objects with methods which expect a pointer.
int Gamma::getStringLength(String* testString)
{
return testString->length();
}
…
String hello = "Hello World";
int strLen = getStringLength(&testString);
This is a bit of a contrived example, but you can see that by using an ampersand before the object name, it is saying "the address of this object". Both String* and &testString will have the same value.
Being able to create objects in both the stack and the heap, and the lack of an automatic garbage collector, means that you have to think about the lifespan of each and every object that you create and where you create it. As we've said above, create objects onto the stack wherever possible. When you create an object on the stack, it will have a scope of the lifespan of it's location.
For instance, if you create an object in a method
void Gamma::doSomething()
{
// String will be created here
String myString;
…
// String will be automatically destroyed and the memory
// freed because we've reached the end of the method. We
// don't need to do anything else.
}
Objects can also have the scope of an object. Consider this header file
class Gamma
{
public:
Gamma();
virtual ~Gamma();
private:
String mString;
};
In the second example, there will be an object called mString on the stack. It will be created when an instance of Gamma is created, and destroyed when Gamma is destroyed. You don't need to do anything else. Easy, isn't it?
You need to be much more careful when you are creating objects on the heap. They won't be automatically destroyed when the method or object goes out of scope. Objects on the heap are really useful because of this. You can create an object in one class and pass the pointer to another class, or you can use it internally.
There is a design pattern called Resource Allocation is Initialisation (RAII). This pattern says that when you create a class, create the objects you need in the constructor and destroy then in the destructor.
//Constructor
Gamma::Gamma()
{
// Instance heap objects you need here
myString = new String();
}
// Destructor
virtual Gamma::~Gamma()
{
delete myString;
}
This means that although myString will be created on the heap, then when Gamma goes out of scope myString will be destroyed.
There are many cases where this isn't appropriate though. You could have an application which needs to send complex messages between classes. Each message is of the class 'Message'.
class Message
{
public:
void setMessage(const char* message);
const char* getMessage();
void setStatus(int status);
int getStatus();
private:
String mMessage;
int mStatus;
};
It’s a little class which can store a text message and a status value. We can see that when Message is instanced, a string and an int are allocated on the stack.
Class Gamma needs to send messages to class Delta. Delta has the following method.
void Delta::receiveMessage(Message* message)
{
// Got the message
}
Objects on the heap are really powerful, but with that power comes great responsibility. Here is a quick review of some things to remember
If you look on the MoSync forum, or in the MAP library, you will find some debug methods for creating objects. These functions replace new and delete and keep a track of which objects have been instanced on the heap and which source file did it. When your application exits on the emulator, it will report about which objects haven't been deleted. This can help you track down memory leaks. To use them, replace all of your new keywords with newobject() and delete with deleteobject().
So you've got some killer design skills for Java or .net. Maybe you've mastered IoC containers or double dispatch and you can see how they are going really help in C++. This is good, and you can certainly use these techniques, but there are some other considerations you need to keep in mind with mobile development. If you've been doing desktop or enterprise development, then you're used to working in environments which are much more powerful than mobile. You will have lots and lots of small, specialised classes which are great for working with. Each class supports multiple interfaces and has been created to perform one small task. The reality of non-managed environments and polymorphism is that creating classes is slow, and casting objects is slow. Not so slow that you shouldn't do it, or you will be waiting all the time for your application, but slow enough that if you do use design patterns which involve a lot of tiny classes, and a lot of casting between interfaces, then you may be wondering why the application isn't as speedy as you imagined.
You will get better speed by creating fewer classes with fewer interfaces, and on the stack rather than on the heap. Flatter designs will result in faster code. Of course, this is then a trade between the design you would use in Java and the speed you want in C++, and in many instances you won't find the code slow, but if you've got routines which create lots of instances of objects (in a loop for instance), then you need to be aware of where you can improve speed.
If you can combine classes to put methods together in the same object, then you will save memory and be faster. Better still, if you can create utility functions in C rather than C++ objects then this will be even faster. Typically factories make a good example where C code can be used, as well as utilities like decorators don't have to be in classes. Many developers on the web will tell you to code in C by default, and only use C++ and classes where you need to.
When you develop an application you want it to be as fast and as memory-efficient as possible. And that's even more important when you are developing for mobile devices which have slower CPUs, limited memory, and limited power resources. The MoSync SDK lets you target a huge range of devices with your applications, but you should always bear in mind the limitations of the devices you are writing apps for. Here we provide some guidelines to help you optimize your application's performance, size, and power consumption.
MoSync includes many libraries that we have carefully optimized for performance on a wide range of devices. Try to use these libraries wherever possible. In particular, if you are developing C++ applications, make full use of:
Pipe-Tool is MoSync's code transformation engine. It is, among other things, a code verifier and optimizer and it performs dead code elimination to produce small, efficient output files.
Pipe-Tool is automatically invoked by the MoSync IDE during the normal build process. It can also be run on-demand from the command line. The dead code elimination process is optional and still in an experimental state, but you can turn it on by enabling Activate Dead Code Elimination in your project's build settings (select Project > Properties > MoSync Project > Build Settings > Compiler Flags) or, on the command line, by passing the -elim flag to Pipe-Tool.
We've chosen to not support threads directly in MoSync, but instead we have implemented all essential threaded operations asynchronously. Whenever you start such an operation, it will run in the background and send a notification in the form of an event when it's done. By encapsulating asynchronous operations in the runtime we can ensure that the behavior is consistent on all devices, and you never have to care about thread synchronization. Some platforms implement asynchronous operations internally without threads, for instance Symbian, where they strongly encourage the use of Active Objects over threads.
To keep you application responsive when it's doing a lot of computations, it is a good idea to periodically check for events. This can be done either by invoking some event handling mechanism or by using the Moblet framework, and by doing the computations in blocks so that the execution returns to the main loop from time to time. It is also necessary to make sure the EVENT_TYPE_CLOSE event is received and handled, as it indicates that the application has been forced to quit for some reason.
The CPUs in many mobile devices are based on the ARM architecture. The CPUs can have different clock frequencies and cache sizes, and some have no cache at all. What mobile CPUs generally have in common is that they are all far less powerful than the ones you're used to develop for on a regular PC.
Any piece of code that is going to use a lot of CPU time should be carefully optimized. Finding the right algorithm is more likely to be important than doing low-level optimizations. Also such optimizations are usually done by the compiler (in our case GCC), so it is always good to know your compiler in order to keep the amount of work to a minimum.
If you're in need of extreme performance, basic speed optimization tricks can help:
Many mobile devices do not have a floating-point unit (FPU). Their floating-point operations are done in software. That results in much slower processing than on regular PCs. To improve performance, the best way to deal with decimals on these devices is to use fixed-point arithmetic with integers (see, for example, http://en.wikipedia.org/wiki/Fixed-point_arithmetic).
MoSync syscalls (defined in maapi.h) incorporate platform-dependant code that is optimized for the architecture they are running on. Try to use them as much as possible, even if the same functionality is possible to re-implement in other ways. This will not only make things faster, but also smaller.
Divisions may be really slow as they aren't available natively on most ARM processors. Use shifts when possible or pre-calculate reciprocal 1/x values and do multiplications instead.
If you have to read a lot of small pieces of data from a data object, try to buffer data in memory. Doing a lot of calls to maReadData may be slow.
If your application needs to read from and write to memory a lot, try to access memory as integers whenever possible. This is even more important when targeting Android and Java ME devices. XML parsing, for instance, relies on heavy use of byte accesses. Whenever possible use some more approriate binary format.
Try experimenting with different GCC optimization flags (right-click on your project and select Build Configurations > Manage > Build Settings > Compiler Flags > Additional GCC Switches). The -o3 swtich should in most cases be slightly faster than -o2, although it may slightly enlarge the size of the binary.
It's worth mentioning that if you are used to programming in Java, you tend to use as few classes as possible, due to their size and speed overhead. But C++ objects are pretty lightweight and faster than their Java equivalent so you do not need to be so restricted.
MoSync features a recompiler that transforms MoSync code into native ARM code at start up. For CPU-intensive applications, the recompiler can provide a substantial speed boost. As of June 2010, this recompiler is available on Windows Mobile, Symbian s60v3 and s60v5. Work is in progress to bring the recompiler to s60v2 and Android. (on our MDLbenchmark test on Symbian 5th edition, the MoSync ARM recompiler increased performance by more than 300%.)
Battery power is drained when hardware is in use, especially the CPU. It's therefore important to optimize for performance, making the CPU complete its work faster. The syscall maWait puts the thread in suspend mode until an event has been sent, leaving the CPU for use by other threads/processes, thus using less CPU and battery power. The Moblet framework does this automatically.
All phones have different screen sizes. They are often very small with low resolutions, making it more important to choose graphics wisely. Fonts or images should be visible on all sizes of screens.
Many mobile devices have small RAM sizes and most likely a lot better permanent storage capabilities. It's important to take this into account when developing applications for them. Unloaded binaries (.ubin) and unloaded media files (.umedia) are good formats to use for resources as they will be kept in permanent storage as long as they aren't used. (For more information about these resource types, see the Resource Compiler Reference.)
Resources such as images and media files can take up a lot of space in the final package so try to keep them as small as possible. There are many free and commercial tools available for optimizing and compressing resources without noticeably reducing their quality. Generally, you should use the PNG format for images: we have ensured support for it across all capable devices (PNG is generally smaller than GIF anyway). If you have photographic images, you should to use the JPEG format. Most modern devices support it, although some of the older ones may not so it may be worth checking.
Try not to do too many small heap allocations as this will fragment the heap. The result will be slower heap allocations and more memory usage. As you code in C or C++ it's also good to verify that you haven't got any memory leaks. This can be done using a simple trick shown in MAP/MemoryMgr.h: basically you save information about in which file, function, or line every allocation is done, and remove that whenever it is freed. This information can be dumped at anytime to see what memory leaks you have.
If you have more tips about optimizing applications for mobile devices, please share them with us by leaving a comment below.
Android developers will find much to like in the MoSync SDK. Like the native Android SDK, the MoSync SDK utilizes Eclipse as its development environment. Here we provide some advice on building Android application using the MoSync SDK.
Package settings for Android applications can be found under Properties > MoSync Project > Android for your project. Here you can set the application's package name and version code and sign the package with your credentials.
The application package name is used by the Android OS to identify your application. The default package name is com.mosync.app_<Project Name>.
The application version code is used by the Android Market to check for application updates.
You need to sign your Android application before it can be installed on an Android device. You can create your own self-signed certificate (see http://developer.android.com/guide/publishing/app-signing.html). Just add the information about your certificate in MoSync and your application will be signed when you build it.
From within the MoSync IDE you can search for connected Android devices. Click the small down-arrow next to the icon of a mobile phone and magnifying glass on the top bar of the IDE then select Scan for Android USB device. (If your device is not found make sure you have installed the connection software which came with the device.)
Newer Android devices (2.1 onwards) can also send applications via Bluetooth. This is enabled on your phone. To search for Bluetooth devices, choose Scan for Bluetooth device instead. When you have selected your device and choosen a default device profile for it, you can send the application to the device.
Bluetooth is not supported by Android 1.5 and 1.6.
One of the more powerful features of the Android platform is its ability to let applications run in the background. However, many devices on other platforms (particularly Java ME) do not allow you to do this, they just stop working if you switch to another application. Therefore, be careful if you are creating Android applications that rely on being able to run in the background and you intend to port them to other platforms.
MoSync applications built for Android 1.6 and later uses the Android manifest settings to handle all types of screen resolutions. At this time all resolutions are allowed.
Applications based on MoSync are able to access touch and key input, and
can access all the image and sound formats supported by the Android OS.
MoSync 2.7:
All of Apple's iPhone, iPad and iPod touchscreen devices run the same operating system: iOS. Currently, the only way to download applications to an iOS device without voiding its warranty is via the Apple App Store. Here we provide advice on building successful iPhone apps with the MoSync SDK.
Apple imposes strict rules and guidelines on how applications made available through its App Store are to be built. That means to successfuly build an iOS application with the MoSync SDK, you will need to install the MoSync SDK for OS X on an Apple Mac running Snow Leopard (OS X version 10.6). You will also need Xcode 3.2.4 with the iPhone OS SDK. To build and distribute an application for anything else than the simulator you will need to join Apple's Developer Program.
If you do not have an Apple Mac available right now, you can install the MoSync SDK for Windows on an Windows machine. You will still be able to build your project, but the output will be an Xcode project which will then need to be built on an Apple Mac Snow Leopard running Xcode version 3.2.5.
Apple provides detailed guidelines describing how a well-behaved iPhone application should be written.
Generally, MoSync runtimes are completely conformant with Apple's guidelines, so you should have no trouble getting your application in the Apple App Store. Note, however, that Apple expects all applications to be closed by the "Home" button on their device, and are likely to reject applications which explicitly show an "Exit" button. If you want such a button on other platforms, simply skip it on iOS:
#include <maprofile.h> ... #ifndef MA_PROF_SUPPORT_OS_IPHONEOS <code for initializing an exit button> #endif
An application may be closed when the phone receives a call or if the application uses too much memory. Therefore one thing users rely on is that the state of an application is stored at all times, so that when the application is restarted, its state can restored. This can easliy be implemented using MoSync's store syscalls defined in maapi.h (maOpenStore, maWriteStore...). When the application receives an EVENT_TYPE_CLOSE event, make sure you write the state to a store, so that it can be restored whenever the application is restarted.
JPEG and PNG are the supported image resource formats.SVG images, including application icons, are not supported by iOS.
The playback audio codecs are described in the iOS Reference library.
MoSync 2.5, 2.6
MoSync 2.6
When you package an application for a Symbian device, you need to specify a UID for the package. MoSync can generate test UIDs for you to use during development. Optionally, can also self-sign your packages by specifying a key file and certificate. Here we describe how to set UIDs and do self-signing.
Symbian requires that each application has a UID to uniquely identify it.
When you create a project, MoSync automatically generates random UIDs for you within the range reserved by the Symbian Foundation for development and testing use. There are different ranges of these reserved UIDs in different editions of Symbian.
To view or change the current UIDs for an application, right-click on your project in the Project Explorer view, and select Properties > MoSync Project > Symbian.

If you need to, you can generate new random UIDs in the reserved range by clicking the Generate Test UIDs button.
These UIDs are intended just for use while you are doing development on your own machine. When you application is ready for public distribution, you will need to enter, in these boxes, UIDs provided by the Symbian Foundation for your application. Visit www.symbiansigned.com for more information.
To install Symbian applications on 3rd and 5th edition devices, they must be signed. MoSync generates a default private key file and certificate for self-signing.
If you wish to use your own key file and certificate to sign a particular application, right-click on your project in the Project Explorer view, and select Properties > MoSync Project > Symbian > Self-Signing.

(The default key file and certificate for all projects is shown in this screenshot.)
Tick the Enable Project Specific Settings checkbox. Enter the paths to your key file and certificate. In the Passkey field, enter the password for the key file. Click Apply.
The MoSync SDK includes OpenSSL which you can use to generated private key files and certificates. OpenSSL can be found in the MoSync /bin folder. Visit www.openssl.org for more information.
MoSync 2.5:
It's easy to add application icons to your project. All you need to do is to add a file to the project with the *.icon extension, for example App.icon (you can pick a name you like), write in a few lines of XML, and add the icon images to the project. MoSync does the rest.
Here is an example of a .icon file:
<?xml version="1.0" encoding="UTF-8"?> <icon> <instance size="default" src="Icon.svg" /> <instance size="64x64" src="Icon.svg" /> <instance size="32x32" src="Icon.png" /> </icon>
It is generally sufficient to just specify the default instance size option, the other options are not mandatory:
<?xml version="1.0" encoding="UTF-8"?> <icon> <instance size="default" src="star2t.svg" /> </icon>
SVG is the recommended image format and works for all platforms. An example of an open-source drawing program you can use to create SVG files is Inkscape.
To know if the
application icon was added correctly during the build process, you only
need to look at the last few lines of the IDE console for guidance.
Some quirks that have been observed:
Please keep in mind that this feature of the MoSync SDK is experimental. Some platforms may show unexpected results. Let us know if you find issues.
In many games and applications you will want to play a sound. This may be backing music in a game, sound effects or alerts which require user input. The MoSync SDK provides an audio API to help you do that.
Sound files can come from two places, either sounds you've packaged up with your application when you've distributed it, or they can be downloaded over the data network at runtime. Either way, you need to create a resource which the API can recognise and pass to the operating system.
The 'Adding Resources to a Project' goes into a detail on how to add sound files to your project at build-time for packaging with your release. In short, a sound file needs to be added as either a .media or a .umedia resource with a MIME type.
Due to limitations in the platform-provided API's there are a set of restrictions. Currently, it's not possible to play MP3 files on the Windows Mobile platform and the API only supports playing of one sound at a time. If you want to make sure that all MoSync supported devices will be able to play your resources it is recommended that you use wav files.
To play sound files you have downloaded, then the easiest way is with the AudioDownloader. There is an example which downloads and plays an MP3 file in the tutorial 'Downloading Audio from the Internet'.
Whether you are planning on packaging audio with your application, or planning on downloading it, it is essential that you specify the MIME type of the audio before you want to play it. The two tutorials linked above contain much more detail about how to do this in each scenario, but this is the short version.
If you are packaging your audio, you will have an entry in the resource file which looks something like this:
.res MUSIC .media "audio/mpeg", "music.mp3"
The directive .media means that it will be treated as a loaded binary resource. That is, it will be loaded into the application memory when the application starts. Alternatively, you can use .umedia which will mean that the audio is loaded on demand, but there will be a slight delay.
After the .media directive, then there is the MIME type as a string. You can find common MIME types on Wikipedia. The final part is the file name you want to enclose.
If you are downloading and playing sounds at run time, then you should probably use the AudioDownloader class. This is create and configure an appropriate resource for you. When you specify the URL to download from, you also specify the MIME type. The web server you are downloading from (assuming it is a web server) may also provide the MIME type, and may also overwrite your MIME specification.
To play a sound you use the maSoundPlay function.
maSoundPlay(RES_SOUND);
Just provide the correct resource and the audio file will start playing immediatly if successful. If the function returns any negative value it means that it failed.
If you, for some reason, wish to stop playing the sound you just use the maSoundStop function.
maSoundStop();
If you wish to restart the sound you can use this:
if(maSoundIsPlaying()) maSoundStop(); maSoundPlay(RES_AUDIO, 0, maGetDataSize(RES_AUDIO));
First you can check if your sound is still playing. If so, you can stop it before playing it again. maSoundPlay always plays the sound from the beginning.
Audio volume in MoSync is defined as values between 0 and 100, where 100 is the maximum volume. To get the volume you use:
int volume = maSoundGetVolume();
and to set the volume you use:
maSoundSetVolume(volume);
/**
* @file PlayAudio.cpp
*
* This program shows how one can work with playing sounds and music.
*
* Todo: You need to add an audio resource file which you want to play.
* In this example we have used Resource.lst file with following contents:
* < .res RES_AUDIO
* .media "Audio/x-waf", "mobilesorcery2.wav" >
*
* @Author Anders Malm
*/
#include <MAUtil/Moblet.h>
#include "MAHeaders.h"
using namespace MAUtil;
/*
* Moblet class for playing music.
*/
class MyMoblet : public Moblet
{
public:
MyMoblet();
void keyPressEvent(int keyCode);
void setVolume(int change);
};
/*
* The constructor for Moblet class
*/
MyMoblet::MyMoblet()
{
MAExtent e = maGetScrSize();
maSetColor(0x0);
maFillRect(0, 0, EXTENT_X(e), EXTENT_Y(e));
maSetColor(0xffffff);
maDrawText(0, 0, "Press 5 to Restart sound");
maDrawText(0, 20, "Press 8 to Stop sound");
maDrawText(0, 40, "Press 7 to Decrease volume ");
maDrawText(0, 60, "Press 9 to Increase volume ");
maDrawText(0, 80, "Press 0 to Exit");
maUpdateScreen();
// Panic message in case of failure.
if(maSoundPlay(RES_AUDIO, 0, maGetDataSize(RES_AUDIO)) < 0)
maPanic(0,"error playing sound!");
}
/*
* For controlling music volume.
*/
void MyMoblet::setVolume(int change)
{
int volume = maSoundGetVolume();
volume += change;
if(volume<0) volume = 0;
else if(volume>100) volume = 100;
maSoundSetVolume(volume);
}
/*
* Key press events
* Pressing key 0, Exits the program.
* Pressing key 8, Stops playing sound.
* Pressing key 5, Starts playing sound.
* Pressing Keys 7 and 9, sets volume down and up respectively.
*/
void MyMoblet::keyPressEvent(int keyCode)
{
switch(keyCode)
{
case MAK_0:
maExit(0);
break;
case MAK_8:
maSoundStop();
break;
case MAK_5:
if(maSoundIsPlaying())
maSoundStop();
maSoundPlay(RES_AUDIO, 0, maGetDataSize(RES_AUDIO));
break;
case MAK_7:
setVolume(-10);
break;
case MAK_9:
setVolume(10);
break;
}
}
/**
* Main execution of the program starts from here.
*/
extern "C" int MAMain()
{
Moblet::run(new MyMoblet());
return 0;
}; This example application hows how to use MoSync's sound API. The example demonstrates how to play and loop a sound once.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
This application plays an mp3 file with the message "Mobile sorcery - making mobile magic".
CameraDemo is a simple application built with MoSync that demonstrates how to control a device's camera. It also uses the MoSync Widget API.
![]() | ![]() | ![]() |
| Main screen, Android | Main screen, iOS/iPhone | Settings screen, Android |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
The application makes extensive use of the MoSync Widget API. It has three different screens:
The project is divided into several files. Each screen is implemented in a separate set of header and cpp files.
The main.cpp file is the main file of the project. It includes the code for creating MainScreen.
ImageScreen.cpp contains the code for creating and handling the ImageScreen, while SettingScreen.cpp implements a class that creates and handles the SettingsScreen.
WidgetUtil.cpp contains simple wrappers for setting and getting properties of the widgets (similar to the files seen in our example application HelloNativeUI).
The .h header files contain the forward declarations for the code in the .cpp files.
In
this tutorial we take a look at how to control a device's cameras
through the MoSync Camera API. With the Camera API you can discover the
number of cameras a device supports, set properties like zoom and image
format, embed previews in your application, and, of course, take a
picture. We also have an example application for you to look at, CameraDemo, that demonstrates some of the basic principles described here.
Here are the list of the syscall functions in the Camera API:
The
recommended way of using the new Camera API is together with Widget API. To use the camera together with the Widget API follow these
steps:
1. Get the number of available cameras on the device by calling maCameraNumber.
2. Add an instance of MAW_CAMERA_PREVIEW to your application with maWidgetCreate.
3. Set the widget parameters (only width and height are recommended).
4. Select one of the cameras by calling maCameraSelect:
maCameraSelect(MA_CAMERA_CONST_BACK_CAMERA);
5. Bind the preview and the camera by calling maCameraSetPreview so that the camera uses that preview for its live view.
void createCameraWidget ()
{
mCameraPreview = maWidgetCreate(MAW_CAMERA_PREVIEW);
widgetSetPropertyInt(
mCameraPreview,
MAW_WIDGET_WIDTH,
MAW_CONSTANT_FILL_AVAILABLE_SPACE);
widgetSetPropertyInt(
mCameraPreview,
MAW_WIDGET_HEIGHT,
MAW_CONSTANT_FILL_AVAILABLE_SPACE);
//bind the widget to the default camera
maCameraSetPreview(mCameraPreview);
maWidgetAddChild( mMainLayoutWidget, mCameraPreview);
}6. Check the available functionality on the device’s camera (zoom support, flash support, etc.) by calling maCameraGetProperty.
char buffer[256];
maCameraGetProperty(MA_CAMERA_FLASH_SUPPORTED, buffer, 256);7. Start the camera by calling maCameraStart.
8. Change the properties as required by calling maCameraSetProperty.
9. Call maCameraSnapshot to
take snapshots. Here You can see an example function that takes picture
snapshots and stores them in a single place holder called mLastEnc.
void takeSnaphot()
{
if(mLastEnc != 0)
maDestroyObject(mLastEnc);
mLastEnc = maCreatePlaceholder();
int res = maCameraSnapshot(mCurrentSizeIndex, mLastEnc);
if (res != MA_CAMERA_RES_OK)
maPanic(res, "Failed to takeSnapshot");
}10. Call maCameraStop to stop the camera when you are finished with it.
11. Destroy the Widget if required.
Camera properties can be set and read through the maCameraSetProperty and maCameraGetProperty functions:
Read/Write:
Read Only:
For more details about these functions, see the MoSync API Reference Manual.

The Camera API for the MoSync Android runtime currently uses Android 2.2 (API Level 8) which only supports one camera.
The MoSync SDK provides several different collection objects, suitable for different occasions. Collections let you deal with sets of object collectively, but the way you access the collection varies.
Collections are not implemented consistently in MoSync though, so different collection types are not as interchangable as you might expect.
Typically, collections will be created on the stack rather than the heap. This will mean that if you have a collection of object pointers (the objects themselves will be in the heap), and the collection goes out of scope, you may loose the pointers to the objects in the heap and you won't be able to access them. The objects will still exist though, and you've got a memory leak. Keep close track of collections, and ensure that they are in a suitable scope. Object scope is very commonly used.
class MyClass
{
public:
MyClass();
virtual ~MyClass();
private:
Vector<MyObject*> myVector;
};In the above example, the Vector of MyObject pointers will be created when the object is created, and destroyed when the object is destroyed. The objects the pointer point to will not be destroyed unless you specifically destroy them. You can do this in the class destructor if you do not wish to refer to those objects again.
MyClass::~MyClass()
{
//Destroy the objects in my Vector
Vector_each(MyObject*, itr, myVector) {
delete *itr; //Delete the object
}
}Always be aware of the lifespan of objects in collections, and delete the objects as necessary.
In most collections, there are ways to iterate through the contents. These are specific to the collection type, and methods for iteration are described with each collection type. They are not consistent, so don't assume that because you can use one method for iterating one type of collection it will be exactly the same for another.
In C++ there isn't an iteration interface, nor is there a keyword for iteration. For example, in C# there is the IEnumerable interface and the foreach keyword which lets you iterate through any collection:
foreach(String in myStringCollection)
{
}This isn't supported in C++, so iteration is slightly more verbose.
Arrays and Vectors are the simplest collections in MoSync. They provide easy access to stored objects and data, and can be returned by functions and methods.
The simplest collection type is an array. This is supported in C and C++ rather than being a collection supported in MoSync specifically. It provides random access (that is, you can access any item in the collection), but it stores its contents sequentially in memory. This can cause problems if you are storing a lot of large objects, as the contiguous memory may not be available.
You can create an array by using the [] operators. Arrays can be of any object or primitive type. You must specify the size of the array when you create it and arrays cannot be easily resized, nor can items be easily inserted into them. They are small, require no additional overhead and are fast. This code will create an array of twenty chars.
char myCharArray[20];
Any item in the array can be accessed by its zero-based index number.
char thirdChar = myCharArray[2]; // Zero-based
Values can be written as well
myCharArray[2] = 'c';
When you have finished with an array, you will need to use the delete [] instruction, and not delete.
delete [] myCharArray;
Which will then delete every item in the array.
Typically in arrays (and most collections), you'll store a primitive value (char, int, byte et cetera), or an object pointer. You can store objects in the array directly, but enough contiguous memory must be available.
To iterate through an array, you access the array with the [] operator sequentially. You do need to know the size of the array before you start, but you need to know that to create it. For example
for(int i = 0; i < 20; i++)
{
printf("%c", myCharArray[i]);
}Vectors are part of the MAUtil namespace. To use them, you will need to include MAUtil/Vector.h.
#include <MAUtil/Vector.h> using namespace MAUtil;
A vector is an object wrapper around an array. All the storage will be done in the array, but the vector will let you iterate through the collection, insert items into the collection and resize the collection.
Vectors are similar to C# and Java List<> collections. MoSync List<> collections are not. See below for details of MoSync List<>.
You don't need to specify a size when you create a vector.
Vector<MyObject*> myVector;
What you do need to specify is the type of data you are going to store, by adding the type name between the angle brackets. Once you specify this, you can only add items of that type. In the above instance, these are MyObject pointers. You can only add MyObject pointers to this vector, and not MyObjects themselves or pointers of a different class.
You can add items into the vector using the .add() method.
myVector.add(new MyObject());
You can also insert items at a specific point.
myVector.insert(2, new MyObject());
Existing items will be moved down the underlying array. This is a comparitvely expensive operation, so only do it if the order is important.
Vectors maintain the order in which you add items. If you iterate through the vector, you will find objects in the same order you added or inserted them.
Individual items can be removed from vectors using the remove() method. There are three different ways you can remove items from a vector.
myVector.remove(MyObject**);
This is a pointer to a MyObject pointer. We'll look at iterators shortly, but MyObject** will probably be an iterator.
myVector.remove(1);
Removes the second item from the zero-based index.
myVector.remove(1, 3);
To completely empty a vector, you can use the clear() method.
Removes the second, third and fourth items from the vector. Remember, this does not delete any objects if your vector contains pointers. It only removes the pointers. If you want to delete the object you must still use delete.
The vector starts with a small array of the type you've specified. By default it will create an array of the type containing four items. If you add a fifth, then the a new array is created, and all the items are copied across. The new array will be twice the size of the old array. If you exceed the reserved space, then the array will be recreated and the data carried across again. The obviously adds overhead. If you know that you want 20 items, then create it with space for 20 items. You can do this in three ways.
Firstly, you can set the size in the constructor. As Vectors are normally created on the stack, then there is no opportunity to use the new instruction. Instead, in C++ you can specify it when your object is created. In your header file (.h) you can have something like this:
class MyClass
{
public:
MyClass();
virtual ~MyClass();
private:
Vector<MyObject*> myVector;
};And in the code file (.cpp) you can specify the size of the vector in the constructor.
#include "MyClass.h"
MyClass::MyClass() : myVector(20)
{
}This will initialise the vector with a size of 20. There are also two methods for sizing the vector, resize() and reserve(). Both will set the size of the underlying array, but resize() will move the current cursor to the end of the array. This means that if you resize(20) and then .add(new MyObject()) then the vector will have 21 items in it and have a capacity of 40. In general, use reserve() when you want to allocate memory. You cannot resize() or reserve() to a size smaller than you are currently using.
You can get the current usage by using the size() and capacity() methods. If you want to know how many items are in a vector, use size(). To find out how many it can take, use capacity(). To easily find if the vector is empty, use the empty() method.
if(myVector.empty())
{
// Do something.
}Vectors, like arrays, are random access. You can access any item in the vector using [].
MyObject* myObject = myVector[3];
You can also get direct access to the array using the pointer() method.
To iterate a vector, you use a vector iterator. These are pointers to each item in the vector, and are of the type Vector<Type>::iterator. For example
Vector<MyObject*>::iterator
You can get iterators to the first object, and to the point beyond the last object using the begin() and end() methods. Because the underlying array is in contiguous memory, then the iterators are sequential. The iterator is really a pointer to the type of the object (or value) stored. In our example, the iterator will be of a type MyObject**. It is a pointer to a MyObject pointer.
We can use the iterators from begin() and end() to test our iteration.
for(Vector<MyObject*>::iterator itr = myVector.begin();
itr != myVector.end();
itr++)
{
// Do something.
}This will then give us a MyObject** for each loop, called itr. You can use the object stored as normal if you dereference it.
MyObject* currentObject;
for(Vector<MyObject*>::iterator itr = myVector.begin();
itr != myVector.end();
itr++)
{
currentObject = *itr; // Dereference it.
currentObject->method();
}There is also a macro you can use a short cut for iterating vectors. Vectors are now the only collection to have such a macro.
Vector_each(Type, iterator variable, vector);
For instance, instead of the long for statement earlier, we can have the more readable
Vector_each(MyObject*, itr, myVector)
{
// Do something.
}If you change the vector during an iterative process, the iterator may become invalid, with undefined consequences. Don't add or remove items from a vector whilst you are iterating through it.
Lists are part of the MAUtil namespace. To use them, you will need to include MAUtil/List.h.
#include <MAUtil/List.h> using namespace MAUtil;
If you come from a Java or C# background, List will not behave as you expect. The MoSync equivalent of a Java/C# List is Vector<>. In MoSync Lists are doubly-linked lists.
MoSync lists allow you to create a collection of items, where each item knows which is the item before it and after it in the list. This has a big impact on how you iterate through a list.
As there isn't an underlying array, then you don't need to specify the size of your collection, nor is there an impact on performance for inserting an item in the list. Each object or value you store will be wrapped in a very light object, so there is a very small memory overhead, but its flexibility is superb.
The downside of this is that there isn't any method of random access. You have to navigate the list serially, although you can go backwards and forwards through the list.
You create the list in a similar way to the vector.
List<MyObject*> myList;
You can then add items very easily to either the beginning or the end of the list by using addFirst() and addLast() respectively.
You can only add items into the middle of the list, or remove items from the if you've got an iterator.
You can get an iterator in the same way as you can with a vector, using the begin() and end() methods. You can then access the objects and values stored using the prev() and next() methods. You can test to see if you are at the start or end of a list using the hasPrev() and hasNext() methods.
The iterators for lists are of the type List<type>::ListIterator and List<type>::ConstListIterator. Note the capitalisation of Iterator for this iterator.
List<MyObject*>::ListIterator itr = myList.begin();
MyObject* currentObject;
while(itr.hasNext())
{
currentObject = itr.next();
}Note that you don't increment the iterator like you do with vectors. The next() and prev() methods return the value stored and increment the iterator.
You can insert items into list without much of a perform hit as there is no array to reallocate. You do have to do this from an iterator though.
itr = myList.begin();
while(itr.hasNext())
{
if(itr.next() == 1)
{
// Add the value 2 after this item.
myList.insert(itr, 2);
}
}Equally, remove is done through the iterator. When you add an item using insert it is placed after current iterator. When you remove() an item, it removes the item from the current position. ListIterators are not corrupted if you alter the collection, unlike vectors. Remember, if you remove a pointer to an object, you are not destroying the object itself. You still need to call delete.
The code below shows creating and altering a List<int>.
#include <MAUtil/Moblet.h>
#include <conprint.h>
#include <MAUtil/List.h>
using namespace MAUtil;
class MyMoblet : public Moblet
{
public:
List<int> myList;
MyMoblet()
{
// Create a list with an item missing.
myList.addFirst(0);
myList.addLast(1);
myList.addLast(3);
// Show the original list
showList();
// Now add 2 into the list
List<int>::ListIterator itr = myList.begin();
itr = myList.begin();
while(itr.hasNext())
{
if(itr.next() == 1)
{
// Add the value 2 after this item
myList.insert(itr, 2);
lprintfln("Added 2");
}
}
// Now show the list again
showList();
// Now remove 1 from the list
itr = myList.begin();
while(itr.hasNext())
{
if(itr.next() == 1)
{
// Remove this item
myList.remove(itr);
lprintfln("Removed 1");
}
}
// Now show the list again
showList();
}
void keyPressEvent(int keyCode, int nativeCode)
{
this->close();
}
void showList()
{
lprintfln("I've got %d items", myList.size());
List<int>::ListIterator itr = myList.begin();
while(itr.hasNext())
{
lprintfln("Next value : %d", itr.next());
}
}
};
extern "C" int MAMain()
{
Moblet::run(new MyMoblet());
return 0;
}There are two conceptually related, but utterly separate collections in MoSync - Stack and Queue. They both are designed for serial access to collections where the order of the collection is vital.
Stacks are part of the MAUtil namespace. To use them, you will need to include MAUtil/Stack.h.
#include <MAUtil/Stack.h> using namespace MAUtil;
The Stack collection (capitalised to show that we don't mean the stack program memory, but a Stack<> collection), is a vector, but where you can only access the most recently added item. You can put as many items as you want onto the Stack, but you can only get the latest item. If you imagine a stack of books, you can see that it is only the book at the top which is accessible. This kind of collection is also called first-in-last-out or very occasionally, FILO.
You create a Stack like you would a vector
Stack<MyObject*> myStack;
Unlike vectors though, you cannot specify a size in advance. It uses the vector's default initial size of 4, and will resize itself when it needs to.
When you want to add an item on a Stack, you are said to push it onto the Stack. The method for adding to a stack is then
myStack.push(new MyObject());
When you want to remove an item from the stack, you are said to pop it off the Stack.
myStack.pop();
Remember, if you have a collection of object pointers, popping an item off the stack will not destroy the object. You have to call delete yourself.
To get access to the next item on the Stack using the method peek().
MyObject* nextObject = myStack.peek();
You can test the size of the Stack using size() although you cannot test its capacity. You can also see if it has no items in it using empty(). You can remove all the items from the stack at once using clear().
There are no iterators in the stack. If you want to find an item, you have to keep popping items off the top until you get the one you want. If you want to remove an item from the middle, you need to copy the data to another Stack.
As you'll see from the example below, iterating Stacks is laborious. They are best suited to times when the order is important. They are frequently used to allow users to retrace their steps. For instance, you can keep track of the order the user navigated the screens in your application. When the users wants to go back one screen, then you can pop the last value off your stack.
#include <MAUtil/Moblet.h>
#include <conprint.h>
#include <MAUtil/Stack.h>
using namespace MAUtil;
class MyMoblet : public Moblet
{
public:
Stack<int> myStack;
MyMoblet()
{
// Create a list with an item missing.
myStack.push(3);
myStack.push(1);
myStack.push(0);
// Show the original stack
showStack();
// Now add 2 into the stack
// We need another stack to copy removed items to.
Stack<int> tempStack;
while(myStack.peek() != 1)
{
// Copy the top of the stack to another stack. Remember that the new stack will
// have everything in reverse order
tempStack.push(myStack.peek());
myStack.pop();
}
// Add the value 2
myStack.push(2);
// Now copy everything back again
while(tempStack.size() > 0)
{
myStack.push(tempStack.peek());
tempStack.pop();
}
// Now show the Stack again
showStack();
// Now remove 1 from the stack
while(myStack.peek() != 1)
{
// Copy the top of the stack to another stack. Remember that the new stack will
// have everything in reverse order
tempStack.push(myStack.peek());
myStack.pop();
}
// The item at the top is 1. Remove it
myStack.pop();
// Now copy everything back again
while(tempStack.size() > 0)
{
myStack.push(tempStack.peek());
tempStack.pop();
}
// Now show the Stack again.
showStack();
}
void keyPressEvent(int keyCode, int nativeCode)
{
this->close();
}
void showStack()
{
lprintfln("I've got %d items", myStack.size());
// We need to copy the Stack to another stack whilst we go through it.
Stack<int> tempStack;
while(myStack.size() > 0)
{
lprintfln("Next value : %d", myStack.peek());
tempStack.push(myStack.peek());
myStack.pop();
}
// OK, we've shown them all, now we need to put myStack back together.
while(tempStack.size() > 0)
{
myStack.push(tempStack.peek());
tempStack.pop();
}
}
};
extern "C" int MAMain()
{
Moblet::run(new MyMoblet());
return 0;
}Queues are part of the MAP namespace. To use them, you will need to include MAP/Queue.h, and ensure that you've got MAP.lib included as a library in your project settings. Alternatively, copy the file Queue.h out of the includes directory and include it directly in your project, although if you do this, you will need to replace newobject() with new and deleteobject() with delete, or alternatively, implement the MemoryMgr class as well.
#include <MAP/Queue.h> using namespace MAP;
Queues are logically very similar to Stacks, but the implementation is quite different. Differences in implementation will be highlighted as the collection is described.
Logically, a queue is the same as a Stack, with the exception that the first item is the only one available, not the last item. This is sometimes called first-in-first-out or very occasionally FIFO.
To create a queue, it is almost the same as stack
Queue<MyObject> myQueue;
The important difference to note is the data type you provide it. MoSync queues only contain pointers. You provide it with the type of data pointer you want. The above code will create a Queue of MyObject pointers, and not MyObject, despite what it looks like. If you had the code
Queue<MyObject*> myQueue;
You would get a queue of MyObject**. Equally then
Queue<int> myQueue;
Will create a queue of int* and not int.
When you add an item to a queue, this is called enqueueing, and the method is enqueue(). To remove a method, you dequeue() it. Whereas with the Stack, when you peek() at a value it leaves it on the Stack and have to pop() it off, dequeue() will remove it from the collection. It is the responsibility of the code calling dequeue() to delete the object after use if necessary to prevent memory leaks.
myQueue.enqueue(new MyObject()); MyObject* currentObject = myQueue.dequeue();
Whilst Queues were not designed for random access, there are methods in the MoSync implementation for accessing values at will. There aren't any iterators with queues however.
You can read values using peekAt() method, providing the method with the index number of the value you want, or peek() which will return the next item, although these will leave the item in the queue.
You can also find the location in the queue of a specific object. The find() method will return an items index number.
Like vectors, you can set capacity of the queue, and it has an array internally for storage. Unlike a vector, you cannot resize a queue, so when it is full, then that's it. Your item will not be added, no return value will be given by enqueue() and no error will be raised, so it is important to check the amount of space left in the queue using getCapacity() (not capacity() like in vector) and getCount() (not size()).
You can remove all the items in the queue (but not delete the objects) using clear().
Queues are useful for marshalling activities. For instance, if you've got a long list of items which need to be downloaded, rather than creating an instance of Downloader for each of them, you can have one Downloader and a queue. You can create a class which gets the next URL from the queue and downloads the data. Once it is complete, it can check the queue again for the next request.
There are some collections in MoSync which are a little more powerful, allowing you to access their contents through you own index. The basis for these is the Dictionary. Whilst you never create a Dictionary on its own, only classes derived from Dictionary they have a common syntax.
Dictionaries are collections of Pairs (you may know these also as Key/Value pairs). Each pair has a key with which you can reference your value. Often, you don't need to know about the pairs in the collection, but if you iterate through a Dictionary, then your iterator will be a pair.
To create a Dictionary, you need to create one of the derived classes, Map, HashMap or Set. They all follow the same pattern
Map<Key Type, Value Type> myMap; HashMap<Key Type, Value Type> myHashMap; Set<Key Type, Value Type> mySet;
For example, you can create a collection of the names of your friends and their phone numbers. Both their names and numbers will be stored as strings. The names will be the key and the phone number the value.
Map<String, String> myFriends;
You can then add items to the collection.
myFriends.insert("Rupert Bear", "Norwood 1212");The insert() method actually returns another Pair, this time with a Dictionary::Iterator and a boolean value. The iterator points to the value you've just added, and the boolean contains true if the insert was successful.
Note, unlike Vectors, there is no add method, because Dictionaries don't keep the same concepts of ordering.
Dictionary classes are all random-access, you can have access to any item at any time. We can find Rupert's phone number at any time. The find method returns a Pair<String, String>. The Pair has two properties for the key and value. Rather than being called key and value, they are called first and second. The key is in first, and the value is in second.
String& rupertsNumber = myFriends.find("Rupert Bear")->second;Map and HashMap also provide support for [] operators. This doesn't return the Pair but just the value.
String& rupertsNumber = myFriends["Rupert Bear"];
myFriends.erase("Rupert Bear");is valid. Note that the method is erase() and not remove() as it is on vectors and lists.
So, Dictionaries are power collections we can use very flexibly to store data. There are some differences between the three collections.
The Map is the simplest of the Dictionary classes. It is a simple mapping between the key and the value. For a given key, it will return the location of the value. It achieves this by comparing the key provided with its list of keys. It checks each one, and when it finds a match it will return the value. For this reason, Map is most suitable when the collection is small. With a very large collection, any search operation may have to compare every key in its collection until it finds the correct value. The elements in Map are sorted from lower to higher key values.
The HashMap converts the key you provide using a hash function. It then assigns the value into a location in memory depending on the value of the hash. This is important, as it can calculate this hash again when you want to retrieve the value. This means that it doesn't have to compare all of the keys looking for the value you want. It does mean that it does a little more work than a Map, but it is much more suitable for larger collections, e.g. collections which are likely to have more than five entries.
The Set is like a map, except that values are unique as well as keys. As the values are unique, then the storage is in the order of the values, and not the keys. This means that it is unlikely that when you iterate through a collection, that the values are in the same order as they were entered in. Sets are essential when having unique keys and unique values is essential. Set does not support the [] operator, so you have to use the .find() method to retrieve values. The keys in a Set are not hashed.
Dictionary Iterators cannot be unassigned, which makes iterating through Dictionaries quite verbose. There also isn't a handy macro like there is for vector. You have to either already have an Iterator or create one in the for statement.
for(Map<String, String>::Iterator itr = myFriends.begin();
itr != myFriends.end();
itr++)
{
// Do something.
}To create an iterator, you need to type it exactly as the Dictionary is typed, so if you've got
Map<String, String> myFriends;
Then the Iterator has a type of
Map<String, String>::Iterator
As described above, Iterators provide access to Pairs. You need to use the first and second properties on them for the key and value respectively.
for(Map<String, String>::Iterator itr = myFriends.begin();
itr != myFriends.end();
itr++)
{
lprintfln("Friend: %s Number: %s", itr->first.c_str(), itr->second.c_str());
}Below is code to create an manipulate a HashMap<String, String>. You will see how the order changes.
#include <MAUtil/Moblet.h>
#include <conprint.h>
#include <MAUtil/HashMap.h>
#include <MAUtil/String.h>
using namespace MAUtil;
class MyMoblet : public Moblet
{
public:
HashMap<String, String> myFriends;
MyMoblet()
{
// Add some friends
myFriends.insert("Rupert Bear", "Norwood 1212");
myFriends.insert("Noddy", "Playtown 2020");
myFriends.insert("Windy Miller", "Trumpton 2323");
// Show the original dictionary
showDictionary();
// Find a friend
String friendsNumber;
friendsNumber = myFriends.find("Rupert Bear")->second;
lprintfln("Rupert's number is %s", friendsNumber.c_str());
// Erase a friend
myFriends.erase("Noddy");
// Show the new dictionary
showDictionary();
// Find a friend by iterator
HashMap<String, String>::Iterator myFriend = myFriends.begin();
lprintfln("My first friend is %s whose number is %s",
myFriend->first.c_str(), myFriend->second.c_str());
}
void keyPressEvent(int keyCode, int nativeCode)
{
this->close();
}
void showDictionary()
{
lprintfln("I've got %d items", myFriends.size());
for(HashMap<String, String>::Iterator itr = myFriends.begin();
itr != myFriends.end();
itr++)
{
lprintfln("Friend: %s Number: %s", itr->first.c_str(),
itr->second.c_str());
}
}
};
/*
* Main program starts here.
*/
extern "C" int MAMain()
{
Moblet::run(new MyMoblet());
return 0;
}; The MAUtil classes Set, Map and HashMap provide generic containers similar to std::set, map and unordered_map in the STL or Java's Set, Map and Hashtable. They provide many of the same familiar operations. Here we describe examples for Set, Map, and HashMap:
/**
* @file Set.cpp
* @author Naveed Asif
*
* Description:
*
* In this tutorial we will learn the use of Set
* container. Initially a list of numbers is
* created and then the difference between erase()
* clear() is shown.
*/
#include <MAUtil/Moblet.h>
#include <conprint.h>
#include <MAUtil/Set.h>
using namespace MAUtil;
class MyMoblet : public Moblet
{
public:
// Set is declared.
Set<int> myNumbers;
MyMoblet()
{
// Add some numbers.
myNumbers.insert(786);
myNumbers.insert(111);
myNumbers.insert(222);
myNumbers.insert(333);
// Shows the original dictionary in the console.
// Note: The dictionary values will be displayed in
// ascending order.
showDictionary();
// Locates and Erases any specific Number.
myNumbers.erase(333);
// Look at the dictionary and notice that 333 is erased.
showDictionary();
// This will delete all the members of container.
myNumbers.clear();
// Will show that you got 0 members.
showDictionary();
}
/**
* Called when a key is pressed on the keypad.
*/
void keyPressEvent(int keyCode, int nativeCode)
{
if (MAK_BACK == keyCode || MAK_0 == keyCode)
{
close();
}
}
/**
* showDictionary function is used to display all the
* members in myNumbers container.
*/
void showDictionary()
{
printf("I've got %d Numbers", myNumbers.size());
if (myNumbers.size() > 0)
{
printf("Numbers are:");
}
for(Set<int>::Iterator iter = myNumbers.begin();
iter != myNumbers.end();
iter++)
{
printf("%d", *iter);
}
}
};
/*
* Main function where the program starts
*/
extern "C" int MAMain()
{
Moblet::run(new MyMoblet());
return 0;
}
/**
* @file Map.cpp
* @author Naveed Asif
*
* Description:
*
* In this tutorial we will learn the use of Map
* data structure. Initially a list of friends is
* created and then the Iterator's methods begin(),
* erase(), and find() are used.
*/
#include <MAUtil/Moblet.h>
#include <conprint.h>
#include <MAUtil/Map.h>
#include <MAUtil/String.h>
using namespace MAUtil;
class MyFriend
{
private:
String myName;
String myAddress;
public:
MyFriend(String name, String address)
{
myName = name;
myAddress = address;
}
void show()
{
printf("%s, %s", myName.c_str(), myAddress.c_str());
}
};
class MyMoblet : public Moblet
{
public:
// Map is declared.
Map<String, MyFriend*> myFriends;
MyMoblet()
{
// Add some friends.
addFriend("Rupert Bear", "Norwood, England");
addFriend("Ghuman", "Stockholm, Sweden");
addFriend("Windy Miller", "Trumpton 2323");
// Shows the original dictionary in the console.
// Note: The dictionary values will be displayed in
// ascending order.
showDictionary();
// Finds a friend using the find method and displays it
// in the console.
printf("--------------");
printf("Found friend:");
MyFriend* myFriend = myFriends.find("Rupert Bear")->second;
myFriend->show();
// Locates and erases a friend.
myFriends.erase("Ghuman");
// Look at the dictionary and notice that "Ghuman" is erased.
showDictionary();
// Finds the first entered friend.
printf("--------------");
printf("My first friend is:");
Map<String, MyFriend*>::Iterator iter = myFriends.begin();
iter->second->show();
}
/**
* Add a new friend to the dictionary.
*/
void addFriend(String name, String address)
{
myFriends.insert(name, new MyFriend(name, address));
}
/**
* Called when a key is pressed on the keypad.
*/
void keyPressEvent(int keyCode, int nativeCode)
{
if (MAK_BACK == keyCode || MAK_0 == keyCode)
{
close();
}
}
/**
* showDictionary function is used to display all the
* pair values in myFriends Map function
*/
void showDictionary()
{
printf("--------------");
printf("I've got %d friends:", myFriends.size());
for(Map<String, MyFriend*>::Iterator iter = myFriends.begin();
iter != myFriends.end();
iter++)
{
iter->second->show();
}
}
};
/*
* Main function where the program starts
*/
extern "C" int MAMain()
{
Moblet::run(new MyMoblet());
return 0;
}
The HashMap works same like Map does except that Map always displays results in ascending order. You can simply change Map to HashMap in above example and it will work.
The containers have a number of things in common. They have default constructors, copy constructors and destructors. Elements are copied by value, so care should be taken when dealing with pointers. Large elements should be passed by pointer or reference-counted. There are Iterators and ConstIterators. The functions find(), begin() and end() can return either type. The erase() function works either with a Key or with an Iterator, but not with a ConstIterator. We can also use size() and clear() functions.
The constructor has an optional argument for specifying the comparison function. The default comparison function uses the Key's operator<, so if your Key doesn't have it and you can't readily add it, this argument is useful.
Set has only one datum per element, whereas Map and HashMap have two data per element: a Key and a Value. Both must be specified when inserting a new element. Both are also accessible from Iterators. Map and HashMap also have the operator[].
HashMap's constructor has an optional argument for specifying the hash function. The default value is THashFunction< Key >. This template function has no default implementation. MoSync ships with implementations for MAUtil::String and int. If you use another key type, you'll need to implement a hash function for it.
Set and Map are sorted. The comparison function decides the sorting order.
HashMap is unsorted. The comparison function is only used in case of hash collision. While HashMap Iterators present the elements in a certain order, that order may change whenever an element is added or removed and should not be relied upon.
All the classes have reference documentation. Also, the source code is available in $MOSYNCDIR/include/MAUtil/ in your MoSync package.
The MAUtil::Vector class provides a generic, dynamically resizeable container similar to std::vector in the STL, Java's Vector or a .NET List. It provides many of the same familiar operations.
A Vector can be used as a generic collection, allowing you to grow the set whilst maintain the order in which items were added. Vectors add items as their value type. When you add or insert an item on the list, it adds the value or object to that list. If you have a Vector of a complex object type, it will add that object to the list, and not a pointer to it, unless you explicitly request it.
For example
Vector<UserDetail> mUserDetails;
Will create a Vector of UserDetail objects, and not a Vector of UserDetail*. Not all collections in MoSync behave in this manner. To create a Vector of pointers to UserDetails objects, use
Vector<UserDetail*> mUserDetails;
Vectors are generic collections, so you define the type of object you want to store when you define the Vector. The snippet below demonstrate creating Vector of int on the stack.
Vector<int> mInts;
Vectors store their items in contiguous memory. Internally, there is an array which is used for storage with the Vector class maintaining the order. Collections, including Vector, can cause you to run into memory allocation (malloc) errors if there isn't enough free contiguous memory left. Broadly speaking, if you are storing a complex object type like the UserDetail object in the example above, you are always better off storing pointers than the values. If you are using primitive types (int, byte), then store the values.
There are two ways you can add new items into a Vector, the add() and the insert(). The method add() appends the new item at the end of the list.
mInts.add(5);
You can also insert an item into the Vector at a requested position using the method insert().
mInts.insert(2, 100);
Where the first parameter is the index number you wish to insert the number (on a zero-based index) and the second is the value you wish to store. All subsequent entries are moved along. This has the potential to be very slow on large collections, so try to sort items before you enter them into the Vector.
As the Vector is based on an array, you can still access the items using the [] operators. You can use the index number to change the value of an item in an array. This won't cause objects to be deleted, so if you are storing pointers to objects, then you will need to delete the item to prevent a memory leak.
UserDetails* mNewUser; Vector<UserDetails*> mUserDetails; ... // Overwrite the first entry. UserDetails* temp = mUserDetails[0]; mUserDetails[0] = mNewUser; delete temp; // Delete the old entry
You can remove an item from a Vector using the remove() method. There are two ways this can be called. Firstly, you can request for a specific index number to be removed, but you can also remove with an iterator. There is more about iterators below.
mUserDetails.remove(0);
Again, removing items from the Vector won't delete them from memory if they are pointers to objects. You need to delete them explicitly or you will have a memory leak.
UserDetails* temp = mUserDetails[0]; mUserDetails.remove(0); delete temp;
Removing items from the end of the list is very quick, but if you remove from the middle (or the start) of the list, then the other items need to be reordered, which can be slow.
You can work you're way through all the items in a Vector in two different ways. As the Vector is based on an array, you can iterate through the items by index number
Vector<int> numbers;
....
// iterate through the vector using the
// [] operator, printing each element.
for(int i = 0; i < numbers.size(); i++) {
printf("numbers[i]: %d", numbers[i]);
}A second method is to use the iterator. Iterators are pointers to the items in the Vector, but are of a type
Vector<T>::iterator
Note that with Vectors the iterator has a low-case 'i' whilst in other collections (Set for example) the iterator has an upper-case 'I'.
Vector<int> numbers;
for(Vector<int>::iterator i = numbers.begin(); i < numbers.end(); i++)
{
printf("%d", *i);
}You can use the iterator to step through items in the Vector using the iterators returned by the methods begin() and end(). Also note that the iterator is a pointer to the value, so you will have to dereference it with an *.
Finally, there is a macro to make iteration more readable. You can use the macro Vector_each to iterate the Vector.
Vector_each(int, i, numbers)
{
// The iterator needs to be dereferenced.
printf("numbers[i]: %d", *i);
}Vector_each takes three arguments; the type stored by the Vector, the variable name you want to refer to the iterator and finally the Vector itself.
There's an important distinction between the size and capacity of a Vector. Vectors grow dynamically to accomodate additional elements that are added to them. When an element is added, exceeding the current capacity, the capacity is doubled. However, the size only increases by one. This snippet demonstrates the behaviour:
for(int i = 0; i < 10; i++)
{
numbers.add(i);
printf("Size: %d Capacity: %d", numbers.size(), numbers.capacity());
}
The output looks like this:
Size: 1 Capacity: 4 Size: 2 Capacity: 4 Size: 3 Capacity: 4 Size: 4 Capacity: 8 Size: 5 Capacity: 8 Size: 6 Capacity: 8 Size: 7 Capacity: 8 Size: 8 Capacity: 16 Size: 9 Capacity: 16 Size: 10 Capacity: 16
In this case, the memory used to store the Vector elements is reallocated twice, each time requiring all the elements to be copied to the newly allocated memory location.
It is possible to reserve() a certain capacity, which is useful in cases when the number of elements to add is known beforehand (but not at compile time) in order to avoid superfluous reallocations:
numbers.reserve(11);
for(int i = 0; i < 10; i++)
{
numbers.add(i);
printf("Size: %d Capacity: %d", numbers.size(), numbers.capacity());
}
The output looks like this:
Size: 1 Capacity: 11 Size: 2 Capacity: 11 Size: 3 Capacity: 11 Size: 4 Capacity: 11 Size: 5 Capacity: 11 Size: 6 Capacity: 11 Size: 7 Capacity: 11 Size: 8 Capacity: 11 Size: 9 Capacity: 11 Size: 10 Capacity: 11
Note
Most functions that somehow manipulate the size of the vector do not affect the capacity if the new size is smaller than the previous. Do not assume that resize(0) will free up memory if the Vector previously contained thousands of elements.
The elements of a Vector are stored linearly in an array. This means that they can be accessed using pointers. There is a function pointer() which returns a T* pointer to the internal storage array. There are also two types of typedefed iterators, one regular and one const. These map directly to T* pointers as well.
This tutorial will show you the basics of HTTP connections in MoSync. You will see how easy it is to write applications which can access HTTP-based information. You will also see how easy it is to stream information over HTTP. This example is written from a Moblet template.
#include <mautil/connection.h>
#include <mastdlib.h>
#include <conprint.h>
#define CONNECTION_BUFFER_SIZE 1024
connection.h is included to provide the basic connection functionallity.
mastlib.h is included to add the atoi function which converts the contents of an array to an int.
conprint.h adds the printf function which writes text to the screen as a simple console.
CONNECTION_BUFFER_SIZE defines the size of the buffer in which data is collected.
class MyMoblet : public MAUtil::Moblet, private MAUtil::HttpConnectionListener
To provide the functionallity we inherit function declarations from the HttpConnectionListener class.
void httpFinished(MAUtil::HttpConnection *conn, int result);
void connRecvFinished(MAUtil::Connection *conn, int result);
void connReadFinished(MAUtil::Connection *conn, int result);
The httpFinished function is a callback which is called whenever a http connection is initiated and we can recieve a response. When we use the recv function for the http connection connRecvFinished is called everytime a new chunk of data is recieved. If we use the read function instead, the connReadFinished function will be called when the read is done. More about these functions later in this tutorial.
char mBuffer[CONNECTION_BUFFER_SIZE];
MAUtil::HttpConnection mHttp;
mHttp is a MAUtil::HttpConnection object which represents the actual connection. Each one of these may only handle one connection at the time so to enable multiple connections we need to define multiple HttpConnection objects. Always make sure that a connection is closed before connecting to it again.
MyMoblet::MyMoblet() : mHttp(this)
The constructor sets itself as the listener for the HttpConnection object so that the callbacks declared in MyMoblet will be used.
InitConsole();
gConsoleLogging = 1;
In our entry point, MAMain we initialize the console and enable logging. This means that everything that everything that we send to the console is also logged in a log file. If you handle large amount of data and would want to output information to verify behaviours of your application this will help you. This file is located in the Output folder of your project and is called log.txt.
Too initiate an http connection we call the create function of the HttpConnection object. All you need to provide is the url and if you need to use GET or POST. In this example we send a POST request to a server.
int res = mHttp.create(url, HTTP_POST);
if(res < 0) {
printf("unable to connect - %i\n", res);
} else {
mHttp.finish();
mIsConnected = true;
}
If the create function returns a value below zero this means that it have failed for some reason. Please check the API references for all the possible return values. It's only possible to have one active connection on each HttpConnection object. Due to this we must make sure that we don't try to reconnect an active connection. If the create call was successful we can now set request headers. Since we don't need it we can call the finish function directly.
When we have a connection with the server the callback function httpFinished will be called.
MAUtil::String contentLengthStr;
int responseBytes = mHttp.getResponseHeader("content-length", &contentLengthStr);
int contentLength = 0;
if(responseBytes == CONNERR_NOHEADER)
printf("no content-length response header\n");
else {
printf("content-length : %s\n", contentLengthStr.c_str());
contentLength = atoi(contentLengthStr.c_str());
}
First we check for the "content-length" response header, if it's not found we will recieve an CONNERR_NOHEADER response. If it's found we recieves the actual content length as an char array of numbers. It's then converted it to an int using the atoi function.
if(contentLength >= CONNECTION_BUFFER_SIZE || contentLength == 0) {
printf("Receive in chunks..\n");
mHttp.recv(mBuffer, CONNECTION_BUFFER_SIZE);
} else {
mBuffer[contentLength] = 0;
mHttp.read(mBuffer, contentLength);
}
If we don't have any content length or it's larger then our recieving buffer we can't just read all the data. We have to read multiple times until we reaches the end. This is done by calling the recv function of the HttpConnection object.
If we know the content length and the recieving data fits inside the buffer we can read it all directly. This is done by using the read function in HttpConnection.
The difference between the two is that recv specifies the total amount of bytes which it can recieve while read specifies the number of bytes it shall read. Each of these methods has its own callback functions. Depending on the function you use connRecvFinished or connReadFinished callback functions will be called.
if(result >= 0)
printf("connReadFinished %i\n", result);
else
printf("connection error %i\n", result);
mHttp.close();
The connReadFinished callback function first check if the result is not negative. A negative result means an error might have happened. Check the return value against the API documentation. Positive results means that data was received. The connection shall be closed manually now since no more data will be received on this connection.
if(result >= 0) {
printf("connRecvFinished %i\n", result);
mHttp.recv(mBuffer, CONNECTION_BUFFER_SIZE);
return;
}
else if(result == CONNERR_CLOSED) {
printf("Receive finished!\n");
} else {
printf("connection error %i\n", result);
}
mHttp.close();
The connRecvFinished callback function works a little bit different. If the result is positive we have received that amount of bytes. If so we can't close the connection since more data will be received. If it's negative we must check if it's CONNERR_CLOSED. CONNERR_CLOSED doesn't need to be an error. Usually it means that the sending server has sent its data and closed the connection to verify the receiver about it. When a negative value is returned the connection shall be closed.
In this tutorial we have had a look at how easy it is to access HTTP information and also stream such information to your application. With this basic knowledge you will easily build your applications which will use web based information.
For further information also read the sockets tutorial and the tutorial concerning the downloader.
#include <MAUtil/Moblet.h>
#include <mautil/connection.h>
#include <mastdlib.h>
#include <conprint.h>
#define CONNECTION_BUFFER_SIZE 1024
class MyMoblet : public MAUtil::Moblet, private MAUtil::HttpConnectionListener
{
public:
MyMoblet();
void httpFinished(MAUtil::HttpConnection *conn, int result);
void connRecvFinished(MAUtil::Connection *conn, int result);
void connReadFinished(MAUtil::Connection *conn, int result);
void keyPressEvent(int keyCode);
private:
void initiateConnection(const char* url);
char mBuffer[CONNECTION_BUFFER_SIZE];
MAUtil::HttpConnection mHttp;
bool mIsConnected;
};
MyMoblet::MyMoblet() : mHttp(this)
, mIsConnected(false)
{
printf("http connection tutorial.\n");
printf("press softkeys to send http requests.\n");
printf("press 0 to exit\n");
}
// connect to the given url if not other connection is active
void MyMoblet::initiateConnection(const char* url) {
if(mIsConnected) {
printf("already connected\n..");
return;
}
printf("\nconnecting to %s", url);
int res = mHttp.create(url, HTTP_POST);
if(res < 0) {
printf("unable to connect - %i\n", res);
} else {
mHttp.finish();
mIsConnected = true;
}
}
void MyMoblet::httpFinished(MAUtil::HttpConnection* http, int result) {
printf("HTTP %i\n", result);
MAUtil::String contentLengthStr;
int responseBytes = mHttp.getResponseHeader("content-length", &contentLengthStr);
int contentLength = 0;
if(responseBytes == CONNERR_NOHEADER)
printf("no content-length response header\n");
else {
printf("content-length : %s\n", contentLengthStr.c_str());
contentLength = atoi(contentLengthStr.c_str());
}
if(contentLength >= CONNECTION_BUFFER_SIZE || contentLength == 0) {
printf("Receive in chunks..\n");
mHttp.recv(mBuffer, CONNECTION_BUFFER_SIZE);
} else {
mBuffer[contentLength] = 0;
mHttp.read(mBuffer, contentLength);
}
}
void MyMoblet::connReadFinished(MAUtil::Connection* conn, int result) {
if(result >= 0)
printf("connReadFinished %i\n", result);
else
printf("connection error %i\n", result);
mHttp.close();
mIsConnected = false;
}
void MyMoblet::connRecvFinished(MAUtil::Connection * conn, int result){
if(result >= 0) {
printf("connRecvFinished %i\n", result);
mHttp.recv(mBuffer, CONNECTION_BUFFER_SIZE);
return;
}
else if(result == CONNERR_CLOSED) {
printf("Receive finished!\n");
} else {
printf("connection error %i\n", result);
}
mHttp.close();
mIsConnected = false;
}
// Press 0 to exit. Soft left and soft right will initiate new connections
void MyMoblet::keyPressEvent(int keyCode) {
switch(keyCode) {
case MAK_0:
maExit(0);
break;
case MAK_SOFTLEFT:
initiateConnection("http://www.example.com/");
break;
case MAK_SOFTRIGHT:
initiateConnection("http://www.mosync.com/");
break;
}
}
extern "C" int MAMain() {
InitConsole();
gConsoleLogging = 1;
MAUtil::Moblet::run(new MyMoblet());
} Here we take a look at how to use the MAUtil's Connection API to communicate over sockets using TCP. We will illustrate how to use them by making a simple FTP client.
An FTP client begins by setting up a socket to the FTP server, authorize itself and then continues by sending instructions. All communication is done in plain text which makes the protocol both easy to understand and use. For further information about the FTP protocol see cr.yp.to/ftp.html.
We will implement all functionality as functions in a class inherited from Moblet, so we begin by creating a project from a Moblet template, adding a few #include directives, and declaring inheritance from the MAUtil::ConnectionListener class:
#include <MAUtil/Moblet.h>
#include <MAUtil/Connection.h>
#include <MAUtil/Util.h>
#include <conprint.h>
#include <mastdlib.h>
using namespace MAUtil;
class MyMoblet : public Moblet, ConnectionListener
{
Then add the member variables of the class, a Connection instance, and a temporary string buffer. The string buffer will be used to store the incoming responses from the server:
private: Connection mConnection; char lineBuffer[1024];
We continue by defining the Constructor. In the initialization list we initialize the connection by passing a pointer to this (the MAUtil::ConnectionListener). In the constructor we connect the connection to a socket, i.e. the FTP server we're going to communicate with. FTP communication defaults to port 21, but in some cases FTP servers may use other ports. We verify that the connection has been successfully initiated by checking the return value from connect.
public:
MyMoblet() : mConnection(this)
{
int res = mConnection.connect("socket://ftp.sunet.se:21");
if(res < 0)
{
maPanic(res, "mConnection.connect failed");
}
}
Now we will add some helper functions to receive, parse, and send the FTP response and requests. First we add a function that receives incoming data to the temporary string buffer:
void getNextFtpResponse()
{
mConnection.recv(lineBuffer, 1024);
}
When the response has been received the connRecvFinished function derived from the ConnectionListener, which we will implement later, is invoked. Next we implement a function to put an FTP request. It adds a line breaking sequence that conforms to the FTP standard and writes the request to the connection. The connWriteFinished function will be invoked when the request has been written.
void putFtpRequest(const char *req)
{
char temp[1024];
int len = sprintf(temp, "%s\015\012", req);
mConnection.write(temp, len);
}
Finally, we add a function that parses the response code of a response line. (The link to the FTP protocol description at the top of this guide describes the format of a response.)
We first trim the spaces in the beginning and then parse the following number:
int parseFtpResponseCode(const char *lineBuffer)
{
int i=0;
char temp[16];
while(lineBuffer[i]==' ') { i++; }
// trim spaces in the beginning
while(isdigit(lineBuffer[i])) temp[i++] = lineBuffer[i];
temp[i] = 0;
return atoi(temp);
}
Now that the helper functions are ready we can implement the actual communication. First we implement the connectFinished function derieved from the ConnectionListener which checks if everything went well and if that is the case, receives the next FTP server response.
void connectFinished(Connection* conn, int result)
{
if(result < 0)
{
printf("mConnection.connectFinished failed");
return;
}
getNextFtpResponse();
}
The connWriteFinished will look exactly the same. Whenever we've sent an FTP request we want to receive a new FTP response.
void connWriteFinished(Connection* conn, int result)
{
if(result < 0)
{
printf("mConnection.write failed");
return;
}
getNextFtpResponse();
}
When we've received a response from the server we can decide on what to do next. The final function connRecvFinished derived from the ConnectionListener will be called when a response has been received. First we split the lines of the response into a list of strings, one for each line. The response code will be the same for each line, so we parse the response code of the first line. By analyzing the response code, the client program can determine what state the FTP connection is in and choose what to do next.
We will only implement a few steps in the initial handshaking procedure. After the PASV command has been sent, a response with a new IP address and port is recieved. This IP address should be used to set up a data connection. All data traffic will be handled over this connection. Even the result from requests like LIST, which list all files in a directory. Implementing this functionality is left as an exercise for the reader.
void connRecvFinished(Connection* conn, int result)
{
if(result < 0)
{
printf("mConnection.recv failed");
return;
}
// We may have recieved several lines in one response,
// but all of them will begin with the same response code.
Vector<String> responses;
stringSplit(lineBuffer, "\015\012", responses);
// the last one will always be an empty string
responses.resize(responses.size()-1);
for(int i = 0; i < responses.size(); i++) printf("%s", responses[i].c_str());
int code = parseFtpResponseCode(responses[0].c_str());
switch(code)
{
// 220 welcome - we respond with a user (anonymous in this case)
case 220: putFtpRequest("USER anonymous"); break;
// 331 identify yourself in a password - we can send any password as we're anonymous.
case 331: putFtpRequest("PASS dummy"); break;
// 230 thanks - we enter passive mode
case 230: putFtpRequest("PASV"); break;
}
}
};
If you've done everything right, the result will look like this: 
Many people are developing Bluetooth applications in MoSync. Some of the most interesting applications involve creating a new Bluetooth service so that the user’s phone can receive incoming messages on Bluetooth and act on them. In this tutorial we take a look at using the MAUtil::Server class to provide Bluetooth services.
In the MoSync MAUtil library there is a class called Server. It is a base class that you can adapt to accept network connections over Bluetooth and TCP. You create a new Bluetooth service by creating a new Server instance and inheriting from ServerListener. Your class becomes a wrapper around Server and can process both incoming and outgoing messages.
The ServerListener interface allows your service class to respond to events raised by your Server instance. There are two methods that you need to implement: serverAccepted and serverAcceptFailed. These methods inform your application when a new connection has been made to your server, or when an attempt to connect has failed.
When you receive a new connection, the serverAccepted method is called, and it is passed a pointer to a new Connection object. This is the same class as you would use for outgoing connections so all of the same methods for reading and writing data are available. The only difference is that you’ve got to code responses to incoming data.
A very simple Server implementation would look like this:
#include <MAUtil/Moblet.h>
#include <MAUtil/Server.h>
#include <conprint.h>
using namespace MAUtil;
class MyServer : public ServerListener
{
private:
Server mServer;
MAHandle mConn;
public:
MyServer() : mServer(this), mConn(NULL)
{
}
~MyServer()
{
//Close the server before we exit
if(mServer.isOpen())
mServer.close();
}
void MyServer::connect()
{
if(mServer.isOpen())
lprintfln("Already open");
else
{
//Start accepting incoming TCP requests on port 81
mConn = mServer.start("socket://8103");
if(mConn < 0)
lprintfln("Service failed - is the port blocked?");
else
lprintfln("Service started");
}
}
//ServerListener
void MyServer::serverAcceptFailed(Server* server, int result)
{
lprintfln("Connection failed");
}
void MyServer::serverAccepted(Server* server, Connection* conn)
{
lprintfln("Connection accepted");
}
};
class MyMoblet : public Moblet
{
public:
MyMoblet()
{
MyServer myServer;
myServer.connect();
}
};
extern "C" int MAMain()
{
Moblet::run(new MyMoblet());
return 0;
};
As you can see from the code, the class MyServer creates a new server and binds itself to TCP port 81. Any requests to the phone on that port will now be answered by MyServer.
Binding to Bluetooth addresses is a little more complex. Instead of simply binding to a port you need to bind to the Bluetooth address of the device, and provide a service UUID.
Each Bluetooth service has its own UUID (universally unique identifier). These are common across platforms, just as TCP ports are. If you create a brand-new service, you should generate a new UUID for it. If you are implementing an existing service (such as OBEX Push), then you should use the existing UUID. Common UUIDs have been defined in the file MAUtil/mauuid.h.
When Bluetooth clients are searching for your service, they will need to know what the UUID is. If you are writing the client software as well, you’ll need to use the UUID to discover the service. See our tutorial on Discovering Devices and Services with Bluetooth for more information.
In the MoSync SDK, Bluetooth service UUIDs are defined as being a struct of an int[4]. Bluetooth UUIDs are 32 bytes long, but large parts of the UUID are common to all Bluetooth UUIDs. If you want to create your own UUID, you would need to check that it isn’t being used by any other Bluetooth service, and also ensure that its unique segment (the first int in the struct) ANDs with 0x1000 (4096). The following is a line from mauuid.h, defining the UUID for the serial port service.
DEFINE_BTMAUUID(SerialPort_Service_MAUUID, 0x1101);
Its unique segment is 0x1101. The first "1" signals that it is a specific service, and not a service collection (compare with DEFINE_BTMAUUID(RFCOMM_PROTOCOL_MAUUID, 0x0003);). The remaining value 0x101 (257) is the part that matches the standard definition for serial port.
Your UUID must be unique. In this example, we will use a value of 355. We can then define our new service UUID as follows:
DEFINE_BTMAUUID(Example_Service_MAUUID, 0x1163);
The format of a Bluetooth service URL is:
btspp://localhost:<service uuid>[;name=<plain text name of the service>]
If we were creating a new service, we would need to have created an MAUUID which we could write to the string. When translated, our MAUUID is 0000116300001000800000805f9b34fb.
This little function will create a valid URL:
void MyServer::formatUrl(char* output, MAUUID& serviceID, const char* servicename)
{
sprintf(output, "btspp://localhost:%08x%08x%08x%08x;name=%s\0", serviceID.i[0], serviceID.i[1], serviceID.i[2], serviceID.i[3], servicename);
}You can now use the URL to start the server. The connect method takes this URL instead.
#include <MAUtil/Moblet.h>
#include <MAUtil/Server.h>
#include <MAUtil/mauuid.h>
#include <conprint.h>
using namespace MAUtil;
DEFINE_BTMAUUID(Example_Service_MAUUID, 0x1163);
//This class sets up the server connection, and manages the bindings.
class MyServer : public ServerListener
{
private:
Server mServer;
MAHandle mConn;
void MyServer::formatUrl(char* output, const MAUUID& serviceID, const char* servicename)
{
sprintf(output, "btspp://localhost:%08x%08x%08x%08x;name=%s\0", serviceID.i[0], serviceID.i[1], serviceID.i[2], serviceID.i[3], servicename);
}
public:
MyServer() : mServer(this), mConn(NULL)
{
}
~MyServer()
{
//Close the server before we exit
if(mServer.isOpen())
mServer.close();
}
void MyServer::connect()
{
if(mServer.isOpen())
lprintfln("Already open");
else
{
//Start accepting incoming BT requests for Example_Service_MAUUID
char buffer[255];
const char* servicename = "Example Service";
formatUrl(&buffer[0], Example_Service_MAUUID, servicename);
lprintfln("url: %s", buffer);
mConn = mServer.start(buffer);
if(mConn < 0)
lprintfln("Service failed");
else
lprintfln("Service started");
}
}
//ServerListener
void MyServer::serverAcceptFailed(Server* server, int result)
{
lprintfln("Connection failed");
}
void MyServer::serverAccepted(Server* server, Connection* conn)
{
lprintfln("Connection accepted");
mConnHandler->start(conn);
}
};
class MyMoblet : public Moblet
{
private:
MyServer myServer;
public:
MyMoblet()
{
myServer.connect();
}
};
extern "C" int MAMain()
{
Moblet::run(new MyMoblet());
return 0;
};
This won’t let you start accepting connections though. This is just the server binding information. To accept connections, you need to create a ConnectionListener.
If you’ve run the above examples, you will notice that neither the serverAccepted or the serverAcceptFailed methods have been called. To make the server binding work, you need to call the accept method, and pass it a ConnectionListener.
ConnectionListener will be familiar to anyone who has developed a network client in MoSync. It responds to connection events from the Connection class. The ConnectionListener has the following methods you need to implement:
void connectFinished(Connection* conn, int result); void connRecvFinished(Connection* conn, int result); void connWriteFinished(Connection* conn, int result); void connReadFinished(Connection* conn, int result);
When your server starts, it will return you a normal Connection object. Just as when you are developing a client application, you need to be able to respond to incoming and outgoing data, and to be able to read from and write to the stream. The ConnectionListener you will create will do this for you, and actually implement the details of your protocol.
A common way to develop this ConnectionListener is to create a connection handler. This is the class which will maintain the connection state and manage the data flow.
class MyConnectionHandler : public ConnectionListener
{
private:
Connection* mConn;
char buffer[64];
public:
MyConnectionHandler();
~MyConnectionHandler();
//Provide a method to tell the connection handler to start receiving data
void MyConnectionHandler::start(Connection* conn)
{
mConn = conn;
//Wait to receive a few bytes
mConn->recv(&buffer, 63); //Don't receive more than the buffer size.
}
//ConnectionListener interface
void MyConnectionHandler::connectFinished(Connection* conn, int result)
{
lprintfln("Connection to a client has been established");
}
void MyConnectionHandler::connRecvFinished(Connection* conn, int result)
{
lprintfln("%d bytes have been received.", result);
}
void MyConnectionHandler::connWriteFinished(Connection* conn, int result)
{
lprintfln("%d bytes have been written", result);
}
void MyConnectionHandler::connReadFinished(Connection* conn, int result)
{
lprintfln("%d bytes have been read", result);
}
};This example is just about as simple as it can be. The class inherits from ConnectionListener and provides the methods for receiving notification of data reads and writes. When one of these is called, it just writes the notification to the console.
There is also a method start. This is so we can start the connection handler with a valid connection, and it can start requesting data from the stream. As an example, we’re going to create a server that receives data, counts the number of bytes it has received in total, and respond to the client with this value. We’ve got a buffer to read into, but we’re not really interested in the data, just the values, so we can write the data to the console and keep track of the quantity. When data is received, we’re going to increase the total counter, create a text value to that amount and write it to the output stream.
void MyConnectionHandler::connRecvFinished(Connection* conn, int result)
{
if(result > 0)
{
lprintfln("%d bytes have been received.", result);
//Increase the byte counter
total += result;
//Write the data to the console
lprintfln("%s", buffer);
//Write the running total to the output stream
sprintf(&writeBuffer[0], "%9d", total);
mConn->write(&writeBuffer, 10);
//Reset the read buffer
memset(&buffer, 0, 64);
//Receive some more data
mConn->recv(&buffer, 63);
}
else
{
//An error condition has been reached
lprintfln("Error - %d", result);
}
}We’ve also put an error check in there to ensure that no error codes have been sent.Now we’ve got a connection handler that can read and write data, we can call the accept method on the Server.
{
if(mServer.isOpen())
lprintfln("Already open");
else
{
//Start accepting incoming BT requests for Example_Service_MAUUID
char buffer[255];
const char* servicename = "Example Service";
formatUrl(&buffer[0], Example_Service_MAUUID, servicename);
lprintfln("url: %s", buffer);
mConn = mServer.start(buffer);
if(mConn < 0)
lprintfln("Service failed");
else
{
lprintfln("Service started");
//Accept the connection
mServer.accept(new MyConnectionHandler());
}
}
}Once the server has bound to the port or service, the serverAccepted method is called, and you can start your connection handler receiving data.
In a more sophisticated example, you would also need a listener to the connection handler for it to report errors to, and to close the connection when it has finished. The complete listing is below
#include <MAUtil/Moblet.h>
#include <MAUtil/Server.h>
#include <MAUtil/mauuid.h>
#include <conprint.h>
using namespace MAUtil;
DEFINE_BTMAUUID(Example_Service_MAUUID, 0x1163);
//This class handles the connection and implements the details of the protocol
class MyConnectionHandler : public ConnectionListener
{
private:
Connection* mConn;
char buffer[64];
char writeBuffer[10];
int total;
public:
MyConnectionHandler() {}
//Provide a method to tell the connection handler to start receiving data
void MyConnectionHandler::start(Connection* conn)
{
total = 0; //Receive 0 bytes so far
mConn = conn;
//Wait to receive a few bytes
mConn->recv(&buffer, 63); //Don't receive more than the buffer size.
}
//ConnectionListener interface
void MyConnectionHandler::connectFinished(Connection* conn, int result)
{
lprintfln("Connection to a client has been established");
}
void MyConnectionHandler::connRecvFinished(Connection* conn, int result)
{
if(result > 0)
{
lprintfln("%d bytes have been received.", result);
//Increase the byte counter
total += result;
//Write the data to the console
lprintfln("%s", buffer);
//Write the running total to the output stream
sprintf(&writeBuffer[0], "%9d", total);
mConn->write(&writeBuffer, 10);
//Reset the read buffer
memset(&buffer, 0, 64);
//Receive some more data
mConn->recv(&buffer, 63);
}
else
{
//An error condition has been reached
lprintfln("Error - %d", result);
}
}
void MyConnectionHandler::connWriteFinished(Connection* conn, int result)
{
lprintfln("%d bytes have been written", result);
//Clear the write buffer
memset(&writeBuffer, 0, 10);
}
void MyConnectionHandler::connReadFinished(Connection* conn, int result)
{
lprintfln("%d bytes have been read", result);
}
};
//This class sets up the server connection, and manages the bindings.
class MyServer : public ServerListener
{
private:
Server mServer;
MAHandle mConn;
MyConnectionHandler* mConnHandler;
void MyServer::formatUrl(char* output, const MAUUID& serviceID, const char* servicename)
{
sprintf(output, "btspp://localhost:%08x%08x%08x%08x;name=%s\0", serviceID.i[0], serviceID.i[1], serviceID.i[2], serviceID.i[3], servicename);
}
public:
MyServer() : mServer(this), mConn(NULL)
{
}
~MyServer()
{
//Close the server before we exit
if(mServer.isOpen())
mServer.close();
}
void MyServer::connect()
{
if(mServer.isOpen())
lprintfln("Already open");
else
{
//Start accepting incoming BT requests for Example_Service_MAUUID
char buffer[255];
const char* servicename = "Example Service";
formatUrl(&buffer[0], Example_Service_MAUUID, servicename);
lprintfln("url: %s", buffer);
mConn = mServer.start(buffer);
if(mConn < 0)
lprintfln("Service failed");
else
{
lprintfln("Service started");
//Accept the connection
mConnHandler = new MyConnectionHandler();
lprintfln("Created the handler");
lprintfln("Requesting accept");
mServer.accept(mConnHandler);
}
}
}
//ServerListener
void MyServer::serverAcceptFailed(Server* server, int result)
{
lprintfln("Connection failed");
}
void MyServer::serverAccepted(Server* server, Connection* conn)
{
lprintfln("Connection accepted");
mConnHandler->start(conn);
}
};
class MyMoblet : public Moblet
{
public:
MyMoblet()
{
MyServer myServer;
myServer.connect();
}
};
extern "C" int MAMain()
{
Moblet::run(new MyMoblet());
return 0;
};
In our Discovering Devices and Services with Bluetooth tutorial we demonstrated how the MAUtil::BluetoothDiscoverer class can be used to locate nearby devices and find out which Bluetooth services they support. Once you’ve discovered a device and a service you will need to write a client for that service and open a data connection to the server. That's what we will be doing in this tutorial.
To create a connection to the Bluetooth device that you want to communicate with, you can use the Connection class in the MAUtil library (#include <MAUtil/Connection.h>). The Connection class wraps up common connection commands into one easy-to-use object.
Creating Connection objects is discussed at length in the tutorial Downloading Data from the Internet, but the one thing you do have to do though is to implement ConnectionListener. The ConnectionListener has the following methods you need to implement:
void connectFinished(Connection* conn, int result); void connRecvFinished(Connection* conn, int result); void connWriteFinished(Connection* conn, int result); void connReadFinished(Connection* conn, int result);
When the Connection object reads to writes data, it will inform your ConnectionListener of the result.
//ConnectionListener
void connectFinished(Connection* conn, int result)
{
lprintfln("Connection established");
}
void connRecvFinished(Connection* conn, int result)
{
lprintfln("Received %d bytes", result);
}
void connWriteFinished(Connection* conn, int result)
{
lprintfln("Wrote %d bytes", result);
}
void connReadFinished(Connection* conn, int result)
{
lprintfln("Read %d bytes", result);
}To create the Connection, you need to be able to format a URL to the desired Bluetooth server correctly. This is the only real difference between connecting to a Bluetooth service and connecting to an HTTP resource on the Internet.
This tutorial assumes that you’ve either already followed the discovery processes in our tutorial Discovering Devices and Services with Bluetooth. That tutorial explains how to find the service you want to connect to, and introduces the classes BtDevice and BtService.
When you want to create a URL to connect to a Bluetooth service, you need the MABtAddr address class from BtDevice and the port number from BtService. The example we are working through today assumes you’ve already got the both a BtDevice and a BtService.
The Bluetooth URL is in the format:
btspp://<device address>:<service port>
The device address is in an MABtAddr object in BtDevice.address. The MABtAddr is a struct that contains byte[6]. Each of these bytes needs to be converted to two-character hex value in array order.
This little function will convert it for you:
void BluetoothClient::formatConnection(char* output, BtDevice& device, int port)
{
MABtAddr a = device.address;
sprintf(output, "btspp://%02x%02x%02x%02x%02x%02x:%i",
a[0], a[1], a[2], a[3], a[4], a[5], port);
}Once connected, you’ve got the same Connection object as you have for connecting to the Internet. You can read and write into the connection.
In this example, we are going to create a client which is for the Bluetooth service created for the tutorial Creating a Bluetooth Server. In that tutorial, the service simply receives a stream of bytes, counts them, and then returns a running total to the client. Our client is going to connect to that server, send a short string, and then listen for the count to be returned.
To do this, we need to expand the implementation of ConnectionListener we produced earlier. The first stage is to make the connection to the correct URL. This means we need to write a short method to start the connection:
void BluetoothClient::connect(BtDevice& device, BtService& service)
{
char buffer[100];
formatConnection(&buffer[0], device, service.port);
mConn.connect(buffer);
}We use the formatConnection method from earlier to create the URL, and make a connection. If successful, our connectFinished method will be called:
void BluetoothClient::connectFinished(Connection* conn, int result)
{
lprintfln("Connection established");
//Connection finished, start sending data
mConn.write("123456", 6);
}Once the connection is open, we can write data into it. As with all Connection objects, the write is asynchronous, so don’t write from local variables as they can go out of scope before the write has completed. Here, we are just writing six bytes representing the characters one to six. Once the write has finished, our connWriteFinished method will be called.
void BluetoothClient::connWriteFinished(Connection* conn, int result)
{
lprintfln("Wrote %d bytes", result);
//Listen for response
mConn.recv(&readBuffer, 63);
}We know that we’ve written data to the server, so now we can wait for the server to respond with the lenght of the data we’ve sent. There is a char[64] already declared to read the response into. When data has been received, our connRecvFinished method will be called.
void BluetoothClient::connRecvFinished(Connection* conn, int result)
{
lprintfln("Received %d bytes", result);
//Received the data
lprintfln("Server response: %s", readBuffer);
//Finished
mConn.close();
}We can echo the server’s response to the screen, and hopefully it tells us that we’ve sent six bytes. Now that we’ve completed our exchange, we can close the connection. Obviously, this is a simple example to demonstrate the process, but all application level protocols can be implemented in this fashion.
There is a conversation between the client and the server, but the responses and the actions will depend on the protocol you wish to create. The complete source code follows:
#include <MAUtil/Moblet.h>
#include <MAUtil/Connection.h>
#include <MAUtil/BluetoothDiscovery.h>
#include <conprint.h>
using namespace MAUtil;
class BluetoothClient : public ConnectionListener
{
private:
Connection mConn;
char readBuffer[64];
void BluetoothClient::formatConnection(char* output, BtDevice& device, int port)
{
const byte* a = device.address.a;
sprintf(output, "btspp://%02x%02x%02x%02x%02x%02x:%i",
a[0], a[1], a[2], a[3], a[4], a[5], port);
}
public:
BluetoothClient() : mConn(this)
{}
~BluetoothClient()
{
if(mConn.isOpen())
mConn.close();
}
void BluetoothClient::connect(BtDevice& device, BtService& service)
{
char buffer[100];
formatConnection(&buffer[0], device, service.port);
mConn.connect(buffer);
}
//ConnectionListener
void BluetoothClient::connectFinished(Connection* conn, int result)
{
lprintfln("Connection established");
//Connection finished, start sending data
mConn.write("123456", 6);
}
void BluetoothClient::connRecvFinished(Connection* conn, int result)
{
lprintfln("Received %d bytes", result);
//Received the data
lprintfln("Server response: %s", readBuffer);
//Finished
mConn.close();
}
void BluetoothClient::connWriteFinished(Connection* conn, int result)
{
lprintfln("Wrote %d bytes", result);
//Listen for response
mConn.recv(&readBuffer, 63);
}
void BluetoothClient::connReadFinished(Connection* conn, int result)
{
lprintfln("Read %d bytes", result);
}
};
Implementing Bluetooth in your application is usually done in three stages. Firstly, there is device discovery: getting the phone to scan for other devices in range. Secondly, there is a service discovery: querying a discovered device to see which protocols and services it supports. Lastly, there is the implementation of a service, a specific transfer of data. This tutorial covers the first two steps: discovering devices and services.
The first stage working with Bluetooth is discovering other Bluetooth devices. These could be other phones or mobile devices, laptop or desktop computers or any other Bluetooth-enabled device.
Note: The MoRE emulator you use to develop and test MoSync applications supports Bluetooth if the PC you are using supports it. Developers with Bluetooth enabled (as is very common on laptops) will see their PC search for devices just as their phones will.
We provide several C++ Bluetooth discovery classes in the MoSync SDK. These classes perform an asynchronous search of Bluetooth devices, and return information about each device, including its name and its unique address. To use the Bluetooth discovery classes, include the header file MAUtil/BluetoothDiscovery.h in your application.
BluetoothDeviceDiscoveryListener
To implement Bluetooth discovery, you need to create a class which will respond to Bluetooth events. If you are creating a MAUI application, this will often be a MAUI::Screen class. In the following example, we've built a screen called Devices. It searches for and reports on Bluetooth devices in detectable range. When we define this class, we make it inherit from the interface class BluetoothDeviceDiscoveryListener:
class Devices : public Screen, public BluetoothDeviceDiscoveryListener
{We also need it to implement the two methods defined in BluetoothDeviceDiscoveryListener, btNewDevice and btDeviceDiscoveryFinished:
#include <MAUtil/BluetoothDiscovery.h>
...
//Members for the BluetoothDeviceDiscoveryListener
void btNewDevice (const BtDevice &dev);
void btDeviceDiscoveryFinished (int state);To perform a Bluetooth device discovery, you will need an instance of BluetoothDiscoverer:
//The BT discovery class
BluetoothDiscoverer* mDiscoverer;The process will be that you create an instance of the BluetoothDiscoverer, and set the BluetoothDiscoverer's listener to be your new class. This instructs the BluetoothDiscoverer to inform your class whenever it finds a Bluetooth device, and when it has finished looking for them.
The specific method for starting a device discovery is startDeviceDiscovery() to inform your class whenever it finds a Bluetooth device, and when it has finished looking for them:
//Create the bt discoverer mDiscoverer = new BluetoothDiscoverer(); mDiscoverer->startDeviceDiscovery(this, true);
Unlike many other event-driven classes in the MoSync SDK, you provide a single listener class when you start a device discovery, not when you create the class. You can start the discovery process and pass it a pointer to your BluetoothDeviceDiscoveryListener class ('this' in the example), and a boolean value to say whether you want it to discover the devices' names.
The reason you have to specify the listener as a parameter in the method call is that the same BluetoothDiscovery class is used for device discovery and service discovery, but the listeners which are required to respond to events are different.
Getting the names can take a few seconds longer, so if you don't need them, you don't need to spend time on getting them all.
Note: Getting names is not guaranteed. The discovery class will negotiate with each device and request its name, but some devices are slow and time out, and sometimes they move out of range between detecting their existence and retrieving their names. You should always code defensively for device names, and either substitute their address or leave them out of your UI if you can't detect their name.
When the discoverer detects a device, it will call the listener's btNewDevice method. It will pass a reference to a BtDevice (BtDevice&). BtDevice is a struct which contains a MAUtil::String for the name, and another struct containing the Bluetooth address called MABtAddr.
void Devices::btNewDevice (const BtDevice &dev)
{
lprintfln("Found new device");
mDevices.add(dev);
mContentBox->add(createLabel(dev.name.c_str()));
}When the discover has completed its search, it will call the btDeviceDiscoveryFinished() method of the listener:
void Devices::btDeviceDiscoveryFinished (int state)
{
lprintfln("Device discovery finished");
mStatus->setCaption("Idle");
mIsWorking = false;
}
Below is the code for our example screen. It searches for devices and builds a list of nearby devices. (Note: this code requires UIBuilder.cpp and UIBuilder.h, which are available as a zip file at the bottom of this tutorial.)
Devices.h
/**
* @file Devices.h
* @author Sam Pickard, Naveed Asif
*
* Description:
*
* In this file we define the specifications for the Devices.
*
*/
#ifndef DEVICES_H_
#define DEVICES_H_
#include <MAUI/Screen.h>
#include <MAUI/Layout.h>
#include <MAUI/Widget.h>
#include <MAUI/ListBox.h>
#include <MAUtil/Moblet.h>
#include <MAUtil/BluetoothDiscovery.h>
#include <MAUtil/Set.h>
#include "UIBuilder.h" // Is attached at the bottom of this tutorial.
#include "Services.h"
#include <conprint.h>
using namespace MAUI;
using namespace MAUtil;
/*
* Devices class declaration.
*/
class Devices : public Screen, public BluetoothDeviceDiscoveryListener
{
public:
Devices(Moblet* moblet);
virtual ~Devices();
// Members for the BluetoothDeviceDiscoveryListener.
void btNewDevice (const BtDevice &dev);
void btDeviceDiscoveryFinished (int state);
void keyPressEvent(int keyCode);
private:
Layout* mMainLayout;
ListBox* mContentBox;
Label* mStatus;
Label* mTitle;
Label* mInstructions;
Moblet* mMoblet;
Services* mServices;
// The BT discovery class.
BluetoothDiscoverer* mDiscoverer;
bool mIsWorking;
// Keep a list of the devices you've found.
Vector<BtDevice> mDevices;
void reset();
};
/*
* MyMoblet class definition.
*/
class MyMoblet : public Moblet
{
public:
MyMoblet();
private:
Devices* mainScreen;
};
#endif /* DEVICES_H_ */
Devices.cpp
/**
* @file Devices.cpp
* @author Sam Pickard, Naveed Asif
*
* Description:
*
* In this file we define the different methods for the Devices class.
*
* Instructions:
*
* Pressing * key will search for the Bluetooth devices, select any
* of the devices and press key 5 to see what services this device
* supports.
*
*/
#include "Devices.h"
MyMoblet* moblet;
/*
* Devices class implementation.
*/
Devices::Devices(Moblet* moblet) : mMoblet(moblet)
{
// Create the main layout.
mMainLayout = (Layout*)createMainLayout("", "Exit");
this->setMain(mMainLayout);
// These are the labels that will be displayed in layout.
mTitle = (Label*)mMainLayout->getChildren()[0]->getChildren()[0];
mInstructions = (Label*)mMainLayout->getChildren()[0]->getChildren()[1];
mStatus = (Label*)mMainLayout->getChildren()[0]->getChildren()[2];
// The list box that will display the discovered Bluetooth devices.
mContentBox = (ListBox*)mMainLayout->getChildren()[0]->getChildren()[3];
// Captions for the labels.
mStatus->setCaption("Idle \n");
mTitle->setCaption("Bluetooth Devices");
mInstructions->setCaption("Press * to search for Devices");
// Create the services screen.
mServices = new Services(this);
// Create the bt discoverer.
mDiscoverer = new BluetoothDiscoverer();
// Not searching yet.
mIsWorking = false;
}
/*
* Destructor for the Devices class.
*/
Devices::~Devices()
{
reset();
}
/*
* Key press events
*/
void Devices::keyPressEvent(int keyCode)
{
switch(keyCode)
{
case MAK_SOFTRIGHT:
mMoblet->close();
break;
case MAK_STAR:
// Clear any old results
Vector_each(BtDevice, itr, mDevices)
delete itr;
mDevices.clear();
Vector_each(Widget*, itr, mContentBox->getChildren())
delete *itr;
mContentBox->clear();
// Start the bluetooth discovery
if(!mIsWorking)
{
mIsWorking = true;
mStatus->setCaption("Searching");
mDiscoverer->startDeviceDiscovery(this, true);
}
break;
case MAK_2:
case MAK_UP:
case MAK_4:
mContentBox->selectPreviousItem();
break;
case MAK_8:
case MAK_DOWN:
case MAK_6:
mContentBox->selectNextItem();
break;
case MAK_5:
case MAK_FIRE:
mMainLayout->clear();
mMainLayout->drawWidget();
// mMainLayout->requestRepaint();
// You cannot perform two bluetooth operations at the same time.
if(!mIsWorking)
{
mServices->getServices(mDevices[mContentBox->getSelectedIndex()]);
mServices->show();
}
break;
}
}
/*
* Finds devices and add them to the content list.
*/
void Devices::btNewDevice (const BtDevice &dev)
{
lprintfln("Found new device");
mDevices.add(dev);
mContentBox->add(createLabel(dev.name.c_str()));
}
/*
* Device discovery finished.
*/
void Devices::btDeviceDiscoveryFinished (int state)
{
lprintfln("Device discovery finished");
mStatus->setCaption("Idle");
mIsWorking = false;
}
/*
* Reset the device list.
*/
void Devices::reset()
{
// Remove the current items.
Vector_each(Widget*, itr, mContentBox->getChildren())
delete *itr;
// Clears the list box contents.
mContentBox->clear();
// Clear the Bluetooth device storage.
Vector_each(BtDevice, itr, mDevices)
delete itr;
mDevices.clear();
}
/*
* MyMoblet class declaration.
*/
MyMoblet::MyMoblet()
{
// The default font and skins are declared.
gFont = new MAUI::Font(RES_FONT);
gSkin = new WidgetSkin(RES_SELECTED, RES_UNSELECTED, 16, 32, 16, 32, true, true);
// Returns a reference to the single instance of
// Engine class, using lazy initialization.
Engine& engine = Engine::getSingleton();
engine.setDefaultFont(gFont);
engine.setDefaultSkin(gSkin);
// This returns screen coordinates.
MAExtent screenSize = maGetScrSize();
scrWidth = EXTENT_X(screenSize);
scrHeight = EXTENT_Y(screenSize);
// Creates a new instance of the main screen.
mainScreen = new Devices(this);
mainScreen->show();
}
/*
* Entry point of the program. The MAMain function
* needs to be declared as extern "C".
*/
extern "C" int MAMain()
{
moblet = new MyMoblet();
Moblet::run(moblet);
return 0;
}
The second stage of the process of impementing Bluetooth is service discovery. Once you've got the address of a Bluetooth device, you can query it to see what services it can perform. These will vary greatly between devices. A mobile phone will provide different services from a printer. This is very important if you are trying to implement a specific Bluetooth service on your platform, as you can test other Bluetooth devices to see if they support the protocols you are trying to create.
Just as in device discovery, we use the BluetoothDiscoverer class to find services. Instead of calling the startDeviceDiscovery method, we call startServiceDiscovery. To do this, we need a class which inherits from BluetoothServiceDiscoveryListener. In the device discovery phase this was the screen class.
The example shows a different screen for service discovery, so we can use the Services screen as the listener as well.
class Services : public Screen, BluetoothServiceDiscoveryListener
To implement BluetoothServiceDiscoveryListener, you need to implement the following methods:
void btNewService (const BtService &serv);
void btServiceDiscoveryFinished (int state);When a new service is called, then your implementation of btNewService will be called, and just as in the device discovery, when it is complete it will call your btServiceDiscoveryFinished.
Your btNewService method will be passed a struct of the type BtService. This contains the name of the service (as a MAUtil::String), a port number, and vitally, a Vector<MAUUID>.
MAUUIDs are the MoSync SDK implementation of Bluetooth UUIDs (universally unique identifiers). These UUIDs are constants, and are common to all Bluetooth implementations. Each UUID maps to a Bluetooth service. If you decide to create a brand new Bluetooth service, then you should generate a new UUID for it. If you implement an existing Bluetooth service, then you should use the existing UUID. The MoSync SDK contains definitions of common Bluetooth services in MAUtil/mauuid.h for you to use.
To start a service discovery phase, you need to call the startServiceDiscovery method. This is being called from a method in our example Services object, where the Devices object has passed a BtDevice to the Services object for it to use in the search for services.
void Services::getServices(BtDevice& device)
{
if(!mIsWorking)
{
mIsWorking = true;
mStatus->setCaption("Searching");
mDiscoverer->startServiceDiscovery(device.address, RFCOMM_PROTOCOL_MAUUID, this);
}
}
Unlike the device discovery phase, you also need to specify the service class you are interested in. This specifies that we want to find Bluetooth services which operator over radio, so we are looking for the RFCOMM_PROTOCOL_MAUUID.
This UUID is also specified in MAUtil/mauuid.h. When you search in this way, you are searching for all the services which are available over Bluetooth radio, rather than over TCP or UDP. You can also search for more specific service groups like OBEX or UPnP, or even a specific service like OBEX push.
A word of caution: If you try to start a service discovery before the previous discovery has finished, the application will crash. The BluetoothDiscoverer class can't tell you directly when it is busy, so you will need to keep your own flag, which in this example is mIsWorking.
Once your service search is running, you will receive a call to your listener's btNewService(BtService&) method. This receives the BtService struct as defined above. You can filter services you may be interested in by comparing their UUIDs with values in MAUtil/mauuid.h. In our example, we are going to keep a Vector<BtService> of the services we've discovered, but also report the service names to the screen. The names come through populated, and you don't have to look up the name in a table.
void Services::btNewService (const BtService& serv)
{
lprintfln("Found new service %s", serv.name.c_str());
mContentBox->add(createLabel(serv.name.c_str()));
mServices.add(serv);
}When the service discovery phase is complete, your listener's btServiceDiscoveryFinished method is called.
void Services::btServiceDiscoveryFinished(int state)
{
lprintfln("Service discovery finished");
mStatus->setCaption("Idle");
mIsWorking = false;
}
The complete listing for Services is below
Services.h
/**
* @file Services.h
* @author Sam Pickard, Naveed Asif
*
* Description:
*
* In this file we define the specifications for the Services.
*
*/
#ifndef SERVICES_H_
#define SERVICES_H_
#include <MAUI/Screen.h>
#include <MAUI/Layout.h>
#include <MAUI/Widget.h>
#include <MAUI/ListBox.h>
#include <MAUtil/Moblet.h>
#include <MAUtil/BluetoothDiscovery.h>
#include <MAUtil/Set.h>
#include "UIBuilder.h" // Is attached at the bottom of this tutorial.
#include <MAUtil/MAUUID.h>
#include <conprint.h>
using namespace MAUI;
using namespace MAUtil;
/*
* Services class declaration.
*/
class Services : public Screen, BluetoothServiceDiscoveryListener
{
public:
Services(Screen* previous);
virtual ~Services();
void getServices(BtDevice& device);
// Members for the BluetoothServiceDiscoveryListener.
void btNewService (const BtService &serv);
void btServiceDiscoveryFinished (int state);
void keyPressEvent(int keyCode);
private:
Screen* mPrevious;
Widget* mMainLayout;
ListBox* mContentBox;
Label* mStatus;
Label* mTitle;
// The BT discovery class.
BluetoothDiscoverer* mDiscoverer;
bool mIsWorking;
// Keep a list of the services you've found.
Vector<BtService> mServices;
void reset();
};
#endif /* SERVICES_H_ */
Services.cpp
/**
* @file Services.h
* @author Sam Pickard, Naveed Asif
*
* Description:
*
* In this file we define the methods for the Services class.
*
*/
#include "Services.h"
/*
* Services class implementation.
*/
Services::Services(Screen* previous) : mPrevious(previous)
{
// Create the UI.
mMainLayout = createMainLayout("", "Back");
this->setMain(mMainLayout);
// These are the labels that will be displayed in layout.
mTitle = (Label*)mMainLayout->getChildren()[0]->getChildren()[0];
mStatus = (Label*)mMainLayout->getChildren()[0]->getChildren()[1];
mContentBox = (ListBox*)mMainLayout->getChildren()[0]->getChildren()[2];
// Captions for the labels.
mStatus->setCaption("Idle");
mTitle->setCaption("Bluetooth Services");
// Create the bt discoverer.
mDiscoverer = new BluetoothDiscoverer();
// Not searching yet.
mIsWorking = false;
}
/*
* The desctructor.
*/
Services::~Services()
{
reset();
delete mDiscoverer;
}
/*
* Key press events.
*/
void Services::keyPressEvent(int keyCode)
{
switch(keyCode)
{
case MAK_SOFTRIGHT:
mPrevious->show();
break;
case MAK_2:
case MAK_UP:
case MAK_4:
mContentBox->selectPreviousItem();
break;
case MAK_8:
case MAK_DOWN:
case MAK_6:
mContentBox->selectNextItem();
break;
}
}
/*
* Starts searching for the services.
*/
void Services::getServices(BtDevice& device)
{
if(!mIsWorking)
{
mIsWorking = true;
mStatus->setCaption("Searching");
mDiscoverer->startServiceDiscovery(device.address, RFCOMM_PROTOCOL_MAUUID, this);
}
}
/*
* Returns all the services supported by the device.
*/
void Services::btNewService (const BtService& serv)
{
lprintfln("Found new service %s", serv.name.c_str());
mContentBox->add(createLabel(serv.name.c_str()));
mServices.add(serv);
}
/*
* Service discovery finished.
*/
void Services::btServiceDiscoveryFinished(int state)
{
lprintfln("Service discovery finished");
mStatus->setCaption("Idle");
mIsWorking = false;
}
/*
* Reset the services list.
*/
void Services::reset()
{
// Remove the current items.
Vector_each(Widget*, itr, mContentBox->getChildren())
delete (*itr);
mContentBox->clear();
// Clear the Bluetooth device storage.
mServices.clear();
}
With this example, we can now detect Bluetooth devices in range, and query them for the services they offer.
Now that we have done that, we probably want to Create a Bluetooth Client to access those services.
| Attachment | Size |
|---|---|
| UIBuilder.zip | 2.01 KB |
This example application acts as a Bluetooth client. It is designed to work with our BluetoothServer example application.
![]() | ![]() |
| Start up/connection | Sending data |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
To use this example application with our BluetoothServer application, you will need two Bluetooth capable devices. Make sure that Bluetooth is turned on on both devices and that the devices are paired before running the server and the client applications.
The file Common.h from the BluetoothServer project is included in the client. It is assumed that both project folders BluetoothClient and BluetoothServer are located in the same directory. Common.h contains variables and functions shared between the BluetoothServer and BluetoothClient projects (including the service UUID), and contains a full description of how to use the projects together.
Note: Before you build and run this application, you need to enter the address of the BluetoothServer device in sServerAddress in Client.cpp. When you start up our BluetoothServer application on a device it will show you this address.
Note that when making your own projects that use Bluetooth, you need to enable Bluetooth for your project under Properties > MoSync Project > Application Permissions.
When this application starts up on a device or in the MoRE emulator it will attempt to connect to the server identified by sServerAddress. If the connection is sucessfully established you will see the message "Connected to server". (If you are having trouble getting Bluetooth clients to connect to Bluetooth servers, you are not alone! Check out our dedicated forum topic Bluetooth Ache for some helpful advice.)
The zero or back key exits the application, but pressing other keys on the keypad or touching the screen will send the data to the Bluetooth server application: the keycode and the data sent are echoed on the client's screen.
This application acts as a Bluetooth server. It is designed to work with our BluetoothClient example application.
![]() | ![]() | ![]() |
| On start up | Connection established | Receiving data |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
To use this example application with our BluetoothClient application, you will need two Bluetooth capable devices. Make sure that Bluetooth is turned on on both devices and that the devices are paired before running the server and the client applications.
The file Common.h contains contains a full description of how to use the projects together, along with the variables and functions shared between the BluetoothServer and BluetoothClient projects (including the service UUID).
Note: when making your own projects that use Bluetooth, you need to enable Bluetooth for your project under Properties > MoSync Project > Application Permissions.
This application sets up an RFCOMM service with a particular UUID and listens for connections. When this application starts up successfully on a device (or in the MoRE emulator on a computer) with activated Bluetooth capabilities you will see the message "Server started successfully" followed by the server device's Bluetooth address in hexadecimal. You need to supply this address in the BluetoothClient application as the value of sServerAddress.
When a connection is accepted from the BluetoothClient application, the connection ID is shown along with the client device's Bluetooth address.
As data is received from a client (in BluetoothClient when a key is pressed or the screen is touched), the connection ID and the data are printed to the screen. The data is usually sent one character at a time, but may be buffered if the connection is slow.
There are a thousand reasons why you might want your application to get information from the Internet. Perhaps you want to download today’s Dilbert cartoon, or get specific data for the user, or serve adverts, or connect to a web interface. Maybe you want to implement a new protocol, like FTP or Jabber. In this tutorial we’re going to show you how to get data over HTTP.
MoSync provides a wide range of connection objects and interfaces. There are three levels of abstraction for Internet connections, and you can write code against any of them:
At the lowest level, you can use functions in the MoSync API directly. You can use the method maConnect() to open a socket to connect to any port on the Internet. You can implement protocols which aren’t supported in MoSync on a higher level (like HTTP and HTTPS) by formatting a URL like this:
socket://<server name>[:<port>]<parameters>
so you can create your own protocol support for IMAP and POP3 to make an email client, and the documentation come with the basics of an FTP client.
You can use this method to connect to Bluetooth devices as well, with the format
btspp://<address>
We are going to concentrate on HTTP connections in this tutorial though, and although the API provides some HTTP specific methods, we’re going to focus on the download components in MAUtil.
The second level of abstraction is with MAUtil::Connection objects. These are C++ objects and are much more suitable for use in a Moblet application.
With HttpConnection objects you can access the HTTP 1.0 protocol so you can set HTTP headers before you send, and create new wrapper classes for implementing specific HTTP functions. For instance, you can use HttpConnection to implement an online authentication system, which you can then reuse.
Connections send messages to ConnectionListeners. When you are working with either a Connection or an HttpConnection, you will almost certainly need to create a class which inherits from ConnectionListener or HttpConnectionListener, and implements its methods. We find that very often this class is "my screen", which we define as:
class MyScreen : public Screen, ConnectionListener
and then implement the methods:
void connectFinished(Connection* conn, int result); void connRecvFinished(Connection* conn, int result); void connWriteFinished(Connection* conn, int result); void connReadFinished(Connection* conn, int result);
These methods are your opportunity to respond to data coming back, and you can do whatever you want in there.
At the highest level are the Downloader classes. These are very high level classes that wrap much of the mechanics of getting data over HTTP for you. These are the classes which we use most often, and if you just want to download some XML or a picture then these are the classes you should use too.
The Downloader class itself wraps HttpConnectionListener, and it is very simple to use. You simply tell it the URL you want to get data from and give it an MAHandle to load the data into.
If you want to know when your download has completed, you have to implement a listener too. You do this by inheriting from DownloadListener and implementing the interface. There is an example of this in the next section of the tutorial.
A second downloader is the BuffDownloader. This is rather more specialised, and instead of downloading to a placeholder, it downloads to the heap.
There are two downloaders at an even higher level: AudioDownloader and ImageDownloader. These are both wrappers for Downloader, but create the appropriate resources in memory for handling these items. More on these later.
Finally, you can create your own custom Downloader. You can inherit from Downloader, and perform some of your own downloading tasks, just as you can implement Connection to manage your own application protocol.
In all probability, what you actually want to do is download some data from the web. The easiest way to do this is to use the Downloader class and to create a DownloadListener to go with it. To do this we can make my Screen which requests the download from the DownloadListener. To do this in a reusable way, we create a DownloadScreen class.
#ifndef _DOWNLOADSCREEN_H_
#define _DOWNLOADSCREEN_H_
#include <MAUI/Screen.h>
#include <MAUI/Layout.h>
#include <MAUtil/Downloader.h>
#include "IScreenCoordinator.h"
#include "..\Utilities/Util.h"
#include "..\Utilities\IDownloadScreenListener.h"
#include "..\Widgets\SoftKeyBar.h"
using namespace MAUI;
using namespace MAUtil;
class DownloadScreen : public Screen, public DownloadListener, public ISoftKeyBarListener
{
public:
DownloadScreen(Screen* previous, IScreenCoordinator* mainScreen);
~DownloadScreen();
void download(const char* url, const char* storeName);
void keyPressEvent(int keyCode);
void setDownloadListener(IDownloadScreenListener* dll);
void notifyProgress(Downloader *dl, int downloadedBytes, int totalBytes);
void finishedDownloading(Downloader *dl, MAHandle data);
void error(Downloader* dl, int code);
void downloadCancelled(Downloader* dl);
void softKeySelected(int buttonID);
private:
Screen* previous;
IScreenCoordinator* mainScreen;
Layout* layout;
Image* image;
ListBox* listBox;
Downloader* dl;
IDownloadScreenListener* listener;
MAHandle _store;
};
#endif //_DOWNLOADSCREEN_H_
This code will build my screen, manage the downloads, and inform its own type of Listener (IDownloadScreenListener) when downloads are complete. (It doesn’t inform the IDownloadScreenListener of anything other than successful completion, as the user interaction for a failed download can be handled by this screen.)
#ifndef _IDOWNLOADSCREENLISTENER_H_
#define _IDOWNLOADSCREENLISTENER_H_
//Interface
class IDownloadScreenListener
{
public:
virtual void downloadComplete();
};
#endif //_IDOWNLOADSCREENLISTENER_H_
DownloadScreen.h is implemented in DownloadScreen.cpp:
#include "DownloadScreen.h"
//Handles a download
const char* store;
DownloadScreen::DownloadScreen(Screen* previous, IScreenCoordinator* mainScreen)
: previous(previous), mainScreen(mainScreen)
{
dl = new Downloader();
dl->addDownloadListener(this);
image = (Image*)createMainLayout(BLANK, BACK_BUTTON, this);
layout = (Layout*) image->getChildren()[0];
listBox = (ListBox*) layout->getChildren()[1];
Label* l = createLabel("Starting download", 32);
listBox->add(l);
this->setMain(image);
}
DownloadScreen::~DownloadScreen(void)
{
if(dl->isDownloading())
dl->cancelDownloading();
delete dl;
}
void DownloadScreen::setDownloadListener(IDownloadScreenListener* dll)
{
listener = dll;
}
void DownloadScreen::download(const char *url, const char* storeName)
{
if(dl->isDownloading())
{
//lprintfln("Busy.");
//dl->cancelDownloading();
}
else
{
lprintfln("Downloading %s", url);
store = storeName;
dl->beginDownloading(url);
}
}
void DownloadScreen::downloadCancelled(Downloader *dl)
{
//lprintfln("Cancelled");
listBox->add(createLabel("Download has been cancelled"));
}
void DownloadScreen::error(Downloader *dl, int code)
{
lprintfln("Error: %d", code);
listBox->add(createLabel("Sorry, an error has occured"));
}
void DownloadScreen::finishedDownloading(Downloader *dl, MAHandle data)
{
//Save the store
MAHandle h = maOpenStore(store, MAS_CREATE_IF_NECESSARY);
maWriteStore(h, data);
maCloseStore(h, 0);
lprintfln("Finished download");
if(listener != NULL)
{
//lprintfln("Calling listener");
listener->downloadComplete();
}
//lprintfln("Showing calling screen");
previous->show();
}
void DownloadScreen::notifyProgress(Downloader *dl, int downloadedBytes, int totalBytes)
{
Label* l = (Label*)listBox->getChildren()[0];
char* cap = new char[255];
sprintf(cap, "Downloaded %d of %d bytes", downloadedBytes, totalBytes);
l->setCaption(cap);
delete[] cap;
//lprintfln("Downloaded %d of %d bytes", downloadedBytes, totalBytes);
}
void DownloadScreen::softKeySelected(int buttonID)
{
switch(buttonID)
{
case SoftKeyBar::LSK:
break;
case SoftKeyBar::FIRE:
break;
case SoftKeyBar::RSK:
previous->show();
break;
}
}
void DownloadScreen::keyPressEvent(int keyCode)
{
switch(keyCode)
{
case MAK_2:
case MAK_4:
case MAK_UP:
listBox->selectPreviousItem();
break;
case MAK_6:
case MAK_8:
case MAK_DOWN:
listBox->selectNextItem();
break;
case MAK_0:
if(dl->isDownloading())
{
dl->cancelDownloading();
}
}
}
This download screen can be used from many different screen. For instance, if you've got a screen which shows a calendar where the user can drill into different days to see what their schedule is for that day. This screen can download a package of data from the Internet of events created for the user. When you want to download an update, my EventScreen calls DownloadScreen and passes it the URL it wants to download. This DownloadScreen handles all of the mechanics.
The DownloadScreen has inside it a Downloader object, and it implements DownloadListener. It creates a Downloader when it is constructed, and deletes it when it is destroyed. When the DownloadScreen’s download method is called, it passes the URL to the Downloader and starts downloading.
As the Downloader raises events to the DownloadScreen through the DownloadListener interface, the screen can keep the user informed about their download. When it has finished, it informs the calling screen that it has completed, so that screen can carry on.
To use it, call it from EventsScreen.cpp. This is a partial listing.
#include "EventsScreen.h"
#include <mastring.h>
EventsScreen::EventsScreen(Screen* previous, MainScreen* mainScreen)
: previous(previous), mainScreen(mainScreen)
{
image =(Image*) createMainLayout(BLANK, BACK_BUTTON, this);
layout = (Layout*) image->getChildren()[0];
listBox = (ListBox*) layout->getChildren()[1];
this->setMain(image);
urlptr = NULL;
dlscreen = new DownloadScreen(this, mainScreen);
dlscreen->setDownloadListener(this);
}
EventsScreen::~EventsScreen()
{
if(urlptr != NULL)
delete [] urlptr;
delete dlscreen;
}
void EventsScreen::downloadComplete()
{
listBox->getChildren().clear();
createEventScreen();
}
void EventsScreen::keyPressEvent(int keyCode)
{
switch(keyCode)
{
case MAK_2:
case MAK_4:
case MAK_UP:
listBox->selectPreviousItem();
break;
case MAK_6:
case MAK_8:
case MAK_DOWN:
listBox->selectNextItem();
break;
case MAK_0:
dlscreen->download(formatUrl(), EVENTSTORAGE);
dlscreen->show();
break;
}
}
When the user presses 0 on their keypad, it tells the DownloadScreen the URL to download from, and the name of the store to write the data to. More on that later.
When the data has been completely downloaded, the EventsScreen::downloadComplete() method is called, and the screen can repopulate itself from the downloaded data.
In the above example, the DownloadScreen class implements DownloadListener. In particular, it implemented these functions:
void notifyProgress(Downloader *dl, int downloadedBytes, int totalBytes); void finishedDownloading(Downloader *dl, MAHandle data); void error(Downloader* dl, int code); void downloadCancelled(Downloader* dl);
By doing this, the download screen is informed about what is happening to the downloader. The implementation code for these is here:
void DownloadScreen::downloadCancelled(Downloader *dl)
{
//lprintfln("Cancelled");
listBox->add(createLabel("Download has been cancelled"));
}
void DownloadScreen::error(Downloader *dl, int code)
{
lprintfln("Error: %d", code);
listBox->add(createLabel("Sorry, an error has occured"));
}
void DownloadScreen::finishedDownloading(Downloader *dl, MAHandle data)
{
//Save the store
MAHandle h = maOpenStore(store, MAS_CREATE_IF_NECESSARY);
maWriteStore(h, data);
maCloseStore(h, 0);
lprintfln("Finished download");
if(listener != NULL)
{
//lprintfln("Calling listener");
listener->downloadComplete();
}
//lprintfln("Showing calling screen");
previous->show();
}
void DownloadScreen::notifyProgress(Downloader *dl, int downloadedBytes, int totalBytes)
{
Label* l = (Label*)listBox->getChildren()[0];
char* cap = new char[255];
sprintf(cap, "Downloaded %d of %d bytes", downloadedBytes, totalBytes);
l->setCaption(cap);
delete[] cap;
//lprintfln("Downloaded %d of %d bytes", downloadedBytes, totalBytes);
}
When the Downloader tells the calling screen of an error, or that the download has been cancelled, or that it has downloaded some of the data, then you can tell the user by updating the screen. When the download has finished, you can call the IDownloadScreenListener, and show the previous screen.
Often when using images in MoSync, then the images are available to you as a developer, and you can package them with your application, as described in the tutorial 'Adding Resources to a Project'. However, there will be many scenarios where you want to show a picture you've not been able to package. This may be because there are too many pictures, or you are responding to user input. An image search of Google or Bing would be an example of this, there you cannot possibly know what the user is going to search for, nor could you package the images in advance.
There is a class which has been specifically created to remove some of the complexities of downloading images from the Web. The ImageDownloader class is defined in MAUtil/Downloader.h, and will create an image resource for you. To use the ImageDownloader, you will need to create a new class which inherits from DownloadListener. By doing this, your program will be informed when the image has downloaded and is ready to display.
/**
* @file DownloadImage.cpp
*
* This program downloads and displays an Image file from the Internet.
*
* Todo: You need to goto Project -> Properties -> Build Settings and
* add MAUtil.lib, MAUI.lib libraries in Additional Libraries.
*
* @author Sam Pickard, Naveed Asif
*/
#include <MAUtil/Moblet.h>
#include <MAUI/Screen.h>
#include <MAUI/Image.h>
#include <MAUtil/Downloader.h>
#include <conprint.h>
using namespace MAUtil;
using namespace MAUI;
/*
* Class that downloads an image file from
* the Internet.
*/
class MyScreen :
public Screen,
DownloadListener
{
public:
MyScreen()
{
// Message: Starting application.
lprintfln("Starting application");
// A new instance of ImageDownloader is created.
mImageDownloader = new ImageDownloader();
mImageDownloader->addDownloadListener(this);
mImageResource = maCreatePlaceholder();
// Message: Starting download.
lprintfln("Starting download");
// The image shall be downloaded from the following url.
mImageDownloader->beginDownloading(
"http://shop.abc.net.au/multimediaitems/images/product_images/4/482912.png",
mImageResource);
}
/*
* The destructor.
*/
virtual ~MyScreen()
{
delete mImageDownloader;
maDestroyObject(mImageResource);
}
/*
* The function is fired in case of download cancellation.
*/
void downloadCancelled(Downloader* downloader)
{
lprintfln("Cancelled");
}
/*
* Method displays error code in case of error in downloading.
*/
void error(Downloader* downloader, int code)
{
lprintfln("Error: %d", code);
}
/*
* On successful download completion, the image file is shown on screen.
*/
void finishedDownloading(Downloader* downloader, MAHandle data)
{
lprintfln("Completed download");
// Create a new image on screen with this picture.
Image* myImage = new Image(0, 0, 240, 320, NULL, false, false, mImageResource);
this->setMain(myImage);
this->show();
}
/*
* Notifies download progress.
*/
void notifyProgress(
Downloader* downloader,
int downloadedBytes,
int totalBytes)
{
lprintfln("Downloaded %d of %d bytes", downloadedBytes, totalBytes);
}
private:
ImageDownloader* mImageDownloader;
MAHandle mImageResource;
};
/*
* Moblet for the image download.
*/
class MAUIMoblet : public Moblet
{
public:
MAUIMoblet()
{
// Create the screen.
mScreen = new MyScreen();
mScreen->show();
}
/*
* Key press events are handled here.
*/
void keyPressEvent(int keyCode)
{
if(keyCode == MAK_0 || keyCode == MAK_BACK)
{
maExit(0);
}
}
void keyReleaseEvent(int keyCode)
{
// todo: handle key releases
}
/*
* The destructor.
*/
virtual ~MAUIMoblet()
{
delete mScreen;
}
private:
MyScreen* mScreen;
};
/**
* Main function that starts the program.
*/
extern "C" int MAMain()
{
Moblet::run(new MAUIMoblet());
return 0;
}
In this example, the DownloadListener is also a MAUI Screen class. When the finishedDownloading method is called, the MAHandle 'data' contains a handle to the downloaded image. You can then display this as any other MAUI image, or in a game or a C application, you can use the function maDrawImage().
If you tried this with a Downloader object instead of an ImageDownloader, you’ll get an ‘Invalid Resource Type’ error message when you tried to create the image. Instead, you’d need to call:
maCreateImageFromData(h, source, position, imageLength);
to covert the resource type for you.
In addition to the standard methods of downloading data using the Connection, HttpConnection, or Downloader objects, the MoSync SDK provides a special downloader, the AudioDownloader class, for retrieving audio files from the Internet. The AudioDownloader is a useful wrapper for the Downloader class and is specifically for audio files.
Usually, when you create an audio resource on a server you set its MIME type. The MIME type determines how the device should play the sound file. You can find a list of common MIME types on Wikipedia. You can also specify a MIME type for the audio file when you download it.
It is very important to understand how the MIME type set on the server interacts with the MIME type set on the download to determine the final MIME type of the file. This is because the server MIME type has precedence.
The conclusion from this is that you should always set the MIME type for the download.
This code below will download and play an MP3 file from the web and set its MIME type to 'audio/mpeg', which is suitable for MP3 files.
/**
* @file DownloadAudio.cpp
*
* This program downloads and plays an audio file from the Internet.
*
* Todo: You need to goto Project -> Properties -> Build Settings and
* add MAUtil.lib, MAUI.lib libraries in Additional Libraries.
*
* @author Sam Pickard, Naveed Asif
*/
#include <MAUtil/Moblet.h>
#include <MAUI/Screen.h>
#include <MAUtil/Downloader.h>
#include <conprint.h>
using namespace MAUtil;
using namespace MAUI;
/*
* Class that downloads and plays audio file from
* the Internet.
*/
class MyScreen :
public Screen,
public DownloadListener
{
public:
MyScreen()
{
// Message: Starting application.
printf("Starting application\n");
// A new instance of AudioDownloader is created.
mAudioDownloader = new AudioDownloader();
mAudioDownloader->addDownloadListener(this);
mAudioResource = maCreatePlaceholder();
// Message: Starting download.
printf("Starting download\n");
// The audio resource starts downloading here.
mAudioDownloader->beginDownloading(
"http://downloads.bbc.co.uk/doctorwho/sounds/exterminate.mp3",
mAudioResource,
"audio/mpeg",
true);
}
/*
* The destructor.
*/
virtual ~MyScreen()
{
delete mAudioDownloader;
maDestroyObject(mAudioResource);
}
/*
* The function is fired in case of download cancellation.
*/
void downloadCancelled(Downloader* downloader)
{
lprintfln("Cancelled");
}
/*
* Method displays error code in case of error in downloading.
*/
void error(Downloader* downloader, int code)
{
lprintfln("Error: %d", code);
}
/*
* On successful download completion, the audio file is played.
*/
void finishedDownloading(Downloader* downloader, MAHandle data)
{
lprintfln("Completed download");
// Plays the downloaded file.
maSoundPlay(mAudioResource, 0, maGetDataSize(mAudioResource));
}
/*
* Notifies download progress.
*/
void notifyProgress(
Downloader* downloader,
int downloadedBytes,
int totalBytes)
{
lprintfln("Downloaded %d of %d bytes", downloadedBytes, totalBytes);
}
private:
AudioDownloader* mAudioDownloader;
MAHandle mAudioResource;
};
/*
* Moblet for the download audio.
*/
class MAUIMoblet : public Moblet
{
public:
MAUIMoblet()
{
// Create the screen.
mScreen = new MyScreen();
mScreen->show();
}
/*
* Key press events are handled here.
*/
void keyPressEvent(int keyCode)
{
if(keyCode == MAK_0 || keyCode == MAK_BACK)
{
maExit(0);
}
}
/*
* The destructor.
*/
virtual ~MAUIMoblet()
{
delete mScreen;
}
private:
MyScreen* mScreen;
};
/**
* Main function that starts the program.
*/
extern "C" int MAMain()
{
Moblet::run(new MAUIMoblet());
return 0;
}
There are obvious occasions when you want do download data from the Internet for your games or application. There are even obvious occasions when you want to download images and sounds using the ImageDownloader and AudioDownloader. What might appear less obvious is the use of a Custom Downloader.
Custom Downloaders are more useful than you might think. These are classes where you have implemented ConnectionListener, but got it to do something with the data before consuming it.
A great, if lengthy, example is the mapping component below. This is a custom widget (not part of the MoSync MAP SDK) to make scrollable, zoomable maps using the CloudMade map tiles. Initially, this used an ImageDownloader to get each and every tile separately from CloudMade. This was very slow, not because the data connection was slow, but because the HTTP latency was so great. It needed to negotiate a connection to the server 36 times to build a screen.
Instead, this connects to a small web application which will take requests for an indefinite number of tiles at once. It will go and get those tiles from CloudMade, cache them in memory for quick retrieval later, and return them to me in a single download. The application can then rip the tiles out of the stream and pass them to the map for display.
This has been implemented as a CustomDownloader. It allows for additional logic to be wrapped in the download mechanism, so other classes do not need knowledge of the connection to get the correct data.
#ifndef _MAPTILEDOWNLOADER_H_
#define _MAPTILEDOWNLOADER_H_
#include <MAUtil/Connection.h>
#include "MapTileDownloadListener.h"
using namespace MAUtil;
using namespace DatiloMapping;
namespace DatiloMapping
{
class MapTileDownloader : public ConnectionListener
{
public:
MapTileDownloader();
virtual ~MapTileDownloader();
void startDownloading(const char* url);
void cancelDownloading();
void removeListener(MapTileDownloadListener* listener);
void addDownloadListener(MapTileDownloadListener* listener);
void connectFinished(Connection* conn, int result);
void connRecvFinished(Connection* conn, int result);
void connReadFinished(Connection* conn, int result);
void connWriteFinished(Connection* conn, int result);
bool isDownloading();
private:
Vector<MapTileDownloadListener*> downloadListeners;
Connection* mapConn;
bool activeDownload;
void throwTile();
void processDownload();
void iterateTiles(int next);
void readKeyLength();
void readKey();
void readImageLength();
void readImage();
int dlStage;
ushort tileCount;
int keyLength;
int downloadedBytes;
int nextTile;
bool fetchComplete;
bool connectionOpen;
int tileSize;
byte kl; //key length
char* keyBuffer;
MAHandle h;
};
};
#endif //_MAPTILEDOWNLOADER_H_
#include "MapTileDownloader.h"
#include <conprint.h>
#include <madmath.h>
MapTileDownloader::MapTileDownloader()
{
h = maCreatePlaceholder();
keyBuffer = new char[10];
mapConn = new Connection(this);
activeDownload = false;
}
MapTileDownloader::~MapTileDownloader()
{
maDestroyObject(h);
delete mapConn;
delete [] keyBuffer;
}
//Start a download
void MapTileDownloader::startDownloading(const char* url)
{
if(mapConn->isOpen())
mapConn->close();
activeDownload = true;
int res = mapConn->connect(url);
if(res < 0)
return;
}
void MapTileDownloader::processDownload()
{
dlStage = 0;
nextTile = 0;
fetchComplete = false;
mapConn->read(&tileCount, 2); //Read exactly two bytes
}
void MapTileDownloader::iterateTiles(int next)
{
nextTile = next;
//Read through each tile
if(nextTile < tileCount)
{
//Reset the buffers
memset(keyBuffer, 0, 10);
readKeyLength();
}
else
{
mapConn->close();
activeDownload = false;
Vector_each(class MapTileDownloadListener*, itr, downloadListeners)
{
(*itr)->complete();
}
}
}
void MapTileDownloader::readKeyLength()
{
dlStage = 1;
mapConn->read(&kl, 1); //Read exactly one byte
}
void MapTileDownloader::readKey()
{
dlStage = 2;
mapConn->read(keyBuffer, kl);
}
void MapTileDownloader::readImageLength()
{
dlStage = 3;
mapConn->read(&tileSize, 4);
}
void MapTileDownloader::readImage()
{
dlStage = 4;
//Remove any existing obejct
maDestroyObject(h);
maCreateData(h, tileSize);
mapConn->readToData(h, 0, tileSize);
}
//Returns a tile to the listener
void MapTileDownloader::throwTile()
{
Vector_each(class MapTileDownloadListener*, itr, downloadListeners)
{
(*itr)->finishedDownloading(keyBuffer, h, tileSize);
}
maDestroyObject(h);
//Get the next tile
iterateTiles((nextTile + 1) % 36);
}
//Handle add/remove of listeners
void MapTileDownloader::removeListener(MapTileDownloadListener* listener)
{
Vector_each(class MapTileDownloadListener*, itr, downloadListeners)
{
if((*itr) == listener)
{
downloadListeners.remove(itr);
break;
}
}
}
void MapTileDownloader::addDownloadListener(MapTileDownloadListener* listener)
{
downloadListeners.add(listener);
}
//ConnectionListener events
void MapTileDownloader::connectFinished(Connection* conn, int result)
{
processDownload();
}
void MapTileDownloader::connRecvFinished(Connection* conn, int result)
{
}
void MapTileDownloader::connReadFinished(Connection* conn, int result)
{
fetchComplete = true;
switch(dlStage)
{
case 0:
iterateTiles(0);
break;
case 1:
readKey();
break;
case 2:
readImageLength();
break;
case 3:
readImage();
break;
case 4:
throwTile();
break;
}
}
void MapTileDownloader::connWriteFinished(Connection* conn, int result)
{
}
void MapTileDownloader::cancelDownloading()
{
if(mapConn->isOpen())
{
mapConn->close();
}
activeDownload = false;
}
bool MapTileDownloader::isDownloading()
{
return activeDownload;
}
This gets a stream of tiles. It reads the first two bytes of the stream to get the number of tiles in the stream, and then for each tile it reads the key so the map will know where this image goes. It then reads the length of the image, and then the image data itself. As it gets each tile, it throws it to a listener which can pass it to the map, so it is drawing tiles as they come down. By implementing a custom listener like this, you will get a speed improvement of ten-fold!
This example application checks the ability of the application and device to connect to the internet.
![]() | ![]() |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When the application starts, use the keypad keys or touch the screen to connect to the Internet via HTTP or HTTPS. The application also has a "repeat " function that you can toggle on and off: if you toggle that function on and then connect, the connect and download process will loop continuously.
This example application demonstrates how to scan for Bluetooth devices and services, store the results in a database, display a list of services, and connects to one of them.
![]() | ![]() | ![]() |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
The application scans for nearby Bluetooth devices and services, stores the results in a database, displays a list of services, and connects to one of them. The user can start to scan for Bluetooth devices by pressing '5'. When the scan is completed a list of the discovered devices and their corresponding MAC addresses is presented. The user can at any time abort the scan by pressing 0. When the scan is complete, each of the discovered devices will be searched for Bluetooth services. Finally, a list of services will be presented for each device.
When the device and service scan is completed the user can test the different services by pressing the fire key. A menu containing the discovered devices and their corresponding services can be shown by pressing the Fire key. The user can test a service on a particular device by navigating with the Up and Down keys and pressing the Fire key, the emulator then tries to connect to the selected service. Note that all devices and services might not fit on the screen, by pressing Up or Down at the ends a new batch of devices will be shown.
No touch support is provided in this application.
OtaLoad demonstrates network connections, the downloading of an application "over-the-air", and the ability of one MoSync application to run another.
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
OtaLoad is a small application that downloads another MoSync application "over the air" (using HTTP), caches it in permanent storage and executes it. If there is already a copy of the application in the cache, the user is given the option to run it immediately or ask the server for a new version.
Important! Before running this application on the MoSync emulator or on a target device, do the following:
The target application must be a .comb file and must contain you compiled program and any resources (images, etc.) that it needs. The target application cannot contain any unloaded resources such as ubin or umedia. When you compile your target application, MoSync will put it in the /Output or /FinalOutput folder in your workspace. Find the .comb file and put on a webserver. If you haven't got a webserver you can use free services like http://www.dropbox.com to host your file.
Note: this API is experimental and currently available only in our nightly builds.
The MoSync Database API provides a set of syscall functions that enable you to create and access databases from your C/C++ code using the SQL query language. The Database API makes use of the SQLite database manager on the supported platforms (see Feature/Platform Support).
The MoSync Database API consists of a set of low-level syscall functions:
These are the main steps you need to follow when you use the Database API:
If you want to delete the database, delete the database file using the MoSync File API.
// Compute average age of persons in the database.
// Variable to hold the age of a person.
int age;
// Variable to hold the age sum.
int ageSum = 0;
// Number of persons.
int numberOfPersons = 0;
// Query all rows from the table named "person".
MAHandle cursor = maDBExecSQL(db, "SELECT age FROM person");
// Iterate of the result set.
while (cursor > 0 && MA_DB_OK == maDBCursorNext(cursor))
{
// Get the age of the current row (first field has index zero)
// and update variables.
maDBCursorGetColumnInt(cursor, 0, &age);
ageSum += age; ++ numberOfPersons;
}
// Compute average age.
if (numberOfPersons > 0)
{
float ageAverage = (float) ageSum / (float) numberOfPersons;
printf("Average age is: %.1f\n", ageAverage);
}
Our example application DatabaseTest which is included in the MoSync SDK demonstrates more features of the Database API.
Note: this example application is currently available only in our nightly builds.
This simple example application demonstrates how to use the MoSync Database API. This example works on all platforms supported by the API (see Feature/Platfom Support).
![]() | ![]() |
| Initial screen (MoSync Emulator) | After test (MoSync Emulator) |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
The project consists of one file, main.cpp, which contains commented source code to help understand the Database API. The example database used has a table called "pet" which contains data about pets. The database is created by the program. The tests made include making queries and checking that the results match the expected values.
There are several ways to save or read data from a mobile device. Reading and writing to the Internet can be done with Connection classes, but can be labourious without specific helper classes. The simplest way of saving your data is with a MoSync store. This tutorial looks at creating stores, writing to them and reading them.
The simplest way of saving your data is with a MoSync store. Stores are saved on the device, and are supported on all MoSync-supported platforms. A store is a single file that can easily be read from and written to. On Symbian S60 platforms, stores can be shared between different applications; on other platforms stores are private and separate.
To create a store, use the function maOpenStore(). This function takes two parameters, a const char* with the name of the store, and an int representing the options for the store. At the moment, there is only one option, you can choose to use it or not. This is defined as MAS_CREATE_IF_NECESSARY and it will create a new store if it doesn't exist.
The function maOpenStore() returns an MAHandle, a reference to the store that you can use with other functions.
MAHandle myStore = maOpenStore("MyStore", MAS_CREATE_IF_NECESSARY);If the store doesn't exist on the phone, it will be created and an MAHandle will be returned. If it does exist, it will just return the handle.
If the file cannot be created (for example, if there is no room on the device or there is a fault on the device) the value returned will match one of the STERR error values.
When you run your application in the MoRE emulator, you'll find that the stores are created in a folder called /stores in your output folder. Stores cannot currently be deployed with your application, and they have to be created at runtime.
If you want to find out whether or not a store exists, call maOpenStore() with the flags set to 0. The value STERR_NONEXISTENT is returned if the store doesn't already exist.
MAHandle testStore = maOpenStore("MyStore", 0);
if(myStore == STERR_NONEXISTENT)
{
// Store doesn't exist.
}
else
{
// Store does exist, and testStore is a valid handle to it.
}Stores don't have a sophisticated system for accessing and writing. They simply provide a method for saving application data to the device. Each time a store is written, it is overwritten. You cannot append to existing stores or edit the store directly. A store is written to from a data resource. This isn't resizable, but you can edit the contents, and you can write variables into it and read their values out again.
You can create new data resources at runtime, but you need to define an MAHandle for it first. You also need to know how much data you need to store. To create a new data resource, you use the command maCreateData(). This returns either RES_OK if there is enough memory to create it or RES_OUT_OF_MEMORY if not. You need to pass the MAHandle to it as a parameter, along with the size. You can create a new, empty MAHandle with the function maCreatePlaceholder().
String password = "p45sw0rd";
MAHandle myData = maCreatePlaceholder();
if(maCreateData(myData, password.length()) == RES_OK)
{
}You can now write data using the method maWriteData().
String password = "p45sw0rd";
MAHandle myData = maCreatePlaceholder();
if(maCreateData(myData, password.length()) == RES_OK)
{
maWriteData(myData, password.c_str(), 0, password.length();
}The maWriteData() function needs the MAHandle of the data resource, a pointer to the object you want to write, the offset from the beginning of the data resource and the length of the data you wish to write. This means that you can write the variable to where ever you want in the data resource. If you are writing several pieces of data, you'll either need to keep track of their relative positions in the data, or user DataHandler as described below to do it for you.
To write the data resource to the store, you use the method maWriteStore(). This takes the MAHandle of the store, and the MAHandle of the data.
int result = maWriteStore(myStore, myData);
Anything which was in the store previously is overwritten. If maWriteStore() returns > 0, then it has been written correctly. Other values should map to STERR. The one to watch out for here is STERR_FULL which means that there is no more storage left.
int result = maWriteStore(myStore, myData);
switch(result)
{
case > 0:
// Everything is fine, and the data is saved.
break;
case STERR_FULL:
// Failed, not enough space to save the data.
break;
case STERR_NONEXISTENT:
// Failed, the store doesn't exist!
break;
case STERR_GENERIC:
// Unknown error, possibly a device fault.
break;
}As a word of warning, although our example shows a password being written to a store you should be aware that this data is not completely private. Different systems provide different security measures. On a J2ME device, such data is fairly safe. A hacker would have to know a lot about the data to be able to access it. On S60 devices however, the user can freely browse the stores you've written using their file manager. Plain text stores can be opened up and read, and images you've written to the store can be displayed. If there is any sensitivity to the data you are writing, then it is strongly suggested that you encrypt it before you write it to the store.
When you've finished writing, you also need to close the store. This is done with the function maCloseStore().
maCloseStore(myStore, 0);
The second parameter (0 in this example), indicates whether or not the store should be deleted when you close it. If it is 0, you want to keep it; if you provide any other int value the store will be deleted. This is how stores are deleted, there is no other explicit function to delete stores.
void deleteStore(const char* storeName)
{
MAHandle store = maOpenStore(storeName, 0);
if(store != STERR_NONEXISTENT)
{
// Delete the store.
maCloseStore(store, 1);
}
}
Just as you write to stores from data resources, you read from them in the same way. The function maReadStore() copies the data in a store to a data resource, indicated by an MAHandle.
MAHandle myData = maCreatePlaceholder();
MAHandle myStore = maOpenStore("MyStore", 0);
if(myStore != MAS_NONEXISTENT)
{
// The store exists, so we can read from it.
int result = maReadStore(myStore, myData);
if(result == RES_OUT_OF_MEMORY)
{
// This store is too large to read into memory - error
}
}
Once the store has been read into the data resource, the values can be read out of it. Of course you need to know how much data to read: you can get the size of the data resource with the function maGetDataSize(), and then read the data using the method maReadData().
char password[maGetDataSize(myData)]; maReadData(myData, &password, 0, maGetDataSize(myData));
To use maReadData, you need to know how many bytes to read from the data resource. In the example above, the password is the only data being stored, so we can easily read out all of the data.
If the store contains both a username and a password, then it has to be a bit more sophisticated. You are probably not using fixed lengths for strings, so you need to store some extra data about how long each string is. If you put a byte containing the length of the string (or an int if it is a lot) before the actual string data, then you can read it back more easily. These are called Pascal strings or P-Strings, and you can also use them in MoSync resource files. To read out a P-string, you need to read the first byte.
// Read a p-string. byte len = 0; // You now need to track your position in the data. int position = 0; // Read the length. maReadData(myData, &len, position, 1);// Read 1 byte from position // Move onto the next byte. position++; // Read the string. char password[len + 1]; //String may not be null-terminated. maReadData(myData, &password, position, len); // Add a null-terminator. password[len+1] = '/0'; // Move the position on, so we're ready for the next read. position += len;
So, if you are reading more than one item out of the data, then you need to keep track of your place in the data.
Once you've finished with the data, you can release it from memory.
maDestroyObject(myData);
This deletes the data resource from memory, but does not destroy the store.
If you want to write several different values to the data resource, and then to the store, then there is a utility called DataHandler. This can help you write several values to the resource by tracking the offsets for you. You need to include the header file MAUtil/DataHandler.h
#include "MAUtil/DataHandler.h"
using namespace MAUtil;
...
String username = "m0sync";
String password = "p45sw0rd";
// Save the values to a data resource.
MAHandle myData = maCreatePlaceholder();
// The size of the data we need, including four bytes for
// the length of each string.
int size = username.length() + 4 + password.length() + 4;
if(maCreateData(myData, size) == RES_OK)
{
DataHandler* handler = new DataHandler(myData);
int usernameLength = username.length();
handler->write(&usernameLength, 4);
handler->write(username.c_str(), usernameLength);
int passwordLength = password.length();
handler->write(&passwordLength, 4);
handler->write(password.c_str(), passwordLength);
}
int result = maWriteStore(myStore, myData);
if(result > 0)
{
// Written successfully.
maCloseStore(myStore, 0);
}
else
{
// Failed, delete the store.
maCloseStore(myStore, 1);
}
As you can see from the above example, the DataHandler class takes away some of the complexity of reading and writing to stores, treating them more like a Java StreamReader or StreamWriter class. Unlike the example above where we were reading data out of the resource and having to keep track of the position, the DataHandler will manage it for us, and allow serial access.
MAFS is a reimplementation of the Standard C File I/O routines. It operates on either a binary image attached as a resource or using local stores for permanent storage. The binary image is actually a virtual filesystem generated using our tool Bundle. This comes in handy when porting applications that use a lot of data stored as files in the file system: just use the Bundle tool on the data folder to generate an image, attach it as a resource in the MoSync application, and mount it using the API functions provided.
A policy has been implemented to handle transparently the permanent storage of files. The fopen function first looks to see if the file exists in permanent storage. If that is the case, everything is written or read from that permanent storage. If no file is found in permanent storage, it continues to search for the file in the binary image. Reading from such a file is done by buffering data from the binary resource. Whenever such a file is written to, a copy of the data is created and saved as permanent storage.
Any reference documentation for the f* functions of the Standard C File API will work as reference, but we've also included documentation for them in our own reference documentation. There are two special functions for mounting the filesystem image and unmounting it. There can only be one filesystem image mounted at once.
Use the function setCurrentFileSystem to mount it and freeCurrentFileSystem to unmount it:
To show how it works, we begin by making a .bun file using the Bundle-tool.
First create a text-file:

Then generate the .bun-file:

Finally we include the .bun file as an unloaded binary resource:
.res R_TEST_FILESYSTEM .ubin .include "test.bun"
We can now write a small program that mounts the bun-file, opens and reads the text-file. Let's do it using the Moblet-architecture:
#include <MAUtil/Moblet.h>
#include <MAFS/File.h>
#include "MAHeaders.h"
using namespace MAUtil;
/*
* MyMoblet class that will show how to use File System.
*/
class MyMoblet : public Moblet
{
public:
MyMoblet()
{
char text[1024];
setCurrentFileSystem(R_TEST_FILESYSTEM, 0);
FILE *file = fopen("text.txt", "r");
if(!file) maPanic(1, "Could not open file!");
if(!fgets(text, 1024, file)) maPanic(1, "Could not read string!");
maSetColor(0x00ff00);
maDrawText(2, 2, text);
maUpdateScreen();
}
};
/*
* The main execution of the program starts here.
*/
extern "C" int MAMain()
{
Moblet::run(new MyMoblet());
return 0;
};
The MoSync SDK 2.6 includes an application profiler which can output performance statistics whenever you run the MoRE emulator. That makes it easy to track down performance issues and optimize your application.
To run a profiling session, right click on your project and select Profile As > Profile on MoSync Emulator.
Your
application will launch in the usual way, and a new tab will open in
the editor view. As soon as the application terminates, the profiling
data will show on this new tab. (At this time MoSync only supports
post-mortem profiling.)
There are two sub-tabs at the bottom of the view: Hotspots and Call Tree.
The Hotspots sub-tab lets you see which functions are taking the most time:
The Call Tree sub-tab shows which functions called which and the time spent in each:
The following columns are shown:
Click on any of the column headings to sort the results by that column. Click again to sort them in reverse order.
At the top right corner of the profiling view, there is a Quick Filter text box. Whatever you type there will be used to filter out functions. For example, to see all MoSync syscalls, type "ma". The filter is not case sensitive.
As well as the Quick Filter,
there are more advanced filtering options in the launch configuration
dialog box. To open the launch configuration dialog box, select Run > Run Configurations
from the main menu, then look for Profiled MoSync Emulated App in the
tree. You will see the application that you just launched there.
Highlight your application in the tree. Information about the application will be shown on the right. Select the Profiling tab. Here you will find the advanced filtering options:
To be able to shared profiling data, there is functionality to save a session to file. To do this, select File > Save As from the main menu and choose a file location. To open a profiling session, select File > Open and choose the file to open.
The MoSync SDK includes a powerful debugger that makes it easy to step through your code and get an overview of the state of your program as each statement executes.
Our debugger is a reimplementation of the GNU debugger. (For more information see: http://www.gnu.org/software/gdb/.) The debugger has been customized for MoSync and is fully integrated with MoSync's Eclipse-based IDE. The debugger allows you to:
Before you start the debugger, check that you have a Debug build configuration available, as follows:
button on the main toolbar. To break the execution of your program while it is running, click the Pause button: 
The application will enter a suspended state and you can inspect variables and see the stack-trace.
To stop the debugging session, click the Stop button: 
Note: if you happen to pause execution while inside an external library (such as the ones bundled with MoSync), you will not be able to see any source code: external libraries are not provided in the MoSync package.
To set a breakpoint, do one of the following:

Now click the
Debug button. When the program reaches the breakpoint, the program will be suspended and you will be able to debug the application from there - inspecting variables, stepping line-by-line, setting new breakpoints, and so on.
When execution reaches a breakpoint or you pause execution manually, you can step through the code line-by-line. This helps you see what code paths the application executes along and what values are assigned to variables after an expression has been evaluated. There are three buttons to help you step through the code:
Step Into executes a line. If the line is a call to a function, the debugger steps into it.
Step Over executes a line. If the line is a call to a function, the debugger executes the function call and breaks after it has returned .
Step Return continues the execution until the execution has returned from the current function.
When execution reaches a breakpoint or you pause execution manually, you can inspect the current content of variables. All the variables in the local scope are visible, including static variables, local variables, and arguments to functions. The content of structures and arrays can be expanded by pressing the + sign next to them.
To inspect a global variable you must add it as a watch expression. There are two ways to do this:


Right-click the name of a global variable in the editor, select Add Watch Expression , and click OK.
To be able to debug your program you need to have a debug build configuration with debugger-compatible build settings (for instance, all optimizations turned off).
This also applies to libraries, which is why special unoptimized debugging versions of the libraries need to be linked against instead (our debugging libraries all end with a capital "D").
A default debug build configuration will be created whenever you create a new project, but if you don't have one or you want to create another one, do the following:
To use your new Debug build configuration:
MoSync's test framework, Testify, simplifies the writing of complex test cases. You can use it to test several methods in a class, or just to write a single test for one function. There is not much more you need to do than write your tests (unfortunately it can't do that part for you) and press Run.
Note: From release 2.4, Testify replaces our previous test framework, MATest.
Before you start using Testify, we would like to introduce you to two important concepts: hooks and functors.
A hook is the mechanism you use to add your test or test listener to Testify at link time. It's just a class which you instantiate, preferably in the same file as your test. A typical use of a hook looks like this:
static Testify::TestHook hook( new MyTestCase( ) );
where Testify::TestHook is the actual hook, and MyTestCase is a test case that you've written.
The workhorse of Testify are the function or method wrappers, otherwise
known as "functors". If you've ever used the Boost library, you might
be familiar with the concept. A functor wraps a function or a method,
possibly along with its parameters, and can conveniently be called
without having to care about it's details.
A typical use of a functor in Testify looks like this:
Testify::bind( MyFunction )
or like this:
Testify::bind( MyFunction2, 1, 2.0f )
where MyFunction and MyFunction2 are functions in your code. The second case wraps two parameters which are to be passed to MyFunction2 while invoking it.
When it comes to methods, it's slightly different, you also have to
pass the object which the method belongs to as well, from inside the
class, the constructor for instance. It could look like this:
Testify::bind( &MyClass::myMethod, this )
and of course, in this case you can wrap parameters as well.
Once you've written your tests and their hooks and you are ready to run them, you only need to link to testify.lib and run your program as usual. Testify will take care of booting itself and running the tests, you do not need to care about the details. Any existing MAMain will be overridden (not overwritten) as long as you are linking to testify.lib.
Testify::TestFunction is used to run test functions. These are normally never used explicitly.
Testify::TestCase
is a class which is inherited when you need a bit more support, such as
set up and tear down before or after each test or each case.
Testify::TestListener
describes an interface that can be overridden to make your own custom
listeners to the events that Testify broadcasts. Events occur when a
test suite starts or ends, when a test starts or ends, or when a test
fails.
To add your own custom test listener to Testify, you use the hook concept, but this time you use Testify::ListenerHook, i.e:
static Testify::ListenerHook( new MyTestListener( ) );
Now let's look at how to write a simple test case. We'll start with the testing of a simple function. The steps involved are the following:
Example (in your application):
#include <testify/testify.hpp>
static void SumTest ( void )
{
for ( int i = -100; i < 100; i++ )
TESTIFY_ASSERT( (i-i) == 0 ); // This tests the boolean result of the assertion, this could be replaced with TESTIFY_ASSERT_EQUAL( i-i, 0 ). If the assertion is false, the test fails.
}
static Testify::TestHook myHook( Testify::bind( SumTest ), "Summation test" ); // The Test Case is being hooked in.The MoSync IDE provides full support for writing tests and executing them in the MoRE emulator.
The wizard will add two new build configurations to your project, one called Test and one called Test_Debug. These new build configurations are equivalent to the normal Release and Debug build configurations but include the designated test directories.
Both of the new test build configurations also include the Testify library (testify.lib). You can view the included libraries in your project's build setting (Project > Properties > MoSync Project > Build Settings > Paths and Files > Additional Libraries).
Once a test suite has been created and tests have been added as described in Creating a Test above, it's time to run them.
This application either renders a Quake 1 model or, in benchmark mode, measures the raw speed of the target device's CPU. This application is useful for comparing performance across devices.
![]() | ![]() |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
Behaviour
The behaviour of this application is controlled by the project's build configuration settings. Before building the project (or running it in the MoRE emulator), select one of the Render or Benchmark build configurations from the build configuration selector on the toolbar:

When built in Render mode, this application renders a wireframe animation and shows the current frames-per-second.
When built in Benchmark mode, this application calculates the average frames-per-second that the CPU can render and can be used as a benchmark score to test the performance of different devices.
This application provides a battery of tests to help you check the capabilities and limitations of a mobile device.
![]() | ![]() |
The code for this application is available from our Code repository.
When you run this application on a mobile device it will begin running through a series of tests. The application periodically prompt for user input. Device capabilities checked by the tests include:
Press 0 to exit the application.
* Some Java phones do not support battery charge level detection and keypad locking so these tests will fail on those devices.
This example application uses the debug logging and user panic functions in MoSync. Note: The purpose is to stress the system, and create an error. There is no output to screen.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When started, a pop up with the message “i is greater than 3” should appear.
None of the keys should be operable, just click OK on the popup to close it.
Throughout the execution of your program, the MoSync SDK can supply it with events. These are typically things which is happening to the phone. For instance, a button has been pressed or the screen has been touched. They also cover more advanced functions such as 'nothing has happened for a few seconds' or 'the phone has a new location from the GPS'.
This example is a simple "Hello World!" program. Console-type applications that exit when they finish are quite uncommon on mobile devices, so we show in this example how provide an event loop that keeps the application running until the user presses a key, in this case the zero (0) key.
It waits for an event to occur using the maWait() function. It then creates an MAEvent struct. These MAEvent objects contain the details of the event which has occurred. You can query them to see the type of event that has occurred, and also for any relevant data to that event, such as which key has been pressed, where the screen has been touched and what the new location is.
This example also shows how to detect close events. A close event is an event that is generated when a user attempts to forcibly terminate the application in some (platform-dependent) way, commonly by using some type of task manager. The purpose of the close event is to notify the application that it will be closed down very shortly (the exact amount of time being platform-dependent) and that it should perform emergency shutdown operations, such as saving critical data.
Here is an example in C:
/**
* This program shows that how can we handle events in MoSync.
* Here we are handling Close event using the C code.
*
* @file EventHandlingCProgram.C
*
* @author Chris Hughes
*/
#include <ma.h> // the standard MoSync header
#include <conprint.h> // provides printf()
int MAMain()
{
printf("Hello world!\n");
// Declare a MoSync event struct.
MAEvent MyEvent;
while(1)
{
// Wait for an event
maWait(0);
// Store the latest event in the event struct.
maGetEvent(&MyEvent);
// determine whether or not it is a key press
if(MyEvent.type == EVENT_TYPE_KEY_PRESSED)
{
// ...and whether it was the '0' key.
if(MyEvent.key == MAK_0)
{
// ...in which case we exit.
maExit(0);
}
}
else if(MyEvent.type == EVENT_TYPE_CLOSE)
{
// ...and also if we get a close event.
maExit(0);
}
}
return 0;
}
The function maGetEvent() populates your MAEvent object with the relevant data. You can then test the property type to see what is the event which has occurred. The values in type are defined in maapi.h, and cover key presses, screen touching, location, your application being sent to the background, the phone changing from landscape to portrait (and vice versa) and closing. By testing the type of the event, you only have to code for the events you are interested in.
Event handling in C++ can be quite different. You can make use of these C functions if you wish in C++ code, but if you are building an application on the MoSync SDK in C++ then there is an event-based framework already available to you.
The basis of this framework is the Moblet class, which is a C++ class which can handle your main application loop. The Moblet class already has virtual methods built in for handling common system events. including key presses, key releases, screen touches, screen movement and screen releases as well close events and 'custom events' for location and other events in the future.
If you are using Moblet to build your application, then you will create a new class which inherits from the Moblet base class. Moblet only provides virtual methods for event handling, so you'll have to supply your own code, but it is a much cleaner way of processing these system events.
For instance, if you want to capture the key presses from the C example above, you would implement keyPressEvent(int keycode, int nativeCode). You can then compare the value of button pressed with the value you are looking for.
As an aside, when you capture key presses you get two values. The first (referred to as keyCode) is a platform independent value. There is a long list of keys which you can handle in this way defined in maapi.h. In the example below, we are looking for the 0 key, so we can compare it with MAK_0. This way, we don't need to have code to check the key value for the 0 key on each platform. There are also some keys which may be implemented on just a few handsets. The Android 'back' key, or volume keys on a phone are not implemented in the platform independent way as their are so few phones which support them. You can still handle key presses from these buttons through, by accessing the nativeCode value of the button, which is platform specific.
And here is a similar example in C++ which makes use of MoSync's moblet framework:
/**
* This is another program for handling events using C++ syntax.
*
* @file EventHandlingCPPProgram.cpp
*
* @author Chris Hughes
*/
#include <MAUtil/Moblet.h>
using namespace MAUtil;
// Moblet class declaration.
class MyMoblet : public Moblet
{
public:
MyMoblet()
{
maSetColor(0xFFFFFF);
maDrawText(0, 32, "Hello World!");
maUpdateScreen();
}
// Handles key press event.
void keyPressEvent(int keyCode, int nativeCode)
{
if(keyCode == MAK_0)
{
closeEvent();
close();
}
}
// Handles key release event.
void keyReleaseEvent(int keyCode, int nativeCode)
{
}
};
/*
* Programs main functionality starts here.
*/
extern "C" int MAMain()
{
Moblet::run(new MyMoblet());
return 0;
}
It's not just Moblet which has methods for handling system events. In the MoSync SDK User Interface Library MAUI, the Screen class also has similar methods for handling system events, so you can process these events differently depending on which part of your application the user is using.
HelloMoblet is a well-commented example application for beginners. It demonstrates how to use MoSync's Moblet framework to wrap your application to ensure timely response to key events.

This example is included in the MoSync SDK installation in the /examples/Moblet folder. For information on importing the examples into your workspace, see Importing the Examples.
This application provides a very basic example of how to use MoSync's Moblet framework to detect key events and use timers. When started, it displays the text "Hello Moblet!" The text can be moved around using the joystick or you can click on the screen and the text will jump to that position.
The code is very well commented so that you can see what's happening at each step. Examine the source code of the application (in the file main.cpp) to learn how the program works.
This simple application shows how to handle multitouch events so that your applications can react to pinches, swipes and rotatation. This application is based on the MoSync Moblet framework.

This example is included in the MoSync SDK installation in the /examples/Moblet folder. For information on importing the examples into your workspace, see Importing the Examples.
When the application runs, the screen is intially blank. Touch the screen in one, two, or more places. (If you are running the application in the MoRE emulator, right-click on the screen to start MoRE's multitouch emulation mode.) At each touch point a red rectangle will be displayed, along with the ID of the touch point.
(Note that only some touchscreen devices support multitouch, and that the maximum number of touch points a device can handle varies: iPhone = 5, iPad = 11, HTC Wildfire = 3, Samsung Galaxy S = 5, MoRE emulator = 2.)
Try lifting one or more fingers, and pinching, skewing, swiping - the rectangles will follow your touches. Touch IDs are reused when you lift a finger and then touch again.
Examine the source code of the application to learn how the program works. Note the use of MAUtil::Map to store the collection of touch IDs and their coordinates.
This tutorial gives you a short introduction to developing mobile applications with MoSync. If you’ve never created a mobile application with MoSync before, this is a great place to start. In this tutorial, we’re going to create a new project in Eclipse, create a new screen, and interact with the user.
The MoSync platform can be used in two very broad ways. Firstly, if you’re porting an existing C game to mobile, or writing a new one in C or C++, then MoSync provides a very lightweight compatibility API to get your game running on as many phones as possible, and as quickly as possible. This provides low-level APIs to sound and screen which you can use. More about this approach is explained in the topic Classic Procedural Applications.
If you are doing something which doesn’t require direct access to graphics, then there is a higher-level set of APIs and an event-based environment ready for you to work with: Moblets. Moblets are a quick way to create rich and attractive mobile applications.
The MoSync SDK includes a complete IDE (integrated development environment) that you can write your programs in. The MoSync IDE is based on a popular open-source IDE called Eclipse. Java developers will be familiar with the IDE concept already, and anyone with experience of Visual Studio or other similar system will find MoSync very easy to work with.
To get started with this tutorial, Launch MoSync then close the Welcome page. When you’ve done that, you’ll have a screen which looks like this:

Here you can see all the main views of the IDE (in Eclipse terminology, each panel is called a "view"). On the left is the Project Explorer view which will soon show your project's folders and files, in the centre is the Edit view where you will write code, and on the right are the Device Profiles view and (hidden behind it) the Finalizer view.
Now select New > Project from the IDE's File menu. You will get a dialog box like this:

Select MoSync Project and then press then Next button.
Now you need to give your application a name. For this tutorial, call it MoSyncDemoApp:

Note: do not use spaces or any character which isn't a letter or a number into the application name. It can cause problems with the compiler later if the file path has a space in, or a character that can be interpreted differently.
On the next screen, you’ve got a series of options for the type of application we want to use. Although there is an option to create a Moblet project, we want to select the MAUI Project.

MAUI is the moblet user interface (UI) library from MoSync. It contains common UI controls you can use in your application. We will be creating some MAUI controls in this tutorial, and later tutorials will delve much deeper into the inner workings of MAUI.
There, you should now have a screen which looks like this, and is waiting for you to enter some code.

To create our Moblet application, we have to use some controls from the MAUI library. The first one we want to use is the Screen control. This is a canvas which we can put other controls on, and can be shown to the user.
The code that the project wizard creates looks something like this:
#include <MAUtil/Moblet.h>
#include <MAUI/Screen.h>
#include <MAUI/Label.h>
using namespace MAUtil;
using namespace MAUI;
/**
* MAUI is short for MoSync API User Interface.
*
* A Screen is a MAUI object that holds widgets.
*/
class MAUIScreen : public Screen
{
public:
/**
* Create widgets in the constructor.
*/
MAUIScreen()
{
mBackgroundArea = new Label(
0, // Left
0, // Top
0, // Width
0, // Height
NULL // Parent widget
);
mBackgroundArea->setBackgroundColor(0xFFFFFF);
mTouchArea = new Label(
100, // Left
100, // Top
50, // Width
50, // Height
mBackgroundArea // Parent widget
);
mTouchArea->setBackgroundColor(0x000000);
// Set the main widget of the screen. This will
// resize the widget to fit the screen.
setMain(mBackgroundArea);
}
/**
* Deallocate objects in the destructor.
*/
virtual ~MAUIScreen()
{
delete mBackgroundArea;
delete mTouchArea;
}
/**
* Called when a key is pressed.
*/
virtual void keyPressEvent(int keyCode, int nativeCode)
{
// Default color is white.
int color = 0xFFFFFF;
switch (keyCode)
{
case MAK_1:
color = 0xFF5555;
break;
case MAK_2:
color = 0x55FF55;
break;
case MAK_3:
color = 0x5555FF;
break;
}
// Set the new background color.
mBackgroundArea->setBackgroundColor(color);
}
/**
* Called when the screen is touched.
*/
virtual void pointerPressEvent(MAPoint2d point)
{
// Center the touch area at the pointer position.
mTouchArea->setPosition(point.x - 25, point.y - 25);
// We need to repaint the parent when a child
// widget is changed.
mBackgroundArea->requestRepaint();
}
private:
Label* mBackgroundArea;
Label* mTouchArea;
};
/**
* A Moblet is a high-level class that defines the
* behaviour of a MoSync program.
*
* To use MAUI you need a Moblet, but a Moblet can
* be used with or without the MAUI library.
*/
class MAUIMoblet : public Moblet
{
public:
/**
* Initialize the application in the constructor.
*/
MAUIMoblet()
{
mScreen = new MAUIScreen();
mScreen->show();
}
/**
* Deallocate objects in the destructor.
*/
virtual ~MAUIMoblet()
{
delete mScreen;
}
/**
* Called when a key is pressed.
*/
void keyPressEvent(int keyCode, int nativeCode)
{
if (MAK_BACK == keyCode || MAK_0 == keyCode)
{
// Call close to exit the application.
close();
}
}
private:
MAUIScreen* mScreen;
};
/**
* Entry point of the program. The MAMain function
* needs to be declared as extern "C".
*/
extern "C" int MAMain()
{
Moblet::run(new MAUIMoblet());
return 0;
}
This isn’t a tutorial on the C language, there are plenty of those already, but we can break this down into three recognisable sections.
Firstly, at the top of the code is the declaration of a new class MAUIScreen, which is inheriting from the MAUI Screen class. This is where we are going to do our work today.
Beneath that is the class MAUIMoblet. This is some standard code which creates a new instance of MAUIScreen and calls the show() method, which displays the screen on the mobile.
Finally, at the end is the main function (called MAMain) which creates our new Moblet code.
The Moblet code exists to give the developer access to some basic phone functions. It manages the environment, and it can tell you when a key has been pressed, when the screen has been touched, what the screen size is, and so on. By basing our application on the Moblet code, we automatically have access to all of these things, regardless of the device it is going to run on. We are not going to have to change any code between an Android device, Symbian device, a Windows Mobile device, or a phone running J2ME.
To create our screen, we need to look at the code for MAUIScreen:
class MAUIScreen : public Screen
{
public:
/**
* Create widgets in the constructor.
*/
MAUIScreen()
{
mBackgroundArea = new Label(
0, // Left
0, // Top
0, // Width
0, // Height
NULL // Parent widget
);
mBackgroundArea->setBackgroundColor(0xFFFFFF);
mTouchArea = new Label(
100, // Left
100, // Top
50, // Width
50, // Height
mBackgroundArea // Parent widget
);
mTouchArea->setBackgroundColor(0x000000);
// Set the main widget of the screen. This will
// resize the widget to fit the screen.
setMain(mBackgroundArea);
}
/**
* Deallocate objects in the destructor.
*/
virtual ~MAUIScreen()
{
delete mBackgroundArea;
delete mTouchArea;
}
/**
* Called when a key is pressed.
*/
virtual void keyPressEvent(int keyCode, int nativeCode)
{
// Default color is white.
int color = 0xFFFFFF;
switch (keyCode)
{
case MAK_1:
color = 0xFF5555;
break;
case MAK_2:
color = 0x55FF55;
break;
case MAK_3:
color = 0x5555FF;
break;
}
// Set the new background color.
mBackgroundArea->setBackgroundColor(color);
}
/**
* Called when the screen is touched.
*/
virtual void pointerPressEvent(MAPoint2d point)
{
// Center the touch area at the pointer position.
mTouchArea->setPosition(point.x - 25, point.y - 25);
// We need to repaint the parent when a child
// widget is changed.
mBackgroundArea->requestRepaint();
}
private:
Label* mBackgroundArea;
Label* mTouchArea;
};
There is some handy code here already, which creates two labels BackgroundArea and TouchArea. We will craete another MAUI control, a Label. Just like all the other environments, this label control will let you put text on the screen.
Lets' add some more code in the MAUIScreen constructor and put another label control in it. To do this, we first need to provide our program with a font. There is a separate more detailed tutorial available for creating new fonts in your project "Creating New Fonts".
In MAUI, fonts are bitmap fonts, and the tools to create new fonts have been provided in the download. Creating new fonts will be the subject of another tutorial though, so here we will simplify things by using a font which has already been created.
To include the font in our application, we need to create a resource file. A resource file is a file which contains the paths to all of the external resources that an application requires, including fonts, images, and sounds, which are then packaged up with your application.
To create a resource file, right-click on the name of your application on the left hand side of the Eclipse window, and select New > Other. From the dialog box that appears, select MoSync Resource File.

Click Next. Type the file name res.lst, then click Finish. You will see the new file appear in the MoSyncDemoApp project.
Open up res.lst and add the following entry.
.res MYFONT .bin .include "../../examples/MAUI/MAUIex/pretty.mof"
MoSync font files have the .mof extension. This one, pretty.mof, is supplied with one of the examples.
Obviously, you’ll need to change the path here if you’ve installed MoSync anywhere other than C:\MoSync. Note that the path to the font file cannot be absolute. Furthermore you must use either forward slashes in the path or escaped backslashes like this:
.include "..\\..\\examples\\MAUI\\MAUIex\\pretty.mof"
Now that you’ve included the font file in the project, you can reference it your program. To do this, you need to add an additional #include directive. You’ll also need to reference the Font class. Add these lines to the existing list of includes:
#include <MAUI/Font.h> #include "MAHeaders.h"
MAHeaders is a special file which is created when you build the application. It provides a reference (known as an MAHandle) to your program.
With these included, we can create a font in the application:
Font* f = new Font(MYFONT);
And we can use it to create a label:
Label* l = new Label(0, 0, 50, 50, NULL);
l->setFont(f);
l->setCaption("Welcome to my mobile application");There is another way where we can create all of this on one line, but that is for another tutorial, or for you to explore yourself.
If you now click the Run button on the toolbar, you’ll see your first mobile application!

You can trace the execution of your application with a command lprintfln(). This sends a formatted line to debug console in Eclipse. You need to add an include directive as:
#include <conprint.h>
If you add the line:
lprintfln("Starting");as the first line in the constructor code, then you will see this in the console window in Eclipse. Use lprintfln as you write your program so you can see what it being executed.
You can now use the Moblet interfaces to interact with the user. We can capture key presses and cause different things to happen. In our application, we want it to exit.
There are five basic events for user interaction. Key press, key release, screen touch, screen drag and screen release. Each of these events has already been set up for you, you just need to write some code to react to these events in the screen. In fact, in the Moblet class, you can even see example stubs for these. However, I want to capture key presses in the MyScreen class
void keyPressEvent(int keyCode)
{
lprintfln("Caught a key press");
if(keyCode == MAK_5)
maExit(0);
}The function ‘keyPressEvent’ has already been set up for you by the Moblet, you just need to implement it. By adding this code to the screen, we can capture key presses. Every time a key is pressed, then it will write a line to the console, so you can see it working. The MoSync APIs also contain constants representing all of the keys. You can find the full list in the maapi.h File Reference in the MoSYnc API Reference Guide.
If the key pressed is 5 on the keypad, then we’re going to do a brute force exit of the program. There is a Moblet::close() method which is probably preferred, but this will do for our demonstration.
There we have it, a mobile application. You now got a basis for creating your own applications. If you want to check what you’ve got against my program, here is my listing:
#include <MAUtil/Moblet.h>
#include <MAUI/Screen.h>
#include <MAUI/Label.h>
#include <MAUI/Font.h>
#include "MAHeaders.h"
#include <conprint.h>
using namespace MAUtil;
using namespace MAUI;
class MyScreen : public Screen {
public:
MyScreen() {
lprintfln("Starting");
Font* f = new Font(MYFONT);
Label* l = new Label(0, 0, 50, 50, NULL);
l->setFont(f);
l->setCaption("Welcome to my mobile application");
setMain(l);
}
~MyScreen() {
// todo: delete main widget of this screen
}
void keyPressEvent(int keyCode)
{
lprintfln("Caught a key press");
if(keyCode == MAK_5)
maExit(0);
}
private:
};
class MAUIMoblet : public Moblet {
public:
MAUIMoblet() {
// initialize
screen = new MyScreen();
screen->show();
}
void keyPressEvent(int keyCode) {
// todo: handle key presses
}
void keyReleaseEvent(int keyCode) {
// todo: handle key releases
}
MyScreen* screen;
~MAUIMoblet() {
delete screen;
}
};
extern "C" int MAMain() {
Moblet::run(new MAUIMoblet());
return 0;
};
This example application catches key events and displays the keycodes of pressed keys.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
The screen says "Hello moblet!", after which the application awaits key presses. Each key (except the zero or right-softkey) will have its key codes (presscodes) echoed on-screen:
The application also keeps count of the number of keys that have been pressed and released. Key combinations, such as SHIFT-A, will have two or more consecutive presscodes and releases as shown in the example screen above.
There is no touchscreen support in this example, it just works with the physical keys of the device.
Motris is a variation of the old classic game with a similar name.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
A classic game. Highest scores are saved on the server, if a network connection is available.
This application requires the device to have a physical keyboard.
This program tests simple graphics on the phone, catching a key event and adding some action.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
Pressing FIRE bounces the yellow block.
The MoSync Facebook Library implements most of the Facebook Graph API. Here we describe how to connect to Facebook through the MoSync Facebook library, retrieve information about them, post links, vidoes and other object types, create new albums, and a whole host of other cool operations.
Facebook
is a modeled as a social graph. Its official API, the Facebook Graph API,
represents the objects in the graph (people, photos, albums, events...)
and the connections between them (friend relationships, photo tags...).
Every
object in the social graph has a unique ID. You can fetch any object
from Facebook if you know the ID. Alternatively, people with usernames
can be accessed using their username as an ID. There is also a special
identifier "me" which refers to the current user.
You
can retrieve the public information about a user (first name, last
name, profile picture) by using the ID or the username. To get
additional information about a user, you must first get their permission
for which you need to get an access token. After you obtain the access
token, you can perform authorized requests and publish on behalf of that
user.
The MoSync Facebook Library defines a FacebookManager class
that provides the interface between the Facebook platform and your own
application. Use this class if you want to retrieve data, publish on
Facebook, or retrieve an access token for your application.
Authentication
involves retrieving the access token and asking for extended
permissions. For the official Facebook documentation on the
authorization flow see: http://developers.facebook.com/docs/authentication/.
Retrieving a user access token
allows your application to access a user’s basic information (that is
information that is available publicly or by default on Facebook). If
your application needs more than this basic information, you must
request specific permissions from the user.
To get the access token from Facebook you must first redirect the user to the Facebook OAuth Dialog. With the MoSync Facebook Library this is very easy:
String appID = "13234625675"; //the application id mFacebookManager = new FacebookManager( app_ID ); String oAuthUrl = mFacebookManager->getOAuthUrl(); mLoginScreen = new FacebookLoginScreen(); mLoginScreen->setUrl ( oAuthUrl ); mLoginScreen->show(); //displays the login screen
After the user logs in, we are redirected to the
redirect_uri. The access token is passed in the redirect_uri. The redirect_uri must be parsed to get the access token. An example of how to extract the access token can be found in our FacebookDemo example application in FacebookDemoMoblet::customEvent.
After retrieving the access token, we must send it to the FacebookManager:
mFacebookManager->setAccessToken(accessToken);
You must request specific permissions from the user if your app needs more information than the user has made available to everyone on Facebook. To do this, pass the FacebookManager the permissions you need.
Note: If your application also needs permissions, you must pass those permissions to FacebookManager when it is first created.
In the MoSync Facebook Library we specialize the GetPermissionsFor template class for each Facebook object type. It is used to fill a Set object with the permissions that are needed to make connections to a Facebook object or to publish an object.
MAUtil::Set<MAUtil::String> permissions;
To get the permissions needed to retrieve a Note object for the current user or current user’s friend (also for the connections of Note objects) we use:
// "user_notes" "friends_notes" GetPermissionsFor<Note>::retrievingData(permissions);
To get the permissions needed to publish a note on behalf of the user or user’s friend we use:
//"create_note", "publish_stream" GetPermissionsFor<Note>::publishingData(permissions);
To get all the permissions available, so that we can make any request (retrieve data, connections, and publish), we use:
// "user_notes" , "friends_notes", "create_note", "publish_stream" GetPermissionsFor<Note>::allPosibleRequests(permissions);
You can also just get the permissions needed to retrieve a field from a user object (for example, a biography), or for a connection, as we show in the example below:
MAUtil::Set<MAUtil::String> permissions;
permissions.insert("offline_access"); //ask for a access_token that doesn’t expire
GetPermissionsFor<User>::Retrieve::onlyConnections(permissions);
GetPermissionsFor<User>::publishingData(permissions);
GetPermissionsFor<Album>::allPosibleRequests(permissions);
GetPermissionsFor<Checkin>::allPosibleRequests(permissions);
GetPermissionsFor<Comment>::allPosibleRequests(permissions);
GetPermissionsFor<Note>::allPosibleRequests(permissions);
GetPermissionsFor<Photo>::allPosibleRequests(permissions);
GetPermissionsFor<Post>::allPosibleRequests(permissions);
//the app id that is generated when you create your application
String application_ID = "7125765764";
mFacebookManager = new FacebookManager(application_ID, permissions);
String oAuthUrl = mFacebookManager->getOAuthUrl();
mLoginScreen = new FacebookLoginScreen();
mLoginScreen->setUrl(oAuthUrl);
mLoginScreen->show(); //this displays the login screenOur Facebook Library implements most of the Facebook objects described in the Graph API documentation (http://developers.facebook.com/docs/reference/api/). The implementation can be found in /Facebook_lib/GraphAPI/GetFacebookObjects/FacebookObjects in your installed MoSync package.
Objects currently implemented include:
You can access the properties of an object using the FacebookManager. To retrieve an object your application has to register as an ObjectRequestListener with the FacebookManager. To do this, we inherit from ObjectRequestListener and override the functions we are interested in.
If we want to retrieve User objects, we override void facebookObjectReceived(const User &). If we want to retrieve Album objects, we override void facebookObjectReceived(const Album &).
For example, to access the public information about a User, with the username btaylor and an album with the id 99394368305 (Coca-Cola's wall photos):
class MyApplication: public ObjectRequestListener
{
public:
// ObjectRequestListener override. This function will be called by the
// FacebookManager when a User object is retrieved from Facebook
virtual void facebookObjectReceived(const User &object);
// ObjectRequestListener override. This function will be called by the
// FacebookManager when an Album object is retrieved from Facebook.
virtual void facebookObjectReceived(const Album &object);
//ObjectRequestListener override. Called when the request fails.
virtual void queryError(int code, const MAUtil::String &path);
};
String application_ID = "13234625675"; //the application id
mFacebookManager = new FacebookManager( application_ID );
mFacebookManager->setObjectRequestListener(this);
mFacebookManager->requestObject<User>(btaylor);
mFacebookManager->requestObject<Album>(99394368305); When the response from Facebook is received, the JSON data is parsed and converted to the type of object we requested (e.g User). FacebookManager sends this object to the listener.
We
use FacebookManager to retrieve connections for an object. To make a
connection request we need to know the ID of the object. If the Facebook
object is the current user, we can use me
instead of an ID. We also need to inherit from ConnectionsManagerListener and register with the FacebookManager as a listener.
To see what connections are available for an object we use the Connections template class found in /GetConnections/Connections.h. The template is specialized for every Facebook object type defined by the library.
To see what connections are available for an album, we use the Connections<Album>
class. Connections<Album>
has four static functions that correspond to the four connections an
Album can have: likes, photos, comments, picture. Each returns a string
representing the keyword for that connection. For example, Connections<Album>::likes() returns "likes".
The Connections<Checkin>
class defines two functions that return the keywords for the two
connections that a Checkin has (likes and comments), so to ask for all
the connections a Checkin we use:
mFacebookManager->requestConnection( ckeckin_id, Connections<Checkin>::likes() ); mFacebookManager->requestConnection( checkin_id, Connections<Checkin>::comments() );
To request the albums, feed, and notes connections for the current user, and also request the comments connections for one of the user’s albums we use:
class MyApplication : public ConnectionsManagerListener
{
public:
MyApplication();
//The following functions are ConnectionsManagerListener overrides.
//connType parameter - represents the keyword for the connection we requested.
//For the news feed for example it will be "feed".
//objectId parameter - string representing the id of the object for which
// we requested the connection.
//Function called by FacebookManager when the "albums" connection
//is retrieved from Facebook.
void received( const Vector<Album> &albums, const String &connType, const String &objectId );
//Function called by FacebookManager when the "feed" connection
//is retrieved from Facebook.
void received( const Vector<Post> &posts, const String &connType, const String objectId );
//Function called by FacebookManager when the "notes" connection
//is retrieved from Facebook.
void received( const Vector<Note> ¬es, const String &connType, const MAUtil::String objectId ) ;
//Function called by FacebookManager when the "comments" connection
//is retrieved from //Facebook
void received( const MAUtil::Vector<Comment> &comments, const MAUtil::String &connType, const String &objectId )
//override of ConnectionsManagerListener called when the request failed
void queryError(int code, const MAUtil::String &path) ;
};
MyApplication::MyApplication()
{
//the application id
String application_ID = "13234625675";
mFacebookManager = new FacebookManager( application_ID );
mFacebookManager->setConnectionRequestListener(this);
//request for the albums connection for the curent user
mFacebookManager->requestConnection( Connections<User>::albums(), "me" );
//request for the notes connection for the curent user
mFacebookManager->requestConnection( Connections<User>::notes(), "me");
//request for the feed connection for the curent user
mFacebookManager->requestConnection( Connections<User>::feed() , "me");
}
void MyApplication::received( const Vector<Album> &albums, const String &connType, const String &objectId)
{
Album firstAlbum = albums[0];
mFacebookManager->requestConnection( Connections<User>::comments(), firstAlbum.getId() );
}We can request only the fields you want from an object. For example, if we just want to retrieve the name and ID of all of the user’s albums we do not want any other fields. To do this we call the overload function requestConnection and pass it a vector with jus the fields we want:
Vector<String> fields;
fields.add("id");
fields.add("name");
mFacebookManager->requestConnection("albums", fields, "me");We use FacebookManager to publish to Facebook or to delete Facebook objects. To get the result of a publish or delete request, we inherit from the PublishingListener class and register with the FacebookManager as a PublishingListener:
class MyApplication: public PublishingListener
{
public:
//PublishingListener override
//This function is called when a remove or an unlike request
//was completed successfuly
void publishingResponseReceived(bool success, const String &path);
//PublishingListener override
//This function is called when a new Facebook object was created successfully.
void publishingResponseReceived(bool const String &newObjectId, const String &path);
//PublishingListener override. Called when the request fails.
virtual void queryError(int code, const MAUtil::String &path);
};
String application_ID = "13234625675"; //the application id
mFacebookManager = new FacebookManager( application_ID );
MyApplication *myApp = new MyApplication();
//register as a PublishingListener, so that MyApplication is informed
//about the result of the publish request.
mFacebookManager->setPublishingListener(myApp); To like a Facebook object we call the FacebookManager function void Like(const String &id). The "id" parameter is the ID of the object to be liked. To like an album, for example, we use:
mFacebookManager->like( album.getId() );
Similarly, to unlike a Facebook object we call the FacebookManager function void Unlike(const String &id).
mFacebookManager->unlike( comment.getId() );
Here comment represents some Comment object we retrieved from Facebook.
Various types of objects can be added to Facebook through the functions in the FacebookManager class. For a comprehensive list of the functions available through this class, see the MoSync API Reference.
Objects that can be added include:
To add a comment on a Facebook object we call the FacebookManager function addComment:
String myMessage = "I like this post"; mFacebookManager-> addComment(post.getId(), myMessage);
Here we use post.getId to identify the object to which we wish to add the comment. Similarly we can use the FacebookManager function addUser to add a User object to a FriendList:
mFacebookManager->addUser( myFriendList.getId(), "7692649746983");
Here "7692649746983" is the unique ID of the friend we want to add.
Some
functions in FacebookManager are a little more complicated. To add an
event on behalf of the current user (or one of that user's friends) we
use the function addEvent which requires several parameters, along with some optional ones:
void addEvent(
const MAUtil::String &USER_ID, //mandatory
const MAUtil::String &eventName, //madatory
const UnixTimeStamp &eventStart_time, //mandatory
const UnixTimeStamp &eventEnd_time = UnixTimeStamp(), //optional
const MAUtil::String &message= "", //optional
const MAUtil::String &location = "", //optional
const MAUtil::String &privacyType = "OPEN"); //optional
For example:
//event name
String eventName = "party";
//event starts in 06/12/2012 at 8:15 :30
UnixTimeStamp startTime(Date("2012", "12", "6"), Time("8","15","30"));
//event ends in 06/12/2012 at 11:20:00
UnixTimeStamp endTime(Date("2012", "12", "6"), Time("11", "20","00"));
//the event’s description
String eventDescription = " MoSync annual Christmas party";
//the event takes place in Stockholm
String eventLocation = "Stockholm";
mFacebookManager->addEvent( "me",
eventName,
startTime,
endTime,
eventDescription,
eventLocation);To add a Post on the user’s wall (or on one of the user's friends walls) we call addPostOnWall:
void addPostOnWall(
const MAUtil::String &ID, //mandatory
const MAUtil::String &message, //mandatory
const MAUtil::String &link, //mandatory
const MAUtil::String &name = "", //optional
const MAUtil::String &caption = "", //optional
const MAUtil::String &description = ""); //optional
For example:
mFacebookManager->addPostOnWall ( "me", //id
"Post added with MOSYN SDK", //message
"http://www.youtube.com/watch?v=FL7yD-0pqZg", //link
"New Post :)", //name
"Link from You Tube" //caption
"Testing adding a post on wall with MOSYNC_SDK"); //descriptionThe result will be a wall post that looks something like this:
FacebookManager provides a set of functions for removing objects the Graph API. The objects that can be removed include:
To remove a user from a FriendList we call the FacebookManager
function removeUserFrom:
String myFriendListID = "1234567"; String friendID = "0101010101"; mFacebookManager->removeUserFrom ( myFriendListID, friendID);
In this example we retrieve albums, posting a link on the user's wall, post a link for all the user's friends, add a like and a comment to an album, and delete a FriendList.
class MyApplication: public MAUtil::Moblet, public ConnectionsManagerListener, public PublishingListener
{
public:
MyApplication();
// ConnectionsManagerListener overrides
/*
* This function is called when a "albums" Connection was completed sucessfully
*/
virtual void received(const MAUtil::Vector<Album> &albums,
const MAUtil::String &connType,
const MAUtil::String &objetcId);
/*
* This function is called when the "likes", "movies", "music", "books", "accounts",
* "activity", "friendlists", "interests" and "television" Connection was requested.
* @param connType - the ConnectionType. It can have the following values: "likes",
* "movies", "music", "books", "accounts", "activity", "friendlists", "interests"
* and "television"
*/
virtual void received(const MAUtil::Vector<CategoryData> &likes,
const MAUtil::String &connType,
const MAUtil::String &objetcId);
/*
* This function is called when the "friends", "members" or "tags" Connection
* was requested.
* @param connType - the ConnectionType. It can have the following values:
* "friends", "members" or "tags"
*/
virtual void received(const MAUtil::Vector<IdNamePair> &friends,
const MAUtil::String &connType,
const MAUtil::String &objetcId);
/*
* This function is called when a Connection was requested, and the request failed
*/
virtual void errorReceivingConnection(int code,
const MAUtil::String &connType,
const MAUtil::String &id);
// PublishingListener overrides
/ *
* This function is called when a remove or an unlike request was
* completed sucessfully.
*/
virtual void publishingResponseReceived(bool success, const MAUtil::String &path);
/*
* This function is called when a new object was created successfully
* (Album, Like, Comment, StatusMessage etc).
*/
virtual void publishingResponseReceived(const MAUtil::String &data,
const MAUtil::String &path);
/*
* This function is called when a publish/remove request failed
*/
virtual void queryError(int code, const MAUtil::String &path);
private:
void requestAlbumsConnection();
void addComment(const String &id);
void addLike(const String &id);
void postLinkOnWall(const String &id);
void requestFriendListsConnection();
void deleteFriendList(const String &id);
private:
FacebookManager *mFacebookManager;
};
MyApplication::MyApplication()
{
String applicationId = "265721237478169";
mFacebookManager = new FacebookManager(applicationId);
mFacebookManager->setAccessToken("476927849827395873465923695798723");
//register as a ConnectionManagerListener so that we retrieve the
//requested data from FacebookManager
mFacebookManager->setConnectionRequestListener(this);
//register as a PublishingListener so that we are informed by the
//FacebookManager about the result of the publish request
mFacebookManager->setPublishingListener(this);
//request the albums of the user. We will add a comment and a like
//to the first album
requestAlbumsConnection();
//request the FriendLists of the user. We will delete the first FriendList
requestFriendListsConnection();
//Posting a link on wall for the user
// We post for the current user (that logged in), so we can use "me" as an id.
postLinkOnWall("me");
}
void MyApplication::requestAlbumsConnection()
{
mFacebookManager->requestConnection("albums");
}
void MyApplication::addComment(const String &ID)
{
mFacebookManager->addComment("Testing adding a comment with MOSYNC SDK", ID); //adding the comment to the object with the id "ID"
}
void MyApplication::Like(const String &ID)
{
mFacebookManager->Like(ID); //like the Facebook objetc with the id "ID"
}
void MyApplication::postLinkOnWall(const String &id)
{
mFacebookManager->addLinkOnWall( id, //the id.
"http://www.mosync.com/", //the link we want to post
"Testing posting a link on wall with MOSYNC SDK"); //the message to display.
}
void MyApplication::requestFriendListsConnection()
{
mFacebookManager->requestConnection("friendlists");
}
void MyApplication::deleteFriendList(const String &id)
{
mFacebookManager->removeFriendList(id);
}
//Retrieving albums
void MyApplication::received(const MAUtil::Vector<Album> &albums,
const MAUtil::String &connType,
const MAUtil::String &objetcId)
{
Album album = albums[0];
addComment( album.getId() ); //Adding a comment to an album
addLike( album.getId() ); //Adding a like to an album
}
void MyApplication::received(const MAUtil::Vector<CategoryData> &friendlists,
const MAUtil::String &connType,
const MAUtil::String &objetcId)
{
if( connType == "friendlists" )
{
deleteFriendList( friendlists[0].getId() ); // f) deleting a FriendList.
}
}
void MyApplication::received(const MAUtil::Vector<IdNamePair> &friends,
const MAUtil::String &connType,
const MAUtil::String &objetcId)
{
if( connType == "friends" )
{
for (int i=0; i<friends.Size(); i++) //Posting a link for all the user's friends
postLinkOnWall( friends[i].getId() );
}
} This example application demonstrates how to log on to Facebook from your application, how to retrieve information, and how to manage posts (publish and delete posts). This application makes use of the MoSync C++ Facebook Library, C++ NativeUI Library, and C Widget API.
This application only works on Android and iOS (iPhone) devices.
![]() | ![]() | ![]() |
| Log on screen in the WebView widget | Information menu with NativeUI controls | Retrieving a photo album |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When the application starts on a device with an Internet connection, the user is shown the log on screen to Facebook displayed in a WebView widget. After the user logs on to Facebook, the main menu is displayed providing the user with a host of options for working with Facebook.
By navigating through the menus, the user can retrieve information about the Facebook objects he or she owns (albums, activities, check-ins, posts, etc.), and also information about the user’s friends. Tapping on a retrieved Facebook object opens a menu with all the connections and publishing options that the Facebook Graph API provides.
For example, to see all the comments related to an album, the user taps albums > display album > album name > comments. Other options for albums include create album, retrieve photos, like, and unlike.
The user can post a link, a video, a picture, or a status message on their own Wall or on their friend’s Wall or on an event’s Wall. The user can create albums, checkins, events, comments, notes, event responses, and friend lists, delete comments, notes, and friend lists, and like/unlike any Facebook object.
The application uses MoSync Widget API buttons and menus to collect user input. Each button represent a request to Facebook that will be handled by the Facebook Graph API.
For example, when the activities button is clicked, an "activities" connection request for the current user is sent to the Graph API. The JSON data received from server is parsed and converted into a list of objects containing the name, id, category and date created fields.
When the user clicks a "create object " button, a request to create the object is sent to the Graph API. When the request has been completed, a screen with the ID of the new object is displayed. Similarly, when objects are deleted, the "Object removed" message is displayed.
All objects that a user can "like" and "unlike" according to the Graph API documentation can be liked or unliked in the FacebookDemo application.
The project is divided into folders:

The FacebookManager files contain the FacebookManager class. This is the class that is used for communicating with Facebook.
GetPermissions.h contains a GetPermissionsFor template class. This is specialized for each Facebook object type. It is used to fill a Set object with the needed permissions for retrieving connections for a Facebook object type or to publish an object of that type.
The /GraphAPI folder contains the implementation of the Graph API. It is divided into three subfolders:
The /HTTP folder contains all the low-level communication to the server (sending the request, retrieving the JSON data, and so on).
The /JSON_lib folder contains the MoSync JSON library.
Pressing the BACK button closes the application.
This example application searches Wikipedia, based on user input and selected categories. It makes use of functions in the MoSync Widget API.
![]() | ![]() | ![]() |
| Home screen on Android | Summary screen on Android | Web screen on Android |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples .
When this application is started, the HomeScreen is presented. From here the user can search Wikipedia articles, filter by category, and specify the number of results to return. Tapping the Next button initiates the search.
While the application engine computes the result in the background, a progress bar indicates progress. When the results are ready, they are displayed as a list of matching article titles. The user can select which Wikipedia entires to show, or select all of them.
In the next screen a snippet of each of the selected articles is displayed, and tapping on a snippet opens the complete article in a WebView widget.
The project is divided into several files:
On the Home Screen:
On the Titles Screen:
On the Summary Screen:
On the Web Screen:
The MAUI user interface components use bitmap fonts in its own format. These files are converted from a specific, but common, format for bitmap fonts. The MoSync download comes supplied with a freeware tool called BMFont for creating bitmap fonts from the fonts installed in Windows. MoSync developers can use BMFont to create their own fonts for use in their applications.
If you look in your MoSync installation folder, normally in C:\MoSync, you’ll find a folder called bin\BMFont. In there is the BMFont application by Andreas Jönsson, a freeware application which can create bitmap fonts. Bitmap fonts differ from standard TrueType fonts normally found on Windows. TrueType fonts describe the shape of each letter as vectors, which means that they can be scaled up and down without losing detail. Bitmap fonts are of a fixed size, and scaled bitmap fonts will appear jagged.
When you’re using MAUI, it only supports bitmap fonts, so you need to make sure that the size you create is the size you want. You can put as many fonts as you wish into your application, but each widget will only support one font. You cannot change fonts in the middle of a label for instance. If you want bold or italics in your application, you need to create them as separate fonts.
MAUI fonts only support the ASCII character set, so some characters and languages are not currently supported. They will be replaced in your application with spaces.
To create a new font, start BMFont. You can see on the left all of the available characters, and on the right, the character groups supported by this font. As MAUI fonts only support ASCII characters, then stick with the ‘Basic Latin + Supplement’ option. Other characters will take up space in the font file, and won’t render.
If you’re absolutely sure you won’t need some characters in your application, then leave them out. It will save space.
Clicking on the square next to ‘Basic Latin + Supplement’ will select all the characters in the set.
Note: Some fonts only contain ASCII characters. If this is the case, there aren’t any options on the right. This is very important. Most people’s font problems come from not getting these settings correct.
There are several formats for bitmap fonts, and the MoSync conversion tool (mof) will only convert from one of these.
Configure BMFont's settings as follows:
For BMFont v1.12 and MoSync 2.5+:

For BMFont v1.9 and MoSync 2.4 and earlier:

1. Change the Charset option from Unicode to OEM. If necessary, change the option in the dropdown box to ANSI.
2. Unless space is at a real premium, then I would say that having the anti-alias font smoothing is always worth it. There are some examples later. Set it to 1 pixel. This will double the size of the final font, but the quality difference is high.
3. At the bottom right of this dialog box, change the Font descriptor to Binary
4. Change the Textures option to PNG.
When you do this, and click OK, you’ll see the changes to font and size reflected in the main window.
1. Fonts on your computer screen look bigger than they do on your phone. Compare the size of your phone’s screen to the emulator. Make fonts bigger than you think you need.
2. Small fonts on the emulator will be unreadable on a real phone. Use them with great care.
3. Many fonts are too narrow. They may look wonderful in Photoshop, but they don’t necessarily translate onto a mobile phone. Clear, bold fonts are best.
4. You can get free fonts easily on the web. Google ‘free fonts’ for lots of sources.
5. When you save the fonts, give them clear descriptions like Arial16ptBold.fnt
When you’re happy with the fonts save it with these settings. This will create at least two files, one with a .fnt extension, and one with the name you’ve given to the font with _0.png. If you’ve got more than one png file, then go back to the font settings screen, and increase the size of the png. I don’t think that there is a limit on the size of this, but the font conversion tool will only work with one image.
To be able to use the font in the MAUI application, you need to convert from the created format to the internal format used by MoSync. There is a command-line tool for that in the bin sub folder of the MoSync root, usually C:\MoSync\bin.
Open a command line. You can do this by selecting Run from the Windows menu, and entering the command cmd.
The first thing you need to do is get to the correct directory. Assuming you’ve done a default installation of MoSync you need to type:
cd c:\MoSync\bin
and press Enter.
The prompt should now confirm your location. If you type ‘mof’ and press enter, you get a small help screen for using the tool.
The format of the commands for mof are
| -fontData | The name of the font file you’ve created |
| -fontImage | The name of the font image file you’ve created |
| -outFile | The name you want to give it |
| -fontColor | The color you want the font to be in. |
We’ll look at coloured fonts later in the tutorial.
If you’ve entered the command correctly, you’ll get a confirmation message, and your new file will be created in the bin folder. You should copy this to the resources folder of your project.
To use the fonts you’ve created, you need to add references to them in your resources file. If you want to know more about this, then there is a separate tutorial, but here is the code I’ve used.
.res STANDARDFONT .bin .include "resources/pretty.mof" .res YAHOOFONT .bin .include "resources/Yahoo.mof" .res YAHOOSMOOTH .bin .include "resources/YahooSmooth.mof"
To use a font in your application, you need to add a reference to MAHeaders.h and MAUI/Font.h in your code, and create a new Font in code.
// Create the fonts Font* yahooFont = new Font(YAHOOFONT);
You can then reference this when creating labels.
// Create a screen title, using the Yahoo font Label* titleLabel = new Label(0, 0, 240, 32, layout, "MoSync!", 0x0000C0, yahooFont);
I’ve created a short example application using free fonts I’ve created in BMFont.
// Create the fonts Font* standardFont = new Font(STANDARDFONT); Font* yahooFont = new Font(YAHOOFONT); Font* yahooSmoothed = new Font(YAHOOSMOOTH); // Create a layout Layout* layout = new Layout(0, 0, 240, 320, NULL, 1, 4); //Create a screen title, using the Yahoo font Label* titleLabel = new Label(0, 0, 240, 32, layout, "MoSync!", 0x0000C0, yahooFont); titleLabel->setAutoSizeY(true); titleLabel->setHorizontalAlignment(Label::HA_CENTER); // Smoothed label Label* smoothLabel = new Label(0, 0, 240, 32, layout, "MoSync!", 0x0000C0, yahooSmoothed); smoothLabel->setAutoSizeY(true); smoothLabel->setHorizontalAlignment(Label::HA_CENTER); //Create some more text, using the standard font Label* newsLabel = new Label(0, 0, 240, 32, layout, "Here is some interesting information. In 1964, a gang of eight pigs held their farmer hostage for 14 hours. When questioned, they said 'oink'.", 0xC00000, standardFont); newsLabel->setAutoSizeY(true); newsLabel->setMultiLine(true); this->setMain(layout);
This is the application running:
For comparison, I’ve blown-up the two title bars. One has the smaller but un-smoothed font, and the second is the larger, anti-aliased font. There is a big difference.
If you have one font, or at least one font you use the most in an application, then you don’t need to specify it whenever you create a label. You can use the Engine object in MAUI to specify the default font.
Engine& eng = Engine::getSingleton(); eng.setDefaultFont(standardFont);
You can then create labels without specifying a font, and it will use the one you set up here.
The label constructor is different though if you don’t specify a font. You can’t pass the label text without supplying a background colour and a font, so if you want to use the default font, you need to call the setCaption(text) method.
// Create some more text, using the default font
Label* newsLabel = new Label(0, 0, 240, 32, layout);
newsLabel->setCaption("Here is some interesting information.
In 1964, a gang of eight pigs held their farmer hostage for
14 hours. When questioned, they said 'oink'.");
newsLabel->setBackgroundColor(0xc00000);
newsLabel->setAutoSizeY(true);
newsLabel->setMultiLine(true);
This will produce exactly the same result as the previous code.
Finally a note on coloured fonts. By default, the mof tool will produce the font in white. However you can produce fonts in whatever colour you want, but in only one colour at a time. You can’t have fonts with coloured borders for instance. You’ll need to produce a mof file for every colour of every font you want to use.
You can only use one font per label as well, so you can’t change colour in the middle of a label, or move to a bold font.
To create a font in a different colour, you need to add –fontColor <colour in hex> at the end of the mof command. For instance:
mof –fontData YahooSmooth.fnt –fontImage YahooSmooth_00.png –outFile
YahooSmoothRed.mof –fontColor 0C0000
Note: Font colours are specified like web colours, with a byte for their red, green and blue values. You don’t need to put anything to specify that this is a hex number though, so ‘0c0000’ is right but ‘0xC00000’ won’t work.
Coloured fonts still anti-alias well.
This example application demonstrates how to count, load, and manage device fonts for text drawing using maDrawText and maDrawTextW and the Device Fonts API.

Note: This example only works on Android and iOS devices at this time.
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When this application is started, it will present a list of the fonts that are installed in the device and the user can access. For devices that include more fonts than the screen can fit, the user is able to scroll through them.
The first column shows the font name, the second show how the font is printed using maDrawText and the third using maDrawTextW. Some fonts might be limited in the way that they can be drawn on the screen using these two functions.
This example application demonstrates how to count, load, and manage a device fonts for your NativeUI applications.
![]() | ![]() |
| On IOS | On Android |
Note: This example only works on Android and iOS devices at this time.
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When this application is started, it will present a list of the fonts that are installed in the device and the user can access, using a ListView widget. For devices that include more fonts than the screen can fit, the user is able to scroll through them.
The project consists of a single file called main.cpp.
The MAUI::Font class draws text using bitmap fonts defined in a mof-file. In this guide we show how to convert a bitmap font to a mof-file, and how to add the file as a resource to a MoSync project. We then create a MAUI::Font instance and draw some text with it.
We will be using two tools in this tutorial:
BMFont is a bit map font generator that can render any existing truetype font as a bitmap font. This program is bundled with the MoSync SDK for Windows and can be found in the /bin/BMFont folder along with its documentation. (If you are using the MoSync SDK for OS X you will need to find your own font tool for creating a bitmap font, or use one of the bitmap fonts that are readily available for that platform.)
mof.exe is a command line tool that converts bitmap font files to mof format required by MAUI::Font. It can be found in the /bin folder.
First, create a new folder for the project called /fonttest in the MoSync /projects directory.
Now open the BMFont tool and configure its settings as follows:
For BMFont v1.12 and MoSync 2.5+:

For BMFont v1.9 and MoSync 2.4 and earlier:

Note that:
Select all the characters that you want to include in your font. (If you want all characters, use the Edit > (Un)Select All Chars command.)
Select Options > Visualize to see what your bitmap font will look like:

Next, select Options > Save bitmap font as and save your font to our /fonttest folder as a Bitmap font (*.fnt) file: 
Convert the font using the MAUI font generator (mof.exe) from the Windows command line:

The MAUI font generator takes the following parameters:
Import the newly created .mof file into your project.
The resulting mof-file can be added to your MoSync project as a binary resource and passed to the constructor of MAUI::Font to create a runtime instance of the font.
To draw text using the font, use one of the methods drawString or drawBoundedString. The drawBoundedString method features linebreaking and is therefore slower, so it is recommended to use drawString when possible. We'll show this by making a simple example.
Start Eclipse and create a new project called fonttest. Make it a Moblet project. Also, in the project's build settings, add MAUI.lib to Additional Libraries.
Begin by adding a new resource file called res.lst with the contents:
.res R_FONT .bin .include "myfont.mof"
In the source file, add the following inclusions:
#include <MAUtil/Moblet> #include <MAUI/Font.h> #include "MAHeaders.h"
Font.h. is required for bitmap font handling. MAHeaders.h, which will be generated from the compiled resource file, contains the handles to the resources in the resource file.
In the code we will begin by adding an instance of MAUI::Font as a member to the Moblet. We will also make sure it is initialized with a handle to our font resource.
using namespace MAUtil;
class MyMoblet : public Moblet {
private:
MAUI::Font font;
public:
MyMoblet() : font(R_FONT) {
}
Finally we use the font to draw a text whenever the user presses a key.
void keyPressEvent(int keyCode) {
font.drawString("Hello world!", 2, 2);
maUpdateScreen();
}
void keyReleaseEvent(int keyCode) {
// todo: handle key releases
}
};
extern "C" int MAMain() {
Moblet::run(new MyMoblet());
return 0;
};
The font system in MoSync uses a set of functions that create and manage font handles (that behave like any other MAHandle object), which can then be used either in the context of maDrawTextW or NativeUI as needed by the application (Note: MAUI does not support this font system).
Note: The Device Fonts API is currently only implemented in the MoSync Android and iOS runtimes.
The system works around the concept of font handles. You can obtain a font handle in two ways:
Once you acquire a font handle, you can use it either with:
You can have multiple font handles loaded at any time. A font handle can be used by multiple widgets and maFontSetCurrent at the same time. If for some reason you find yourself not in need of a font handle any more, you can delete it using maFontDelete. Never attempt to delete a font that is being used by a NativeUI widget or maFontSetCurrent.
Both maDrawText and NativeUI widgets will work even if a font handle is
not specified, in which case they will use a default system font.
Color is handled by the systems that
use the font objects, and as such they are not part of this API.
NativeUI Widgets have a font color property that is set independently of
the font object. maDrawText uses the color set by maSetColor.
Size
is set at font creation, and is part of the font object. However,
currently NativeUI objects have a "set font size" property. The behavior
when using font handles in conduction with the font size property is
undefined. Users are advised to only set the font size during the
creation of the font handle if they plan to use fonts other than the
default one in their applications.
The folowing constants are defined in the Device Font API:
Note that you can use both bold and italic styles by using FONT_STYLE_BOLD|FONT_STYLE_ITALIC.
Using
different fonts and font weights is an easy way to bring attention to
the important information in your application. A very simple thing you
could do is call maFontLoadDefault three times to create a normal, a bold, and an italic version of the FONT_TYPE_SANS_SERIF font, then use these fonts with maFontSetCurrent (or NativeUI widgets) as they are needed.
Or
suppose your application allows the user to enter and edit blocks of
text, and you want to allow the users to be able to make use of all the
fonts available on the device. You can code a NativeUI widget that lists
all the installed fonts, and allows the user to select one. To do this
you could first call maGetCount to get the total number of fonts, and then fill the list by subsequently calling maFontGetName for all indices. When the user selects a font from that list, your code calls maFontLoadWithName, with that font's name as a parameter, and passes the handle to the EditBox widget.
As
a third example, suppose you want to use Comic-Sans in your
application, even though it's the worst font ever seen other that for
comics. that font is not available on all devices, so to make sure that
every one of your users has to suffer that travesty of typography, you
can bundle it with your application, and when the time comes to unleash
it upon the unsuspecting eyes of your users, you call maLoadFontWithName("ComicSans",12), and load the handle to your widgets.
MoSync graphics operations are always performed to a "draw target". By default, this draw target is the screen, but you can create images that can be drawn to, using maCreateDrawableImage().
These mutable images behave exactly like any other images, and can be used with maDrawImage() or maDrawImageRegion() - the only difference is that they can't be transparent. Also, all drawing operations respect the "clip rectangle", which is a rectangular portion of the screen that is affected by drawing operations. By default, the clipping rectangle is the whole screen.
To create an image you can draw to, you must have a placeholder resource to use. Either you can put one in the resource file for your application (see tutorial about resources), or you can create one dynamically at run time. We will demostrate how to create one dynamically:
MAHandle myPlaceholder = maCreatePlaceholder();
Then, to create the drawable image:
maCreateDrawableImage(myPlaceholder, 32, 32);
This will have created a 32x32 pixels drawable image. Now, to set the draw target to be this image:
maSetDrawTarget(myPlaceholder);
This function returns the previously set target, and it might be a good idea to save that information. However, if you know that the previous target was the screen, you can just use the constant HANDLE_SCREEN to set it back:
maSetDrawTarget(HANDLE_SCREEN);
Clipping allows you to limit the part of the screen that can be drawn to. This might be useful when implementing graphical user interfaces, games or anything involving window-like behavior. Clipping rectangles are per draw target - that is, the screen and every drawable image has one. Consequently, you must take care to set the appropriate draw target using setDrawTarget() before specifying its clipping rectangle:
maSetDrawTarget(myPlaceholder);
maSetClipRect(0,0,16,16);
To retrieve the current clip rect:
MARect myRect;
maGetClipRect(&myRect);
#include <MAUtil/Moblet.h>
#include <MAUtil/String.h>
#include <mastdlib.h>
using namespace MAUtil;
#define BORDER 40
class MyMoblet : public Moblet {
public:
MyMoblet() {
MAExtent scrSize = maGetScrSize();
int width = EXTENT_X(scrSize);
int height = EXTENT_Y(scrSize);
MAHandle myPlaceholder = maCreatePlaceholder();
maCreateDrawableImage(myPlaceholder, 32, 32);
maSetDrawTarget(myPlaceholder);
// Fill with blue
maSetColor(0x0000ff);
maFillRect(0, 0, 32, 32);
maSetColor(0xff00);
// draw green triangle
maLine(0,10,10,0);
maLine(0,0,0,10);
maLine(0,0,10,0);
maSetDrawTarget(HANDLE_SCREEN);
maSetClipRect(BORDER,BORDER,width-BORDER*2, height-BORDER*2);
// Draw purple background
maSetColor(0xff00ff);
maFillRect(0,0, 200, 200);
for(int i = 0; i < 10; i++) {
maDrawImage(myPlaceholder, i*40, i*40);
}
// Draw white text
maSetColor(0xffffff);
maDrawText(0,BORDER, "This text is also clipped");
maUpdateScreen();
}
};
extern "C" int MAMain() {
Moblet::run(new MyMoblet());
return 0;
}; The Framebuffer API provides an API for overriding the backbuffer of MoSync. In order to use this API, the program should use maFrameBufferGetInfo to fill a structure containing such information as the native pixel format and screensize of the underlying system. These parameters should then in turn be used to allocate memory for a backbuffer.
The custom backbuffer is enabled by using the maFrameBufferInit syscall. By using maFrameBufferClose, the overridden backbuffer is disabled. In order to make a program pixel format and screensize independent, actual drawing should be done using the information retrieved by using the syscall maFrameBufferGetInfo. Increased performance may be gained by using different code paths for different bit depths and creating optimized innerloops.
Note: Whenever a EVENT_TYPE_SCREEN_CHANGED event is sent from the runtime (i.e., when the size of the screen has changed), the native framebuffer gets invalidated and needs to be reinitialized. Just use maFrameBufferClose and maFrameBufferInit in sequence and everything should be just fine.
To illustrate how the API is used we're going to do a simple example. We will implement a function to plot a pixel using a desired color. Be aware that, usually when doing a program using direct pixel access, the backbuffer is traversed linearly, hence a pixel plotting routine may be very inefficent.
First we include the standard MoSync API header file and create a forward reference to the plotPixel function.
#include <ma.h> void plotPixel(MAFrameBufferInfo *fbi, byte *backbuffer, int x, int y, int color);
Then we begin creating our MAMain. The framebuffer is initialized as previously explained. Information is retrieved by filling an instance of a MAFrameBufferInfo structure, called info with information and then allocate info.sizeInBytes amount of memory for our backbuffer. The backbuffer is then enabled using maFrameBufferInit.
int MAMain()
{
MAFrameBufferInfo info;
maFrameBufferGetInfo(&info);
byte *backbuffer = new byte[info.sizeInBytes];
maFrameBufferInit(backbuffer);We then begin doing actual drawing. First we clear the screen to black using memset. As black is usually mapped to 0 on all pixel formats we may do this using a memset on the backbuffer.
memset(backbuffer, 0, info.sizeInBytes);
Then we plot the actual pixel using our plotPixel routine. We must pass our MAFrameBufferInfo struct, a pointer to the backbuffer, the x and y coordinate and the color on the form 0x00rrggbb (same form as used by maSetColor).
plotPixel(&info, backbuffer, info.width/2, info.height/2, 0xffff00);
Then we copy the backbuffer to the screen by calling maUpdateScreen and wait for a keypress or close event.
maUpdateScreen();
while(true)
{
MAEvent e;
while(maGetEvent(&e))
{
if(e.type == EVENT_TYPE_CLOSE ||
e.type == EVENT_TYPE_KEY_PRESSED)
{
maExit(0);
}
}
}Finally we disable our custom backbuffer by calling the syscall maFrameBufferClose. This isn't necessary as it is done automatically when the system is shut down, but is done just to illustrate how it is used.
maFrameBufferClose(); }
Now we're going to explain how to implement the plotPixel function. A pixel may be stored using different amount of bytes for different bit depths. For instance 16-bit color normally uses 2 bytes per pixel and 24/32-bit color uses 4 bytes per pixel. Each color component is represented by a set of bits of these bytes. For 32-bit color modes each color component is usually a byte or 8 bits, but for 16-bit color modes a common setup is 5 bits for red, 6 bits for green and 5 bits for blue. This information is located in the MAFrameBufferInfo struct. The plotPixel function begins by extracting the color components from the color argument and converts them to the right bit depth.
void plotPixel(MAFrameBufferInfo *fbi, byte *backbuffer, int x, int y, int color)
{
int r = ((color>>16)&0xff)>>(8-fbi->redBits);
int g = ((color>>8)&0xff)>>(8-fbi->greenBits);
int b = ((color)&0xff)>>(8-fbi->blueBits);Then we make a switch-statement that depends on the amount of bytes per pixel, so that we may work with the backbuffer using the the correct data type. First we need to find the scan line by multiplying the y-coordinate with the pitch of the screen (the actual width of the backbuffer). Then we type cast the reference pointing at the beginning of the scan line to the correct data type and index it using the x-coordinate to find the correct pixel. Finally encode the color components using the framebuffer information.
switch(fbi->bytesPerPixel)
{
case 2: ((short*)&backbuffer[y*fbi->pitch])[x] =
(r<<fbi->redShift)|(g<<fbi->greenShift)|(b<<fbi->blueShift);
case 4: ((int*)&backbuffer[y*fbi->pitch])[x] =
(r<<fbi->redShift)|(g<<fbi->greenShift)|(b<<fbi->blueShift);
}
} This example application demonstrates how to use OpenGL ES 1.1 to control a device's graphics hardware.

This example is included in the MoSync SDK installation in the /OpenGLES/examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When this application is started you will see a red rotating square.
The code of the project is collected in one single file. It shows how to use the GLMoblet in order to create an OpenGL ES 1.1 based application. It has a set of helper functions for setting up the initial state: gluPerspective, initGL, and setViewport.
The init function first calls setViewport to setup the projection matrix. Next it calls initGL to setup the OpenGL context state.
The draw function first clear the screen to a dark red color and continues by setting up the modelview matrix, by calling the OpenGL functions for manipulating the matrix. Next it sets the color for the square and send the pointer to the structure describing the vertices of the square. Next it fills the structure with the vertex coordinates and draws the primitive as a triangle strip.
The only button that the program responds to is the back key. If it is pressed the application exits.
This example application demonstrates how to use OpenGL ES 2.0 to control a device's graphics hardware.

This example is included in the MoSync SDK installation in the /OpenGLES/examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When this application is started you will see a trippy pattern moving on the screen.
The code of the project is collected in one single file. It shows how to use the GLMoblet in order to create an OpenGL ES 2.0 based application. It has a set of helper functions for loading shaders (‘loadShader’) and checking for errors (‘checkGLError’).
The ‘init’ function first calls initGL which loads the vertex and fragment shader, sets up the default state and maps variables to the uniforms of the shader. In the ‘draw’ function, the uniforms that contain the current time in seconds and the multiplicative inverse for the screen resolution, are updated and a triangle fan that covers the entire screen are drawn.
The shader is set to be used so the shader program will run for each pixel on the screen. The shader generates a pattern by calculating colors as a function of time, x and y coordinates.
MoSync provides a number of primitive graphics operations at the syscall level.
int maSetColor (int rgb); void maSetClipRect (int left, int top, int width, int height); void maGetClipRect (MARect *out); void maPlot (int posX, int posY); void maLine (int startX, int startY, int endX, int endY); void maFillRect (int left, int top, int width, int height); void maFillTriangleStrip (const MAPoint2d *points, int count); void maFillTriangleFan (const MAPoint2d *points, int count); void maDrawText (int left, int top, const char *str);
The maSetColor() function sets a "current color" which will be used by any subsequent primitive operations. The maSetClipRect() and maGetClipRect() functions are used to either define or query a rectangular area of the screen that is affected by graphics operations. The rest of the functions each draw a primitive. All functions deal with coordinates in one way or another, and these coordinates are pixels coordinates with the origin located at the top-left corner of the screen. The positive x axis goes from left to right, while the positive y axis goes from top to bottom: 
The maPlot() function is used to plot individual pixels at given coordinates using the current color:
// Set the current color to a bright green. maSetColor(0x00ff00); // plot a pixel at 10, 10. maPlot(10, 10); // Update the screen. maUpdateScreen();
The maLine() function is used to draw a line between two pairs of coordinates using the current color:
// set the current color to a bright green. maSetColor(0x00ff00); // draw a line from (10,10) to (50, 50). maLine(10, 10, 50, 50); // update the screen. maUpdateScreen();
The maFillRect() function is used to fill a rectangle between with a given top-left corner, width and height.
// set the current color to a bright green. maSetColor(0x00ff00); // draw a rectangle between (10, 10) and (60, 60). maFillRect(10, 10, 50, 50); // update the screen. maUpdateScreen();
Triangle strips are an efficient way of drawing several triangles that share common vertices, since those vertices do not need to be repeated. The following image illustrates such a triangle strip, consisting of triangles 1,2,3,4 and vertices A,B,C,D,E,F:

The maFillTriangleStrip() function is used to fill a rectangle between {10, 10} and {40, 40} using a triangle strip.
// Set the current color to a bright green.
maSetColor(0x00ff00);
MAPoint2d points[] =
{
{10, 10}, {40, 10}, {10, 40}, {40, 40}
};
maFillTriangleStrip(points, 4);
// Update the screen.
maUpdateScreen();
The maFillTriangleFan() function can be used to draw a polygon:

A triangle fan is a primitive in computer graphics that saves on storage and processing time. It describes a set of connected triangles that share one central vertex. If N is the number of triangles in the fan, the number of vertices describing it is N+2. This is a considerable improvement over the 3N vertices that are necessary to describe the triangles separately:
MAPoint2d points[8];
points[0].x = points[0].y = 40;
points[7].x = points[7].y = 40;
for(int i = 0; i < 7; i++)
{
float t = 2*M_PI*i / 6.0;
points[i+1].x = 40 + 30*cos(t);
points[i+1].y = 40 + 30*sin(t);
}
maSetColor(0xff00ff);
maFillTriangleFan(points, 8);
maUpdateScreen();
The maDrawText() function is used to render text using a device-dependent font. It is useful for things like debug printouts or simplier UI:s. For consistent, flexible fonts, have a look at the MAUtil::Font class - see Font tools.
// set the current color to a bright green. maSetColor(0x00ff00); maDrawText(10, 10, "Hello world!"); // update the screen. maUpdateScreen();
Graphun is a 3d graph visualizer built with MoSync. It evaluates a custom expression for every point on a grid and displays the result. This advanced application makes extensive use of NativeUI, and it uses an OpenGL view to display the graphs.
![]() | ![]() | ![]() |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples. The source code is browsable on our Github repository.
This example is also available on various app stores and online marketplaces.
This application is intended for touchscreen devices. It uses NativeUI and OpenGL so it will work only on iOS (iPhone, etc.) and Android devices at this time.
When the application starts up for the first time it displays the graph for the expression sin(x*10.0*y+time)*0.5. As this expression includes time as a variable, the graphical display will continuously change as time changes. The user can change the expression by touching in the expression field and entering a new expression.
The Help page in the application provides some example expressions that the user can select for demonstration purposes. The Help page also includes advice on using the application, information about predefined constants, and so on.
The grid can be rotated to inspect the result from different angles by swiping the screen. Settings are available through the spanner icon in the lower left corner of the screen. The shading of the grid can be turned on and off, and three resolutions can be selected.
HelloOpenGLES is a well-commented example application for beginners. It demonstrates how to use OpenGL for Embedded Systems from your MoSync Application.
Note that this example application makes use of NativeUI and therefore only runs on iOS (iPhone) and Android devices. It will not run on MoRE, the MoSync Emulator.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When the application runs, the screen displays a rotating, textured box.
Examine the source code of the application to learn how the program works. The extensive code comments highlight various aspects of working with OpenGL, including:
MAUtil::FrameBuffer emulates a 4 or 8 bits per pixel, pallettized display using the FrameBuffer API of MoSync. To initialize the library you provide the FrameBuffer_init with information about the size, colour format and orientation of the screen.
You may then set entries in the palette using either FrameBuffer_setPalette or FrameBuffer_setPaletteEntry.
The FrameBuffer_copyRect colour converts, scales and rotates a selected area of the the source, treated as image pixels with the information provided when initializing the library, into the native framebuffer. The function will automatically scale the backbuffer to fit the screen using pixel doubling/halving. When doing pixel halving, the colours of the pixels will be averaged to get a better reproduction of the actual image. It is a very handy API for porting old desktop applications that used the framebuffer of the VGA/EGA display.
There's two important things to keep in mind:
Here is a simple example (written in C) showing how it is used:
#include <ma.h>
#include <MAUtil/FrameBuffer.h>
// We allocate a 160*120 pixels large 8 bits per pixel backbuffer.
unsigned char backbuffer[160*120];
int MAMain()
{
int i;
// Initialize the FrameBuffer library with no special flags and the default orientation.
FrameBuffer_init(160, 120, ORIENTATION_0, 0);
// Create a greyscale palette.
for(i = 0; i < 256; i++)
{
FrameBuffer_setPaletteEntry(i, i, i, i, 0);
}
while(1)
{
MAEvent event;
// Retrieve the time and use it to generate a color index for
// all pixels in the backbuffer.
int time = maGetMilliSecondCount()/10;
memset(backbuffer, time, 160*120);
while(maGetEvent(&event))
{
switch(event.type)
{
// Make sure we catch the close event and if we do, exit.
case EVENT_TYPE_CLOSE:
maExit(0);
break;
// Whenever the screen area or orientation of the screen changes,
// we reinitialize the FrameBuffer library.
case EVENT_TYPE_SCREEN_CHANGED:
FrameBuffer_close();
FrameBuffer_init(160, 120, ORIENTATION_0, 0);
break;
}
}
// Copy, convert, scale and rotate the backbuffer to the native backbuffer.
FrameBuffer_copyRect(0, 0, 160, 120, 0, 0, backbuffer, 160);
// Update the screen (copy the native backbuffer to the actual screen).
maUpdateScreen();
}
return 0;
}
The graphics API provides a set of functions equivalent to those found in the standard MoSync API, with the addition of a transformation stack. This provides a useful mechanism for keeping transformation state without explicitly managing it on the application side. It is useful for any sort of hierarchical rendering, ranging from UI to advanced graphical effects.
The transformation matrix stack is manipulated through a number of functions:
In many cases, especially when dealing with hierarchical UIs, the ability to save and restore multiple levels of clipping rectangles is desirable. The clipping stack provides such a mechanism. It is manipulated using two simple functions:
The following functions are provided for drawing operations, each mapping directly to a corrresponding syscall:
Here's a short example program showcasing the use of the transformation stack. For an example of how to use the clipstack, the source code of MAUI::Engine is recommended.
#include <MAUtil/Moblet.h>
#include <MAUtil/Graphics.h>
#include <madmath.h>
#include <mastdlib.h>
using namespace MAUtil;
/**
* Draws a square centered at the origin with respect to the current
* translation with the given size.
*/
void drawBox(int size)
{
Gfx_fillRect(-size/2, -size/2, size, size);
}
/**
* Draws a blue square at centered at the origin with respect to the current
* translation. Then, recursively, draws four boxes of half the size
* centered at each corner of the original one, and with half the color
* intensity. Then, recurse until the size drops to 2.
*/
void artwork(int size, int color = 0xff)
{
if(size <= 2) return;
// Save transformation state.
Gfx_pushMatrix();
maSetColor(color);
// Draw main box
drawBox(size);
// Draw the four corner boxes
Gfx_pushMatrix();
Gfx_translate(-size/2, -size/2);
artwork(size/2, color >> 1);
Gfx_popMatrix();
Gfx_pushMatrix();
Gfx_translate(size/2, -size/2);
artwork(size/2, color >> 1);
Gfx_popMatrix();
Gfx_pushMatrix();
Gfx_translate(size/2, size/2);
artwork(size/2, color >> 1);
Gfx_popMatrix();
Gfx_pushMatrix();
Gfx_translate(-size/2, size/2);
artwork(size/2, color >> 1);
Gfx_popMatrix();
// Restore transformation state.
Gfx_popMatrix();
}
class MyMoblet : public Moblet
{
private:
int exitStartX;
int exitStartY;
public:
MyMoblet()
{
// Aquire screen dimensions
MAExtent scrSize = maGetScrSize();
int width = EXTENT_X(scrSize);
int height = EXTENT_Y(scrSize);
// Clear initial state of transformation matrix.
Gfx_clearMatrix();
// ...and save it
Gfx_pushMatrix();
// Let's start at the center of the screen...
Gfx_translate(width/2, height/2);
// ...and move around in a circle.
for(int i = 0; i < 8; i++)
{
float theta = 2*M_PI*i/8;
// We need to save and restore the transformation matrixc
// for each instance of "artwork" we draw along the circle
// path.
Gfx_pushMatrix();
// Position our pseudo-fractals along a circle that
// scales to fill the screen.
int scale = height > width ? width : height;
Gfx_translate((scale/2)*cos(theta), (scale/2)*sin(theta));
artwork(scale/6);
Gfx_popMatrix();
}
// Restore original transformation matrix
Gfx_popMatrix();
// Draw exit "button"
maSetColor(0xffffff);
const char* msg = "Exit";
MAExtent textSize = maGetTextSize(msg);
exitStartX = width - EXTENT_X(textSize) - 5;
exitStartY = height - EXTENT_Y(textSize) - 5;
maDrawText(exitStartX, exitStartY, msg);
maUpdateScreen();
}
void keyPressEvent(int keyCode)
{
// Exit using right softkey
if(keyCode == MAK_SOFTRIGHT)
maExit(0);
}
void keyReleaseEvent(int keyCode)
{
// todo: handle key releases
}
/*
* Simple exit handling for touch/stylus devices, enabling
* users to simply press the softkey label saying "Exit"
*/
void pointerPressEvent(MAPoint2d p)
{
if(p.x > exitStartX && p.y > exitStartY)
maExit(0);
}
};
/**
* Entry point of the program. The MAMain function
* needs to be declared as extern "C".
*/
extern "C" int MAMain()
{
Moblet::run(new MyMoblet());
return 0;
};

This application demonstrates simple key input, graphics output, and the permanent storage option.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
This example application requires a device with a keypad and arrow keys or a joystick.
A grey screen welcomes you. Use the keypad's arrow keys or joystick to move the pen and draw a black line.
When you exit the program by pressing the "0" key, the sketch is automatically saved to a permanent store. If a has been saved properly, it will be loaded automatically next time you start the program.
OpenGL ES 2.0 is the latest standard for accessing the graphics hardware on embedded devices (in our case Android and iOS). It is heavily based on the concept of shader programs, written using the C-like language GLSL.
At several stages in the graphics pipe-line, shader programs are executed in order to provide maximum freedom to the user. The online API documentation is a good start to understand how to use the API:
http://www.khronos.org/opengles/sdk/docs/man/
OpenGL ES 2.0 is not supported by older devices, so when creating an application that utilizes OpenGL ES one should choose the api version wisely. If you want to be able to support a broad range of devices and do less work, choose OpenGL ES 1.1 or if you want to have all the bells and whistles, sacrificing device compatibility, choose OpenGL ES 2.0.
It is of course possible to create an application that supports both, but as the APIs are incompatible, almost entirely different renderers have to be created.
GLMoblet
The
GLMoblet is a special version of the Moblet that sets up a
fullscreen OpenGL ES view for you and handles all the events that need
to be taken care of. It makes it much easier to write pure OpenGL ES
applications.
To make use of it you need to inherit the class, implement a constructor, and implement two functions: init and draw.
The
GLMoblet constructor takes one parameter: a mask of the GL API versions
your application supports. First it will try to load the most recent
version specified in the mask. If that fails it will try to load the
next most recent version, etc.
If no API can be loaded the program will
exit with a panic message stating that OpenGL ES is not available on the
platform it is running on. As OpenGL ES 1.1 and 2.0 are incompatible, a
program that wants to support both versions needs different code paths
for different api versions. Which version was loaded can be queried in
runtime using the function getApiVersion.
The init function
is invoked when GL has been initialized and the context has been bound.
Here you can do any initialization for the program, like uploading
textures to the graphics hardware. It is important that you don’t use
any GL calls before the init function has been invoked as the GL
context may not have been bound.
Directly after the init function has been invoked the GLMoblet begins to call the function draw at regular intervals (the interval is specified using the function setPreferredFramesPerSecond). The GLMoblet automatically stops drawing if the focus is lost and starts drawing when the focus is gained.
When optimizing an application for performance you can use the function getActualFramesPerSecond to measure the amount of frames per second which should be as close to the preferred amount of frames per second, set using setPreferredFramesPerSecond, as possible. The default preferred amount of frames per second is 50.
3dLines demonstrates basic graphics and key input handling.
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When started the mobile/emulator screen appears as graphics labeled "Start Screen" where the logo wireframe rotates
AdvGraphics tests advanced graphics on the phone and keyboard input.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When started the mobile/emulator screen appears as graphics labeled "Start Screen" where the logo wireframe rotates
Stylus is a simple drawing program, where you draw with your mouse/stylus.
The code for this example can be found in the example folder of the MoSync SDK, typically c:/MoSync/examples on your local installation.

Installation
Expected Output/Behaviour
The screen is black with a color bar on the top end. Use the pointer to draw, select color by clicking desired color bar.
At the time of this writing, touch support is very limited. In the 2.3 release of MoSync full support can be expected.
Key Presses
In this tutorial we take a look at how to detect a device's current geographical location and how to use location data in your application. We also describe some basic strategies for updating location data on a regular basis.
There are two common ways of determining the current location of the user's device:
Most modern smartphones have GPS built in, and many older ones can receive GPS data from a Bluetooth-enabled GPS unit. GPS will give you a more precise position, but it can be slow and unreliable in built-up areas. Cell ID works faster, but requires access to a suitable database.
There are also hybrid solutions which work with combinations of network triangulation, cell IDs and GPS, which fall under the collective name of Assisted GPS (A-GPS).
Some platforms are capable of determining location through other means. In some countries, Android based phones can determine their location by identifying near-by wireless networks.
The MoSync SDK provides an API for interfacing with GPS modules. You don't need to do anything special, just start requesting GPS data for your application.
int res = maLocationStart(); maLocationStop();
These start and stop methods tell the GPS module to start collecting location data, and deliver it to your application.
The function maLocationStart() returns an int. If it returns 1 (MA_LPS_AVAILABLE), then everything is OK. If it returns a value higher than 1, then it can't start because of network conditions, and you should try later. If it returns -1, then location data is not available (probably because the handset doesn't have a GPS unit.)
Note: The MoSync IDE's MoRE emulator does not provide GPS data. It will always return -1.
To receive data, your Moblet needs to respond to system events. You can do this by putting the following code in your Moblet class. This code listens to all events and responds to those that are location messages.
void customEvent(const MAEvent& event)
{
//Check to see if this is a location event
if(event.type == EVENT_TYPE_LOCATION)
{
MALocation& loc = *(MALocation*)event.data;
informListeners(loc);
}
}In this example, we have a private method for passing the location onto the parts of our application that need it.
The location event returns an MALocation object. This object contains the device's latitude and longitude, as well as data about the accuracy of the reading. GPS locations are not definite. They come with a margin of error You'll have to create a strategy for handling the data depending how confident you are with it. More on this later.
You can simply display the latitude and longitude data directly on the screen. Or you can pass it to a map with the current location centered on the screen.
In the following example of a location-handling application, we have a small framework. We have created interfaces for location providers (implemented by Moblet) and for location listeners (our screens which need location data).
Location.h
#ifndef LOCATION_H_
#define LOCATION_H_
#include <maapi.h>
#include <MAUtil/Vector.h>
using namespace MAUtil;
//Provides an interface between Moblet and screens which need location data
class ILocationListener
{
public:
virtual void locationReceived(MALocation& location);
};
class ILocation
{
public:
virtual void addLocationListener(ILocationListener* l);
virtual void removeLocationListener(ILocationListener* l);
virtual void informListeners(MALocation& location);
};
#endif /* LOCATION_H_ */Screens can then subscribe to the Moblet class to register for location data. When a location update comes in, the screen is informed.
MapScreen.h
We can use the ILocationListener interface with a map screen to automatically update the map with the user's location.
#ifndef _MAPSCREEN_H_
#define _MAPSCREEN_H_
#include <MAUI/Screen.h>
#include <MAUI/Layout.h>
#include <MAUI/ListBox.h>
#include <MAP/MapWidget.h>
#include <MAP/LonLat.h>
#include <MAP/MapSourceMgr.h>
#include "Location.h"
using namespace MAUI;
using namespace MAP;
class MapScreen : public Screen, public ILocationListener
{
public:
MapScreen();
~MapScreen();
void show();
void locationReceived(MALocation& location);
private:
MapWidget* map;
bool locRec;
};
#endif //_MAPSCREEN_H_MapScreen.cpp
#include "MapScreen.h"
MapScreen::MapScreen()
{
map = NULL;
}
MapScreen::~MapScreen()
{
}
void MapScreen::show()
{
if(map == NULL)
{
MAExtent screenSize = maGetScrSize();
int scrWidth = EXTENT_X(screenSize);
int scrHeight = EXTENT_Y(screenSize);
map = new MapWidget(0, 0, scrWidth, scrHeight, NULL);
map->setMapSourceKind(MapSourceKind_OpenStreetMap);
LonLat home;
home.lat = 51.49663;
home.lon = 0.00;
map->setCenterPosition(home);
map->setMagnification(14);
this->setMain(map);
}
Screen::show();
}
void MapScreen::locationReceived(MALocation& location)
{
if(map != NULL)
{
LonLat myLoc;
myLoc.lat = location.lat;
myLoc.lon = location.lon;
map->setCenterPosition(myLoc);
}
}Once you've started to get location data, particularly with GPS, you face a new problem. The GPS system reports to your application everytime it gets a fix - approximately once every second. Each reading is slightly different. If you are trying to plot your position on the map, and you automatically pass the raw location data to the map, the pointer or map center will constantly move around, even if the device is still.
To overcome this, you need an update strategy that works something like this:
This keeps the user informed about where they are, without putting a lot of doubt into their minds when it keeps shifting very slightly.
HelloMap is a simple application that displays a slippy (i.e. panning) map.


This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When started, the application displays a map centered on Stockholm (longitude/latitude 18.07, 59.33) with a medium level of magnification. The initial map source is OpenStreetMap. This application uses the Moblet framework.
Use finger/pointer/stylus.
The MapDemo application displays slippy maps and makes use of the MAUI library to provide a simple menu system. The menu system enables the user to switch between map sources and is easy to extend with your own code.
![]() | ![]() |
![]() |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When started, the application displays a map centered on Stockholm (longitude/latitude 18.07, 59.33) with a medium level of magnification. The initial map source is OpenStreetMap. Clicking the left-softkey brings up the menu system. This application uses the Moblet framework.
The Mosync MAP library is a standard library that provides a MapWidget for displaying geographical maps, sometimes called slippy or panning maps, consisting of tiles provided by a map source. This guide introduces the basics of the MAP library and shows you how to create map applications from scratch.
Important: MoSync 2.5 includes an improved MAP Library. If you want to compile in MoSync 2.5 an existing application that uses the 2.4 MAP Library you will need to update that application. See Migrating to the 2.5 MAP Library.
At the heart of the MAP Library is MapWidget.
You can use it as is, or extend it to overlay information on top of the
map. The library contains map classes for using one or more tile-based
map servers such as OpenStreetMap, CloudMade, and Google Maps.
Latitude
and longitude co-ordinates can be converted to meters and pixels (both
global and device). Connection to a location-aware sensor is performed
by the client, and is outside of the scope of the library itself.
The primary public map source is OpenStreetMap (openstreetmap.org).
There is a working hook into Google Static Maps; however use of Google
Static Maps requires a license agreement with Google, so this is more of
a code sample.
There are two examples programs you can use to study the use of the MAP Library:
These examples are written using a memory tracker to allocate and deallocate memory. This makes the code a little more complex than is strictly necessary, but will prove useful if you want to use a memory tracker in your application.
The Map Library provides classes for downloading, managing and displaying map tiles. The library includes:
| MapSource | Abstract base class for provider of map tiles |
| CloudMadeMapSource | MapSource using CloudMade public map tile server |
| GoogleMapSource | MapSource using Google Static Maps as map tile server |
| OpenStreetMapSource | MapSource using OpenStreetMap tile server |
| MapCache | Caches tiles provided by MapSource |
| MapTile | Single tile from MapSource |
| LonLat | Coordinate class |
| PixelCoordinate | Global map pixel coordinate at a specified magnification |
| MapTileCoordinate | Describes a tile’s position in global grid of tiles at a certain magnification |
| MapWidget | Widget displaying slippy map |
| MapViewport | Handles panning and zooming of the map |
| DateTime | Utility class for date |
| Timespan | Utility class for time span |
| MemoryMgr | Utility class for heap resource tracking for debugging |
| Broadcaster | Utility template class for broadcasting to multiple listeners |
| Queue | Utility template class for a simple object queue |
| DebugPrintf | Utility functions for debug output under MSVC compiler |
Include the header files for the map sources you wish to use, for example:
#include <MAP/OpenStreetMapSource.h> #include <MAP/GoogleMapSource.h>
Generally, it is a good idea to use instance variables in your class to refer to the map sources, for example:
MapSource* mOpenStreetMapSource; MapSource* mGoogleStreetMapSource; MapSource* mGoogleAerialMapSource; MapSource* mGoogleHybridMapSource;
The map library comes with two map sources that have been set up for you, OpenStreetMap and GoogleMaps. Here is how to create and set up map sources:
mOpenStreetMapSource = new OpenStreetMapSource(); mGoogleStreetMapSource = new GoogleMapSource(GoogleMapKind_StreetMap); mGoogleAerialMapSource = new GoogleMapSource(GoogleMapKind_Aerial); mGoogleHybridMapSource = new GoogleMapSource(GoogleMapKind_Hybrid);
Set the current map source like this:
mMapWidget->setMapSource(mGoogleAerialMapSource);
This is a bare-bones application with touch interaction -- single touch and drag pans the map; a second touch zooms in a fixed step while pressed, and zooms out when released.
#include <MAUtil/Moblet.h>
#include <MAUI/Screen.h>
#include <MAP/MapWidget.h>
#include <MAP/OpenStreetMapSource.h>
using namespace MAUtil;
using namespace MAUI;
using namespace MAP;
class MapMoblet : public Moblet
{
public:
MapMoblet()
{
mMapWidget = new MapWidget(
0,
0,
EXTENT_X(maGetScrSize()),
EXTENT_Y(maGetScrSize()),
NULL);
// Create a MapViewport for the MapWidget.
// The MapWidget will deallocate the viewport upon destruction.
mMapWidget->setViewport(new MapViewport());
mOpenStreetMapSource = new OpenStreetMapSource();
mMapWidget->setMapSource(mOpenStreetMapSource);
mMapWidget->getViewport()->setCenterPosition(
LonLat(18.07, 59.33), // Position for Stockholm.
true, // Redraw now.
false // Not called from pointer event.
);
// Magnification level (logarithmic scale).
mMagnification = 11.0;
setMagnification(mMagnification);
mScreen = new Screen();
mScreen->setMain(mMapWidget);
mScreen->show();
}
virtual ~MapMoblet()
{
delete mScreen;
delete mMapWidget;
delete mOpenStreetMapSource;
}
void keyPressEvent(int keyCode, int nativeCode)
{
if (MAK_BACK == keyCode || MAK_0 == keyCode)
{
close();
}
}
void multitouchPressEvent(MAPoint2d point, int touchId)
{
if (0 == touchId)
{
beginPanning(point);
}
else if (1 == touchId)
{
zoomIn();
}
}
void multitouchMoveEvent(MAPoint2d point, int touchId)
{
if (0 == touchId)
{
updatePanning(point);
}
}
void multitouchReleaseEvent(MAPoint2d point, int touchId)
{
if (0 == touchId)
{
endPanning();
}
else if (1 == touchId)
{
zoomOut();
}
}
void beginPanning(MAPoint2d point)
{
mMapWidget->getViewport()->beginPanning(point);
}
void updatePanning(MAPoint2d point)
{
mMapWidget->getViewport()->updatePanning(point);
}
void endPanning()
{
mMapWidget->getViewport()->endPanning();
}
void zoomIn()
{
mMagnification += 3.0;
setMagnification(mMagnification);
}
void zoomOut()
{
mMagnification -= 3.0;
setMagnification(mMagnification);
}
void setMagnification(double magnification)
{
mMapWidget->getViewport()->setMagnification(
MagnificationType(magnification));
}
private:
Screen* mScreen;
MapWidget* mMapWidget;
MapSource* mOpenStreetMapSource;
double mMagnification;
};
extern "C" int MAMain()
{
// Optionally, for example if you encounter memory problems, you can
// experiment with the size of the tile cache. Set the cache size like this:
//MapCache::get()->setCapacity(30);
Moblet* moblet = new MapMoblet();
Moblet::run(moblet);
delete moblet;
MapCache::shutdown();
return 0;
}To
be able to compile them with MoSync SDK 2.5, existing applications that
use an older versions of the MAP Library need to be updated, since the
new API is not backwards compatible. Here we explain how to update your
existing code.
The
major change in the API is how map sources are represented. A map
source is a map provider, like OpenStreetMap or GoogleMaps. The old API
used a predefined enumeration of map providers. The new API, by
contrast, uses a more flexible model where the application can define
map source providers.
MoSync 2.4 and earlier:
MapMoblet* moblet = new MapMoblet(); Moblet::run(moblet); delete moblet;
MoSync 2.5:
// Create and run the moblet in the same way as before. MapMoblet* moblet = new MapMoblet(); Moblet::run(moblet); delete moblet; // Free resources allocated by the Map cache. MapCache::shutdown();
The header files for the map source has been changed.
MoSync 2.4 and earlier:
// This header file has been removed from the new map library. #include <MAP/MapSourceMgr.h>
MoSync 2.5:
#include <MAP/MapSource.h> // Typically you include only the header files for the map sources you // wish to use, for example: #include <MAP/OpenStreetMapSource.h> #include <MAP/GoogleMapSource.h>
The MapSourceKind enumeration is replaced by map source classes.
MoSync 2.4 and earlier:
MapSourceKind mMapSourceKind;
MoSync 2.5:
MapSource* mOpenStreetMapSource; MapSource* mGoogleStreetMapSource; MapSource* mGoogleAerialMapSource; MapSource* mGoogleHybridMapSource;
MoSync 2.4 and earlier:
mMapWidget = new MapWidget(0, 0, width, height, NULL);
MoSync 2.5:
// You need to create a MapViewport for the MapWidget. // The MapWidget will deallocate the viewport upon destruction. mMapWidget = new MapWidget(0, 0, width, height, NULL); mMapWidget->setViewport(new MapViewport());
MoSync 2.4 and earlier:
// In the old API an enumeration constant was used to // specify the map source (this was inflexible). mMapWidget->setMapSourceKind(MapSourceKind_OpenStreetMap);
MoSync 2.5:
// In the new API, the application can create the map source, // which is a more flexible approach. The map library comes // with two map sources that have been set up for you, // OpenStreetMap and GoogleMaps. This is how to create and // set these map sources: mOpenStreetMapSource = new OpenStreetMapSource(); mGoogleStreetMapSource = new GoogleMapSource(GoogleMapKind_StreetMap); mGoogleAerialMapSource = new GoogleMapSource(GoogleMapKind_Aerial); mGoogleHybridMapSource = new GoogleMapSource(GoogleMapKind_Hybrid); // Set the map source like this: mMapWidget->setMapSource(mGoogleAerialMapSource);
This application tests the on-board GPS functionality of the phone, via the MoSync Location API.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
Note: This application will only work successfully on a device with activated GPS capabilities. It will run on the MoSync emulator, but no GPS service will be detected.
When the application starts, instrcutions are displayed. Tap the screen (or press the fire button of left softkey) to start the GPS location detection. A "Start" message and return code will be displayed: if GPS is available the return code 1 will be shown. If the device does not have GPS capabilities (including the MoSync MoRE emulator), or the GPS function is not activated on the device, the return code -1 is displayed.
While location detection is active, the following data is shown, periodically refreshed:
Tests the console, heap management and memory allocation on the device.
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
The welcome screen (purple) should appear along with some text and a popup saying 'malloc failed'.
Without quoting all the text, it suffices to say it starts with 'Let's do some math...' and ends with 'Expect a panic'.
None of the keys should operate, only OK on the popup button.
Our
PIM API module is still in the early stage of development, but we have
already implemented many vital elements of PIM management, including
low-level functions for accessing contact lists. Here we take a quick
look at this new interface.
PIM (personal information management) is about accessing the information about the user. PIM data is organized into lists of items, and each item has fields. The device's address book is a typical PIM list, as well as its appointments lists, todo lists, and so on.
Currently we only have functions for working with contact lists. Event lists will be added soon.
We also have a working example application, PIMExample, that demonstrates many aspects of working with the PIM module.
Each
PIM list holds multiple items; for example, the contact list holds
multiple contacts. Each item in the list can have multiple fields of
different types, and each field can have multiple values of the same
type identified by an index.
Some
field values have attributes attached. That makes it possible to define
their purpose (home, mobile, work, husband, custom) and to set them as
"primary" or "default" in case of multiple-value fields. The PIM structure currently supported by our PIM module looks like this:
Contact List
It is important to note that not all fields are available on all platforms. If a field is not supported on running platform and you try to access it, you will get an error. For details of each field, its type and value, the operations it supports, the possible attributes that can be set on its values, and the platforms on which field is available, see the MoSync API Reference online or in the IDE.
For a list of all functions (syscalls) in the PIM module, see the MoSync API Reference.
To open a PIM list, use the function maPimListOpen. If a list of the selected type is available, you will get back a handle to it that you can use in subsequent calls.
MAHandle mContactsListHandle = maPimListOpen(MA_PIM_CONTACTS);
To open the items on the list, use maPimListNext. You will get back a handle to the next item on the list or 0 if there are no more items.
MAHandle pimItemHandle = maPimListNext(mContactsListHandle);
You can create new item in a list using maPimItemCreate.
MAHandle newContactHandle = maPimItemCreate(mContactsListHandle);
The newly created item is empty. The function maPimItemRemove removes an item from the list.
int resultCode = maPimItemRemove(mContactsListHandle, newContactHandle);
if (resultCode < 0)
{
printf("Remove Item Error: %d", resultCode);
}Important! To prevent memory leaks, always call maPimItemClose to close the item as soon as you are finished with it before opening the next item. This function also commits changes made by maPimItemAddValue, maPimItemRemoveValue, and maPimItemSetValue to permanent storage. It should also be used after maPimItemCreate.
int resultCode = maPimItemClose(pimItemHandle);
if (resultCode < 0)
{
printf("Close Item Error: %d", resultCode);
}To close a list when you have finished with it, use maPimListClose. (This function does not close the list's items, but it does invalidate them, so maPimItemClose will now be the only function you can safely use on items.)
int resultCode = maPimListClose(mContactsListHandle );
if (resultCode < 0)
{
printf("Close List Error: %d", resultCode);
}To count the number of fields an item has, use the function maPimItemCount.
int countFields = maPimItemCount(pimItemHandle);
if (countFields >= 0)
{
printf("The item has %d fields", countFields);
}
else
{
printf("Count Item Error: %d", countFields);
}To count the number of values that exist for the field for the item, use maPimItemFieldCount.
int countValues = maPimItemFieldCount(mItemHandle, MA_PIM_FIELD_CONTACT_ADDR);
if (countValues >= 0)
{
printf("The field has %d values", countValues);
}
else
{
printf("Count Item Field Error: %d", countValues);
}Each field of the item has a type. To get the field's type (Address, Birthday, Name, etc.), use maPimItemGetField passing it the the position of the field and the item handle that was returned by maPimListNext.
for (int index = 0; index < countFields; i++)
{
int type = maPimItemGetField(pimItemHandle, index);
if (type > 0)
{
printf("Field %d type: %d", index, type);
}
else
{
printf("Get Field %d Error: %d", index, type);
}
} You can use the maPimFieldType function to get the data type (integer, boolean, string, etc.) of the field. The value returned will be one of the MA_PIM_TYPE_* constants (date, boolean, string array, etc.).
int type = maPimItemGetField(pimItemHandle, 0);
if (type >0)
{
int dataType = maPimFieldType(mContactsListHandle, type);
if (dataType > 0)
{
printf("Field %d data type: %d", type, dataType);
}
else
{
printf("Get Field Type %d Error: %d", type, dataType);
}
} To get the attribute for a value in a field use maPimItemGetAttributes.
for (int index = 0; index < countValues; i++)
{
int attribute = maPimItemGetAttributes(pimItemHandle, MA_PIM_FIELD_CONTACT_ADDR, index);
if (attribute > 0)
{
if ((attribute & MA_PIM_ATTRPREFERRED) != 0)
{
printf("Primary attribute");
}
attribute &= (MA_PIM_ATTRPREFERRED - 1);
printf("Field %d attribute: %d", index, attribute);
}
else
{
printf("Get Field Attribute %d Error: %d", index, attribute);
}
}You can retrieve the label for a value in a field, if the value has a custom label, using the maPimItemGetLabel function. To set a custom label for a value in a field use the function maPimItemSetLabel. The field must of course be writable.
if (countValues > 0)
{
int attribute = maPimItemGetAttributes(pimItemHandle, MA_PIM_FIELD_CONTACT_ADDR, 0);
if (attribute > 0)
{
attribute &= (MA_PIM_ATTRPREFERRED - 1);
if (attribute == MA_PIM_ATTR_ADDR_CUSTOM)
{
MA_PIM_ARGS labelArgs;
labelArgs.item = pimItemHandle;
labelArgs.field = MA_PIM_ATTR_ADDR_CUSTOM;
char* buf = NULL;
int labelSize = 512;
do
{
labelArgs.bufSize = labelSize;
if (buf != NULL)
{
delete[] buf;
}
buf = new char[labelArgs.bufSize];
labelArgs.buf = buf;
resultCode = maPimItemGetLabel(&labelArgs, 0);
} while (resultCode > labelArgs.bufSize);
if (resultCode > 0)
{
printf("Label: %S", (wchar*) buf);
}
else
{
printf("Get Field Label %d Error: %d", 0, resultCode);
}
}
}
else
{
printf("Get Field Attribute %d Error: %d", 0, attribute);
}
}To read the value of a field and copy it to the argument buffer (args.buf ), call maPimItemGetValue. You will need to specify the index of the value ( 0 <= index < maPimItemFieldCount() ). The argument buffer should look like this:
struct MA_PIM_ARGS {
MAHandle item; // Opened by maPimListNext().
int field; // One of the MA_PIM_FIELD constants.
MAAddress buf; // The buffer address where a value is stored.
int bufSize; // The size of the buffer, in bytes.
}If the buffer created is too small, the syscall will return the miminum needed size for your buffer
MA_PIM_ARGS args;
args.field = MA_PIM_FIELD_CONTACT_NAME;
// Get value from name field at position 0.
int resultCode = maPimItemGetValue(&mArgs, 0);
if (resultCode < 0)
{
printf("Get Field %d Value Error %d", 0, resultCode);
}To add a new value to a field, use maPimItemAddValue; to remove a value from a field, use maPimItemRemoveValue; to change a value in a field and the attributes of the value, use maPimItemSetValue passing an args.buf.
For each of these functions the changes are not actually written to permanent storage until the item is closed with maPimItemClose -- if the program exits before then, the changes we be lost.
Usually
a MoSync panic will be thrown if the position is invalid, or a
field/index combination doesn't exist, and so on. On Android and iOS
(iPhone) you can disable panics using the function maSyscallPanicsDisable so that you'll get error codes instead.
Turn panics back on with maSyscallPanicsEnable.
This example application demonstrates how to add, modify and remove a new contact from an address book and how to read contacts from address book.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When this application is started a new contact will be added to a contacts list. All available contact fields will be filled with values.
At the next step the first address value from the new created contact will be modified. After that the new contact will be removed from the list. At this point user has two options:
The project is divided into several files. A brief description of the each file's content is as follows:
This topic describes the different types of resources (such as image, audio files, and binary files) that can be included in your application, and how you make MoSync aware of them and ensure type safety. It also gives a brief overview of how MoSync compiles resources during the build process.
For detailed information about resource compilation, the resource compiler, and resource list files and commands, see the Resource Compiler Reference guide. We also have a general tutorial that looks at various aspects of resource handling and provides oodles of good advice: Adding Resources to a Project.
MoSync uses resource list files (files with the extension .lst) to identify which external resources are to be included in an application. During the build process, the identified resource files are compiled to a single binary file called resources (both the program and resources are combined to a program.comb file also for easy downloading and execution of a program over the internet). This resource file is loaded on application startup and all resources are prepared for use in MoSync API syscalls.
Open MoSync, then select File > New > Other. The New Wizard window will open:

Expand the MoSync folder and select MoSync Resource File. The New Resource Wizard window opens.
Select a parent folder, then enter a filename for your resource file:

A resource list file contains declarations of resources and instructions. Each resource is identified by a .res declaration, followed by instructions for the resource compiler. Optionally you can add a symbolic name for the resource which can be used anywhere in the code to identify the resource. These names will be used to generate a header file with preprocessor definitions, mapping the name to a numeric ID, i.e. a MoSync handle. To make use of the resource, it is convenient to include the MAHeaders.h file and use the symbolic names instead of the actual numbers.
Example:
.res R_MYFACE // resource declaration, with the symbolic name R_MYFACE .dispose // instruction to delete the resource after loading image "myimages/face.png" // image to load - relative path may be included with forward slashes
Using this resource type, any binary data can be stored in a resource for access in MoSync. There's two types of binary resources: standard binary resources (.bin) and unloaded binary resources (.ubin). Standard binary resources will be loaded into memory directly at startup while unloaded binary resources will be kept on permanent storage. Standard binary resources can be read from and written to while unloaded binary resources only can be read from. Note that all changes made to the binary resource will be discarded whenever the application is closed as the memory will be discarded. The use of unloaded binary resources saves memory while sacrificing speed, as it usually is slower to do reads from the permanent storage.
Example:
.res R_MY_DATA .bin .include "my_data.bin"
All paths in a resource file are relative to the MoSync project directory. The filename can include a relative path, but always use forward slashes (for example, files/myaudio/dylan.mp3) or escaped backslashes (\\) in the pathname.
Image resources should be used for loading images from standard image formats. At application start the resource loader will automatically decode images and make them ready to use with the image related syscalls. Different phones support different image formats and sizes. Future MoSync versions will solve this by making it possible to customize what resources to bundle with a specific device or a group of devices in a project. This isn't possible right now, so to be sure that the images can be loaded, you should use png images as we've made sure that png images always can be loaded.
Example:
.res R_PRETTY_IMAGE .image "pretty_image.png"
The media resource is the resource type used for audio. Similar to the binary resource, there's two types of media resources - standard media resources (.media) and unloaded media resources (.umedia). With standard media resources, the audio will be loaded, and sometimes decoded, to memory. With unloaded media resources the sound will be streamed from disk to the extent possible. Some devices cannot stream from disk and will load the whole sound to memory anyway due to limitations in the underlying platform. The media resource statement is followed by a string of the mime-type and then the path to the file that should be included.
Common supported mime-types are:
Example:
.res R_MUSIC .umedia "audio/mpeg", "songs/song.mp3"
The Placeholder is a type of resource that may be used to create new resources programatically. Several syscalls such as maCreateDrawableImage and maCreateData must be passed a placeholder. This placeholder can then be used to identify the dynamically created resource. Note that there is also support to dynamically create placeholders using the maCreatePlaceholder syscall. Also, any resource that is destroyed at runtime becomes a placeholder.
This topic describes how resources (such as image, audio files, and binary files) are compiled by MoSync, and describes the format of the resource list files which contain the commands that are processed by the resource compiler.
MoSynC applications have three distinct sections: code, data, and resources. Resources are files external to your main code that are compiled during the build process into a form ready to be delivered to the target devices. Resources can include:
For more information about resources and how to create them, see the programming guide Compiling Resources. We also have a general tutorial, Adding Resources to a Project, which demonstrates how to make resources available to your applications and discusses many importants aspects of resource handling.
The resource compiler is part of the MoSync Pipe-Tool. It is automatically invoked during the build process but can also be run from the command line using the command:
pipe-tool -R outfile infile1 [infile2 ...]
for example:
pipe-tool -R output/resources audio.lst images.lst other.lst
This command compiles all the resources referenced in the resource list files audio.lst, images.lst, and other.lst and concatenates them into a binary file called resources, ready for deployment to the device.
As well as the binary file, the resource compiler creates the header file MAheaders.h which should be included in your application program. This header file contains the #defines that symbolically link your application to its resources.
To determine what resources it needs to compile, the resource compiler reads the resource list files (.lst) files in your project. A resource list file is a standard text file.
A resource listfile contains one or more resource definitions, and each resource definition in the file contains one or more commands for the compiler. Each resource definition begins with the .res command.
/* Example of a resource list (.lst) file. A project can contain more than one .lst file */ /* Define an image resource */ .res image1 .dispose // delete the image after loading has finished in run time .image "testimage.png", 99, 99 /* Define a file resource */ .res afile .bin .include "testfile.dat" /* Set a label for the beginning of mysprite */ .label mysprite_start /* Define a sprite resource */ .res mysprite .sprite image1, /* XY */ 0, 0, 10, 10, 5, 5 /* Define a binary resource */ .res // a resource with no name but which can be referenced as e.g. mysprite+1 .bin .string "The buck" // string .fill 8, '?' // fill memory .string "stops here!!!" // string with esc codes .byte 1,2,3,4 // bytes .half 5,6,7,8 // shorts .word 9,10,11,12 // ints .include "randomdata.bin" // include file
Resources are numbered sequentially, starting at 1. The resource ID 0 is reserved.
Additionally, the .res command can include a symbolic identifier for the resource, which can be used to reference a previously loaded resource in a later command (see, for example .sprite in the example above).
The .label command can be used to identify the location of resources for the application in run time.
Both standard C and C++ comments can be used in the resource list file.
This section describe the various commands that can be included within the definitions in a resource list file.
.res [symbol]
Initializes a new resource, optionally with the symbolic name symbol:
.res myimage .image "myimage.png"
.image "imagefile"
Declares a resource as an image and loads and stores an image file into the resource. The recommend image format is PNG which is supported by almost all devices. (Any type may be declared but whether or not the device supports it is another matter....) The filename can include a relative path, but always use forward slashes or escaped backslashes in the pathname.
.res picture
.image "myfile\\myimage.png"
.bin
Declares the resource as a binary. A binary resource is created and has 0 length.
.res myfile
.bin
.ubin
Declares the resource as an unloaded binary. A binary resource is created and has 0 length. At runtime this resource will not be memory resident, but is accessed from the file system directly.
.media "MimeTypeString", "MediaFile"
Declares the resource as a media file with a particular MIME type. (Any type may be declared but whether or not the device supports it is another matter....) The filename can include a relative path, but always use forward slashes or escaped backslashes in the pathname.
.res tune1 .media "audio/mp3", "myfiles/mysound.mp3"
.umedia "MimeTypeString", "MediaFile"
Declares the resource as a unloaded media file with a particular MIME type. (Any type may be declared but whether or not the device supports it is another matter....) At runtime this resource will not be memory resident, but is accessed from the file system directly. The filename can include a relative path, but always use forward slashes or escaped backslashes in the pathname.
.res tune2 .umedia "audio/mp3", "mysound2.mp3"
.sprite imageRef, start_x, start_y, size_x, size_y[, ref_x, ref_y]
Declares the resource as a sprite object. It requires an image reference for a previously loaded image. The sprite is cut out from this image at start_x and start_y. The size of the sprite is defined by size_x and size_y. Optionally, the sprite's reference point is defined by ref_x and ref_y. If ref_x and ref_y are omitted, the reference point is set as top-left (0,0).
.res myimage // set symbol for base image .image "myimage.png" // load base image, the top-left is always 0,0 .res mysprite1 .sprite myimage,0,0,10,10 // cut sprite from myimage from 0,0 to 10,10, default reference point = 0,0 .res mysprite2 .sprite myimage,10,0,10,10,5,5 // cut sprite from myimage from 10,0 to 10,10, reference point = 5,5
.tileset "imageFile",tilesize_x,tilesize_y
Declares the resource as a tileset image. The image contains tiles of the specified tilesizes. The filename can include a relative path, but always use forward slashes or escaped backslashes in the pathname.
.res .tileset "mytiles.png",16,16
.tilemap "tilemap.bin",mapsize_x,mapsize_y
Declares a tilemap. The tilemap binary file contains mapsize_x*mapsize_y 16-bit indices that refer to a tileset. The actual connection between tilemap and tileset is created at runtime. The filename can include a relative path, but always use forward slashes or escaped backslashes in the pathname.
.res .tilemap "mytilemap.bin",64,64
.dispose
Marks a resource as disposable. When the resource loader has finished loading all resources, it deletes all those resources marked for disposal.
.res image1 .dispose // dispose of resource after loading .image "myimage.png"
.placeholder
Creates an empty resource that can be filled with something at runtime.
.res myspace .placeholder
.skip
Skips a resource when loading. This can be useful when you have duplicated resource list files and wish to skip some resources in some lists.
myreslist1.lst:
.res image1
.image "myfile/myimage1.png"
.res image2
.image "myfile/myimage2.png"
myreslist2.lst:
.res image1
.image "myfile/myimage1.png"
.res image2
.image "myfile/myimage2.png"
.skip
.label "name"
Creates a marker label resource entry, so the application can search for the resource symbolically at runtime. This allows libraries to find their resources.
.label ui_resource_begin
.enum {variable[=expression][, variable[=expression] ...]}
Defines an enumerated set of variables that can be used in expressions.
.res myenum
.enum
{
a = 0,
b, // assigns to b the value of the next enum (1)
days = 365,
d // assigns to d the value of the next enum (366)
}
.string "string"
For binary resources only: inserts an ASCII string. Note: This string has no null terminator.
.res welcome
.bin
.string "hello" // write non-null-terminated string to binary resource
.cstring "string"
For binary resources only: inserts an ASCII null-terminated string.
.res
.bin
.cstring "hello" // write null-terminated string to binary resource
.pstring "string"
For binary resources only: inserts a Pascal string.
.res
.bin
.pstring "hello" // write Pascal string to binary resource
.fill size, filler
For binary resources only: fills the resource with size bytes of the filler. The data will be inserted at the current data position.
.res
.bin
.fill 8, '?' // insert '?' 8 times
.byte n1[,n2 ...]
For binary resources only: inserts bytes into the resource. The data is inserted at the current data position.
.res
.bin
.byte 1,2,3,4 // write bytes 1,2,3,4 to binary resource
.half n1[,n2] ...
For binary resources only: inserts half words (16 bits) into the resource. The data is inserted at the current data position.
.res myfile
.bin
.half 1,2,3,4 // write shorts 1,2,3,4 to the binary resource
.word n1[,n2] ...
For binary resources only: inserts (32-bit) words into the resource. The data is inserted at the current data position.
.res myfile
.bin
.word 1,2,3,4 // write ints 1,2,3,4 to the binary resource
.include "file"
For binary resources only: inserts a binary file into the resource. The data is inserted at the current data position. The filename can include a relative path, but always use forward slashes or escaped backslashes in the pathname.
.res myfile
.bin
.include "bin/test.bin" // write the contents of test.bin to the binary resource
.index symbol
For binary resources only: add an index so that a single resource can contain sub-indices. A resource with indices will contain an index table, which can be read by the user's program code with the resource index reading functions.
.res
.bin
.index "MySym"
.wideindex
For binary resources only: forces a indexed resource to use 32 bit indices's, so an index table may contain data pointers greater than 64K.
.res
.bin
.wideindex
.set variable[=expression]
Sets a script variable with the value of expression.
.res
.set hello = 1 This tutorial provides an introduction to adding resources, such as images and sounds, to a MoSync application. These external files need to be added into the project, so that they can be packaged with your code and deployed to the device.
The resource compiler is part of MoSync's Pipe-Tool (pipe-tool.exe). When you build your application in Eclipse, the resource compiler concatenates all the resources your program needs into a file called "resources" and then it creates an index by which your program can access the resources.
When it runs, the resource compiler looks for resource list files in your project. Resource list files are files that end with the .lst extension. Each resource list file references one or more resources. You don’t have to do anything special to make this work, you just need to create a file with a .lst extension and identify in it what resources you want to be included in the final packages.
You can include any file that will be useful for your program. Typically these will be images (in .png format), sounds (in .mp3 format), and MoSync-specific formats such as .mof font files.
If you are going to be creating data at runtime, or want somewhere to store downloaded data, then the resource list file is also useful for that. You can create a placeholder resource which is going to have a handle, but doesn’t yet contain any data.
There is a full description of all of the types of data you can put into a resource file in the Resource Compiler Reference. In this tutorial we will focus on a few of the common types of resource you are likely to use.
To add external resources to your app, you need to add a resource list file to your project. A resource list file is a text file with the .lst extension: res.lst or similar would be a good name for it.
Create the resource list file by selecting New > Other from the MoSync IDE's File menu.
Select MoSync Resource File from the list and click Next. Type a filename ending in ".lst" and click Finish. You’ll see the new file appear in the list of files in Project Explorer. It has an icon similar to a Pac-Man ghost. Double-click on the file to open it.
Tool tip: The Eclipse IDE can help with the syntax of writing resource list files with an Intellisense-style option list as you type. Press period (.) and you’ll see it appear.
The resource compiler creates an index of resources of a special type called MAHandle. Under the hood, this is actually an int, but by giving it a special type name it is easy to see where you can use the resources.
To use a resource you’ve compiled, you need to include a reference to file MAHeaders.h which the resource compiler will create in the root of your project:
#include "MAHeaders.h"
This file is a list of C #define directives, mapping the name you’ve given to your resources to the internal index number of the resource in the compiled resources file. You can use these definitions in your code.
As an example, I’ve created a resource file with a font (which we will see later). My res.lst file contains this:
.res MYFONT .bin .include "pretty.mof"
and the MAHeaders.h file that the resource compiler creates contains this:
#define MYFONT 1
This means that if you’ve included MAHeaders.h in my source code, you can use the reference directly.
Font* f = new Font(MYFONT);
If you look at the documentation for Font, then the constructor is
Font(MAHandle handle);
MAHandle means the name of the resource in the resource file (MYFONT), and the MAHeaders.h file maps between the name you have given it and its index position in the resources file. Whenever you see MAHandle in the MoSync documentation, it means the name you’ve given to a resource.
One of the most common types of resource you’ll want to include will be an image. This should generally be a PNG file. Some phones can handle JPEG and GIF images, but PNG has the best overall support, as well as supporting an alpha level for transparency.
To include an image, you need to declare it as a resource in the resource list file in the following way:
.res BACKGROUND_IMAGE .image "images/BG240.png"
Note: the path to the resource cannot be absolute. Furthermore you must use either forward slashes (/) in the path or escaped backslashes (\\).
When this compiles, we will have a reference to BACKGROUND_IMAGE in MAHeaders.h, and this code will create an image:
#include <MAUI/Image.h> ... Image* i = new Image(0, 0, 100, 100, NULL, true, true,BACKGROUND_IMAGE);
This will create a new image from BG240.png, and automatically set the size correctly for the image.
Alternatively, you can set the resource on an existing Image widget.
i->setResource(BACKGROUND_IMAGE);
This is useful for animation. More on that later.
If you want to include a sound file, then there is a specific directive for this. You need to include it as a .media (or a .umedia) file.
You also need to know the MIME type of the audio format you’ve want. You can look this up at http://www.iana.org/assignments/media-types/ but you’ll probably be using MP3 files. Not every phone will play every format (see Feature/Platform Support).
To add an MP3 file, you’ll add this declaration in a resource list file:
.res MUSIC .media "audio/mpeg", "music.mp3"
To add a MIDI file, you’ll add:
.res MUSIC .media "audio/midi", "music.mid"
To use the sound in your application:
maSoundPlay(MUSIC, 0, maGetDataSize(MUSIC));
The second parameter here is the offset position to start playing from, and the last parameter is the number of bytes to play. The function maGetDataSize() returns the size of a resource.
Fonts are bitmaps fonts which are specific to the MAUI user interface library. MoSync comes supplied with a couple of examples, as well as the software (the BMFonts tool) to make your own. To use them in your application, you need to include them in a resource list file.
.res MYFONT .bin .include "pretty.mof"
You can then use them in your own code as follows
Font* f = new Font(MYFONT);
Other tutorials will look at fonts in much more detail.
Placeholders provide a reference to a resource in MAHeaders, but that resource doesn’t exist yet. You’d use this in situations where you are going to either create a resource at runtime (like an image) or download data into a resource, and you want to use that resource in several places.
For instance, if you were writing an app which downloaded an image, you could create a placeholder so you can reference it when it is available:
.res DOWNLOADEDIMAGE .placeholder
You can then download the image to the placeholder.
ImageDownloader* dl = new ImageDownloader();
dl->beginDownloading("http://austinspad.net/img/front_batman.png", DOWNLOADEDIMAGE);This is just an excerpt of the code required for downloading. See the Downloading Data from the Internet tutorial for more information and examples.
When this has completed downloading, you can save the image to local storage:
MAHandle imagestore = maCreateStore("IMAGESTORE", MAS_CREATE_IF_NECESSARY);
maWriteStore(imagestore, DOWNLOADEDIMAGE);
maCloseStore(imagestore, 1);Even if you don’t save it permanently, you can still access the Image you’ve created by referencing the placeholder name you’ve used. You can use this across your whole application, and not just in the scope of the downloader.
You can also create placeholders at runtime. The difference with these is that the reference is not in MAHeaders.h, so it won’t be available to all the classes in your application.
MAHandle TEMPIMAGE = maCreatePlaceholder();
Not every file has to have its own resource label. You can create a series of resources which are each accessed from the same root MAHandle. For instance, if you wanted to create an animation in a MAUI::Image widget, you can set up four frames for the animation in the .lst file.
.res ANIMATION .image "frame1.png" .res .image "frame2.png" .res .image "frame3.png" .res ENDANIMATION .image "frame4.png"
Each image has its own .res declaration, which will create an index number for it, but it doesn’t need to be named. As MAHandle is a synonym for ‘int’, you can perform arithmetic operations on it. This excerpt will update an image every time a downloader informs your listener that more data has been downloaded, and you can update an animation on screen to show your user that it is working.
MAHandle h = ANIMATION;
Image* waitingAnim = new Image(0, 0, 100, 100, NULL);
...
void NotifyProgress(Downloader* dl, int downloadedBytes, int totalBytes)
{
h = h++;
if(h > ENDANIMATION)
h = ANIMATION;
waitingAnim->setResource(h);
}When the listener’s notifyProgress method is called, the resource on the MAUI::Image widget is updated.
There are two variations on some of the examples we’ve seen. Normally, resource files are loaded into memory, and are read directly from there. With some files, this makes perfect sense. You should only include fonts you want to use, and it is going to need access to it. For other resources, such as media files (MP3) and program data, it may be wasteful to have all of them loaded into memory at the same time. You may have three MP3 files, but you can only play one at a time. To handle this more efficiently, you can mark these as being unloaded with either .ubin (for data files) and .umedia (for MP3 files). These will only then be loaded when required.
You can also load other resources on demand. For instance, you can offer the user a choice of skins or background images for the application. Normally, all these resources will be loaded when the application starts, but you can defer it until a time when it is needed. This will reduce the start up time and the memory consumption. Loading resources on demand is slower overall than loading at start up though. The benefits are that you’re not loading resources you won’t need, and that the loading time is spread.
There is no difference in how you use unloaded binary and media resources.
There is another way to work with unloaded resources which are not .ubin or .umedia. The directive .skip means that this resource will not be loaded when the application starts. This is particularly useful if you’ve got large resources which you may not need. They are not taking up loading time or precious memory if you’re not going to use them.
.res BGIMAGE2 .skip .image "resources/background2.png"
Once you’ve created them, you can use them as you would any .image resource. There is no additional code required. They do take slightly longer to load than they would at application start up, but the user probably won’t even notice.
One easy way to localise your application is to keep all the system text like buttons and labels held externally to your compiled application. The application can then read in the strings that it wants to use. You can create a different version of the resource file for each language.
Reading in strings from the resource file isn’t necessarily obvious however, and I’ve created a few example of how you can do it.
C++ Strings are very strange if you come from a Java or C# background. They are not as ubiquitous as they are in Java and C#, and are quite frankly, of limited use.
They are not inherent objects, and many method calls do not accept Strings but char* or const char* instead. This means that you are constantly converting between String and char*, which can be verbose and laborious.
The MoSync resource compiler handles strings in three different formats
.string | Does not include a null-terminator at the end of the string |
.cstring | Does include the null-terminator |
.pstring | A Pascal string, which puts a byte at the start of the string containing the length. |
To read the value of the string, it isn’t as simple as
String* myString = new String(RESOURCENAME);
Instead, you have to make a more explicit call out to the resources file. There is an object which can help with this called DataHandler. This will let you read from the handle, and keeps track of its own position.
bool GetString(DataHandler* dh, String& output)
{
char c;
output.clear();
if(!dh->read(&c, 1))
{
return false;
}
while(c)
{
output.append(&c, 1);
if(!dh->read(&c, 1))
{
return false;
}
}
return true;
}In the first example above, you can see that the method takes a DataHandler and a String as parameters. It uses the DataHandler to read from the resource file one character at a time, and builds the string.
This on its own should be enough to convince you to always use .pstring whenever possible.
You can avoid a String object and create the string in a faster way using this function.
char* GetString(MAHandle stringResource)
{
// Get the length of the string data.
int length = maGetDataSize(stringResource);
// Allocate space for the string data plus the
// null termination character.
char* buffer = new char[length + 1];
// Read data.
maReadData(stringResource, buffer, 0, length);
// Null terminate the string.
buffer[length] = '\0';
// Return the string.
return buffer;
}This returns a char* to your string, but it doesn’t delete it. You will need to call
delete[] buffer;
when you’ve finished with it. It uses the function maGetDataSize() to determine the length of the string and then reads it in one go. It will add the null terminator on, so this would be suitable with resource string of the .string type.
The next example read Pascal strings into a String object without doing it character by character:
bool GetPascalString(MAHandle stringResource, String& output)
{
bool success = false;
output.clear();
DataHandler* dataHandler = new DataHandler(stringResource);
byte length;
if(dataHandler->read(&length, 1))
{
char* buffer = new char[length];
dataHandler ->read(buffer, length);
output.setData(new StringData<char>(buffer));
delete[] buffer;
success = true;
}
delete dataHandler ;
return success;
}It uses the DataHandler as well, and it creates a new StringData object with the string in. This would be a good way to read .pstrings from the resources file.
Finally, the fourth way doesn’t make use of DataHandler, and will probably be the fastest and sleekest way to read strings:
bool GetPascalStringWithoutDataHandler(MAHandle stringResource, String& output)
{
output.clear();
byte length;
// Check that there is at least one byte.
if(maGetDataSize(stringResource) == 0)
return false;
// Read byte size.
maReadData(stringResource, &length, 0, 1);
char* buffer = new char[length];
maReadData(stringResource, buffer, 1, length);
output.setData(new StringData(buffer));
delete[] buffer;
return true;
}It uses the underlying maReadData() function, which is wrapped by DataHandler to read the string from the resource. It also creates a new StringData object, and it deletes its temporary char array.
You can create or load binary data to use in your application. This may be a proprietary data format, or it may be a way of creating screens dynamically using localised resource files. The directive .bin indicates that this should be included as raw binary data.
There are two ways to do this. Firstly, if you’ve already got some binary data you want to use
.res BINARYDEMO .bin .include "resources/data.bin"
This will include your data for you to process as you see fit.
A second way is for you to describe it in the resource file itself.
.res BINARYDEMO .bin .byte 4 //The number of widgets .byte 1 //A label widget .pstring "This is the first item. It is a label" .byte 2 //A button widget .pstring "This is the second item. It looks like a button" .byte 1 //A label widget .pstring "The next item is an image" .byte 3 //An Image widget .word 14422 //The size of the image .include "resources/test.png"
I’ve created some content I want to put on to the screen, using some of the resource techniques we’ve already looked at. I can write a simple parser to create screen dynamically at runtime.
(Creating screens at runtime is the subject of the tutorial Creating New Screens.)
// Read the first byte. This determines the number of widgets
maReadData(BINARYDEMO, &length, 0, 1);
while(completed < length)
{
// Read the next byte. This is the type of widget
maReadData(BINARYDEMO, &widgetType, position, 1);
position++;
switch(widgetType)
{
case 1: // Label
position += getPString(BINARYDEMO, *text, position);
listbox->add(createLabel(text->c_str()));
break;
case 2: // Button
position += getPString(BINARYDEMO, *text, position);
listbox->add(createButton(text->c_str()));
break;
case 3: // Image
lprintfln("Creating image");
// Get the length of the image
maReadData(BINARYDEMO, &imageLen, position, 4);
position += 4;
lprintfln("Image is %d bytes", imageLen);
// Create a temporary placeholder
MAHandle imagePlaceholder = maCreatePlaceholder();
// Create an image from binary data
maCreateImageFromData(imagePlaceholder, BINARYDEMO, position, imageLen);
// Add the image to the listbox
listbox->add(new Image(0, 0, 100, 100, NULL, true, true, imagePlaceholder));
position += imageLen;
lprintfln("Image created");
break;
}
completed++;
}This is an extract from the accompanying source code. It reads through the binary data we’ve put into the resource file, and creates the appropriate widgets at runtime. You can change the content of you application by just changing the resource file. You can share the resource file with clients and translators without giving away all of your code. This is the screen it produces:
The MoSync Sensor API lets your applications communicate with the device's accelerometer and gyroscope, and its magnetic field, orientation, and proximity sensors. (Note that not all devices have hardware sensors. Before you run the application on the device, check which sensors it has using our SensorTest application.). We've a great user guide too.
The MoSync NFC API makes it easy to create applications that read and write standard near field communication tags on the latest Android devices. You can communicate according to the latest standards (NDEF, IsoDep, Mifare Classic/Ultralight), opening a whole range of possibilities for payment, personal identification, and similar close-proximity applications. Try out our NFCExample.
Modern smartphones have a variety of in-built sensors to detect, for example, movement, orientation, rotation, proximity, and magnetic fields. This tutorial explains how to start and stop sensors, and to receive sensor data in your application through the MoSync Sensor API.
Only
the MoSync runtimes for Android and iPhone have sensor support at the
moment, and sensor simulation is not yet available in the MoSync Emulator.
Not all devices have hardware sensors. Before you run the application on the device, check which sensors it has using our SensorTest application.
An
accelerometer is a sensor that measures the acceleration forces. On
most modern mobile devices there is a 3-way axis device that determines
the phone’s physical position. By measuring the static acceleration due
to gravity you can find the angle at which device is tilted and by
measuring the dynamic acceleration due to movement you can analyze the
direction in which the device is moving.
This sensor is available for both the Android and iPhone runtimes.
To start the accelerometer, call the MoSync Sensor API function maSensorStart(sensor, interval).
The first parameter should be SENSOR_TYPE_ACCELEROMETER. The second
parameter should be the desired update interval in milliseconds. Note that each device has a minimum value for this interval and setting a smaller value could stop the sensor.
The maSensorStart function returns SENSOR_ERROR_NONE if the sensor is started successfully, or a SENSOR_ERROR_* in case of error.
After the sensor starts, your application will receive EVENT_TYPE_SENSOR events. The event contains a struct with the following values:
To stop the accelerometer, call maSensorStop(sensor) with SENSOR_TYPE_ACCELEROMETER as the parameter.
The function returns SENSOR_ERROR_NONE, if the accelerometer stopped successfully, or SENSOR_ERROR_* in case of error.
#include <MAUtil/Moblet.h>
#include <MAUtil/util.h>
#include <maapi.h>
#include <conprint.h>
extern "C" int MAMain()
{
maSetColor(0xFF0000);
maUpdateScreen();
// start the accelerometer
maSensorStart(SENSOR_TYPE_ACCELEROMETER, 400);
while(true)
{
MAEvent event;
// listen for events
while(maGetEvent(&event))
{
// check if it’s a sensor type event
if(EVENT_TYPE_SENSOR == event.type)
{
// check if it’s a accelerometer sensor type event
if (SENSOR_TYPE_ACCELEROMETER == event.sensor.type)
{
char buffer[50];
maSetColor(0xFF0000);
sprintf(buffer, "x=%f, y=%f, z=%f",
event.sensor.values[0],
event.sensor.values[1],
event.sensor.values[2]);
maSetColor(0);
maFillRect(0, 0, 1000, 100);
maSetColor(0xFF0000);
maDrawText(10, 10, buffer);
maUpdateScreen();
}
}
}
}
};A gyroscope is a device for measuring or maintaining orientation. It can measure the rate of rotation around a particular axis. Unlike the accelerometer, the gyroscope is not affected by gravity.
This sensor is available for Android and iPhone runtimes.
To start the gyroscope, call maSensorStart(sensor, interval). The first parameter should be SENSOR_TYPE_GYROSCOPE. The second parameter should be the desired update interval in milliseconds. Note that each device has a minimum value for this interval and setting a smaller value could stop the sensor.
The maSensorStart function returns SENSOR_ERROR_NONE if the sensor has started successfully, or a SENSOR_ERROR_* in case of error.
After the sensor starts, your application will receive EVENT_TYPE_SENSOR events. The event contains a struct with the following values:
To stop the gyroscope, call maSensorStop(sensor) with SENSOR_TYPE_GYROSCOPE as the parameter.
The function returns SENSOR_ERROR_NONE if the sensor stopped successfully, or SENSOR_ERROR_* in case of error.
#include <MAUtil/Moblet.h>
#include <MAUtil/util.h>
#include <maapi.h>
#include <conprint.h>
extern "C" int MAMain()
{
maSetColor(0xFF0000);
maUpdateScreen();
// start the gyroscope sensor
maSensorStart(SENSOR_TYPE_GYROSCOPE, 400);
while (true)
{
MAEvent event;
// listen for events
while(maGetEvent(&event))
{
// check if it’s a sensor type event
if(EVENT_TYPE_SENSOR == event.type)
{
// check if it’s a gyroscope sensor type event
if (SENSOR_TYPE_GYROSCOPE == event.sensor.type)
{
char buffer[50];
maSetColor(0xFF0000);
sprintf(buffer, "x=%f, y=%f, z=%f",
event.sensor.values[0],
event.sensor.values[1],
event.sensor.values[2]);
maSetColor(0);
maFillRect(0, 0, 1000, 100);
maSetColor(0xFF0000);
maDrawText(10, 10, buffer);
maUpdateScreen();
}
}
}
}
};A magnetometer is a instrument used to measure the strength or direction of magnetic fields.
This sensor is available for Android and iPhone runtimes.
To start the magnetometer, call maSensorStart(sensor, interval). The
first parameter should be SENSOR_TYPE_MAGNETIC_FIELD. As the
magnetometer does not require an update interval, the second parameter
can be any random number.
The function returns SENSOR_ERROR_NONE if the sensor has started successfully, or a SENSOR_ERROR_* in case of error.
After the sensor starts, your application will receive EVENT_TYPE_SENSOR events. The event contains a struct with the following values:
The values are in microteslas. You can calculate the magnetic north using those values.
To stop the magnetometer, call maSensorStop(sensor) with SENSOR_TYPE_MAGNETIC_FIELD as the parameter.
The function returns SENSOR_ERROR_NONE if the sensor stopped successfully, or SENSOR_ERROR_* in case of error.
#include <MAUtil/Moblet.h>
#include <MAUtil/util.h>
#include <maapi.h>
#include <conprint.h>
extern "C" int MAMain()
{
maSetColor(0xFF0000);
maUpdateScreen();
// start the magnetometer sensor
maSensorStart(SENSOR_TYPE_MAGNETIC_FIELD, 1234);
while (true)
{
MAEvent event;
// listen for events
while(maGetEvent(&event))
{
// check if it's a sensor type event
if(EVENT_TYPE_SENSOR == event.type)
{
// check if it's a magnetic field sensor type event
if (SENSOR_TYPE_MAGNETIC_FIELD == event.sensor.type)
{
char buffer[50];
maSetColor(0xFF0000);
sprintf(buffer, "x = %f, y = %f, z = %f",
event.sensor.values[0],
event.sensor.values[1],
event.sensor.values[2]);
maSetColor(0);
maFillRect(0, 0, 1000, 100);
maSetColor(0xFF0000);
maDrawText(10, 10, buffer);
maUpdateScreen();
}
}
}
}
};A proximity sensor detects the presence of nearby objects.
This sensor is available for Android and iPhone runtimes.
To start the proximity sensor, call maSensorStart(sensor, interval).
The first parameter should be SENSOR_TYPE_PROXIMITY. As the proximity
sensor does not require an update interval, the second parameter can be
any random number.
The function returns SENSOR_ERROR_NONE if the sensor started successfully, or a SENSOR_ERROR_* in case of error.
After the sensor starts, your application will receive EVENT_TYPE_SENSOR events. The event contains a struct with the following values:
Note: the device’s OS establishes the meaning of “near” and “far”.
To stop the proximity sensor, call maSensorStop(sensor) with SENSOR_TYPE_PROXIMITY as parameter.
The function returns SENSOR_ERROR_NONE if the sensor stopped successfully, or SENSOR_ERROR_* in case of error.
#include <MAUtil/Moblet.h>
#include <MAUtil/util.h>
#include <maapi.h>
#include <conprint.h>
extern "C" int MAMain()
{
maSetColor(0xFF0000);
maUpdateScreen();
// start the proximity sensor
maSensorStart(SENSOR_TYPE_PROXIMITY, 123);
while (true)
{
MAEvent event;
// listen for events
while(maGetEvent(&event))
{
// check if it's a sensor type event
if(EVENT_TYPE_SENSOR == event.type)
{
// check if it's a proximity sensor type event
if (SENSOR_TYPE_PROXIMITY == event.sensor.type)
{
char buffer[50];
maSetColor(0xFF0000);
sprintf(buffer, "proximity sensor value = %f",
event.sensor.values[0]);
maSetColor(0);
maFillRect(0, 0, 1000, 100);
maSetColor(0xFF0000);
maDrawText(10, 10, buffer);
maUpdateScreen();
}
}
}
}
};The
device’s operating system uses the accelerometer to determine the
current orientation of the device and can therefore behave as an
orientation sensor.
This sensor is available for Android and iPhone runtimes.
To start the orientation sensor, call maSensorStart(sensor, interval).
The first parameter should be SENSOR_TYPE_ORIENTATION. As the
orientation sensor does not require an update interval, the second
parameter can be any random number.
The function returns SENSOR_ERROR_NONE if the sensor started successfully, or a SENSOR_ERROR_* in case of error.
After the sensor starts, your application will receive EVENT_TYPE_SENSOR events. The event contains a struct with the following values:
type
- SENSOR_TYPE_ORIENTATION
values[0]
- UIDEVICE_ORIENTATION_UNKNOWN
- UIDEVICE_ORIENTATION_PORTRAIT
- UIDEVICE_ORIENTATION_PORTRAIT_UPSIDE_DOWN
- UIDEVICE_ORIENTATION_LANDSCAPE_LEFT
- UIDEVICE_ORIENTATION_LANDSCAPE_RIGHT
- UIDEVICE_ORIENTATION_FACE_UP
- UIDEVICE_ORIENTATION_FACE_DOWN
To stop the orientation sensor, call maSensorStop(sensor) with SENSOR_TYPE_ORIENTATION as the parameter.
The function returns SENSOR_ERROR_NONE if the sensor stopped successfully, or SENSOR_ERROR_* in case of error.
#include <MAUtil/Moblet.h>
#include <MAUtil/util.h>
#include <maapi.h>
#include <conprint.h>
extern "C" int MAMain()
{
maSetColor(0xFF0000);
maUpdateScreen();
// start the orientation sensor
maSensorStart(SENSOR_TYPE_ORIENTATION, 123);
while (true)
{
MAEvent event;
// listen for events
while(maGetEvent(&event))
{
// check if it's a sensor type event
if(EVENT_TYPE_SENSOR == event.type)
{
// check if it's a orientation sensor type event
if (SENSOR_TYPE_ORIENTATION == event.sensor.type)
{
char buffer[50];
maSetColor(0xFF0000);
sprintf(buffer, "orientation sensor value = %f",
event.sensor.values[0]);
maSetColor(0);
maFillRect(0, 0, 1000, 100);
maSetColor(0xFF0000);
maDrawText(10, 10, buffer);
maUpdateScreen();
}
}
}
}
};Our SensorTest example application implements all of the sensor types supported by the MoSync Sensor API. When it is run on a device, it checks for the presence of each type of sensor and shows you the current event data being received from those that it finds.
This example application makes use of the MoSync Sensor API and OpenGL API to graphically display the orientation of the device.
Note: This example only works properly on a physical device with an accelerometer. Currently only Android and iOS devices are supported, and no emulators.

This example is included in the MoSync SDK installation in the /OpenGLES/examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When it is started on a suitable device, this application displays a quad (finite plane) tangential to the ground. The rectangle remains stationary regardless of changes to the orientation of the device. Use the Back button to close the application.
This example makes use of the Sensor API to collect data from the devices accelerometer, and makes use of the Open GL API to display graphically that data. The 3D rendering is done in a seperate module so if you dare you can try and plug in your own 3D renderer and see how your 3D world looks from different angles using the accelerometer. To do this you just implement the Renderer interface and the two functions init and render. Look at the default renderer implementation called SimpleRenderer to see how it is done.
This example application shows how to use the MoSync NFC API which provides C syscall functions to read and write near field communication tags. This example works on the platforms supported by the MoSync Wormhole JavaScript Library and NFC C++ Library (see Feature/Platform Support).
Main screen (Android Emulator)
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
The following technologies are used in this application:
ScreenOrientation is a well-commented example application for beginners. It demonstrates how to detect and respond to changes in screen orientation, and also how to set the orientation mode on platforms that support it. This application is based on the MoSync Moblet framework.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When the application runs, the screen initially displays the message "Started". Turn the device. The screen will repaint showing the new orientation and dimensions.
Examine the source code of the application to learn how the program works.
Note the use of the maScreenSetOrientation syscall to set the screen orientation mode. For platforms that support it (for example, Android), this sycall enables you to lock the orientation mode to just portrait or landscape mode, or to enable switching between them (dynamic mode).
SensorTest is a simple application that demonstrates how to use the functions of the MoSync Sensor API to control a device's sensors, and to receive current measurements.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
This example application implements all of the sensor types supported by the MoSync Sensor API. When it is run on a device, it checks for the presence of each type of sensor and shows you the current event data being received from those that it finds.
The project is divided into 2 files:
Use the Back button to close the application.
The MoSync SDK comes with several useful standard C and C++ code libraries to ease code development.
The C++ Standard Template Library (STL) is a feature-packed code library that will be familiar to many programmers thanks to its all-round usefulness to computer science and industry.It provides many powerful algorithms, containers, associative arrays, and iterators to simplify data handling in advanced applications. We have an example application that demonstrates many of the functions of this library: HelloSTL.
The C Newlib Library is particularly suited for mobile devices and embedded systems. It is a conglomeration of several library parts, all under free software licenses. It provides subroutines for handling files, environment variables, processes, output streams, signals, and memory. (Note: MoSync does not implement the signals and locale sections of the library).
MoSync mastdlib Library is our cut down version of the Standard C Library, libc. It contains the basic string conversions and random number generators. Great when your applications need a small footprint.
The C++ Standard Template Library provides a set of common classes and interfaces that greatly extend the core C++ language. It provides a set of classes such as containers, associative arrays, iterators, functions objects, and strings. It also provides algorithms for counting, sorting, finding, coping, and replacing elements in a container.
STL is almost entirely written in the form of C++ template classes that provide common programming data structures and functions. These template classes are all members of the std namespace.
We provide detailed code examples in the use of STL with MoSync, HelloSTL , that you can download from our GitHub repository. It provides many examples of how to use the containers, algorithms, strings, functors, auto_ptr and other components of STL.
An
iterator is an object that can iterate through a range, pointing to the
elements in the range. All iterators in STL provide at least the operator++, to iterate forward in the range, and the derreference operator(*), which provides the way to access the object to which the iterator points.
All containers define their own iterators, which have different abilities. There are five types of iterator in STL:
STL provides sequence and associative containers. For an associative container, the index does not have to be an integer; it can be any type.
A
special container class that is designed to store bits. It is optimized
for space allocation: each element occupies only one bit.
Bitset is defined in the <bitset> header.
A
container that holds it's elements in multiple blocks of memory and
keeps track of them, making it fast on insertions at the end and also at
the beginning. It doesn't need to copy and destroy objects when it
needs to allocate more memory. Deques invalidate iterators, pointers,
and references when the size is changed.
Deques are the right choice:
Deque is defined in the <deque> header.
List
is implemented as a doubly linked list of elements. std::list doesn't
have random access, it provides only bidirectional iterators. For
accessing an element you have to iterate through list, until you reach
the element. Compared with vector or deque, list is not efficient for
random access.
List is the right choice for:
List doesn’t invalidate an iterator that refers to an element as long as the element is not erased from the container.
The map container is an associative container. An entry in the map is a combination of key - value (std::pair). The key is used to identify an element in the map (the index).
Map sorts its elements automatically by key ( from lower to higher ). The default comparison criterion is std::less,
and it's provided as a default template parameter. Another ordering
criterion, can be provided as the third template parameter. It has to
be a class that defines an operator() taking two arguments of the key type and returns a bool. It can be also just a function (with the same prototype as operator()).
std::map
allows only unique entries. That means that you can't have in a map two
entries with the same key. If you try to insert in map a entry with a
certain key, and inside the map exits already an element with that key,
the element will be overridden.
Map is the right choice:
Map provides bidirectional iterators.
Map is defined in the <map> header.
std::multiset sorts automatically it's elements from lower to higher and accepts multiple copies of an object.
Multiset
sorts automatically it's elements from lower to higher and it is
implemented usually as a binary search tree. The ordering criterion is,
by default, std:less. Another one can supplied as the second template parameter. It can be a function, taking two arguments, of the key type and returning a bool or a class defining operator() with the same prototype.
Multiset is the right choice:
Multiset is defined in the <set> header.
Priority_queue
is implemented as a container adaptor. Containers adapters are classes
that use an encapsulated container and provide a restricted interface to
that container. The underlying container can be a STL container or some
other container type and it has to provide the following public
member functions: back(), push_back(), pop_back().
Priority_queue is defined so that the first element is always the one with the highest value.
The default comparison criterion used is std::less. We can provide another comparison class, a functor, with it's operator() taking two arguments, of the same type as the container elements, and returning a
bool.
priority_queue is defined in the <queue> header.
queue
is implemented as a container adaptor. Containers adapters are classes
that use an encapsulated container and provide a restricted interface to
that container. The underlying container can be a STL container or some
other container type and it has to provide the following public
member functions: front(), back(), push_back(), pop_front().
Queue is designed to operate in a FIFO mode (first-in first-out).
Queue is defined in the <queue> header.
std::set
is an associative container, that stores unique elements. If you try to
insert an object that is equivalent to one that is already in the set,
the set won't make the insertion.
Set
sorts automatically it's elements from lower to higher and it is
implemented usually as a binary search tree. The ordering criterion can
be supplied as the second template parameter and is by default std::less.
The ordering criterion can be a function taking two arguments of the key type and returning a bool. A class defining operator() with the same parameters and returning value as the function can be also used as an ordering criterion.
Set is the right choice:
Set is defined in the <set> header.
std::stack is
implemented as a container adaptor. Containers adapters are classes
that use an encapsulated container and provide a restricted interface to
that container.
The
underlying container can be a STL container or some other container
type and it has to provide the following public member functions: back(), push_back(), pop_back().
Stack is a container that operates as in a LIFO (last in first out) mode.
The elements are inserted and extracted only from the end of the container.
std::stack is defined in the <stack>
header.
Vector
keeps its elements in a dynamic array and maintains its storage as a
single contiguous array of objects (in order to have efficient indexing
and iteration). That means that we can have random access to its
elements, not only though iterators but also with pointers to elements,
just like with regular arrays.
Accessing
the elements of a vector provides almost the same performance as the
regular arrays do. Compared with the other STL containers, vector has
the fastest random access to its elements.
A
dynamic array is allocated first time the vector is constructed. When
vector needs a bigger array, to hold its elements, it will allocate a
new, bigger, chunk of memory and will copy all the elements to this new
chunk, deleting the old chunk and destroying the objects contained in
it.
Vectors
invalidate their iterators on insertions and deletions. Also when the
capacity is exceeded, and new memory has to be allocated.
Vectors are the right choice for:
Vector is defined in the <vector> header.
String is a template class designed to manipulate sequences of characters. It is a special type of container holding characters. The string class is defined in the <string> header.
A functor is a class that can act like a function. It has the advantage that, unlike functions, it can store data.
A
functor is a class/struct that overloads the function call operator so
that an instance of that class acts just like a function ( and can be
supplied were a function is expected ).
For example:
class MyFunctor
{
public:
int operator()()
{
//some implementation
//returns an integer value
}
private:
//some data
};
MyFunctor getNumber;
int someNumber = getNumber(); // MyFunctor::operator()() is calledThe function call operator can be defined to take any number of parameters, or no parameters at all.
STL
algorithms are function templates,implementing algorithms for sorting,
filling, searching containers,comparing ranges, copying ranges, etc.
They
can be used with any type of container (STL container or not) that
provides the proper iterator and holds elements of types that overload
the operators required by the algorithm.
For example the std::count algorithm, compares every element in a container with a value we provide. For comparison it uses operator==, so we have to have inside the container a type that has an operator== defined.
STL algorithms are defined in the <algorithm> header.
A smart pointer that takes ownership of the pointer it stores. When the auto_ptr object is destroyed, the pointer will be deleted.
auto_ptr is defined in the <memory> header.
The pair structure is provided to treat two values as a single unit. It is defined in <utility> header.
If
both values are equal, usually the first element is returned. Both
functions are provided with an additional argument, that is the
comparison criterion.
The default comparison criterion is operator<.
These functions are defined in the <algorithm> header.
This
function is provided to swap the values of two objects. The swap is
possible only if the copy constructor and the assignment operators are
defined.
The function is defined in the <algorithm> header.
Due to platform limitiations some of the STL headers is not included in this package. They will be added later.
For some mobile applications, the user interface elements can take up more than half of the source code. Getting every little detail right can add hours of frustration for the programmer. That’s why we have developed multiple solutions for cross-platform UI development: the NativeUI Library, the Widget API and MAUI. Each, in their own way, ensures UI consistency across multiple platforms from a single source base. Let’s take a look.
![]() |
![]() |
![]() |
| MAUI screen with MAUI widgets (MoRE) | Widget API screen with native widgets (Android) | An HTML UI, designed using jQTouch (Android) |
With the introduction of Wormhole technology in MoSync 2.7 Pyramid, now developers can design their UI in HTML and JavaScript and then use the available device functionality of MoSync using the available libraries. You can browse our documentation for creating HTML based projects in MoSync or communicating between JavaScript and C++.
To create HTML based user interfaces you do not need to use special calls and any normal HTML file would work in MoSync as a UI. It is also possible to use the JavaScript UI frameworks designed specifically for mobile websites (e.g. jQTouch, JQuery mobile, or Sencha Touch) in your MoSync apps.
Widget API
uses the device’s own widgets, allowing you to create applications that
are exactly like the ones you create with the platform’s own SDK. It also brings you the power to integrate a web browser and utilize
OpenGL in your applications. The NativeUI Widget API is primarily aimed at leading-edge
platforms and currently supports both Android and iOS (iPhone, iPad,
iTouch). We’ll be adding more platforms in the near future.
Using the Widget API gives distinct advantages when you need:
(Note that Widget API doesn’t work of course on MoRE, the MoSync emulator, so you must test and develop your application using the Android emulator, iPhone simulator, or a real device. To read more about testing apps in native emulators, see Emulating a Device.)
The NativeUI Library is a high-level wrapper for the Widget API. It supports all the widgets in the Widget API with their specific properties and events.A base Widget class that takes care of instantiated objects and their destruction and provides methods for managing widgets, like addChild, insertChild, and removeChild, and methods for manipulating widgets like setHeight, setVisible, and fillSpaceVertically.
The NativeUI Library includes a background widget manager that handles widget events. You do not have to use the CustomEventListener to catch widget events: you can receive only widget specific events by setting listeners to widget objects. Basic widget functions (setPropertyInt, getPropertyString) can be called at any time instead of the specific functions. And support is provided for fonts.
MAUI
uses custom MoSync screens and widgets, enabling you to create
application user interfaces that look exactly the same across all
platforms. It runs not only on Android and iOS, but also on Windows
Mobile, JavaME, Symbian, Moblin, MoRE ( the MoSync emulator ) and all
the other platforms MoSync supports. This is the user interface solution
to choose if you simply must have an application that looks the same
whatever the device it runs on.
Using MAUI gives distinct advantages when you need:
The Widget API and MAUI are very similar to other user interface solutions
that you will find in proprietary SDKs. The user interface is structured
as a hierarchy of components consisting of containers called screens
and controls called widgets. Different widgets have different functions
and properties which can be set in order to customize their appearance
or behaviour. Special types of widgets called “layouts” give you control
over the positioning of other widgets on the screen. As the user of the
application interacts with your application’s widgets, events are sent
from the MoSync runtime on the device to your code for action.
You
can of course use both Widget API (or NatriveUI Library) and MAUI together in the same application,
switching between Widget API screens and widgets and MAUI screens and
widgets as needed, giving you absolute control over the user interface.
Use Widget API to present the standard application screens that the user
expects to always look the same as others on their device, then provide
highly-customized screens and controls using MAUI. You get the best of
both worlds.
All our user interface solutions are documented in the MoSync API Reference available in both in the download package and on our website: see the entries for NativeUI Library, Widget API and MAUI.
We provide example applications that use MAUI and Widget API in the /examples folder in the download package. In particular, check out our HelloNativeUI and HelloMAUI examples, well-commented beginners applications that show how to define, position and control screens and widgets using Widget API and MAUI, and MAUIex and NativeUIDemo, which demonstrate the variety of widgets available in both libraries. (Read our guide called Importing the Examples to understand how to load and view the examples.)
Our Introduction to MAUI tutorial covers a lot of the basics you need to get started both with MAUI and user interfaces in general.
The MoSync NativeUI Library is built on our Widget API. It provides classes and functions for high-level control of native user-interface elements.
The
NativeUI Library and the underlying Widget API are designed to work
with native user-interface controls. Currently the library supports the
iPhone/iOS and Android platforms.Some widgets specific to the
iPad and Android tablets are not yet available through the library.
You can test your NativeUI Library application directly from the MoSync IDE as long as you have installed at least one native emulator. (NativeUI applications will not, of course, work in the MoSync MoRE emulator.)
The
NativeUI Library is built on our Widget API which provides a
comprehensive range of low-level functions (syscalls), event types, and
constants for creating and working with native user-interface widgets
like screens, layouts, buttons, and many more.
Note: not all of the widget types in the API are supported on all platforms -- they are, after all, native widgets! Full documentation of the Widget API can be found in the MoSync API Reference in the IDE and online.
We provide many example applications that make use of the Widget API or the NativeUI Library (which is itself a high-level wrapper for the Widget API). The examples and the API/Library they use include:
The library is a high-level wrapper that supports all the widgets in the Widget API. It includes:
| Activity Indicator | iOS & Android |
| Button | iOS & Android |
| CameraPreview | iOS & Android |
| Check box | iOS & Android |
| Date Picker | iOS & Android |
| Edit box | iOS & Android |
| GL View | iOS & Android |
| Horizontal layout | iOS & Android |
| Image | iOS & Android |
| Image Browser | iOS & Android |
| Image Button | iOS & Android |
| Label | iOS & Android |
| List View | iOS & Android |
| List View Item | iOS & Android |
| Navigation Bar | iOS & Android |
| Number Picker | iOS only |
| Progress Bar | iOS & Android |
| Relative Layout | iOS & Android |
| Screen | iOS & Android |
| Search Bar | iOS & Android |
| Slider | iOS & Android |
| Stack Screen | iOS & Android |
| Tab Screen | iOS & Android |
| Time Picker | iOS & Android |
| ToggleButton | Android only |
| Vertical layout | iOS & Android |
| Video View | iOS & Android |
| Web View | iOS & Android |
For each type of widget there is a corresponding class, so the routine in which a widget is instantiated is very simple:
WidgetType* myNewWidget = new WidgetType().
Do not forget to include the header file for all widgets, Widgets.h, or each widget class one by one.
The shared methods implemented across all widgets include:
For all properties, we have endeavoured to implement them as separate methods, rather than as setProperty/getProperty function calls.
The library implements separate listeners for each widget that can receive events. Take, for instance the EditBoxListener. The EditBox widget might send 4 types of events:
Those events will notify the user with respectively the callbacks:
More than just one listener can be attached to a widget. Attaching a listener to a widget can be done in this way:
EditBox* myEditBox = new EditBox(); myEditBox->addEditBoxListener(this);
A Dialog is a modal view that can look different depending on the platform:
When a Dialog widget is created it is empty, it has no content. Use setMainWidget(mainLayout) to set the main widget of the dialog.
A Dialog gets visible only after calling show() method.
Usage example:
Dialog* myDialog = new Dialog();
myDialog->setTitle("My Form");
// Set specific iPad property for position, so that
// the dialog arrow points up.
myDialog->setArrowPosition(MAW_CONSTANT_ARROW_UP);
// Set its content.
myDialog->setMainWidget(mainLayout);
...
// Display the dialog at the right time.
myDialog->show();Access to device fonts can be acomplished via font syscalls (see maFontGetCount, maFontLoadDefault, maFontGetName, maFontLoadWithName, etc).
After getting the desired font using maFontLoadDefault or maFontLoadWithName, the handle to the font can be applied via the method setFont to the widgets:
Example:
// Get the first available font of the device.
if ( maFontGetCount() > 0 )
{
char buf[256];
maFontGetName(0, buf, 256);
// Load the font with size 10 and get it's handle.
int fontHandle = maFontLoadWithName(buf, 10);
myLabel->setFont( fontHandle );
}At any time the font color can be set by calling the method setFontColor:
enum Colors
{
INTENSE_BLUE = 0x104E8B ,
LIGHT_BLUE = 0xB2DFEE
};
myLabel->setFontColor(LIGHT_BLUE);Also, the font size can be set for the widget in use, without having to actually modify the font resource:
#define FONT_SIZE_REGULAR 15.3 myLabel->setFontSize(FONT_SIZE_REGULAR);
Note: When building applications that use Native UI, remember to select an iOS or Android target in the right-hand device profile panel.
HelloNativeUI is a well-commented example application for beginners. It consists of a very simple graphical user interface application that uses the NativeUI library and Moblet framework. It illustrates how to create NativeUI screens, and how to position widgets and handle events.
![]() | ![]() |
These screens show the look of the application on Android: its appearance is, of course, different on different platforms because it uses each platform's native GUI controls and settings. Note also that this example will not work on the MoSync emulator (MoRE) because it has no Native UI support yet.
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When the application runs, the user is presented with a simple NativeUI screen with four widgets:
On clicking the Submit button, the password is validated (just validates the length of the password for demonstration purposes).
Examine the source code of the application to learn how the program works. The code commenting highlights various aspects of working with NativeUI screens and widgets, including:
To understand how NativeUI and MAUI (an alternative GUI solution that use's MoSync's own screens and widgets to ensure graphical consistency across all platforms), compare this example application with the HelloMAUI example application.
This example application demonstrates many of the important features of MoSync's NativeUI Library. The library provides a set of C++ classes for handling native user interface components (buttons, toolbars, list boxes, etc.). Under the hood, the library makes use of the C functions in MoSync's Widget API. In the latest version of this example we also demonstrate banner ads.
This example works on all platforms supported by the NativeUI Library (see Feature/Platfom Support).
![]() | ![]() | ![]() |
| Colors screen on Android | Images screen on Android | Web View screen on Android |
![]() | ![]() | ![]() |
| Colors screen on iOS (iPhone) | Images screen on iOS | Web View screen on iOS |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
This application example shows how to use various native widgets (UI components) in a MoSync application. This includes a tab screen, a list view, a web view, and a custom view for an image swiper composed of several widgets.
The example also shows how to use placeholders and strings in the resource definition file. In the /UIWrapper folder is a class library that wraps the MoSync widget system for NativeUI on Android and iPhone.You can use this library in your own applications, and extend it as needed, but note that this is an example library, and is not yet fully documented and does not fully support all features of the NativeUI Widget API.
For the full documentation of the MoSync NativeUI, see the documentation in the package for the include file IX_WIDGET.h and the overview for the Widget API.
The main UI widget in the application is a TabScreen, which has three screens (tabs):
Some techniques demonstrated by the example include:
In the MoSync 3.0 version of this example application, we include a banner advertisment created using the MoSync Advertising Library and API:
![]() | ![]() |
| Advertising banner on iOS | Advertising banner on Android |
This application demonstrates the use of NativeUI screens and widgets to play the traditional game Rock-Paper-Scissors.


Note: These screens show the look of the application on Android. The application's appearance will of course be different on other platforms because it uses each platform's native GUI controls and settings. Note also that this example will not yet work on the MoSync emulator (MoRE) because it has no Native UI support. The platforms that support NativeUI are: Android, iOS and WP7.
This example is included in the MoSync SDK's /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When the application starts the user sees the main application screen with the message "Press PLAY to start game". On tapping "Play" the user is instructed to choose a weapon: rock, paper, or scissors. (The displayed weapons images can be found in the project's /Resources/Images folder.) Tapping a weapon plays the game against the computer opponent. The winner is computed by Game.cpp, and the result of the contest is shown to the user. The application keeps track of wins, ties, and losses, displaying these totals after each round.
The application's project is split into several code files, linked together through header files. In Moblet.cpp we manage the application. In PlayScreen.cpp we define the UI elements. And in Game.cpp we handle the game logic (scoring, etc.). The entry point for the entire application is in main.cpp.
There is one main application screen, Playscreen. All other displays are created from it (for example, by switching backgrounds and showing different sub-sets of widgets) according to the stage of the game that has been reached. PlayScreen.cpp handles the display of the screen, including its layout and the behaviour and positioning of the individual widgets:

To minimize the use of string conversions (using itoa functions) and code duplication, the method setWidgetProperty is used to set the value of an integer property for widgets (properties like MAW_WIDGET_BACKGROUND_COLOR).
A timer is used to switch the label for "Choose you weapon!" (mFlickrLabel) from visible to invisible and back to notify the user that input is required.
This example application makes use of the MoSync NativeUI Library and demonstrates how to use the VideoView widget to embed video in your application.
![]() | ![]() | ![]() |
| On Android, playing a .3gp video from a URL | On iOS, playing a .m3u8 video from a URL | On Android, playing a .3gp video from a local path |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
On iOS and Android:
When it starts up, this application displays a main screen with two tabs, Video and Settings.
On the default Video tab the user can enter the URL of a video file -- of any Android or iPhone/iOS supported formats . (A default URL is provided at start-up, based on the application settings.)
Tapping Load url fetches the file. Tapping Play starts the video.
The settings on the Settings tab enables the user to show or hide the label that displays the video duration, and also the default URL that is loaded when the application starts-up. Pressing Reload returns to the video screen and starts loading the default video.
While a video is playing the user is granted control and the Pause and Stop buttons can be used. After tapping on the video, the platform-specific media controller is displayed.
When loading a new video, any playing video is stopped automatically before the new video plays.
On Android only:
The user can play a local file by entering a local path in the edit box and clicking the Load path button.
This example application makes use of the MoSync NativeUI Library, and through that the VideoView widget in the MoSync Widget API.
The project is divided into several files:
This tutorial introduces the MoSync API for User Interfaces (MAUI). It describes how to use the MAUI library classes to build screens and widgets and how to extend the MAUI model with your own custom components.
MAUI is the collection of user interface components that you can use in your own applications. It is quite possible to create an entire mobile application in MoSync without them, but they provide a lot of basic functionality, and if you make use of them you can save a lot of time. The MAUI model is extendible, and you can create your own components in it.
MAUI is a general-purpose UI framework that helps you develop usable, attractive, responsive user interfaces with a consistent look and feel across all the platforms and devices that MoSync supports. It draws inspiration from popular modern user interface frameworks like Windows Forms, Java SWING and QT, and is designed with the peculiarities and limitations of mobile devices very much in mind.
MoSync comes with an example application called MAUIex which has a lot of useful code that you can copy into your own application.
The fundamental building blocks of MAUI interfaces are screens and widgets.
Screens represent a particular instances of the application's user interface, a whole screen display. A screen is typically associated with a specific activity — like logging in, or browsing a list of albums, or viewing the description of a shopping item. Screens are essentially different logical locations in your application that the user can navigate between to perform different tasks.
To use the MAUI Screen class in your application you need to include the header file:
#include <MAUI/Screen.h>
There is no inherent hierarchy or other relationship between individual screens, although one can be implied or even enforced at the application level. Some screens may be considered side-by-side "siblings" of other screens, others have a hierarchical parent-child relationship.
To show a particular screen (and send all other screens to the background) you use the class's show method. There is also a corresponding hide method.
Screens are containers for widgets. There is always a main widget, which is resized to match the screen resolution of the device. To set the main widget, you use the setMain method, and to get it you use getMain.
The MAUI Screen class implements a number of useful event listeners so that you can detect UI events including key presses and pointer movements.
Every user interface element in MAUI is a widget. Each widget performs a common GUI task. Examples include:
All widgets are direct or indirect subclasses of the base class MAUI::Widget . To use a MAUI widget class in your application you need to include the appropriate header file, for example, if you want to use labels:
#include <MAUI/Label.h>
A widget can be a container for other widgets. For instance, if you want an image with text overlaid, you can create an Image widget, and then set the Image to be the parent of a Label widget. When a parent widget is destroyed, all of its children are destroyed as well.
The UI of a screen is built by creating a hierarchy of widgets.
There is a widget called Layout that can be used to define a grid in which to arrange other widgets, and a widget called ListBox that can be used to make a horizontal or vertical list of widgets. Both ListBox and Layout are designed solely to be containers of other widgets. Others widgets, like Label will be more or less successful containers depending on how you employ them.
A good example of how the Label and ListBox widgets work together can be found in the MAUIex example application that comes with MoSync. Here we can see a typical hierarchy of Layout and ListBox widgets arranging one of that application's screens:

Each screen has a main widget which covers the entire physical screen — in this case it is a Layout widget with one column and two rows: the top row is the main application area, the bottom row is being used to display navigation buttons ("Back"). Inside the main layout widget is a ListBox widget, which allows for vertical scrolling of the main application area.
You can define the size and background colours of widgets, and they are skinnable. When you create a widget, you specify its size, its position and its parent:
Widget* widget = new Widget(0, 0, 240, 320, NULL);
The standard constructor for a widget is new Widget(x position, y position, width, height, parent widget).
On a mobile device, the x and y positions are often less useful than you might imagine. In reality you may find that you do almost all of your positioning through Layout and ListBox widgets, and by setting the padding properties of the widgets with methods like w->setPaddingBottom(5); which will put a margin against the bottom of that widget.
Some standard methods of widgets set the background colour of the widget, and whether it should draw a background at all.
// Set the widget background colour to a dark green widget->setBackgroundColor(0x30A030); // Ensure the widget is drawing a background colour widget ->setDrawBackground(true);
Sometimes you want it to draw a background, and sometimes you don’t. With the widgets here, a dark green background is added to them rather than a skin. However, if you put a layout over an image you want to use as the background, then you need to set setDrawBackground(false) to ensure the layout doesn’t paint over my image where you don’t want it to.
There are a lot of different screen sizes around now. It used to be that there were two or three common sizes which virtually all phones shared. Now, with so many different aspect ratios it is almost impossible to predict what the screen size and shape will be.
However, it is easy to query a device's screen size from within your application using the maGetScrSize() function:
// Returns size of the screen to screenSize. MAExtent screenSize = maGetScrSize(); // Returns width of the screen to scrWidth. int scrWidth = EXTENT_X(screenSize); // Returns height of the screen to scrHeight. int scrHeight = EXTENT_Y(screenSize);
This will give you the height and width of the screen in pixels. To know whether the screen is in landscape or portrait mode, you need to test the sizes:
// If Width is greater than Height of the screen, the screen
// is in Landscape mode otherwise in portrait mode.
if(scrWidth > scrHeight)
{
// Landscape mode
}
else
{
// Portrait mode
}
If you want a widget to be a quarter of the screen size, then you can specify it as:
Widget* alertLabel = new Label(0, 0, scrWidth / 2, scrHeight / 2, NULL);
At the heart of the MAUI model is the Moblet. This is the event-based platform which all MAUI applications are based on. When your application starts, it is the moblet which runs first. The moblet will create (at least) the first screen of your application and show it. The moblet is also responsible for closing your application down, and managing system events. Some events it passes to screens automatically, for instance key presses or screen touches. Other events occur and the moblet may need code to inform your screens of the event, like getting a new location from GPS.
If you create a new MAUI project (see the tutorial on starting a new MAUI project to do this), then you get some standard code. We’ve added some additional comments to it below.
#include <MAUtil/Moblet.h>
#include <MAUI/Screen.h>
#include <MAUI/Label.h>
using namespace MAUtil;
using namespace MAUI;
// This is the Screen class. This is what you'll see displayed on your phone. It inherits
// from MAUI::Screen base class. To put content on the screen, you have to add widgets to it.
class MyScreen : public Screen
{
public:
MyScreen()
{
/*
* todo: initialize the widget hierarchy of this screen and possibly show it
* example:
* Label* l = new Label(0, 0, 50, 50, NULL, "", 0x1f7f1f, NULL);
* setMain(l);
*/
}
virtual ~MyScreen()
{
// todo: delete main widget of this screen
}
private:
};
// This is the Moblet class. This manages the events your application will need, like getting
// key presses and screen touches.
// It also creates an instance of the MAUI::Screen class 'MyScreen', and shows it on screen.
class MAUIMoblet : public Moblet
{
public:
MAUIMoblet()
{
// initialize
screen = new MyScreen();
screen->show();
}
void keyPressEvent(int keyCode)
{
// todo: handle key presses
}
void keyReleaseEvent(int keyCode)
{
// todo: handle key releases
}
MyScreen* screen;
virtual ~MAUIMoblet()
{
delete screen;
}
};
/* This is where your application starts. It creates a new instance of MAUIMoblet (see above)
* and runs it.
*/
extern "C" int MAMain()
{
Moblet::run(new MAUIMoblet());
return 0;
}
You may want to make changes to this when you start a new project. Firstly, you may want screen definitions in their own files, so delete the MyScreen class here, and create it elsewhere. Secondly, Moblet automatically passes key and screen events to my screens, so you don’t need the additional methods here. They would be useful if you wanted to capture screen presses when you’ve not got a screen displayed, or for a button which you can use on every screen, but for your applications you may prefer to handle it screen by screen.
Some developers also don’t start with a Screen, but with their own class of ScreenController. ( This will be the topic of another tutorial. In this example, we're going to show a screen instead.)
#include <MAUtil/Moblet.h>
#include "Screens/Menu.h"
using namespace MAUtil;
using namespace MAUI;
// This is the Moblet class. This manages the events your application will need, like getting
// key presses and screen touches.
// It also creates an instance of the MAUI::Screen class 'Menu', and shows it on screen.
class MAUIMoblet : public Moblet
{
public:
MAUIMoblet()
{
// initialize
menu = new Menu();
menu->show();
}
Menu* menu;
virtual ~MAUIMoblet()
{
delete menu;
}
};
/* This is where your application starts. It creates a new instance of MAUIMoblet (see above)
* and runs it.
*/
extern "C" int MAMain()
{
Moblet::run(new MAUIMoblet());
return 0;
}
Much smaller, this is the basic code that you need to start your application.
The Screen is the main unit of the application. A screen is a container for Widgets, and contains the code to process interaction with the user. The different types of Widget are explained below, but here is some boiler plate code that can be used as templates when you're creating new Screens.
We’re going to look at creating Widgets shortly, but you can use code similar to that you’ll find in the MAUIex example supplied with MoSync. That has some small factory methods which return you the widgets, rather than duplicating code in every screen.
Menu.h
/*
* @file: Menu.h
* @Author: Naveed Asif, Niklas Nummelin
*
* Description:
*
* In this tutorial we will learn how to create a
* menu using Screen, Main Layout, and Labels.
*
* (Util.h, Util.cpp) files and (background_tile_sel.png,
* background_tile_unsel.png) images, and (pretty.mof) font
* can be found in MAUIEx example.
*/
#ifndef _Menu_H_
#define _Menu_H_
#include <MAUI/Screen.h>
#include <MAUI/Layout.h>
#include <MAUI/ListBox.h>
#include <MAUI/Label.h>
#include <MAUI/Engine.h>
#include <MAUI/Font.h>
#include <MAUtil/Moblet.h>
#include "MAHeaders.h"
using namespace MAUI;
using namespace MAUtil;
Widget* createSoftKeyBar(int height, char *left, char *right);
/*
* MainScreen Class definition.
*/
class MainScreen : public Screen
{
public:
// Constructor for the MainScreen class
MainScreen();
// The destructor.
virtual ~MainScreen();
void keyPressEvent(int keyCode, int nativeCode);
void pointerPressEvent(MAPoint2d point);
void pointerReleaseEvent(MAPoint2d point);
private:
ListBox* listBox;
Layout* layout;
Widget *softKeys;
};
/*
* MyMoblet class definition.
*/
class MyMoblet : public Moblet
{
public:
MyMoblet();
void keyPressEvent(int keyCode, int nativeCode);
void keyReleaseEvent(int keyCode, int nativeCode);
void closeEvent();
private:
Screen* mainScreen;
};
#endif /* _Menu_H_ */
This header file defines a new class called ‘Menu’, inheriting from ‘Screen’. For the screen to capture button presses and respond, the method keyPressEvent must be implemented, and there is reference to a ListBox widget called mContentBox.
Menu.cpp
/*
* @File: Menu.cpp
* @Author: Naveed Asif, Niklas Nummelin
*
* Here we include the header file Menu.h
* The Util.h header file contains many useful
* functions for working with widgets.
*/
#include "Menu.h"
#include "Util.h"
/*
* An object of MyMoblet class is created.
*/
MyMoblet* moblet;
/*
* The MainScreen class is defined here.
*/
MainScreen::MainScreen()
{
// The main layout
layout = createMainLayout("", "Exit");
// This will create the list box widget that has
// 3 Labels as its children.
listBox = (ListBox*) layout->getChildren()[0];
listBox->add(createLabel("Label"));
listBox->add(createLabel("Another Label"));
listBox->add(createLabel("Yet another Label"));
// Softkeys will generate soft key bar Exit button
// using create main layout.
softKeys = layout->getChildren()[1];
// Sets the layout as main widget for this screen. The widget will
// be resized to match the screen resolution of the device.
this->setMain(layout);
}
/*
* The desctutor for MainScreen
*/
MainScreen::~MainScreen()
{
delete layout;
}
/*
* This will handle key press events.
*/
void MainScreen::keyPressEvent(int keyCode, int nativeCode)
{
switch(keyCode)
{
case MAK_UP:
listBox->selectPreviousItem();
break;
case MAK_DOWN:
listBox->selectNextItem();
break;
case MAK_SOFTRIGHT:
moblet->closeEvent();
moblet->close();
break;
}
}
/*
* Pointer press events.
*/
void MainScreen::pointerPressEvent(MAPoint2d point)
{
Point p;
p.set(point.x, point.y);
if(listBox->contains(p))
{
for(int i = 0; i < listBox->getChildren().size(); i++)
{
if(listBox->getChildren()[i]->contains(p))
{
int index = listBox->getSelectedIndex();
if(index == i)
{
keyPressEvent(MAK_FIRE, 0);
}
else
{
listBox->setSelectedIndex(i);
}
break;
}
}
}
else if(softKeys->contains(p))
{
if(softKeys->getChildren()[0]->contains(p))
{
keyPressEvent(MAK_SOFTLEFT, 0);
}
else if(softKeys->getChildren()[1]->contains(p))
{
keyPressEvent(MAK_SOFTRIGHT, 0);
}
}
}
/*
* Todo: Pointer release event for Screen.
*
*/
void MainScreen::pointerReleaseEvent(MAPoint2d point)
{
}
/*
* Todo: Key press event for moblet.
*/
void MyMoblet::keyPressEvent(int keyCode, int nativeCode)
{
}
/*
* Key release event for moblet.
*/
void MyMoblet::keyReleaseEvent(int keyCode, int nativeCode)
{
}
/*
* This event is fired at application exit.
*/
void MyMoblet::closeEvent()
{
// do destruction here
delete mainScreen;
}
/*
* MyMoblet class declaration.
*/
MyMoblet::MyMoblet()
{
// The default font and skins are declared.
gFont = new MAUI::Font(RES_FONT);
gSkin = new WidgetSkin(RES_SELECTED, RES_UNSELECTED, 16, 32, 16, 32, true, true);
// Returns a reference to the single instance of
// Engine class, using lazy initialization.
Engine& engine = Engine::getSingleton();
engine.setDefaultFont(gFont);
engine.setDefaultSkin(gSkin);
// This returns screen coordinates.
MAExtent screenSize = maGetScrSize();
scrWidth = EXTENT_X(screenSize);
scrHeight = EXTENT_Y(screenSize);
// Creates a new instance of the main screen.
mainScreen = new MainScreen();
mainScreen->show();
}
/**
* Main function that starts the program.
*/
extern "C" int MAMain()
{
moblet = new MyMoblet();
MyMoblet::run(moblet);
return 0;
}
The constructor calls the factory method to get a basic screen layout. It then creates Label widgets with the menu options.
(Every screen must have one, and only one, main widget. This is considered to be the main widget, and it will be resized to the whole of the screen. Screens cannot have areas which do not have widgets.)
You don’t have to explicitly destroy the widgets you’ve created for this screen. They will be deleted when the screen is disposed if they have been added as children to the screen.
The moblet traps key presses and screen touches, and passes them automatically to the screen which is being displayed. The only thing you need to do as a programmer to get these is to implement the virtual functions keyPressEvent, keyReleaseEvent, pointerPressEvent, pointerMoveEvent and pointerReleaseEvent. In this example, we want to navigate the menu when a button is pressed, so we can capture the keyPressEvent. The method is passed an int, which represents a key. These are mapped to a series of constants.
Probably the most basic widget, the Label will put some text on screen.
Label* myLabel = new Label(0, 0, scrWidth, scrHeight, NULL, "My Label", 0xFFC0C0, myFont);
Label has the standard Widget constructor as described above, but you can also call it a caption to display, the background colour as hex and a font. To use the default font, you have to do it the long way.
Label* myLabel = new Label(0, 0, scrWidth, scrHeight, NULL);
myLabel->setCaption("My label");
By default, labels will only display the first line of the caption. It won’t wrap around onto the next line automatically. You can set it to do this with:
myLabel->setMultiLine(true);
You can also let the label decide how much space it needs. You can specify exactly how big you want the label to be, but you can also let it stretch automatically vertically and horizontally. Generally, you may find that you don’t want to let it resize horizontally, but you do vertically.
// Allow the label to resize vertically automatically. label->setAutoSizeY(true); // Prevent the label from resizing horizontally automatically. label->setAutoSizeX(false);
An image will let you put a picture in your application. These are used frequently as buttons. Creating them is very simple. In addition to the default Widget constructor, there is
// Create a new Image object based on the PNG file in the resources. Image* image = new Image(0, 0, 100, 100, listbox, true, true, IMAGE);
Where the last three arguments are to automatically resize automatically horizontally, resize automatically vertically and the MAHandle of the image resource. By setting the resize arguments as above, you can use this command to create any image you want and it will be the correct size for the image. If you set the resize arguments to false, it does not resize the image. If the sizes you’ve specified are too small, it will crop from the centre of the image. If the sizes are too large, it will show the background colour, if it has been set. This image has been cropped.
If you want to show a border on the image, you can use the padding as described earlier. If you’ve got it automatically resizing, you won’t see the entire image. This is because the widget has sized to dimensions of the image, but then the padding will eat some of that space.
// Create a new Image object based on the PNG file in the resources. Image* image = new Image(0, 0, 150, 150, listbox, true, true, IMAGE); image->setPaddingTop(10); image->setPaddingLeft(10);
This image has padding set.
You can animate images by listening for timer events, and changing the MAHandle of the resource you are using. See the tutorial on resource files for more on this.
The layout widget does not display much in its own right, but it will organise your widgets on screen for you. You can specify a grid into which widgets will be placed. They will be added from top left to bottom right. Don’t confuse this too much with an HTML table. There are some similarities, but the Layout does not give you all the options an HTML table will.
When you create a layout, you specify the number of rows and columns you want.
Layout *mainLayout = new Layout(0, 0, scrWidth, scrHeight, NULL, 1, 2);
In this example, we’ve got one column and two rows, so we can have two widgets, arranged vertically. You cannot add more widgets than you’ve specified space for. It will not automatically grow as you add more. Use a ListBox if you want to do that. If you have more than one column, then horizontal space is allocated evenly between them. You cannot have one column which is narrower than another. Each widget can be given the right amount of space vertically though, but you do have to have just one column to do it. If you have a 2x2 grid, then each cell must be the same size as its neighbour on the same row.
Any specific spacing you’ve set for widgets in a layout will be ignored. You can’t offset a widget within its own cell. You have to make that widget larger if you want it to appear with a border, so the first two arguments when creating a child for a widget can be ignored.
The ListBox is probably the single most useful widget in the standard collection. It is like a Layout, but with two key differences. Firstly, it only works in one dimension. You can have a vertical list or a horizontal list, but you can’t create a grid with it. Secondly, it expands as you put more widgets into it, so you don’t need to know how many widgets it will end up containing.
Note: Don't be tempted by the basic constructor with a ListBox as it won't be size you expect.
If you build a ListBox with the basic parameters, it won't scroll. You'll probably be looking at it wondering why it only has one item in it.
infobox = new ListBox(0, 0, scrWidth, scrHeight, layout);
You need to add all of the arguments specific to ListBox.
infobox = new ListBox(0, 0, scrWidth, scrHeight, layout,
ListBox::LBO_VERTICAL, ListBox::LBA_LINEAR, true);
You can decide whether it is going to grow vertically or horizontally, whether it is going to be animated, and whether it will wrap to the beginning when you get to the end. Typically, an app screen will contain a Layout with a child ListBox. In the diagram below, there is a Layout in a 1x3 grid. The widgets in the Layout have been marked.
The ListBox will not break out of its space in the layout. Should it grow longer than its space, it will scroll as items are selected in it. When a specific widget in the ListBox is selected, it will scroll so that widget is on screen. You can scroll a widget using selectNextItem() andselectPreviousItem() methods. In this example, key press on the screen has been captured, and the application is going to scroll up and down the ListBox (contentBox):
void Menu::keyPressEvent(int keycode)
{
// A full list of the key constants is available at
// http://www.mosync.com/docs/2.0b1/html/maapi_8h.html
switch(keycode)
{
case MAK_SOFTLEFT:
// Quit the application
maExit(0); // Calling the moblet to exit is the proper way
break;
case MAK_8:
case MAK_DOWN:
contentBox->selectNextItem(true); // Select the next item on the menu
break;
case MAK_2:
case MAK_UP:
contentBox->selectPreviousItem(true); // Select the previous item on the menu
break;
case MAK_5:
case MAK_FIRE:
// Decide on the action you want to perform when an option is selected.
// You can get the selected option with
// contentBox->getSelectedIndex();
break;
}
}
You can also decide whether to scroll back to the top once you go past the bottom with the option setWrapping().
An EditBox allows for text capture, so users can use their phone keypad to enter text into the application.
EditBox* editBox = new EditBox(
0, 0, scrWidth, 60, NULL, “”,
0xFFFFFF, aFont, true, true, 256,
EditBox::IM_STANDARD
);
EditBox is probably the most complicated of the standard widgets, as there are different options for capturing key presses. You don’t want navigation keys to start working when someone is trying to type their name in, so you can set the EditBox to manage its own navigation.
When it is activated, it becomes the key press listener and will get the keys entered as well as the screen. This gives you a headache when managing navigation, and you have to create a sensible approach in your application between navigating the screen, and moving the cursor around the text box.
The edit box has a cursor, but its default colour is white, so if you’ve got a white background to your edit box, then you’ll need to change the colour of the cursor with
editBox->setCursorColor(0x000000);
There are two text entry modes. You can use it capture letters, or you can set it so it only takes in numbers. The hash key (#) acts as a temporary shift, so if the user presses # and the 4, they will get an upper case G.
WidgetSkins
Most widgets can have a skin applied. This is a standard image which will be applied to the border and background of the widgets to give them a uniform look and feel. Here is a skin which is supplied in the MAUIex examples. The skin is split into a 3x3 grid, and lines have been drawn to show where the grid is defined. When it is applied to a widget, the corners stay as they are, and the other five sections are tiled to fill the required space. Whatever is in box 5 is tiled over the background of the widget. You do have to be careful with this, as nice looking gradients won’t look so nice when tiled.
To define the skin, you don’t specify the top left and bottom right corners of the center box as you might expect, but instead you specify the horizontal positions of the vertical cuts, and then the vertical positions of the horizontal cuts.
gSkin = new WidgetSkin(
RES_SELECTED, RES_UNSELECTED,
16, 32, 16, 32, true, true
);
The first two arguments are the MAHandles of the images you want to use as the skin. The first one is the skin to apply when the widget has focus (is selected), and one to use when it doesn’t have focus. You then specify the offsets of the vertical cuts, the offsets of the horizontal cuts, and whether the images you want to use contain any transparent elements (which they probably do).
Very importantly, both the selected and unselected skins must be exactly the same size. You can see here the skins being applied to EditBoxes.
The best thing about the Widget model is that it is easily extendible. There are many widgets to handle common features like softkey bars, progress bars, buttons, calendars and sliders. There will be another tutorial which will go into detail on creating your own widgets. In short, you need to inherit from Widget, and implement the drawWidget() method.
This is from the ProgressBar widget:
#ifndef _PROGRESSBAR_H_
#define _PROGRESSBAR_H_
#include <MAUI/Widget.h>
#include <MAUI/Image.h>
using namespace MAUI;
namespace DatiloUI
{
class ProgressBar : public Widget
{
public:
ProgressBar(int x, int y, int width, int height,Widget* parent = NULL);
virtual ~ProgressBar();
int getPercentage();
void setPercentage(int percentage);
void drawWidget();
void setFullImage(Handle image);
void setEmptyImage(Handle image);
private:
Handle mTileFullImage;
Handle mTileEmptyImage;
int mPercent;
void plotSection(MAPoint2d* offset, int width, Handle image);
};
};
#endif // _PROGRESSBAR_H_
The drawWidget() method is the essential one. It will be called when the screen is painted, and it must plot its contents in the confines of the widget.
Here is an extract from the drawWidget() method:
void ProgressBar::drawWidget()
{
int w = this->getWidth() - this->getPaddingLeft() - this->getPaddingRight();
int amountRemaining = (w * percent) / 100;
MAPoint2d* offset = new MAPoint2d();
Point p = this->getPaddedPosition();
Rect r = paddedBounds;
offset->x = r.x;
offset->y = r.y;
// Plot the full section
if(mTileFullImage != NULL)
{
plotSection(offset, amountRemaining, mTileFullImage);
}
else
{
// Plot a progress bar
plotBar(offset, amountRemaining);
}
if(mTileEmptyImage != NULL)
{
offset->x += amountRemaining;
plotSection(offset, w - amountRemaining, mTileFullImage);
}
delete offset;
}
You can see that in the drawWidget method, you can get the PaddedPosition of the widget. This tells you where the Widget is on screen. In the plotSection() method, you get the space you're allowed to use
void ProgressBar::plotSection(MAPoint2d* offset, int width, Handle h)
{
if(mDrawBorder)
{
plotBorder();
}
MARect* clippedImage = new MARect();
Rect r = this->getPaddedBounds();
Extent imageSize = maGetImageSize(h);
while(width > 0)
{
clippedImage->left = 0;
clippedImage->width = width > EXTENT_X(imageSize) ? EXTENT_X(imageSize) : width;
clippedImage->top = 0;
clippedImage->height = r.height > EXTENT_Y(imageSize) ? EXTENT_Y(imageSize)
: r.height;
// lprintfln("Drawing image at x:%d, y:%d", offset->x, offset->y);
Gfx_drawImageRegion(h, clippedImage, offset, 0);
offset->x += clippedImage->width;
width -= clippedImage->width;
}
delete clippedImage;
if(writePercentage)
plotPercentage();
}
The method getPaddedBounds() tells me exactly what space you're allowed to use without drawing over another widget.
Behind all of these widgets is the MAUI Engine. This is the part which you rarely have to use, but provides the functionality for getting your widgets on to the screen.
The Engine is a singleton, and you can get a reference with
Engine& eng = Engine::getSingleton();
The Engine can let you specify default fonts and WidgetSkins, so you don’t need to specify them each time you use them. They will be automatically applied to your widgets. How cool is that?
eng.setDefaultFont(standardFont); eng.setDefaultSkin(standardSkin);
Set up the font and the skins, and apply them to the default methods above.
Screens are the skeleton of your application. They contain the content widgets which are the heart and muscles of your program, but the Screens provide the navigation and structure you will want. You can create screens with their widgets at design time, when you are writing your code, or you can interpret some data to create screens at runtime. We’ll be looking at both of these in this tutorial.
The Screen is the container for the widgets you want to display. It contains functionality so screens know which one is visible, and they can be shown with one command.
When you are creating your application, you will probably want to create screens with different information. To create a new screen at design time, you need to inherit from MAUI::Screen. When you create a new MAUI application in MoSync, then you get some example code to do this. I’ve built a new screen here to show a menu.
#ifndef MENU_H_
#define MENU_H_
#include <MAUI/Screen.h>
#include <MAUI/Layout.h>
#include <MAUI/Image.h>
#include <MAUI/ListBox.h>
#include <MAUI/Label.h>
#include "../Util.h" // From MAUIex
#include "../MAHeaders.h"
using namespace MAUI;
using namespace MAUtil;
class Menu : public Screen
{
public:
Menu();
virtual ~Menu();
void keyPressEvent(int keyCode);
private:
ListBox* contentBox;
};
#endif /* MENU_H_ */
We can see that class Menu inherits from Screen.
In the C++ code we can see what a Screen might do. (This is not a complete listing.)
#include "Menu.h"
// Constructor for Menu. Takes a pointer to the Moblet object created in main.cpp
Menu::Menu(Moblet* moblet) : mlet(moblet)
{
// Build the menu options
buildMenu();
}
/*
* Destructor
*/
Menu::~Menu()
{
}
/*
* Add the menu options to the listbox
*/
void Menu::buildMenu()
{
// Get a basic screen set up from the UI Builder
Widget* w = createScreen(EXITBUTTON, "Menu");
// Get the layout from the created screen. Cast from Widget* to Layout*
Layout* layout = (Layout*)w->getChildren()[0];
// Get the listbox from the layout. Cast from Widget* to ListBox*
listbox = (ListBox*)layout->getChildren()[1];
// Create a button for each menu option, and add it to the listbox.
listbox->add(createButton("Music Demo"));
listbox->add(createButton("Font Demo"));
listbox->add(createButton("Image Demo"));
listbox->add(createButton("Animation Demo"));
listbox->add(createButton("Strings Demo"));
listbox->add(createButton("Skipped Resource Demo"));
listbox->add(createButton("Placeholder Demo"));
listbox->add(createButton("Binary Demo"));
// Set the widget from the UIBuilder as the main widget for the screen
this->setMain(w);
}
A screen contains Widgets (for more information, see the tutorial Introduction to MAUI). In our example, we can see that in the constructor we call buildMenu which calls out to an external function to create Widgets on our behalf. These widgets will make up the content of our screen.
The final command here is setMain(w); Each screen has one main widget, which is the parent widget of this screen. When this screen is painted, it calls the drawWidget method on the main widget to paint it. Each of the children of the main widget will be painted as well.
Note: Screens cannot have any sections which don’t have a widget on. The main widget will be resized to the size of the screen.
To create the screen, you need to create a new instance of it. In the most simple example, the controlling Moblet (see the tutorial Starting a New Moblet Project) will call an initial screen to start.
#include <MAUtil/Moblet.h>
#include "Screens/Menu.h"
using namespace MAUtil;
using namespace MAUI;
/*
* This is the Moblet class. This manages the events your
* application will need, like getting key presses and
* screen touches. It also creates an instance of the
* MAUI::Screen class 'Menu', and shows it on screen.
*/
class MAUIMoblet : public Moblet {
public:
MAUIMoblet()
{
// Initialize menu.
menu = new Menu();
menu->show();
}
/*
* The destructor.
*/
virtual ~MAUIMoblet()
{
delete menu;
}
private:
Menu* menu;
};
/*
* This is where your application starts. It creates a new
* instance of MAUIMoblet (see above) and runs it.
*/
extern "C" int MAMain() {
Moblet::run(new MAUIMoblet());
return 0;
};
This moblet code has a reference to Menu.h, and when it is constructed, it creates a new instance of Menu. It then calls the method show().
Only one screen can be shown at a time. By calling the show() method on a screen you are indicating that this is the screen which should now be shown. There is also a hide() method, which isn't implemented in Screen directly. You can create Screens though which use it. If you've got screens which have some sort of processing capability, you can pause it while the Screen isn't shown if you want to.
The screen which is being shown will automatically be passed key and screen events.
Screen already contains the functionality to automatically receive events raised from the keyboard and the screen (on touchscreen devices), and we can react to these events by providing functionality for the following methods.
void keyPressEvent(int keyCode); void keyReleaseEvent(int keyCode); void pointerPressEvent(MAPoint2d point); void pointerMoveEvent(MAPoint2d point); void pointerReleaseEvent(MAPoint2d point);
Typically, we might want to capture these to control navigation on screen. In our menu, we’ve got a ListBox with the menu options. We want to capture key presses to navigate the menu.
/*
* This is inherited from Screen, and captures key presses.
*/
void Menu::keyPressEvent(int keyCode)
{
// Select the key which has been pressed
switch(keyCode)
{
// Right Soft Key - ask the moblet to close the application.
case MAK_SOFTRIGHT:
mlet->closeEvent();
mlet->close();
break;
// Move up the menu when the navigation up button, the navigation
// left button the number 2 or the number 4 buttons are pressed.
case MAK_UP:
case MAK_LEFT:
case MAK_2:
case MAK_4:
listbox->selectPreviousItem(true);
break;
// Move down the menu when the navigation down, the navigation right,
// the number 8 or the number 6 buttons are pressed.
case MAK_DOWN:
case MAK_RIGHT:
case MAK_8:
case MAK_6:
listbox->selectNextItem(true);
break;
// When the fire button or the number 5 are pressed, show the
// selected screen from the vector.
case MAK_FIRE:
case MAK_5:
lprintfln("Showing screen %d", listbox->getSelectedIndex());
screens[listbox->getSelectedIndex()]->show();
break;
}
}
The KeyPress and KeyRelease events pass an int, which is an index of the button pressed. These are constants in MoSync, and are in the format MAK_. There is a full list available in the MoSync API Reference Guide. In this example, we’ve a simple switch statement. If the right soft key button is pressed, we end the application. If the up, left, 2 or 4 key is pressed, we tell the ListBox to go to the previous item. On the down, right, 6 or 8 buttons, we scroll down. When fire or 5 is pressed, we perform an action based on the selected item in the ListBox. We can see that we’ve created a navigation system just by simply plugging into the functions already available.
When we capture a screen touch, we get a location on screen which has been touched.
void TouchListBox::pointerPressEvent(MAPoint2d point)
{
locateItem(point);
}
We can use this point to identify a widget which has been pressed, or perform any other action you may want to with the screen. I prefer for touch sensitive widgets to handle their own touch events, and I’ll be presenting my TouchListBox in the tutorial Creating New Screens.
When you start writing MoSync apps, you’ll start by creating a couple of screens in the way described above, and then get stuck wondering how to navigate between screens. How does this screen go back to the one before? Or that one over there? In the MAUI example supplied with MoSync, there is a simple method for managing this.
LayoutScreen::LayoutScreen(Screen *previous) : previous(previous)
{
mainLayout = createMainLayout("", "back");
this->setMain(mainLayout);
ListBox* listBox = (ListBox*) mainLayout->getChildren()[0];
Layout *layout = new Layout(0, 0, scrWidth,
scrHeight-mainLayout->getChildren()[1]->getHeight(),
listBox, 3, 4);
layout->setMarginX(5);
layout->setMarginY(5);
layout->setPaddingLeft(5);
layout->setPaddingRight(5);
for(int i = RES_ICONS_START; i != RES_ICONS_END+1; i++)
{
new Image(0, 0, 0, 0, layout, true, true, i);
}
}
When you create a LayoutScreen, you have to pass it the pointer to the previous screen. In my menu example, to create a LayoutScreen, enter
Screen layoutScreen = new LayoutScreen(this));
where this is the menu screen. This means that the LayoutScreen has an anchor to another screen, and when it wants to show the menu again, it can call the show() method on it.
/*
* Pressing soft right key will display previous screen.
*/
void LayoutScreen::keyPressEvent(int keyCode)
{
if(keyCode == MAK_SOFTRIGHT)
{
previous->show();
}
}
This screen doesn’t have to worry about hiding itself. Calling show() on another screen will hide this one.
As well as these fixed screens, you can create Screens at runtime. There may be many occasions where you don’t know what you want on screen yet. It may depend on something the user does, or it may be that it is based on data downloaded from the internet. To manage these, I’ve used a screen which can parse input data and create widgets based on it. This means I can theoretically have any number of screens in my application without running out of memory. I keep a small pool of maybe five screens alive at any one time, and when I need the sixth new screen, I delete the first one. Should I need the first one again, I can recreate it.
The data for your dynamic screen may be included as a binary file in your resources, which is good for default data, explicitly build into your resource files, or downloaded and put into a data store.
If you’ve already got some binary data you want to use, you can include it in the resources file.
.res BINARYDEMO .bin .include "resources/data.bin"
A second way is for you to describe it in the resource file itself.
.res DYNAMICSCREENDEMO .bin .byte 4 // The number of widgets .byte 1 // A label widget .pstring "This is the first item. It is a label" .byte 2 // A button widget .pstring "This is the second item. It looks like a button" .byte 1 // A label widget .pstring "The next item is an image" .byte 3 // An Image widget .word 14422 // The size of the image
I use my own format. I’ve a server which compiles data for my applications and sends it to the phone.
I can build a screen at runtime based on the values in the resource file:
#ifndef BINARYSCREEN_H_
#define BINARYSCREEN_H_
#include "UIBuilder.h"
#include <MAUI/Screen.h>
#include <MAUI/Image.h>
#include <conprint.h>
#include "MAHeaders.h"
using namespace MAUI;
using namespace MAUtil;
class BinaryScreen : public Screen
{
public:
BinaryScreen(Screen* returnTo);
virtual ~BinaryScreen();
void keyPressEvent(int keyCode);
private:
void buildScreen();
Screen* homeScreen;
ListBox* listbox;
int getPString(MAHandle stringResource, String& output, int startPos);
};
#endif /* BINARYSCREEN_H_ */
This BinaryScreen has a reference to the previous screen, so it can return. It also has a method for reading strings from the resource file. This code reads sequentially through the data in the resource file and determines the type of widget it wants to create. It then builds that widget and set the data in it accordingly.
#include "BinaryScreen.h"
BinaryScreen::BinaryScreen(Screen* returnTo) : homeScreen(returnTo)
{
buildScreen();
}
/*
* The destructor.
*/
BinaryScreen::~BinaryScreen()
{
}
/*
* Pressing soft right key shall display home screen.
*/
void BinaryScreen::keyPressEvent(int keyCode)
{
switch(keyCode)
{
case MAK_SOFTRIGHT:
homeScreen->show();
break;
}
}
/*
* This will build screen dynamically at runtime with
* layout and list box.
*/
void BinaryScreen::buildScreen()
{
// Get a basic screen set up from the UI Builder
Widget* w = createScreen(BACKBUTTON, "Menu");
// Get the layout from the created screen. Cast from Widget* to Layout*
Layout* layout = (Layout*)w->getChildren()[0];
// Get the listbox from the layout. Cast from Widget* to ListBox*
listbox = (ListBox*)layout->getChildren()[1];
// This is going to read through a binary resource to create widgets
// dynamically. These are variables required for decoding widgets.
byte len;
int position = 1; // Skip the first byte
byte widgetType;
byte completed = 0;
String* text = new String();
short imageLen;
// Read the first byte. This determines the number of widgets.
maReadData(BINARYDEMO, &len, 0, 1);
while(completed < len)
{
// Read the next byte. This is the type of widget
maReadData(BINARYDEMO, &widgetType, position, 1);
position++;
switch(widgetType)
{
case 1: // Label
position += getPString(BINARYDEMO, *text, position);
listbox->add(createLabel(text->c_str()));
break;
case 2: // Button
position += getPString(BINARYDEMO, *text, position);
listbox->add(createButton(text->c_str()));
break;
case 3: // Image
lprintfln("Creating image");
// Get the length of the image.
maReadData(BINARYDEMO, &imageLen, position, 4);
position += 4;
lprintfln("Image is %d bytes", imageLen);
// Create a temporary placeholder
MAHandle imagePlaceholder = maCreatePlaceholder();
// Create an image from binary data
maCreateImageFromData(imagePlaceholder, BINARYDEMO, position, imageLen);
// Add the image to the listbox
listbox->add(new Image(0, 0, 100, 100, NULL, true, true, imagePlaceholder));
position += imageLen;
lprintfln("Image created");
break;
}
completed++;
}
this->setMain(w);
delete text;
}
/*
* This will read a Pascal string from the resources.
*/
int BinaryScreen::getPString(MAHandle stringResource, String& output, intstartPos)
{
output.clear();
byte len;
// Check that there is at least one byte
if(maGetDataSize(stringResource) == 0)
return false;
maReadData(stringResource, &len, startPos, 1);
char* buffer = new char[len + 1];
maReadData(stringResource, buffer, startPos + 1, len);
buffer[len] = '\0';
output.setData(new StringData(buffer));
delete[] buffer;
return len + 1;
}
The BinaryScreen has a handle helper which will create widgets for it, but you can see that it processes the resource data, looks at the widget type byte and extracts the necessary data to build the screen.
Building screens at runtime is much slower than having them built at compile-time, but it does make localisation easier, and potentially means that you only have to write one screen class, if this can handle all the content you may want.
Using the MAUI library helps you develop powerful graphical user interface applications. You get access to a variety of ready-made user interface widgets and you can register different types of listeners with the widgets, thus responding to higher-level events.
MAUI development is based on the Moblet system, so to create an application with it you first need to make a moblet as shown in the previous example.
The fundamental building block of a MAUI application is called MAUI::Screen. Each screen has their own root widget. Each time show() is called on a screen, that screen is shown and all the others are hidden. When a screen is shown, it means that the root widget of that screen is made active. It can often be very useful to group your application into several screens in order to give your program a logical structure. When a screen is shown, key events are sent to that screen only. When a screen is hidden, each widget that belongs to it is disabled. This normally means that any timer events are unregistered.
Note: if you build this application in the IDE, make sure that you base it on the MAUI template or make sure that the Additional Libraries listed in the build configuration (Project > Properties > MoSync Project > Build Settings > Additional Libraries) include MAUtil.lib and MAUI.lib. You will also need to create and declare your font resources: see Working With Fonts.
#include <MAUtil/Moblet.h>
#include <MAUI/Screen.h>
#include <MAUI/Label.h>
#include "MAHeaders.h"
using namespace MAUtil;
using namespace MAUI;
class MyScreen : public Screen {
public:
MyScreen() {
label = new Label(
0, // set the top-left corner
0, // to be in the top-left corner of the lcd display.
0, // the width and height are set to the width and height of the lcd display
0, // automatically for the root widget in a screen.
NULL, // this widget has no parent widget
"Hello World!", // the caption of the label
0, // use background color 0 (black)
new Font(MY_FONT) // create a new instance of the font stored as the
// resource MY_FONT and set the font of the label to that font.
);
setMain(label); // set the root widget to be the label we just created
}
void keyPressEvent(int key) {
if(key == MAK_0) {
maExit(0); // exit the application when key 0 has been pressed
}
}
private:
Label *label;
};
class MyMoblet : public Moblet {
public:
MyMoblet() {
myScreen = new MyScreen();
myScreen->show();
}
private:
MyScreen *myScreen;
};
// Since this is a C++ program, the main function
// needs to be declared extern "C"
extern "C" int MAMain() {
Moblet::run(new MyMoblet());
} Layouts format your widgets on screen. They provide a grid into which all of your widgets can be aligned. Almost every screen you’ll create will have a Layout widget on it, and whilst they can’t do everything you can imagine, they can help you create some attractive and useful screens.
The layout widget does display much in its own right, but it will organise your widgets on screen for you. You can specify a grid into which widgets will be placed. They will be added from top left to bottom right. Don’t confuse this too much with an HTML table. There are some similarities, but the Layout does not give you all the options an HTML table will.
When you create a layout, you specify the number of rows and columns you want.
Layout *mainLayout = new Layout(0, 0, 240, 320, NULL, 1, 2);
You cannot add more widgets than you’ve specified space for. It will not automatically grow as you add more. Use a ListBox if you want to do that.
If you have more than one column, then horizontal space is allocated evenly between them. You cannot have one column which is narrower than another.
Each widget can be given the right amount of space vertically though, but you do have to have just one column to do it. If you have a 2x2 grid, then each cell must be the same size as its neighbour on the same row.
Any specific spacing you’ve set for widgets in a layout will be ignored. You can’t offset a widget within its own cell. You have to make that widget larger if you want it to appear with a border, so the first two arguments when creating a child for a widget can be ignored.
You add widgets into the layout with the add(Widget* w) method.
/*
* This program will generate a basic menu.
*/
Layout* createMainLayout(const char *left, const char *right)
{
Layout *mainLayout = new Layout(0, 0, scrWidth, scrHeight, NULL, 1, 2);
Widget *softKeys = createSoftKeyBar(30, left, right);
ListBox* listBox = new ListBox(0, 0, scrWidth, scrHeight-softKeys->getHeight(),
mainLayout, ListBox::LBO_VERTICAL, ListBox::LBA_LINEAR, true);
listBox->setSkin(gSkin);
listBox->setPaddingLeft(5);
listBox->setPaddingRight(5);
listBox->setPaddingTop(15);
listBox->setPaddingBottom(15);
mainLayout->add(softKeys);
return mainLayout;
}
This example comes from the MAUIex project supplied with MoSync. Widgets are added into the Layout from left to right and top to bottom. If you have a Layout with a 2x2 grid, the first widget you add will be placed top left, the second top right, the third bottom left and the fourth in the bottom right. If you want to skip a cell, then you have to add a blank widget.
I’ve created a new Widget, which is a grid-based menu where each cell contains an icon and label. You may have seen these on some phones.
To do this, the Widget has inherited from Layout instead of Widget. By doing this you can control some of the placements within your control, and make it really easy to reuse it.
#ifndef _GRID_MENU_H_
#define _GRID_MENU_H_
#include <MAUI/Layout.h>
#include <MAUI/Widget.h>
#include <MAUtil/Environment.h>
#include <MAUtil/Set.h>
using namespace MAUI;
/*
* Interface class to call back to grid menu listener.
*/
class IGridMenuListener
{
public:
virtual void GridMenuItemSelected(int item, Widget* selectedItem);
};
/*
* This class will show the list of member variables and functions
* that are required to form an advanced layout.
* This is not a complete tutorial, some of the member functions which
* can be quite helpful in creating advanced layouts, are
* declared in the following sections.
*/
class GridMenu : public Layout, public KeyListener, public PointerListener
{
public:
GridMenu(int x, int y, int width, int height, Widget* parent = NULL,
int rows = 3, int columns = 3);
virtual ~GridMenu();
void pointerPressEvent(MAPoint2d point);
void pointerMoveEvent(MAPoint2d point);
void pointerReleaseEvent(MAPoint2d point);
void keyPressEvent(int keyCode);
void keyReleaseEvent(int keyCode);
bool handleEvents;
void add(Widget* button);
void addListener(IGridMenuListener* l);
void setSelectedIndex(int index);
int getSelectedIndex();
void selectNext();
void selectPrevious();
void selectNextRow();
void selectPreviousRow();
void setEnabled(bool e);
void drawWidget();
void bindKeyLeft(int keyCode);
void bindKeyRight(int keyCode);
void bindKeyUp(int keyCode);
void bindKeyDown(int keyCode);
void bindKeySelect(int keyCode);
void setPanelActive(int panelID, bool active = true);
private:
IGridMenuListener* listener;
Widget* selectedWidget;
Widget* previouslySelectedWidget;
int _rows;
int _cols;
int itemCount;
int selectedIndex;
void selectButton(int index);
void informListener();
void locateWidget(MAPoint2d, bool inform = false);
bool setContains(Vector<int> s, int value);
Vector<int> moveUpKeys;
Vector<int> moveDownKeys;
Vector<int> moveLeftKeys;
Vector<int> moveRightKeys;
Vector<int> selectKeys;
int origW;
Vector<int> activePanels;
};
#endif
At the top, there is a class IGridMenuListener, for a Screen to be able to attach to the Widget so it can be informed of changes to the menu, such as items being selected. This will appear again in another tutorial on programming Widgets for touch screens.
This class inherits from Layout, has code to capture screen and key presses and for navigation within the menu. It also has the essential drawWidget() method which is required when you create new widgets, although because we’ve inherited an existing Widget and we're not changing how it works, it isn’t essential.
There is a lot of other code to examine in the tutorials about creating your own widgets.
Below is some of the code for managing this advanced Layout. This is not a complete code example.
/*
* Some of the member functions of GridMenu class are declared here.
*/
#include "GridMenu.h"
#include <conprint.h>
GridMenu::GridMenu(int x, int y, int width, int height, Widget *parent,
int rows, int columns): Layout(x, y, width, height, parent, rows, columns)
{
// lprintfln("Inside menu constructor");
origW = width;
itemCount = 0;
selectedIndex = -1;
selectedWidget = NULL;
listener = NULL;
enabled = false;
_rows = rows;
_cols = columns;
// set all the panels to active
for(int i = 0; i < _rows * _cols; i++)
{
activePanels.add(1);
}
this->setPaddingLeft((width - this->getWidth()) / 2);
this->setPaddingRight(5);
this->setBackgroundColor(0xFF0000);
this->setDrawBackground(true);
// lprintfln("Menu constructed");
}
/*
* The destructor for GridMenu class
*/
GridMenu::~GridMenu()
{
}
/*
* The drawWidget member function.
*/
void GridMenu::drawWidget()
{
}
/*
* The add function is used to add widgets to the layout.
*/
void GridMenu::add(Widget *button)
{
if(button != NULL && itemCount < _rows * _cols)
{
Layout::add(button);
itemCount++;
}
// lprintfln("button added");
}
/*
* This function is used to select a widget.
*/
void GridMenu::selectButton(int index)
{
// lprintfln("Selecting button %d", index);
if(index <= itemCount && index > -1)
{
// lprintfln("Testing previously selected widget");
if(selectedWidget != NULL)
{
selectedWidget->setSelected(false);
previouslySelectedWidget = selectedWidget;
}
selectedWidget = getChildren()[index];
// lprintfln("Selecting new button");
selectedWidget->setSelected(true);
// lprintfln("Updating index");
selectedIndex = index;
}
requestRepaint();
}
/*
* To navigate next item or widget in the index.
*/
void GridMenu::selectNext()
{
// lprintfln("Current index: %d", selectedIndex);
int nextItem = (selectedIndex + 1) % itemCount;
// lprintfln("First option: %d", nextItem);
while(activePanels[nextItem] == 0)
{
nextItem = (nextItem + 1) % itemCount;
// lprintfln("Hide the next one and try %d", nextItem);
}
selectButton(nextItem);
}
/*
* This will navigate to previous widget in the index.
*/
void GridMenu::selectPrevious()
{
// lprintfln("Selecting previous");
// lprintfln("selectedIndex: %d", selectedIndex);
// lprintfln("itemCount: %d", itemCount);
int nextItem = selectedIndex - 1;
// lprintfln("nextItem: %d", selectedIndex);
while(activePanels[nextItem] == 0)
{
nextItem--;
if(nextItem < 0) nextItem = itemCount - 1;
// lprintfln("Don't select nextItem: %d", nextItem);
}
selectButton(nextItem);
}
/*
* This will navigate to next row in the grid.
*/
void GridMenu::selectNextRow()
{
int nextItem = (selectedIndex + _cols) % itemCount;
while(activePanels[nextItem] == 0)
nextItem = (nextItem + 1) % itemCount;
selectButton(nextItem);
}
/*
* To navigate to previous row in the grid.
*/
void GridMenu::selectPreviousRow()
{
int nextItem = (selectedIndex + itemCount - _cols) % itemCount;
while(activePanels[nextItem] == 0)
nextItem = (nextItem + itemCount - 1) % itemCount;
selectButton(nextItem);
}
/*
* The setSelectedIndex function sets the value for selected index.
*/
void GridMenu::setSelectedIndex(int index)
{
selectButton(index);
}
/*
* Returns the selected index value.
*/
int GridMenu::getSelectedIndex()
{
return selectedIndex;
}
/*
* The setPanelActive function can set a widget to be active or inactive.
*/
void GridMenu::setPanelActive(int panelID, bool active)
{
activePanels[panelID] = active == true ? 1 : 0;
}
Unlike standard layouts, we don’t want every cell to be active. We don’t want all the cells to have a Widget in, and when you navigate you want it to skip the empty cells. To do this, there is a Vector<int> (although, looking at it now, this could be Vector<byte>), where it can mark cells as active or not.
Vector<int> activePanels;
When the menu is created, the panels can be set to active.
// set all the panels to active
for(int i = 0; i < _rows * _cols; i++)
{
activePanels.add(1);
}
When a widget is added to the menu, it is added to the base Layout and to keep a track of the number of items which have been added.
void GridMenu::add(Widget *button)
{
if(button != NULL && itemCount < _rows * _cols)
{
Layout::add(button);
activePanels.add(1);
itemCount++;
}
// lprintfln("button added");
}
When the user navigates the Layout, we can check to see if the panel is active or not, and decide whether it should be skipped.
void GridMenu::selectNext()
{
// lprintfln("Current index: %d", selectedIndex);
int nextItem = (selectedIndex + 1) % itemCount;
// lprintfln("First option: %d", nextItem);
while(activePanels[nextItem] == 0)
{
nextItem = (nextItem + 1) % itemCount;
// lprintfln("Hide the next one and try %d", nextItem);
}
selectButton(nextItem);
}
Keep moving onto the next panel (going back to the start if necessary) until we find one which is active.
When we move up or down a row, we have to do the same thing:
void GridMenu::selectNextRow()
{
int nextItem = (selectedIndex + _cols) % itemCount;
while(activePanels[nextItem] == 0)
nextItem = (nextItem + 1) % itemCount;
selectButton(nextItem);
}
So, when creating the menu Layout, you can set which panels you want to use.
// Creates an iPhone-style grid menu
Widget* createGridMenu(IGridMenuListener* listener)
{
GridMenu* gridMenu = new GridMenu(0, 0, scrWidth, scrHeight, NULL);
gridMenu->setBackgroundColor(0xFFFFFF);
gridMenu->setDrawBackground(false);
setLabelPadding(gridMenu);
gridMenu->addListener(listener);
Font* f = new Font(FONT);
gridMenu->add(createImage(BLANK));
gridMenu->add(createImage(BLANK));
gridMenu->add(createMenuImage(THEMESICON, "Themes", f, aSkin));
gridMenu->add(createImage(BLANK));
gridMenu->add(createMenuImage(MAPICON, "Map", f, aSkin));
gridMenu->add(createMenuImage(FRIENDSICON, "Friends", f, aSkin));
gridMenu->add(createMenuImage(EVENTSICON, "Events", f, aSkin));
gridMenu->add(createMenuImage(SETTINGSICON, "Settings", f, aSkin));
gridMenu->add(createMenuImage(MESSAGESICON, "Messages", f, aSkin));
gridMenu->setPanelActive(0, false);
gridMenu->setPanelActive(1, false);
gridMenu->setPanelActive(3, false);
gridMenu->setSelectedIndex(2);
return gridMenu;
}
At the end of this, we are setting three panels to be inactive, as you can see from the picture. There is a 3x3 layout, but now it acts like a pyramid.
HelloMAUI is a well-commented example application for beginners. It consists of a very simple graphical user interface application that uses the MAUI library and Moblet framework. It illustrates how to create MAUI screens, and how to position and control widgets.
![]() | ![]() |
This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
When run, the user is presented with a simple MAUI screen with the following widgets:
When the user types using the keypad keys the characters are echoed in the edit box. On clicking the Submit button, the password is validated. Examine the source code of the application (in the file hellomaui.cpp) to learn how the program works. The code commenting highlights various aspects of working with MAUI screens and widgets, including:
For more advanced uses of MAUI, see our MAUIEx application example.
To
understand how MAUI and the NatuveUI Widget API (an alternative GUI solution that
makes use of each platform's user interface controls), compare this
example application with HelloNativeUI.
This application demonstrates the variety of widgets available in the MAUI library and how to use the ListBox and Layout widgets to arrange widgets on a screen.
![]() | ![]() | ![]() |
![]() | ![]() |
This example is included in the MoSync SDK's /examples/MAUI folder. For information on importing the examples into your workspace, see Importing the Examples.
When the application has started the user is presented with a simple menu. Following the menu items takes you to other screens that demonstrate different widgets.
The layout of each screen is controlled by a combination of Layout and ListBox widgets. For example, for the Layout screen:

It is worth taking some time to examine the code of the MAUIex example to understand how the Layout and ListBox widgets work together for each screen.
The following screens are available:
For a comprehensive description of MAUI, see our tutorial called Introduction to MAUI.
MoSync's Tiny XML parser, MTXml, provides an efficient, callback-based way of parsing XML files. MTXml has a SAX-like interface, and is re-entrant: it can start with just the beginning of an XML document and request additional data when needed.
MTXml can handle most XML 1.0 and 1.1 documents. However, in the interests of performance, MTXml is not a conforming XML processor, as defined by the W3C Recommendation. It does not validate documents, and it only checks a few of the well-formed-ness criteria. It even ignores some "fatal errors". Still, it should properly parse a well-formed document.
There are two modes of parsing. One, mtxFeedProcess(), is slower, and converts standard entities and UTF-8 characters to Latin-1 before passing them to the application. The other, mtxFeed(), is faster, and passes such characters without conversion. If you know which parts of your document need conversion and which ones don't, you can do the conversion manually, using mtxProcess().
Here's a minimal C program that uses MTXml.
#include <MTXml/MTXml.h>
#include <conprint.h>
#include <maassert.h>
// For each callback, print its type and parameters.
static void tagStart(MTXContext* context, const void* name, int len)
{
printf("s %i: \"%s\"\n", len, (char*)name);
}
static void tagAttr(MTXContext* context, const void* attrName, const void* attrValue)
{
printf("a \"%s\": \"%s\"\n", (char*)attrName, (char*)attrValue);
}
static void tagData(MTXContext* context, const void* data, int len)
{
printf("d %i: \"%s\"\n", len, (char*)data);
}
static void tagEnd(MTXContext* context, const void* name, int len)
{
printf("e %i: \"%s\"\n", len, (char*)name);
}
static void dataRemains(MTXContext* context, const char* data, int len)
{
printf("r %i: \"%s\"\n", len, data);
}
static void parseError(MTXContext* context, int offset)
{
printf("parseError %i\n", offset);
}
static void emptyTagEnd(MTXContext* context)
{
printf("emptyTagEnd\n");
}
// The XML document is declared here, but not defined.
// Fetching the document is beyond the scope of this example.
extern char gDocument[];
int MAMain(void) GCCATTRIB(noreturn);
int MAMain(void)
{
MTXContext c;
printf("Hello World!\n");
// Set up the context.
c.tagStart = tagStart;
c.tagAttr = tagAttr;
c.tagData = tagData;
c.tagEnd = tagEnd;
c.dataRemains = dataRemains;
c.parseError = parseError;
c.emptyTagEnd = emptyTagEnd;
c.unicodeCharacter = mtxBasicUnicodeConvert;
mtxStart(&c);
// Perform the parsing.
mtxFeed(&c, gDocument);
// Wait for the user to exit.
FREEZE;
}
tagStart() is called when an XML tag starts. tagAttr() is called for each attribute of a tag. tagData() may be called multiple times, to handle pieces of character data inside a tag. tagEnd() is called at the end of each tag. However, if the tag is empty (looks like this: <someTag/>), emptyTagEnd() is called instead of tagEnd().
parseError() is called if the parser encounters something it cannot parse. When that happens, parsing stops. It should not be restarted without resetting the context with mtxStart().
dataRemains() is called if the parser encounters a partial object at the end of the buffer supplied to it. The application should copy that part to the beginning of the buffer and fill the buffer with more data, so that the object may be fully parsed later. In this example, we have a complete XML document available (the external variable gDocument), so dataRemains() is not called.
Please note that this program, as written, will not build, because gDocument is not defined. If you want to compile it, you'll have to supply an XML document to parse.
void
There is a C++ wrapper for the C-based MTXml parser. It can be used in many ways, but one of the most useful ways is by coupling it to a Connection. This allows the CPU-intensive parsing to be split up into more than one call, spreading the load and improving the application UI's response times. Here we provide an example of how to implement such an XmlConnection.
#ifndef XMLCONNECTION_H
#define XMLCONNECTION_H
#include <MAUtil/Connection.h>
#include <MTXml/MTXml.h>
class XCListener
{
public:
// Called when there is a connection error. Parsing stops.
virtual void xcConnError(int code) = 0;
};
class XmlConnection : private MAUtil::ConnectionListener, Mtx::MtxListener
{
public:
XmlConnection();
// Inits an Mtx::Context, sets itself as ConnectionListener,
// starts recieving data, which is passed on to the XML parser.
// Callbacks from the parser are passed on to the XmlListener.
//
// The connection must be ready to recieve data, which means that you
// must have recieved either of two callbacks:
// MAUtil::ConnectionListener::connectFinished() or
// MAUtil::HttpConnectionListener::httpFinished().
//
// You also must not have a read() or recv() operation active.
void parse(MAUtil::Connection* conn, XCListener* xc, Mtx::XmlListener* xml);
// Stops parsing and closes the connection.
// \see mtxStop().
void stop();
// see mtxProcess().
int process(char* data);
private:
Mtx::Context mContext;
MAUtil::Connection* mConn;
XCListener* mXc;
char mBuffer[1024];
char* mPtr;
void mtxDataRemains(const char* data, int len);
void connRecvFinished(MAUtil::Connection* conn, int result);
};
#endif //XMLCONNECTION_H
#include "XmlConnection.h"
XmlConnection::XmlConnection() : mConn(NULL)
{
}
void XmlConnection::parse(MAUtil::Connection* conn, XCListener* xc, Mtx::XmlListener* xml)
{
mConn = conn;
mXc = xc;
mContext.init(this, xml);
mConn->setListener(this);
mPtr = mBuffer;
mConn->recv(mBuffer, sizeof(mBuffer)-1);
}
void XmlConnection::connRecvFinished(MAUtil::Connection* conn, int result)
{
MAASSERT(conn == mConn);
if(result < 0)
{
mXc->xcConnError(result);
return;
}
mPtr[result] = 0;
mPtr = mBuffer;
bool stopped = mContext.feed(mBuffer);
if(!stopped)
{
//parsing may have been interrupted by stop().
mConn->recv(mPtr, sizeof(mBuffer) - 1 - (mPtr - mBuffer));
}
}
void XmlConnection::mtxDataRemains(const char* data, int len)
{
if(mBuffer != data)
{
memcpy(mBuffer, data, len);
}
mPtr = mBuffer + len;
}
void XmlConnection::stop()
{
if(mConn != NULL)
mConn->close();
mContext.stop();
}
int XmlConnection::process(char* data)
{
return mContext.process(data);
}
The trick here is using a static buffer to recieve data, pass it to the parser, have the parser pass the standard XML events to the application, and handle mtxDataRemains(). Any remaining data is copied to the front of the buffer, and the next recv() starts writing where the remaining data ends.
This is streaming XML. :)
If you are writing cross-platform mobile apps in the MoSync® SDK, you will probably want at some point to connect to the Internet to get data. Typically, this data will be in XML or in JSON format. If you are getting XML data, the MoSync SDK has a built in XML parser (MTXml) you can use to parse it. There are also string functions in the MoSync MAUtil library which can be used to read XML in some simple cases. In this tutorial we take a look at retrieving XML data and the various ways of reading the data from it.
There are several ways to get XML data into your application:
Note that this tutorial covers XML only. If you are working with JSON data, we have a blog post called Working with JSON Data that describes how to handle it.
If you've got simple requirements for XML, then you can read it very easily. Take this example from the Yahoo! XML format for weather data.
<title>Conditions for Carcassonne, FR at 10:00 am CEST</title> <geo:lat>43.22</geo:lat> <geo:long>2.35</geo:long>
If we just want to get the latitude out of this data, we don't need to parse the complete XML.
String xml = readXml();//Build a string with the xml in it
int start = xml.findFirstOf("<geo:lat>") + 9;
int end = xml.findFirstOf("</geo:lat>", start);
String lat = xml.substr(start, end - start);We can use the standard String functions to get the values out of the XML. The start of the data can be found by getting the position of <geo:lat>. 9 is added to this value, which is the length of the string we're looking for. The value of start is now the number of characters from the start to the beginning of the latitude value. The end of the value is found in a similar way, but we don't need to add any additional characters. Finally, the value of latitude can be extracted using the substring function (substr), passing it the start location and the length of the data to extract (end - start).
Broadly speaking, there are two ways to handle XML documents: via the DOM or via SAX.
If you load the XML into an object model that represents the XML structure, you can then look at the properties of each XML element in the model and navigate the model with an XPATH. This is very common approach for manipulating XML and is called using a Document Object Model or DOM. Java and C# developers will be very used to dealing with XML like this.
It is easy to use this approach, but can use a lot of memory. If you have a burning need for DOM processing, read the blog post on our website which details a lightweight DOM approach to XML with the MoSync SDK.
<myTag>
it will raise an event to say that it has found an open tag. The program listening to events, or receiving the callback can then decide whether or not to do something with this knowledge.
The MoSync SDK comes with our open source SAX parser called MTXml (the MoSync Tiny XML Parser).
To use the MTXml parser, you need to include the MTXml.lib file in your project dependencies. To include the MTXml.lib file:

You can parse XML from a variety of sources. Most likely this will be from an Internet connection, processing XML as it is being downloaded. The MoSync XML API can start parsing XML from a connection before it has completely downloaded.
To process XML, the minimum you need to do is to create a C++ class which inherits from MTXml/MTXml.h and implements XmlListener. This will contain the callback classes which the XML processor will call when it finds the appropriate XML.
You must implement all of the methods in XmlListener. If you leave any methods unimplemented, the program may crash if a call to an unimplemented method is made. Just create an empty method, or in the case of mtxunicodeCharacter, use the standard implementation.
This is an example from a class which is designed to process XML data. It implements the XmlListener interface, which allows it to process XML.
class XMLProcessor : public XmlListener
{
public:
XMLProcessor();
~XMLProcessor();
//XmlListener
void mtxEncoding(const char* value);
void mtxTagStart(const char* name, int len);
void mtxTagAttr(const char* attrName, const char* attrValue);
void mtxTagStartEnd();
void mtxTagData(const char* data, int len);
void mtxTagEnd(const char* name, int len);
void mtxParseError();
void mtxEmptyTagEnd();
unsigned char mtxUnicodeCharacter(int unicode);
}When you are processing XML you need to keep track of where you are in the file. If your code is processing a complex XML file, you may want to create some sort of state handling. The calls between the callbacks are essentially stateless, and your code has to be robust enough for them to be called in any order -- even in an unexpected order.
The critical parts of the code are the mtxTag... methods. These are called when the processor gets the XML elements. Generally, you are passed the value which has been processed.
We can process the XML we looked at earlier with these mtxTag... methods. Here is the XML again:
<title>Conditions for Carcassonne, FR at 10:00 am CEST</title> <geo:lat>43.22</geo:lat> <geo:long>2.35</geo:long>
The mtxTagStart method is passed the name of the tag. For instance, if the XML contained <title> the mtxTagStart would be called with 'title'. We can examine these values at runtime.
void XMLProcessor::mtxTagStart(const char* name, int len)
{
lprintfln("%s", name);
lprintfln("%d", len);
}When this code is called for the <title> tag, it will display 'title' and 5 in the console.
To be able to read the <title> tag, we need to maintain the state of the XML. When the mtxTagData method is called, it needs to know which tag the data is for. A good way of doing this is by keeping a variable with different values you can test for.
One way of doing this is to create an enum of the different tags you want to process. This code shows an enum representing the tags in the XML, and a private int variable which will keep state:
enum XmlTags
{
TITLE,
LATITUDE,
LONGITUDE
};
int mState; When you receive a tag, you can then set the mState variable.
void XMLProcessor::mtxTagStart(const char* name, int len)
{
if(strcmp(name, "title", 5) == 0) //Compare the char* with the word 'title'
{
mState = TITLE;
}
}In the next section, we will see how we can use this state information when reading data.
When data inside an XML tag is received, the mtxTagData method in your XmlListener will be called. As an example, assume you have this data:
<title>Conditions for Carcassonne, FR at 10:00 am CEST</title> <geo:lat>43.22</geo:lat> <geo:long>2.35</geo:long>
If we imagine that this is the complete feed, then the mtxTagStart method will be called three times, with 'title', 'geo:lat' and 'geo:lon'.
The mtxTagData method will be called at least three times, once with 'Conditions for Carcassonne, FR at 10:00 am CEST', once with '43.22' and once with '2.35'.
mtxTagData may actually be called more than this. If the data source is coming from the Internet, then it may be called before then end of the data. Imagine that the packet we get from the connection contains this data.
<title>Conditions for Carcassonne, FR at 10:00 am CEST</title> <geo:lat>43.2
This is processed, and the XML callbacks are made. The call to mtxTagData for the 'geo:lat' tag will contain '43.2' at this point, and not '43.22'
We then get some more data:
2</geo:lat> <geo:long>2.35</geo:long>
mtxTagData will now have been called four times. In fact, you'll never want to start processing in the mtxTagData method. Save it for mtxTagEnd. A good implementation for mtxTagData would be:
void XmlProcessor::mtxTagData(const char* data, int len)
{
//Add the data to the buffer, but don't process until we've got the end tag
temp.append(data, len);
}Where 'temp' is a String. This will continue to fill up until the end tag is reached.
Because we've been using the mState variable to hold state information, we know how to deal with this data. In mtxTagEnd we can use the data we collected in mtxTagData, and the state information we've set up in mtxTagStart to do something useful with the data.
void XmlProcessor::mtxTagEnd(const char* name, int len)
{
switch(mState)
{
case TITLE:
// At this point, we know we are in the <title> tag, and that we've
// received all the data it contains.
mMyClass->title = temp;
// Use the contents of the string 'temp' we've populated in mtxTagData.
break;
case LATITUDE:
break;
case LONGITUDE:
break;
}
}You can now perform different operations on the data you have got with the state handling you've created.
This application demonstrates connecting to a Web Service using SOAP. It contains a class called SoapRequest which formats an easily modifiable XML Soap request, and a Moblet to test the SOAP communication using a currency converter as an example.

This example is included in the MoSync SDK installation in the /examples folder. For information on importing the examples into your workspace, see Importing the Examples.
Behaviour
When started, the application makes a call to Joel Hainley's Rot13 SOAP service, passing it the string "Hello World!" Rot13 is a simple substitution cypher, and therefore the service returns the string "Uryyb Jbeyq!"
The application demonstrates how to correctly format a SOAP request, and process a response from the web server. It can be easily modified to work with any web service. The screenshot above shows details of the commands being sent over SOAP and the responses, ending with a normal soapError of -6, indicating that the underlying HTTP connection has been closed.
The MoSync API Reference Manuals provide a detailed description of the MoSync sycalls, function libraries, panics, and resource files. Here we describe the reference documents are available for the latest featured release of MoSync.
MoSync API Reference (Doxygen)
|
|
Panics Reference
|
|
Resource Compiler Reference
|
If you are looking for the very latest reference documentation for one of the nightly builds, look under the Help menu in the product itself.
We love open source software and by opening up the Mosync SDK under the GPL license, we aim to give a large group of developers the opportunity to go mobile in a short time on both the Windows and OS X environments. We look forward to working together with you to create new, great applications in mobile, as well as receiving your contributions and suggestions on how to make Mosync even better!
Participation from our community is very important in the success of the MoSync Open Source project. We invite you to participate on many levels. These activities require a certain level of technical skill. As a MoSync community member, you as a user can contribute in many other ways; i.e. by participating in the forum or by blogging about MoSync on the Internet.
We'd really like to see what people have done with the MoSync SDK, and cordially welcome everyone to share their applications. You can find some of our own application on the Example Applications page, and some of our customer's applications on the Who's Using MoSync page.
Before you can contribute code to the MoSync SDK, we need you to do a couple of things:
Send your core patches for review to tony@mosync.com.
Report issues at our Jira Issue Tracker.
What follows are some additional tips on ways to make your bug report better so that someone will be able to help you.
There are the three basic elements of a bug report, this may be only to basic but bear with us. You need to tell us exactly what you did:
"I instructed the program to draw a polygon on the canvas",
what you expected to have happen:
"I expected a red polygon to appear on the screen", and lastly what actually happened
"I got a blue circle, flickering on screen".
The odds are good that if you've found a problem, someone else has found it, too. If you spend a few minutes of your time making sure that you're not filing a duplicate bug, that's a few more minutes someone can spend helping to fix that bug rather than sorting out duplicate bug reports.
Don't report an error message you don't understand as a bug. There are a lot of places you can ask for help in understanding what is going on before you can claim that an error message you do not understand is a bug.
This is a fine line to walk. But there are some general guidelines:
Yes, the MoSync developer community is global and include a great many people who can speak a great many languages. But if you were to report a bug in a language other than English, many (if not most) of the people who would otherwise help you won't be able to.
Every time a new version of a MoSync product is released, many bugs are fixed. If you're using a version of a product that is more than two revisions older than the latest version, you should upgrade to the latest version to make sure the bug you are experiencing still exists. (And it's not a bad idea to try upgrading even if your version is only a version behind the most current one.)
If you have encountered two bugs that don't appear to be related, create a new bug report for each one. This makes it easier for different people to help with the different bugs.
While commercial customers and partners can influence the direction and feature set of the MoSync Mobile SDK, you can too. Submit your feature request in the issue tracker.
Usability reports are feedback from the community about usage of (new) features in the real world. A usability report is a short account of the user's first impact on a newly tried feature, recording his/her expectations and the level of satisfaction achieved.
An usability report should have the following components.
These reports are like any other contribution very important to us.
Send your usability reports to miles.midgley@mosync.com.
The MoSync Issue Tracker is based on Jira and can be found here: jira.mosync.com. Jira allow users to see more than just one project at a time and ongoing work for up-and-coming releases and is integral in our development.
Note: Our oldIssue Tracker is still visible for archive purposes. We have imported all the issues from the old Google issue tracker. We are manually adding attachments, an ongoing task. If you were following an issue on the Goggle issue tracker you will have to resubscribe to that issue in Jira.
Note: To post or follow issues you will need to create a user ID on Jira.

Follow the instructions and log in.
Next you will be presented with a dashboard. This gives an overview of the MoSync project.

At the top right there is a button to create an issue. This screen allows you to define if this issue is a Bug or New Feature. These are currently the only two issue types open to users.

The following screen shows what we would like you to fill in as a minimum.

Issues are usually resolved in 7 stages:
| Open | A newly reported issue, no action taken yet |
| Accepted | A developer has accepted the issue and will soon start working on it |
| In Progress | A developer is working on the issue |
| Resolved | The developer feels that the issue has been dealt with. |
| Code Review | The code is read is ready for code review. |
| Waiting QA | The code has been merged and QA can build and verify the issue is resolved. In most cases the fix will be in the next nightly build. |
| Verified | The QA department has checked the solution and has agreed that it is fixed |
Some things to keep in mind before reporting an issue:
If you have suggestions for improving MoSync, enter it as an issue into the Jira issue tracker. Provide as much information as you like. We love feedback, and we are more than happy to let our user base help us determine the direction of development.
If you are missing a feature in MoSync, why not write it up? The development team keeps a close watch on the Issue Tracker so your queries and posts will usually be attended to within a few days. We are committed to providing the best possible user experience. Help us make MoSync the most powerful mobile development solution on the planet!
These instructions describe how to build a Windows installation package for the MoSync SDK. The completed installation package is an .exe file, just like our featured releases and our nightly builds.
To build the full installation package, you will need a Windows machine, a Mac OS X machine, and a Linux machine. If you omit the iPhone and Moblin runtimes, you can build a partial package on just the Windows machine.
(Instructions for building the MoSync SDK from source on OS X are also available.)
To build the MoSync Eclipse IDE, the MoSync libraries, and the MoSync tools, you will need a computer running Windows (Windows XP, Windows Vista, or Windows 7) and capable of running Visual Studio C++ 2005.
To build the MoSync runtimes you will need:
If you don’t need the iPhone and Moblin runtimes, everything can be built on the Windows machine.
1. Download the source tarball (.tar.bz2) of our current feature release from our website or from our open-source project repository:
Alternatively, get the source tarball for our latest nightly build from our website:
or through TortoiseGit:
git clone https://github.com/MoSync/MoSync.git c:\mb\MoSync-trunk git clone https://github.com/MoSync/Eclipse.git c:\mb\Eclipse
2. Unpack the source tarball into (or, if you have installed TortoiseGit, check it out to):
C:\mb
3. Download target-platform.zip which contains everything needed to build the Eclipse-based IDE. Put the zip-file in:
C:\mb\eclipse\com.mobilesorcery.sdk.product\build
Important! Make sure you install and configure the dependencies in the order listed below. If you do not, terrible things may happen!
4. Download and install Microsoft® Visual Studio® 2005 and apply Service Pack 1. Make sure that you install the runtime MT (Multi Threaded) DLL.
5. Add the following paths to Visual Studio:
\mb\mosync-trunk\tools\ReleasePackageBuild\build_package_tools\include \mb\mosync-trunk\libs \mb\mosync-trunk\libs\MAStd
\mb\mosync-trunk\tools\ReleasePackageBuild\build_package_tools\lib
6. Find the file:
C:\mb\mosync-trunk\tools\ReleasePackageBuild\build_package_tools\include\msvc\stdint.h
Copy it to the directory:
C:\Program Files\Microsoft Visual Studio 8\VC\include\
7. Download and install the following Visual Studio SDKs:
8. Find the files:
C:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0 Smartphone SDK\Include\Armv4i\gdiplus*.h
Copy them to:
C:\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\Smartphone2003\Include\
9. Download and install the Ruby 1.8 (or later).
10. Download Sqlite 3 for Ruby 1.8 and put it in your ruby\bin directory. (If you have installed a later version of Ruby you'll have to find another version of the Sqlite 3 dll.)
11. Install Sqlite 3 Ruby Gem by opening a command (cmd) window and entering:
gem install sqlite3-ruby
12. Accept the installation of dependencies. These are the ones you need:
13. Download and install Java SE Development Kit (JDK) 1.6.
14. Make sure the JDK’s \bin directory has been added to Window’s list of path environment variables, otherwise add it.
15. Download and install the latest version of the SonyEricsson SDK for the Java ME Platform.
16. Download and install the ProGuard 3.7 Java obfuscator.
17. Put the file proguard.jar in the \OnDeviceDebug\bin directory of the J2ME SDK.
18. Download and install ActiverPerl 5.8 Community Edition .
19. Download and install S60 3rd Edition SDK for Symbian OS FP1.
20. Download and install the Extensions plug-in for S60 3rd Edition SDK for Symbian OS, for C++, MR.
21. Download and install S60 2nd Edition SDK for Symbian OS FP3. If the installer asks you which network adapter to use, pick any.
22. Download and install S60 5th Edition SDK for Symbian OS. Make sure you install it in the folder
\Symbian\s60v5\, as that is the location that is assumed by our build scripts.
23. Download the Extensions Plug-in for S60 3rd Edition SDK for Symbian OS, for C++, supporting Feature Pack 1, v2.5. Install it in both 3rd and 5th edition SDKs.
24. Download and unzip symbian-94-fixes.zip. Install it over the s60v5 SDK.
25. Download and unzip symbian-81-extras.zip. Install it over the s60v2 SDK, located in the folder:
\Symbian\8.1a\S60_2nd_FP3\
26. For both 3rd and 5th edition SDKs, run CSL Toolchain (GCCE) Install, found on the Start menu, under:
\S60 Developer Tools\* Edition SDK\v1.0\Tools
27. For each Symbian SDK, make sure that the following folder exists:
\Epoc32\Data\z\resource\apps\
Sometimes, this folder is a file, or does not exist at all, and in both cases this would cause the build to fail.
28. For both 3rd and 5th edition SDKs, find line 31 in the file \epoc32\tools\e32env.pm:
die "EPOCROOT environment variable must be capitalised\n" if (!$found);
29. Disable this line by adding a hash sign (#) in front of it.
30. Download and install CoreUtils for Windows.
31. Download and install Grep for Windows.
32. Download and install Sed for Windows.
33. Make sure the \bin directory of GNU binutils has been added to Window’s list of path environment variables, otherwise add it.
34. If required, build the Moblin runtimes on Linux.
35. If required, build the iPhone runtime on Mac OS X.
(You
do not need to build the Windows Mobile, Java ME, Android, and Symbian
runtimes, they are automatically built by the build script).
36. Locate the file run.bat.example in \mb\mosync-trunk\trunk\tools\ReleasePackageBuild, copy it, and name the copy run.bat.
37. Replace the SDK path in run.bat with one appropriate for your system:
start /B /BELOWNORMAL build_package.bat c:\SonyEricsson\JavaME_SDK_CLDC\OnDeviceDebug\ 2>&1 | tee log.txt
38. Start run_commercial_recompiler.bat. It will set up an environment, then call your run.bat (found in the \mb\mosync-trunk\tools\ReleasePackageBuild folder). You can use one of the other run_*.bat files to build the package in different ways.
If all goes well, an installer package should appear in \mb\MoSyncReleasePackage\.
It will be called something like MoSyncSetup_XXX.exe.
39. Done.
If you want to create the Windows Mobile, Java ME, Android, and Symbian runtimes to use with the OS X version of the MoSync SDK (see building the MoSync SDK from source on OS X), here’s how:
1. Follow the instructions above for Getting the MoSync Source Code
and Installing the Dependencies. (You do not need to get Eclipse or build the SDK.)
2. Run the following command from the command line to set the target MoSync Directory:
set MOSYNCDIR=\mb\MoSyncReleasePackage
3. Go to the folder
\mb\mosync-trunk
and run the following command:
ruby workfile.rb base
4. Go to
\mb\mosync-trunk\tools\ConcurrentBuild
and run the following command:
ruby ConcurrentBuild.rb \mb\MoSyncReleasePackage \mb\MoSync-trunk android javame wm s60
The script will build your runtimes and put them in the \profiles folder under \mb\MoSyncReleasePackage
.
5. Copy the runtimes to your mac installation folder and you can start using them on your Mac OS X version.
6. Done.
These instructions describe how to build an OS X installation package for the MoSync SDK. The completed installation package is an .dmg file, just like our featured releases and our nightly builds.
To build a full installation package that includes all the MoSync runtimes, you will need a Windows, a Mac OS X, and a Linux machine. If you want an installation package that just has the iPhone runtime, you can build the whole thing on a single OS X machine.
To be able to follow these instructions you will need to be registered as an Apple Developer. Instructions for building the MoSync SDK for Windows are also available.
To build the MoSync Eclipse IDE, the MoSync libraries, and the MoSync tools, you will need a Mac OS X Snow Leopard (OS X v. 10.6) computer capable of running Xcode.
To build the MoSync runtimes you will need:
If you only want the iPhone runtime, everything can be built on OS X.
1. Download and install Xcode 3.2.5 toolset from the iPhone Dev Center, including the iPhone SDK.
2. Download and install the 32-bit version of Fink for Snow Leopard.
3. Download and install MacPorts.
4. Download and install IceBerg for Mac OS X.
5. From the Terminal, run the following commands:
sudo fink -b install sdl sudo fink -b install sdl-image sudo fink -b install sdl-ttf sudo fink -b install sdl-sound sudo port install freeimage +universal sudo port install ImageMagick +universal sudo port install doxygen
6. Get the MoSync source code from github repository:
git clone https://github.com/MoSync/MoSync.git MoSync
7. Clone the MoSync Eclipse Repository into the same path as MoSync:
git clone https://github.com/MoSync/Eclipse.git Eclipse
8. Download the zip-package here that contains everything needed to build the Eclipse-based IDE and put it in the folder:
/MoSync/tools/ReleasePackageBuild/
9. In your checked out version of the MoSync SDK trunk, go to the folder:
/MoSync/tools/ReleasePackageBuild/
then run:
./build_mac_package.sh
10. If everything goes as it should, the script will build a .dmg installation package in the folder called /results.
11. Install the .dmg installation package on an OS X machine.
12. If required, build the Moblin runtimes on Linux.
13. If required, build the Windows Mobile, Java ME, Android, and Symbian runtimes on Windows (see Building the MoSync SDK on Windows).
14. Add the runtimes to the folder:
/Applications/MoSync/profiles
15. Done.
If you want to create an iPhone runtime to use with the Windows version of the MoSync SDK (see building the MoSync SDK for Windows ), here’s how:
1. Follow the instructions above for Preparing the Mac and Getting the MoSync Source Code. (You do not need to get Eclipse or make the MoSync package.)
2. Give your user the correct permissions to the /MoSync folder by entering the following command at the Terminal (replace user with you actual user name):
sudo chown -R user /Applications/MoSync
3. To build the MoSync base prerequisites, go to your cloned MoSync source directory and run the command:
ruby workfile.rb base
4. Now you are ready to build the iPhone runtime from source. In your checked out version of the MoSync SDK trunk do:
cd runtimes/cpp/platforms/iphone cp Classes/impl/config_platform.h.example Classes/impl/config_platform.h ruby buildLibraries.rb cp -R template $MOSYNCDIR/profiles/runtimes/iphoneos/1/
5. Find the runtime in the folder:
/Applications/MoSync/profiles/runtimes/iphoneos/1/
6. Copy it to your MoSync installation directory on your Windows computer in the folder:
\MoSync\profiles\runtimes\iphoneos\1\
7. Done.
These instructions describe how to build the MoSync runtimes for Moblin. The runtimes can then be included when you build the MoSync SDK for Windows or build the MoSync SDK for OS X.
To build the Moblin runtimes you will need a machine running Ubuntu (9.10).
1. First install the runtime dependencies in the Linux terminal:
sudo apt-get install gcc g++ ruby rake subversion rpm sudo apt-get install libgtk2.0-dev libexpat1-dev sudo apt-get install libbluetooth3-dev libsdl1.2-dev sudo apt-get install libsdl-image1.2-dev libsdl-ttf2.0-dev sudo apt-get install libfreeimage-dev libssl-dev
Important! Do not install libsdl-sound -- Moblin does not support this library.
2. Download the source tarball (.tar.bz2) of our current feature release from our website or from our open-source project repository:
Alternatively, get the source tarball for our latest nightly build from our website:
or through TortoiseGit:
git clone https://github.com/MoSync/MoSync.git MoSync git clone https://github.com/MoSync/Eclipse.git Eclipse
Important! You
must download the same version as you downloaded to build the MoSync
SDK for Windows or OS X. If you do not, when you try to use the SDK you
may get an “IDL Version Mismatch” error.
3. Run the Linux runtime builder script in the MoSync source directory::
/tools/RuntimeBuilder/linux/build-linux-runtime-package.sh
4. You will now have two files in the current directory:
runtime.ubuntu.r*.i386.dbg.tar.gz runtime.ubuntu.r*.i386.rel.tar.gz
Rename them to:
runtime.dbg.tar.gz runtime.rel.tar.gz
5. If you are building the MoSync SDK for Windows, move the files to the following folder on the Windows build machine,
c:\mb\MoSyncReleasePackage\profiles\runtimes\moblin\1\
You are then ready to run the SDK build script.
If you are building the MoSync SDK for OS X, copy the runtimes to the machine on which you have installed the MoSync SDK, in the directory:
/Applications/MoSync/profiles/runtimes/moblin/1/
6. Done.
This guide explains how to build the MoSync SDK from source on Linux. It shows you how to set up your build environment and how to build GCC, Pipe-Tool, and the MoRE Emulator.
Please remember that support for Linux is limited and the build system was made for Windows. At the moment, it is only possible to build the MoRE Emulator on Linux, and to run some example programs in the Emulator. It is not possible to build the entire MoSync package (with its IDE) on Linux.
The distributions that we ourselves run at MoSync AB are Ubuntu 8.10/9.04/9.10 and Xubuntu 9.10. This description may work with those distributions. If you're using any other distribution, you may need to adapt these instructions.
There are a few prerequisites to building the MoSync SDK. In Ubuntu, they can be installed by:
sudo apt-get install gcc g++ bison flex ruby rake subversion rpm libgtk2.0-dev libexpat1-dev sudo apt-get install libbluetooth3-dev libsdl1.2-dev libsdl-image1.2-dev libsdl-ttf2.0-dev sudo apt-get install libfreeimage-dev gperf
Note that, since the MoSync SDK is continuously evolving, there may be additional dependencies.
The first step is to set up a directory where the compiled binaries, libraries and SDK header files will reside. From now on we will refer to this directory as the installation directory. The installation directory, which resides wherever you want, should contain the following directory structure:
/<installation-directory>
/bin
/include
/lib
/libexec/gcc/mapip/3.4.6
The /include and /lib directories will be created automatically during compilation, but the other directories should be created manually because we need to compile GCC before the MoSync SDK can be compiled.
Once you have created the directory structure, the environment variable MOSYNCDIR should point to the installation directory. If you use bash then this is accomplished by adding the following line to your .bashrc:
export MOSYNCDIR=<installation-directory>
or in csh by adding the following line to .cshrc:
setenv MOSYNCDIR <installation-directory>
When the lines have been added to your .bashrc or .cshrc the shell must be restarted, you can accomplish this by closing the terminal window and opening it again.
MoSync uses its own GCC backend that generates source code for the MoSync virtual machine. In order to build the MoSync GCC we start by downloading the source code from Google Code, the source code can be placed wherever you want, in this example we are using a directory called gcc_trunk. To download the code run svn:
git clone git://github.com/MoSync/gcc.git gcc_trunk
Now go into gcc_trunk and build the compiler, the compilation will fail when trying to compile libgcc since we do not use the standard linker. But the compiler will already have been built and will be placed in gcc_trunk/build/gcc/gcc/.
We build the compiler by performing the following steps:
cd gcc_trunk ./configure-linux.sh cd build/gcc make
Remember that the compilation will fail when trying to build libgcc, on my Ubuntu machine the error output begins with:
libgcc2.s: Assembler messages: libgcc2.s:1: Error: unknown pseudo-op: `.model' libgcc2.s:2: Error: unknown pseudo-op: `.code' ...
In order for the build scripts to find MoSync GCC it has to be moved to the installation directory:
cp gcc/xgcc gcc/cpp $MOSYNCDIR/bin cp gcc/cc1 gcc/cc1plus $MOSYNCDIR/libexec/gcc/mapip/3.4.6/
The source code for the MoSync SDK also resides on Google Code and is downloaded by:
git clone git://github.com/MoSync/MoSync.git mosync_trunk
MoSync uses its own build system coined 'work'. The build system consists of a set of Ruby files that compiles the MoSync SDK. In each directory that contains source files there is a file called workfile.rb, which instructs the build system how compile the source files. To build the fundamental tools of the MoSync SDK, move to the root of mosync_trunk and invoke:
./workfile.rb CONFIG="debug"
The above command builds the tools and libraries in debug mode but you should also build everything in release mode:
./workfile.rb CONFIG=""
You will then have to copy the font used in the emulator to the bin directory, stand in the root of mosync_trunk and invoke:
cp tools/ReleasePackageBuild/build_package_tools/mosync_bin/unifont-5.1.20080907.ttf $MOSYNCDIR/bin/
When this script is finished make sure that $MOSYNCDIR/bin contains cc1, cc1plus, xgcc, pipe-tool and moemu. You may then try the MAUIex example by performing:
cd examples/MAUI/MAUIex/ ./workfile.rb CONFIG="" cd build/pipe_release/ $MOSYNCDIR/bin/moemu -program program -resource ../resources
These coding conventions are guidelines for developers creating MoSync code. These conventions are largely inspired by and derived from existing ones in well-known programming environments such as Java and SDL. As such, they shouldn't come across as exotic to any moderately experienced programmer.
All header files should have #define guards to prevent multiple inclusion. The format of the symbol name should be <PROJECT>_<PATH>_<FILE>_H_.
Don't use an #include when a forward declaration would suffice.
Define functions inline only when they are small, say, 10 lines or less.
When defining a function, parameter order is: inputs, then outputs.
Use standard order for readability and to avoid hidden dependencies: C library, C++ library, other libraries' .h, your project's .h.
Prefer nonmember functions within a namespace or static member functions to global functions; use completely global functions rarely.
Place a function's variables in the narrowest scope possible, and initialize variables in the declaration.
Static or global variables of class type are forbidden: they cause hard-to-find bugs due to indeterminate order of construction and destruction.
In general, constructors should merely set member variables to their initial values. Any complex initialization should go in an explicit Init() method.
You must define a default constructor if your class defines member variables and has no other constructors. Otherwise the compiler will do it for you, badly.
Use a struct only for passive objects that carry data; everything else is a class.
Composition is often more appropriate than inheritance. When using inheritance, make it public.
Only very rarely is multiple implementation inheritance actually useful. We allow multiple inheritance only when at most one of the base classes has an implementation; all other base classes must be pure interface classes tagged with the Interface suffix.
Interfaces should be named using an I- prefix. Example: IMySexyInterface
Make data members private, and provide access to them through accessor functions as needed. Typically a variable would be called mFoo and the accessor function getFoo(). You may also want a mutator function setFoo().
Use the specified order of declarations within a class: public: before private:, methods before data members (variables), etc.
Prefer small and focused functions.
All parameters passed by reference must be labeled const.
We strongly recommend that you use const whenever it makes sense to do so.
Code should be 64-bit and 32-bit friendly. Bear in mind problems of printing, comparisons, and structure alignment.
Be very cautious with macros. Prefer inline functions, enums, and const variables to macros.
Function names, variable names, and filenames should be descriptive; eschew abbreviation. Types and variables should be nouns, while functions should be "command" verbs.
Type names start with a capital letter and have a capital letter for each new word, with no underscores: MyExcitingClass, MyExcitingEnum.
They start with a capital letter and have a capital letter for each new word, with no underscores. A m- prefix is used for member variables. A s- prefix is used for static variables. For instance: myExcitingLocalVariable, mMyExcitingMemberVariable, sMyExcitingMemberVariable
Use capitals and underscore as a separator: DAYS_IN_A_WEEK.
Regular functions have mixed case; accessors and mutators match the name of the variable: myExcitingFunction(), myExcitingMethod(), getMyExcitingMemberVariable(), setMyExcitingMemberVariable().
Enumerators should be named either like constants or like macros: ENUM_NAME.
You're not really going to define a macro, are you? If you do, they're like this: MY_MACRO_THAT_SCARES_SMALL_CHILDREN.
Start each file with a copyright notice, followed by a description of the contents of the file.
Every class definition should have an /** accompanying comment */ that describes what it is for and how it should be used.
Every function should have a /** declaration comment */ which describes use of the function, using @param and @return syntax.
In general the actual name of the variable should be descriptive enough to give a good idea of what the variable is used for. In certain cases, more comments are required.
In your implementation you should have comments in tricky, non-obvious, interesting, or important parts of your code.
Pay attention to punctuation, spelling, and grammar; it is easier to read well-written comments than badly written ones.
Each line of text in your code should be at most 80 characters long.
Preprocessor directives should not be indented but should instead start at the beginning of the line.
Sections in public, protected and private order, each indented one space.
Inconsistent
use of indents, tabs and spaces is a problem in much the same way as
inconsistent naming is. Most text editors have the necessary options.
For example, in Visual Studio, go Tools > Options > Text Editor
> C/C++ > Tabs.
The
following should apply to all MoSync code: one level of indention
equals one tab. A tab is defined as the ASCII character \t. The actual
screen size of the indents can thus be set by and for each user with no
ill effects for others.
Syscalls are named using a ma- prefix. Only actual Syscalls and IOCTLs are named this way. Examples:
void maDisposeLayer(Handle layer);
void maSetMap(Handle layer, Handle srcMapResource, int destX, int destY);
Library functions that are directly associated with the manipulation of some complex datatype (such as a struct) should be prefixed with the name of the type followed by an underscore, followed by the function name in camel case. Examples:
MAVec3_normalize(MAVec3* v); MARect_containsPoint(const MAVec3* v, const MAPoint2d* p);
Library functions that are not directly and strongly related to a datatype should be prefixed with an identifying name for the library, which should always contain an initial 'MA'. Examples:
MAMath_solveLinearSystem(); MAInet_sendMail();
Syscalls
and extensions constitute the lowest-level APIs available in MoSync.
They are typically directly mapped to underlying platform features and
are also subject to a number of restrictions:
The number of parameters is limited to four. If more information must be passed, the stack or struct pointers can be used.
Parameters cannot be function pointers. If a notification mechanism is required, one is required to make use of (custom) events.
The
only allowed parameter types are primitive IDL types (see IDL
documentation) and IDL structs that actually are declared in the
relevant IDL file.
The only allowed return types are primitive IDL types.
MoSync memory cannot be allocated within syscalls, other than in the specific case of built-in or custom events.
Allocation, manipulation and deallocation of native objects (resources) is typically implemented by means of handles.
Typically,
there is an maCreateX() function, which takes a placeholder handle to
represent the allocated native object. Subsequent access to this object
is provided through other syscalls that accept handles as their first
parameter.
Finally,
all objects are destroyed using maDestroyObject(). As an example, these
are some functions that create and manipulate images:
void maCreateImageFromData( in Handle placeholder, in Handle data, in int offset, in int size ); void maCreateImageRaw( in Handle placeholder, in MAAddress src, in Extent size, in int alpha ); void maDrawImage( in Handle image, in int left, in int top ); void maDrawImageRegion( in Handle image, in MARect srcRect, in MAPoint2d dstPoint, in int transformMode );
Since MoSync doesn't support user-created threads, it is important to provide asynchronous interfaces to time-consuming native functionality such as network communication. Since syscalls can't accept function pointers, the central MoSync event system is used to provide progress notification. A few built-in event types are provided in the EVENT struct, but there's also a void* provided that can be used for custom events.
We encourage everyone to help us develop MoSync, and writing new extensions for MoSync is probably the most common thing you will want to do. In this topic we introduce you to some important core concepts that you need to understand and lead you step-by-step through creating an API extension.
This topic assumes that you have a good understanding of how to use MoSync, that you understand the build process, and that you can build the MoRE runtime in Visual Studio. It also assumes that you have some basic familiarity with the MoSync code.
In this section we introduce some core concepts that you will need to understand when you write extensions.

User code includes all the code that you write when you create an application with MoSync along with some of the MoSync libraries, such as the MAUI library.
A runtime is the thing that executes the user code on the device. For each platform that MoSync supports, there is a different runtime. Some runtimes are written in C++, others like the J2ME and Android runtimes are written in Java. Each runtime has two parts: one that executes the user code and one that interfaces to it to provide low-level services.
Communication between the user code and a runtime is through syscalls and events. Syscalls are like the traditional calls a user application makes to an OS kernel. Whenever the user code needs to do something it cannot do on its own, such as creating a socket connection, it performs a syscall to the runtime. To create a socket connection, for example, the syscall is maConnect.
A syscall is an actual instruction which the runtime traps during code execution. The instruction only has one argument, and that is the syscall number. A syscall, like any ordinary function call, can return a value. A syscall can do pretty much any thing you'd like it to do, but what it can never do is to block. If the syscall cannot finish immediately, such as when waiting for socket data, it needs to return and have the blocking call run in a thread in the background. Once it has finished, it will return the result through events which the user fetches through yet another syscall called maGetEvent.
The maIOCtl syscall is a special syscall which is meant for extensions which aren't supported or fully supported on all the MoSync runtimes. What this means in practice is that anything that isn't part of the standard API, that is anything that isn't the least common denominator on all platforms, will be implemented through an maIOCtl. Implementing an MaIOCtl is simpler than implementing an entirely new syscall, and is what you will be using to implement your extensions. The only limitation that the maIOCtl syscall has is that it only takes three parameters. But on the bright side, any or all the three can be user defined structures, which means that you can always pass all the parameters you like in a structure.
Any syscall starts its life in a file called maapi.idl. Here all syscalls, events, and event types (among other things) are defined. To minimize the amount of code redundancy, we have created a tool called idl2 which takes the maapi.idl file and generates several important files:
int maFrameBufferGetInfo ( out MAFrameBufferInfo info );#if IX_SOMETHING . . . #end For maIOCtl declarations the block ends up in a separate file with a similar name. It is in this block that you will be writing API extensions. The idl2 tool also produces wrapper code for any extensions that have been written through maIOCtl. This is another one of the advantages of the idl2 tool. It takes care of all the little details and updates every where that needs to be updated. The wrapper code might look something like this (from libs/MAStd/IX_CELLID.h):
static inline int maGetCellInfo ( MACellInfo* pInfo ) { return maIOCtl( 56, (int)pInfo, 0, 0 ); } In this example we will write a simple extension as an maIOCtl, we will pass a structure with 16 chars in it, and will return the same chars through an event.
We need to make four changes in this file:
Edit tools/idl2/extensions.h file and add to it "#define IX_TUTORIAL". This is needed to process anything that is declared between '#if ...' and '#endif' in the maapi.idl file. Here is the start of our example:
#define IX_RESOURCE_TYPES #define IX_GUIDO #define IX_WLAN #define IX_FILE #define IX_RECORD #define IX_CELLID #define IX_CALL #define IX_STREAMING #define IX_CONNSERVER #define IX_OPENGL_ES #define IX_AUDIOBUFFER #define IX_SEGMENTED_DATA #define IX_PIM #define IX_TUTORIAL
The MAEvent structure contains a field called "type", this field is an integer which identifies the event type. So next we need to add a constant which identifies our custom event. At the end of the block called "constset int EVENT_TYPE_" we add our custom event type:
#if IX_TUTORIAL
TUTORIAL = 10001;
#endifNote: To avoid collisions with future extensions from the MoSync team, we suggest that you always choose a large value for the event constant.
In the version of maapi.idl that we are working with, the entire block looks like this:
constset int EVENT_TYPE_ {
/**
* This event is posted when the operating system sends MoSync a command
* to exit. Causes include the OS shutting down and OS-controlled user
* commands.
* \see maGetEvent()
*/
CLOSE = 1;
KEY_PRESSED = 2;
KEY_RELEASED = 3;
/// Connection
CONN = 4;
/// Bluetooth discovery
BT = 5;
#if IX_GUIDO
/// Has MAEvent::key be the identifier for the TTS session, as returned
/// by maStartSpeaking().
TTS = 6;
#endif //IX_GUIDO
#if IX_WLAN
/// Uses MAEvent::state.
WLAN = 7;
#endif //IX_WLAN
POINTER_PRESSED = 8;
POINTER_RELEASED = 9;
POINTER_DRAGGED = 10;
#if IX_CALL
/// Has MAEvent::state be one of the \link CALLSTATE \endlink constants.
CALL = 11;
#endif //IX_CALL
/**
* While MoSync doesn't have focus, no key events will arrive and the
* screen will not be updated. If the keypad is locked, no application
* will have focus.
* \see maLockKeypad
*/
FOCUS_LOST = 13;
FOCUS_GAINED = 14;
#if IX_STREAMING
/**
* Has MAEvent::data point to a MAStreamEventData.
*/
STREAM = 15;
#endif //IX_STREAMING
//#if IX_LOCATION
/// Has MAEvent::data point to an MALocation.
LOCATION = 16;
/// MAEvent::state is one of the \link #MA_LPS_AVAILABLE MA_LPS
/// \endlink constants.
LOCATION_PROVIDER = 17;
//#endif //IX_LOCATION
#if IX_AUDIOBUFFER
/// MAEvent::state is \> 0 when the audio stream is waiting for more data,
/// or \< 0 on error.
AUDIOBUFFER_FILL = 18;
#endif
SCREEN_CHANGED = 21;
#if IX_TUTORIAL
/// Just a simple event type added for the tutorial
TUTORIAL = 10001;
#endif
}Now that we have a new event type, it is time to create a way through which we can return data to the user from an event. This can be accomplished in two ways, one is to allocate dynamic memory in the runtime and let the runtime copy that memory to user memory. The runtime will also update the data pointer in the MAEvent struct. To do this, you have to write a few macros in the right places. The second method is to create a new struct with the data that you need to return to the user and embed this in the MAEvent struct. The second method has the advantage of being a bit simpler, but at the cost of bloating the MAEvent struct. For the sake of simplicity, we will only go through the later method in this document. So let's get started.
First, we define our struct. We can call it MATutorialEvenData, it needs to contain 16 chars. The next step is to embed it in the MAEvent struct, in the revision of the code base that the author is working with, the entire code will look like this.
struct MATutorialEventData {
char m_data[16];
}
struct MAEvent {
/**
* One of the \link #EVENT_TYPE_CLOSE EVENT_TYPE
* \endlink constants.
*/
int type;
union {
struct {
/**
* In KEY events, this will be one of the
* \link #MAK_UNKNOWN MAK \endlink constants.
*/
int key;
/**
* In KEY events, this will be the native keycode.
*/
int nativeKey;
} ked;
/**
* Tutorial structure
*/
MATutorialEvenData tutorial;
/**
* In POINTER events, this will be the location of the pointer.
*/
MAPoint2d point;
/**
* In \link #EVENT_TYPE_BT BT \endlink events, this will be a value \>= 0 or
* one of the \link #CONNERR_GENERIC CONNERR \endlink constants.
*/
int state;
/**
* Valid only in CONN events.
*/
MAConnEventData conn;
/**
* Used by custom events. See invididual event descriptions.
*/
void* data;
}
}
At this point we have all the parts in place to return data through events, now we just need a way of making a call to the runtime. This is where syscalls and maIOCtl comes in. We will define a new IOCtl in the maIOCtl block (after the opening bracket and before the closing bracket). The maIOCtl will look like this:
#if IX_TUTORIAL
int maSyscallTutorial(in MAString data);
#endif //IX_TUTORIALwhere MAString is a defined as 'typedef char* MAString' at the top of the maapi.idl file.
Now that we've made actual changes to the syscall interface, we need to regenerate all the auto generated files that have to do with syscalls. In Visual Studio, build tools/idl2 and run it. Your output should look like this,
If you instead get this:
D:\workspace\repo-new\MoSync2.3\tools\idl2>Debug\idl2.exe Error opening file "opengl_generated.idl" in maapi.idl on line 2383 Exception: Unknown exception
Then you need to build the opengl_generated.idl, run tools\GLWrapperGenerator\build.bat and run the idl2 tool again.
You probably noticed that for most files it generates three different versions of it. For instance, the IX_TUTORIAL extension goes in:
#ifndef IX_TUTORIAL_DEFS_H #define IX_TUTORIAL_DEFS_H /** \brief A hash of the abstract representation of the API described in this file. * Identifiers, declarations and definitions are included in the calculation of the hash, * but documentation is not. */ #define MAIDL_HASH ((int)0xc2fcb710) /// Just a simple event type added for the tutorial #define EVENT_TYPE_TUTORIAL 10001 #define maIOCtl_maSyscallTutorial 247 #endif //IX_TUTORIAL_DEFS_HIn here we have hash (which is discussed in section 4), the event ID, and syscall ID. We will need these to write the code which handles the maIOCtl call in the runtime. The java version contains similar things.
In the next file we have:
#ifndef IX_TUTORIAL_H
#define IX_TUTORIAL_H
#ifdef __cplusplus
extern "C" {
#endif
/// Just a simple event type added for the tutorial
#define EVENT_TYPE_TUTORIAL 10001
static inline int maSyscallTutorial(const char* data) {
return maIOCtl(247, (int)data, 0, 0);
}
#ifdef __cplusplus
}
#endif
#endif //IX_TUTORIAL_H
As you see, this file is a bit different, there is an actual C function in there, this is because we wrote our new syscall/extension in the maIOCtl block. The idl2 tool knows that anything inside that block is not an actual syscall, but goes through the maIOCtl syscall. The first parameter is the maIOCtl ID, and in the previous file you can see that the preproccesor define "maIOCtl_maSyscallTutorial" is set to 247, which is quite practical and the reason that the previously discussed hash is needed to make sure that both the user libraries and the runtime agree on the same syscall interface.
By this point, we have all the parts in place to do the maIOCtl on the user side. Now you need to write the code on the runtime side which actually handles the IOCtl. In this document, the only runtime we will modify is MoRE, but modifying the other runtimes is similar.
In the source directory, there exists a file runtime/cpp/platforms/sdl/SyscallImpl.cpp, this file handles all the syscalls in the SDL runtime (MoRE). In the Visual Studio project you can find it under Platforms/cpp/sdl/SyscallImpl.cpp. Open it, and add the include "#include <helpers/CPP_IX_TUTORIAL.h>", this will include the definitions that have to do with our example.
Next we need to add the actual code for handling the IOCtl. So, scroll down to the part that says:
SYSCALL(int, maIOCtl(int function, int a, int b, int c)) {This is the actual maIOCtl syscall. In it you will find a big switch statement. We need to add our own handler to this switch case. So just before the default case, we add this piece of code:
case maIOCtl_maSyscallTutorial:
{
char * data;
MAEvent myevent;
// Get pointer to memory
data = (char*)SYSCALL_THIS->GetValidatedMemRange( a, 16 );
// Copy to event
myevent.type = EVENT_TYPE_TUTORIAL;
memcpy( myevent.tutorial.m_data, data, 16 );
// Put in event queue
gEventFifo.put( myevent );
// Return success code
return 1;
} Let's go through the parts of this code. Firstly, a pointer to the argument that was passed to the maIOCtl from the user side, is fetched. The method GetValidatedMemRange takes a pointer to the user side memory and the number of bytes that the pointer points to. If the memory is valid, a pointer will be returned. Otherwise a panic will occur. Secondly, the event type is set and the ASCIIZ string passed by the user is copied to the event structure. Thirdly, the event is put in the event queue, from where it can be fetched by the user through the maGetEvent syscall. And lastly, we return from the maIOCtl syscall.
Assuming that you have Visual Studio correctly set up and you can build MoRE, rebuild MoRE. The executable will be copied to your MoSync installation path (MOSYNCDIR/bin).
This step is very important. Any change you make to the IDL file might change the binary interface of syscalls (specfically syscall IDs). Because of this there is a hash in the generated maapi.h file that is verified against the runtime to make sure the user code and the runtime have been built with the same interface. So we need to remove all the old files and rebuild the libs:
If you have gotten everything to work this far, there should be only one last step remaining, and that is to actually test that it works as expected. In the MoSync IDE, create a project and create in it a file called main.c containing the following code:
#include <ma.h>
#include <IX_TUTORIAL.h>
int MAMain ( )
{
while ( 1 )
{
MAEvent e;
while ( maGetEvent( &e ) != 0 )
{
switch ( e.type )
{
case EVENT_TYPE_CLOSE:
return 0;
case EVENT_TYPE_KEY_PRESSED:
case EVENT_TYPE_POINTER_PRESSED:
maSyscallTutorial( "world!" );
break;
case EVENT_TYPE_TUTORIAL:
printf( "Hello %s\n", e.tutorial.m_data );
break;
}
}
}
return 0;
}If you've done everything correctly, this code will compile and run just fine. And in that case, congratulations, you've just written your first MoSync extension!
MoSync introduces a few new terms, and uses some others in a new way. Here we briefly explain these terms and how we interpret them.
A set of syscalls and other low-level functions that provide access to one or more basic features of a device. We sometimes use this term rather broadly. Examples include the Sockets API and the Map API.
A serial connection to a remote machine, identified by a Handle. There are different types of connections, including TCP, HTTP and Bluetooth.
A model of machine that can execute arbitrary programs, typically a mobile phone (cell phone).
MoSync Events deliver notification of keypresses, stylus movements and the results of asynchronous operations like networking and Bluetooth scans.
An identifier to a resource (e.g. binary file) or object (e.g. a connection) managed by the runtime. There are different types of handles, not interchangable.
A notification sent when an unrecoverable error occurs in a MoSync runtime, library, or user application. See the Panics Reference Guide.
Pipe-tool is our powerful code transformation engine. It takes the output of the GCC compiler, links it with the MoSync libraries, and outputs binary code and/or Java source code depending on the target platforms and devices. Pipe-tool combines the functions of a resource compiler, linker, and code optimizer. It is configured through build configurations.
A resource handle that doesn't identify any resource. It is used in the creation of new resources. The concept of a "placeholder" is used in two contexts. The first is in resource files, to specify "markers" to identify ranges of resources. The second is to create handles for dynamically allocated data objects (using maCreatePlaceholder/maDestoryPlaceholder).
An operating system, or version thereof, that is used by one or more devices. Examples include J2ME, Symbian Series 60, Android, and Windows Mobile.
A piece of data managed by the runtime, for example an image, an audio file, or a binary data file. Each resource is identified by a handle. Resources are compiled with the rest of the program and loaded at startup. They can also be created and destroyed when the program is executing.
Libraries or programs that execute MoSync programs on a given target device. They also provide a uniform interface to low-level system APIs, including graphics, audio, event handling and communications. Platforms supported by MoSync have different runtimes.
System Call - a function that is implemented by a MoSync runtime in code native to a platform.