Tuesday, February 3, 2009

Developing mobile applications using Gear episode 5: Display a splash screen

During the first phase of a MIDlet's life, it's common to find a lot of setup code used to initialize resources, data structures, user interfaces and anything else will be required. In this case, it's a best practice to display a splash screen to inform the user that the application is not frozen but is starting up. With the release of version 1.2.0 of Gear Java Mobile Framework, we've included a consistent yet customizable implementation for this feature.

1 How to achieve it ?
To properly setup Gear SplashScreen, all you have to do is create some keys inside the JAD file:
  • "SplashScreenImage:" -> contains a string with the path to the desired background image
  • "SplashScreenText:" -> contains a string with the desired text
If you are developing your application inside Eclipse with MTJ plugin (former EclipseME), you can easily achieve this by opening the Application Descriptor tab and "Add" the two key-value entries.


If your development environment is a different one, you have to manually insert those keys inside your application's JAD file.

As long as there is at least one of the two keys inside your JAD file, Gear will display the SplashScreen, so if you don't want it, simply don't specify anything.

2 Writing initialization code
Now that the SplashScreen is enabled, all you have to do is to override a single method inside your MIDlet
protected void onMidletInitializationComplete()
and fill it with your custom initializzation logic. We encourage users to follow this practice to put setup code inside this function rather than into the GearMIDlet constructor so they can take advantage from SplashScreen avoiding user interface freezes.
Here is an example of a possible implementation:
protected void onMidletInitializationComplete() {
// Call some custom initializzation methods
initDatabase();
doSomeHeavyDutyWork();
initUserInterface();
// ... and finally show the user the UI
EventManager.getInstance().enqueueEvent(new DisplayWidget(this, LoginForm.class));
}

3 The result
Gear's SplashScreen can display an image background, text and comes with an animated throbber centered vertically and anchored to the bottom of the screen. This is a possible result obtained with it:


Unfortunately this screen-shot is just a static image and you can't actually see the spinning animation of the throbber.

Monday, February 2, 2009

Developing mobile applications using Gear episode 4: On-device debug

Last version of Gear framework (1.2) introduced a new message logging system.
By using Gear logger it's now possible to trace various types of application messages and print out the resulting log on different output types, including device screen.

1. New library debug release
Introducing a logging system in the framework brought a big advantage but leaded also to a performance issue: most of the times the whole logger is useless in the final release of an application and the operations required by the logger to do its work may "steal" precious resources to the rest of the application.
So, starting from version 1.2 we dediced to make two separate releases of the library's JAR: one including the whole logging sub-system and one including only the method stubs.
The two packages are fully compatible, so you can switch anytime between them.

2. Logger structure and usage
The base class of the logging sub-system is Logger. Through this class it is possible to select what kind of messages have to be printed
// Tells the Logger to print gear system level messages
Logger.logSystemMessages(true);
and select the desired output destination
// Tells the Logger to print his messages on to the Standart Output
Logger.out = new StandardOutput();
By default the Logger class is created with NullLogger set as output destination (it doesn't print any message) and logs just user messages (printed by the programmer inside code) and exceptions (any exception printed within code using Logger.out.println(Exception)).
Gear provides three implementation for LogOutput:
  • NullLogger : every method is implemented with an empty body and thus no message will be traced.
  • StandardOutput : prints messages on the Standard Output, usually the development console.
  • GWConsole : displays a graphic console directly on device's screen and prints messages on it.
For example, to print a log message on device's screen, the following code should be used:
Logger.out = new GWConsole();
Logger.logUserMessages(true);
Logger.out.println("Log message");
Note that the second line is not compulsory since user messages logging is enabled by default.

3. Make your own LogOutput
If you have special logging requirements, such as redirecting logs to a remote server, you can write your own custom output target and then use it with Gear's Logger. The class must implement LogOutput interface and should extend the InternalLogger abstract class.
The class structure should look like this one:
public class RemoteLogger implements LogOutput
extends InternalLogger {

// Instance fields ...
// ...

public void println(int logLine) {
if (Logger.isUserMessagsLogged()){
// Network communication ...
}
}

public void println(double logLine) {
if (Logger.isUserMessagsLogged()){
// Network communication ...
}
}

public void println(String logLine) {
if (Logger.isUserMessagsLogged()){
// Network communication ...
}
}

public void println(Exception logLine, Object sender) {
if (Logger.isExceptionsLogged()){
// Network communication ...
}
}

public void println(Exception logLine,
Object sender, String methodName) {
if (Logger.isExceptionsLogged()){
}
}

protected void printSystemMessage(String message) {
if (Logger.isSystemMessagsLogged()){
// Network communication ...
}
}

}

4. Conclusions
Gear's logging system allows keeping track of application activities for debug, statistical or any other purpose, it provides a simple system to filter messages and handle different output targets. In addition to this, the overhead introduced by the Logger system can be stripped without changing any line of code, just by switching from Gear's debug JAR to the release one.

Thursday, January 29, 2009

Developing mobile applications using Gear episode 7: Work with EventManager and async messages

With this tutorial we're going to learn the basic concepts behind EventManager class and how we can send asynchronous messages across our Midlet with Gear Java Mobile Framework. To better understand this guide, we suggest you to read at least this post about configuring Eclipse and to download Gear's latest release (1.2.0).

1.0 EventManager:

Working with Gear in most cases requires to use EventManager class to dispatch asynchronous messages to other Objects within your MIDlet. It's implemented following the Singleton pattern so there will be only one instance of it during execution time and you can reference it wherever you want inside your code via public method getInstance(). Let's go on how to use this class and its methods.

1.1 Events

Every message you want to be forwarded through EventManager must derive from the abstract class Event. It contains the basic structure and methods to keep track of the sending Object and category. Here's an example:
public class ConnectionClosed extends Event {
// Public constructor with empty EventArgs object
public HideMidlet(Object sender){
super(sender);
}
// Public constructor with user defined EventArgs
public HideMidlet(Object sender, ConnectionClosedEventArgs eventArgs){
super(sender, eventArgs);
// Override of getCagegory method to return the desired type
public Category getCategory() {
return Category.APPLICATION;
}
}
1.2 EventArg

As you noticed in last example, you can assign some custom defined arguments to an event to pass on additional data to the receiving Object. To achieve this, you have to extend EventArg class and implement your own private fields along with proper getter and setters. Here's an example:
public class ConnectionClosedEventArgs extends EventArg {
private ConnectionStatus connectionStatus;

public ConnectionClosedEventArgs(ConnectionStatus connectionStatus) {
super();
this.connectionStatus = connectionStatus;
}

public ConnectionStatus getConnectionStatus() {
return connectionStatus;
}

where ConnectionStatus is a user defined class containing additional information about the reason for connection termination.

1.3 Dispatch events

This task is pretty simple. Suppose Object A wants to send some message to Object B (we'll see on the next poit how B will actually receive it). All it have to do is to obtain a reference to EventManager and enqueue the desired message, wrapped inside an Event object.
EventManager.getInstance().enqueueEvent(new MyEvent(this))
That's it. In this particular case, we're sending a MyEvnet (which derives from Event class) and we don't have to care about anything else. EventManager will internally manage our request and dispatch it. Notice we passed "this" parameter to the Event constructor to allow a reference of the original sender to be kept.

1.4 Register and receive Events

In order to receive an Event, an Object must first implement an interface named EventHost and thus it's only method
public void notify(Event event);
and secondly register itself to EventManager by calling
public void registerHost(EventHost host, Event.Category category)
where the second argument is one of the categories mentioned before. A class that is registered to at least one Event.Category will be notified of incoming messages. Whenever you need to unregister an Object from EventManager you can call
public void removeHost(EventHost host)
to totally remove it from the queue or
public void removeHost(EventHost host, Event.Category category)
if you just want to stop being notified for a specific category of events.


1.5 Events and GearMIDlet

By default, GearMidlet register itself to APPLICATION and GRAPHICS categories inside its base constructor, but if you need to be aware of more Events or less you can register/unregister from EventManager as seen in previous sections.

2.0 Putting it all together

With all the concepts from previous section, we can now create a GearMidlet with full support for asynchronous messages:


public class GearTouchDemo extends GearMidlet {

protected boolean onDestroy() {
return true;
}

protected void onPause() {

}

protected void onStart() throws MIDletStateChangeException {
// Enqueue a request to display MainMenu user interface
EventManager.getInstance().enqueueEvent(new DisplayWidget(this, MainMenu.class));
}

public class MainMenu extends GWGrid {
public MainMenu(){
super(2,2);
addItem("Photo browser", "/icons/c1.png");
addItem("Drops", "/icons/c2.png");
addItem("None", "/icons/c3.png");
addItem("Nothing here", "/icons/c4.png");
setTitle("Main menu");
addCommand(CommonCommands.SELECT);
addCommand(CommonCommands.EXIT);
setCommandListener(new MainMenuCommandListener());
}

public void itemClicked(ImageItem clickedItem) {
if (commandListener != null){
commandListener.commandAction(CommonCommands.SELECT, this);
}
}

public void selectElement(){
switch (getSelectedIndex()){
case 0:
// Enqueue a request to display MainMenu user interface
EventManager.getInstance().enqueueEvent(new DisplayWidget(this, PhotoBrowser.class));
break;
case 1:
// Enqueue a request to terminate the MIDlet.
EventManager.getInstance().enqueueEvent(new QuitEvent(this));
break;
default:
displayAlert("Function not implemented");
break;
}
}

}

Tuesday, January 20, 2009

Develop Ogre3D applications using Eclipse on Mac OS X

This tutorial will lead you trough all the steps required to configure Eclipse for Ogre 3D applications development on Mac OS X.

Requirements
To perform the tasks described in this tutorial it is necessary for you to setup a basic development system including:
Application creation
To create your first application start Eclipse and select New -> C++ Project from the File menu.
Now select Hello World C++ Project and give it a name (let's say MyFristOgreApp).

Application configuration
The application is now created, but is not connected in any way to Ogre, thus any ogre specific code, if compiled, would give compilation, link and run-time errors.
To solve this problem you have to include the Ogre framework in your application, and make the project aware of the Ogre and Carbon frameworks position.
  1. Right-click on your project name in the Project Explorer and select Import, then select import from File System.
    Browse to the Dependencies directory of the OgreSDK folder, select the subfolders and then import it in the Frameworks subdir for your project.

  2. Now right-click again on your project name in the Project Explorer and select Properties.
    Move to C/C++ General -> Paths and Symbols and press the Add button.
    Select Frameworks/Ogre.framework/Header directory in you workspace and check Add to all configurations, Add to all languages and Is a workspace path.
    Do the same for Frameworks/Cg.framework/Header and Frameworks/include directories.
    Press Add again, select /Developer/Headers/FlatCarbon folder and check only Add to all configurations, Add to all languages this time.


  3. Move to Library Paths tab and press Add; again check Add to all configurations, Add to all languages and Is a workspace path and add Framworks/lib/Release directory.


  4. Now select C/C++ Build ->Settings from the tree menu on the left and set the configuration selector to [ All configurations ].
    Click on C++ Linker -> Libraries and add ois to Libraries


  5. Finally click on C++ Linker -> Miscellaneous and write -F${CWD}/../Frameworks -framework Ogre -framework Carbon -framework IOKit -framework Cg in the Linker flags text box.

Last bug-fix
Now your IDE is correctly configured but your application will not compile due to an error within the Frameworks/Ogre.framework/Headers/OSX/OgreTimerImp.h file. Edit this file and change the line #include <ogre/OgrePrerequisites.h> to #include <OgrePrerequisites.h>.

Conclusion and last hints
Now this setup will allow you to compile any Ogre based application, however, if you want to work with Ogre official tutorials, you have to go through some further steps:
  1. Import in you application the headers required by the tutorial you are working on (most of the times ExampleApplication.h and ExampleFrameListener.h are required).
    You can find them in the Samples directory of your OgreSDK.
  2. Import the Media directory of your OgreSDK into your project's root (this directory contains all the tutorials required textures, models, etc... )
  3. Import the .cfg files from you OgreSDK and modify them to match the path of your Media directory (typically ../Media is good).
  4. Add this command: install -d ${CWD}/Contents/Resources && cp -f ${CWD}/../*.cfg ${CWD}/Contents/Resources to your project's Post-build step (set it in the Build steps tab of the C/C++ Build -> Settings configuration form and remember to do it for all configurations)

Monday, January 19, 2009

ZappOne.tv FAQ

In this little FAQ I will address some common questions about ZappOne.tv

First things first, what's this thing all about ?
ZappOne.tv is a Rich Web 2.0 Interactive Ajax Enabled Multimedia Videoclip Streaming Internet Application (oh yes and also iSomething).
Said with poorer words, it's a Web application based on a very simple concept: create an enhanced experience with YouTube.
In straight words, a continuous stream of YouTube videoclips without the hassle of clicking on next video's link.

How to reach this paradise ?
Simply go to ZappOne.tv website and start using it

What can i do with it?
Well, you can search YouTube media library for your favourite videoclips and watch them one after another.

Ok, but how ?
The easiest way is to put in some keywords into the tex box on the homepage, then you can press on the GO! button and enjoy your videclips.
Following you can find two screenshots along with some explaination about other functions.

This is the main search page for ZappOne.tv

  • Keyword to search for: here you can insert your keywords separated by a space
  • Ordering: this selection determines which order your results will be displayed (default is by most relevant to lesser)
  • Filter criteria: these options let you filter and further optimize your search results by selecting only ones that match checked categories (this is very usefull for music :P )
  • Recent tags: just to remember what you have searched so far
  • Popular tags: the classic Web 2.0 tag cloud containing most used keywords by every user browsing through ZappOne.tv (you can click them to add to your search)
  • Submit Button: the button with a "Go!" label. As it's name suggests, it starts your experience. Plain and simple.

This is an example of a result page

  • Current video: Just to remember you what are you looking at. Also contains a link to the original media on YouTube
  • Playlist: a strip with the thumbnails of your search results. You can scroll it and peek what will be the next videoclip to be shown.
  • Remove button: by hovering over a thumbnail you will be able to exclude it from the playlist by simply clicking on this red button (you can then restore it by pressing it again)
  • Link button: have you found a particular playlist you want to share with your best friends ? Here's a link to show them from this point on.

Who developed this marvel ?
digitalapes, of course ;)

Now tell me the real thing: how much does it cost ?
Nothing. ZappOne.tv is absolutly costless and ad-free. The only thing we ask you is to give us a little of feedback on your experience. That's it.

What am I waiting for ?
Don't know ... go visit ZappOne.tv