MorkaLork Development

Interesting stuff I've picked up over the years...

Adding a splash screen

2009-07-17 14:15:18 | 1221 views | j2me splash screen MIDlet

What is a splash screen?



Some times when you run a mobile app you get to see a screen first, maybe with the producing company´s name or the name of the app etc. Anyways, you might want to add a splash screen. Looks nice. Adds to the apps depth. =D

Well, what we need is an image. Preferebly a .jpg or .gif image in a certain size. You need to know how big a display you have so you can check this by running the app with these two lines:

What we'll also do is take a short look at the Canvas object. This differs from the Form object in several ways. You don't add objects to the Canvas, you paint it onto it. If you want to add text for example you have to use the drawString() method and specify the coordinates where you want the string to appear.
This will be explained in the code.

We will use this picture which has the width 240 and height 290:
A MorkaLork logo :P

The application will contain three files:

SplashMIDlet.java: The MIDlet
SplashScreen.java: The splash screen
CanvasScreen.java: The screen we will show after the splash screen

Let's start by looking at the SplashScreen.java class:


SplashScreen.java




package org.morkalork.splash;

import java.io.IOException;
import javax.microedition.lcdui.*;
import java.util.*;
/**
* A splash screen!
* @author maffelu
*/
public class SplashScreen extends Canvas{
//===================FIELDS=========================
private Display display;
private Displayable nextDisplayable;
private Timer timer;
private Image image = null;

//===================CONSTRUCTOR====================
/**
* Creates a new SplashScreen object
* @param display A Display object
* @param nextDisplayable The next Displayable object to show (after splash screen)
*/
public SplashScreen(Display display, Displayable nextDisplayable){
this.display = display;
this.nextDisplayable = nextDisplayable;

timer = new Timer();

try{
//We've put the image in the base directory
image = Image.createImage("/org/morkalork/splash/MorkaSplash.jpg");
}
catch(IOException ioe){
System.out.println("Error: " + ioe.getMessage());
}

display.setCurrent(this);
}

/**
* If a key is pressed, dismiss the splash screen
* @param keyCode Any key
*/
protected void keyPressed(int keyCode){
dismiss();
}

/**
* If a pointer is pressed, dismiss the splash screen
* @param x The X coordinate
* @param y The Y coordinate
*/
protected void pointerPressed(int x, int y){
dismiss();
}

/**
* Dismisses the splash screen and shows the
* next screen
*/
private void dismiss(){
timer.cancel();
display.setCurrent(nextDisplayable);
}

/**
* The painting of the canvas, is never called directly but rather
* by repaint.
* @param g A Graphics object
*/
protected void paint(Graphics g){
g.setGrayScale(255);
g.fillRect(0, 0, g.getClipWidth() -1, g.getClipHeight() -1);
g.drawImage(image, 3, 10, Graphics.TOP | Graphics.LEFT);
}

/**
* Showing will begin soon...
*/
protected void showNotify(){
timer.schedule(new CountDown(), 5000);
}

/**
* A class to handle the dismissal of the splash screen
* @author maffelu
*/
private class CountDown extends TimerTask{
/**
* Dismisses the splash screen
*/
public void run(){
dismiss();
}
}
}


Since this is a Canvas base class we extend the Canvas class which has an abstract method called paint. Paint is where the canvas gets painted and that's where we have to add everything we want on our screen (compare to Form objects where you 'add' items to the Form).
Some important things about painting a canvas:

Unless you want the last screen as background, start of by painting the entire screen in either a color or a picture. This is done as follows:


fillRect(X, Y, width, height);


X and Y represents where you want to start horizontally and vertically (0 and 0 means start from the beginning =D). Width and height are how far you want to paint (if you want to paint the whole screen, set this to screen width and height, more about this later).
But before starting to paint, you need to set a color to use. Use the setGrayScale method for this:


setGrayScale(x);


X here is the grayscale value (0-255 where 0 is black and 255 is white).

After doing this, you're ready to add something to the canvas. We add an image, so the pain method looks like this:


protected void paint(Graphics g){
g.setGrayScale(255);
g.fillRect(0, 0, g.getClipWidth() -1, g.getClipHeight() -1);
g.drawImage(image, 3, 10, Graphics.TOP | Graphics.LEFT);
}


This means we set the color to use to 255 (white) and we paint the whole screen with that color.
After that we add an image by using the drawImage method. The first parameter is the image object to paint, the second parameter is pixels from the left, the third the pixels from the top and the fourth is the anchor point.

However, as we see, we need an image object. In this class we have a field called image:


private Image image = null;


This field is set in the constructor to an image we've placed in the same directory as the class file:


try{
//We've put the image in the base directory
image = Image.createImage("/org/morkalork/splash/MorkaSplash.jpg");
}
catch(IOException ioe){
System.out.println("Error: " + ioe.getMessage());
}


Notice that (if you are not used to the directory system in java) the files are located in the package name (org.morkalork.splash = org/morkalork/splash/files) which is where we put the image.

Now, if we've entered a faulty path or the image is the wrong type we'll eventually get an error in the Paint method:

Error: null
java.lang.NullPointerException:


So it's important to make sure this path is correct!

We also use a Timer object. This is because we want the user to be able to either press the splash screen away OR wait for it to dissapear.
We set the timer schedule in the showNotify method making sure it runs as soon ass the application runs.
Now, the schedule method takes two parameters, a TimerTask object and the amount of time (ms) to run until the task executes:


protected void showNotify(){
timer.schedule(new CountDown(), 5000);
}


Now, the task to run is a method called dismiss. The CountDown class has only one method, run, which it has to implement when TimerTask is extended and it runs the dismiss method that looks like this:


private void dismiss(){
timer.cancel();
display.setCurrent(nextDisplayable);
}


When you instantiated this class you had to give a displayable to be used when dismissing the splash screen, it is what we use here.


CanvasScreen.java




package org.morkalork.splash;

import javax.microedition.lcdui.*;

/**
* Displays a canvas with information about itself
* @author maffelu
*/
public class CanvasScreen extends Canvas{
private Command cmdExit;
private int width;
private int height;

public Command getCmdExit(){
if(cmdExit == null){
cmdExit = new Command("Exit", Command.EXIT, 0);
}
return cmdExit;
}
/**
* constructor
*/
public CanvasScreen(SplashMIDlet parent) {
width = this.getWidth();
height = this.getHeight();

this.addCommand(getCmdExit());
this.setCommandListener(parent);
}

/**
* Paint a new screen
*/
public void paint(Graphics g) {
//Set the drawing color to white
g.setGrayScale(255);
//Draw a big white rectangle over the whole screen (over the previous splash screen)
g.fillRect(0, 0, width -1, height -1);

//Set the drawing color to black
g.setGrayScale(0);
//Output text (3 pixels from the left)
g.drawString("Canvas information:",3,0,Graphics.TOP|Graphics.LEFT);
g.drawString("Width: " + width, 3, 12, Graphics.TOP|Graphics.LEFT);
g.drawString("Height: " + height, 3, 24, Graphics.TOP|Graphics.LEFT);
}
}


This is a Canvas object where we display some information about the canvas size.
What we can learn here is that we once again have to repaint the background to white. If we don't do this the text will be outputted on top of the splash screen.
So first we change the color to 255 (white) and repaint the entire screen. After that we set the color to 0 (black) and start drawing our strings.
We have to position the strings ourself (with Form objects, this is done automatically when adding objects to the Form) so what we do is that every string starts 3 pixels from the left, then with a iterating distance from the top (0, 12, 24).


SplashMIDlet.java




package org.morkalork.splash;

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

/**
* Displays a splash screen and a Form
* @author maffelu
*/
public class SplashMIDlet extends MIDlet implements CommandListener{
private Display display;
private Command cmdExit;
private CanvasScreen canvasScreen;

/**
* Empty constructor
*/
public SplashMIDlet(){
canvasScreen = new CanvasScreen(this);
}

/**
* Switches the current screen to a new screen
* @param alert An Alert screen, or NULL
* @param next The new display object
*/
public void switchDisplay(Alert alert, Displayable next){
display = Display.getDisplay(this);

if(alert == null){
display.setCurrent(next);
} else {
display.setCurrent(alert, next);
}
}

/**
* Starts the MIDlet by showing the splash screen
*/
public void startMIDlet(){
cmdExit = new Command("Exit", Command.EXIT, 0);
display = Display.getDisplay(this);
switchDisplay(null, new SplashScreen(display, canvasScreen));
}

/**
* Exits the MIDlet
*/
public void exitMIDlet(){
notifyDestroyed();
}

public void commandAction(Command command, Displayable displayable){
if(displayable == canvasScreen){
if(command == canvasScreen.getCmdExit()){
exitMIDlet();
}
}
}

public void startApp() {
if(display == null){
startMIDlet();
}
}

public void pauseApp() {
}

public void destroyApp(boolean unconditional) {
}
}


The MIDlet has a switchDisplay method to swap the screens. A splash screen can be shown as an Alert object as well, but that feels sort of like cheating, and we don't want to cheat ?=).
It's in the constructor we run the splash screen:


switchDisplay(null, new SplashScreen(display, canvasScreen));


Basically, what we do is that we switch display to a new SplashScreen instance sending the current display to use, and the canvasScreen object to show after the splash screen. We do not want to show an Alert object (hence the null).


Screenshots




The splash screen
Showing the splash screen


The canvas information screen
The canvas information


Article comments

Feel free to comment this article using a facebook profile.

I'm using facebook accounts for identification since even akismet couldn't handle all the spam I receive every day.