Timers are always an important part of programming. They are even more important in the mobile domain as the two of the most used applications on the mobile phone are games and auto synchronizing network enabled application. Both these types of applications are heavily dependent upon the timers for there functioning. Sensing this Sun Microsystems has included the classes Timer and TimerTask in the Mobile Information Device Profile (MIDP). These two classes are very easy to use and enable us to perform complex timing functions. They can be used in a number of tasks like:
Thus the timing functionality is very important. We will now discuss the classes Timer and TimerTask more extensively. However before pursuing further I would like to tell you an important fact, the Timer class can not guarantee the exactness of the intervals. Thus we should not use the Timer class for very accurate time keeping tasks like the stop watch. We have given the example code for a stop watch just to make you familiar with the programming for timers. Timer The Timer class is contained within the package java.util of the Mobile Information Device Profile (MIDP). The Timer class provides us with 2 types of timekeeping, namely:
Timer provides one time execution for tasks like animating the splash screen or displaying the help automatically after some time, once. There are 2 methods in the Timer class which can schedule the Timer to run once, namely: o public void schedule (TimerTask task, Date time) This method can be used for scheduling the specified task for execution at the specified time. If the current time is already past the time mentioned by the programmer, the task is scheduled for immediate execution. o public void schedule (TimerTask task, long delay) This method schedules execution of the specified TimerTask after a specified amount of delay.
The repeated execution of tasks is required for certain situation like the gaming applications and the auto synchronizing applications. Games generally involve animation where the changes in frames are timed through the use of Timers with repeated execution. The Timer class provides the following methods for repeated executions:
Fixed delay repeated executions In this type of scheduling the tasks are scheduled to run relative to the actual time of the execution of the previous execution. o public void schedule (TimerTask task, Date firstTime,long period) This method can be used for scheduling the specified task repeatedly for execution beginning at the specified time. o public void schedule (TimerTask task, long delay,long period) This method schedules execution of the specified TimerTask repeatedly after a specified amount of delay. Fixed rate repeated executions In this type of scheduling the tasks are scheduled to run at regular intervals of time. If one execution is delayed then the other executions will occur rapidly thus ensuring that in the longer run the frequency of the executions is the reciprocal of the specified period. o public void scheduleAtFixedRate (TimerTask task, Date firstTime, long period) This method can be used for scheduling the specified task repeatedly for execution beginning at the specified time. o public void scheduleAtFixedRate (TimerTask task, long delay, long period) This method schedules execution of the specified TimerTask repeatedly after a specified amount of delay.
TimerTask
This class represents the task which has to be scheduled by the Timer. The TimerTask is an abstract class and implements the ‘Runnable’ interface and thus contains the run () method. The actions which should be performed in the executions of the Timer should be implemented in run () method. We will now see an extensive practical example of using the Timer and TimerTask class.
Example Code: Timer & TimerTask This example shows how to work with Timer and TimerTask. This application display’s a stopwatch. The main feature of this application is that we can store upto 32 different split second timings in an array and display it on canvas. Please remember that the MIDP timer should not be used for timing events that require absolute precesion like track and field events.
The following keys are used in our stopwatch:
Ø ‘*’ button It is used to start and stop the stopwatch. Ø ‘0’ button It is used to set the stopwatch to zero. Ø ‘#’ button It is used to activate the split second functionality.
/*************************/ /* TimerMIDlet.java */ /*************************/ import javax.microedition.midlet.*; import javax.microedition.lcdui.*;
/** * @author SKJ * @version 1.0.0 */
public class TimerMIDlet extends javax.microedition.midlet.MIDlet { private Display display;
//defineing object variable private TimerCan can;
public void startApp() { this.display = Display.getDisplay(this) ; this.can = new TimerCan() ;
//setting current display this.display.setCurrent(this.can) ; }
public void pauseApp() { }
public void destroyApp(boolean unconditional) { } }
/*************************/ /* TimerCanvas.java */ /*************************/ import javax.microedition.lcdui.* ; import java.util.* ;
/** * @author SKJ * @version 1.0.0 */
public class TimerCan extends Canvas { // for Timer private Timer timer ;
// variable to store time private int hour[] ; private int sec[] ; private int min[] ; private int msec[] ;
// Canvas variables private int maxX ; private int maxY ;
//array incement and decrement private int current ;
//g.DrawString variable to display in next line private int ctrY ;
//store font lenght to display in center of canvas private int length ;
private int offsetY ;
//time variable private String time ;
//font hight and width private int strWid ; private int strht ;
private boolean scroll ; private int countpl ; private int rect ;
//Array increment and decrement variable private int counter ;
//for start and stop of time private boolean start ; private boolean stop ;
private boolean yes ;
//constructor public TimerCan() { super() ; try { //getting heigth and width of canvas this.maxX = this.getWidth() ; this.maxY = this.getHeight() ;
//initilizing variable this.ctrY = 0 ; this.rect = 0 ; this.countpl = 0 ; this.current = 0 ; this.offsetY = 0 ;
//Initializing array with Size 33 this.hour = new int[33] ; this.min = new int[33] ; this.sec = new int[33] ; this.msec = new int[33] ; this.start = false ; this.stop = true ; this.yes = true ; this.scroll = false ;
//initilizing array to zero for(int j = 0 ; j <= 31 ; j++) { this.hour[j] = 0 ; this.min[j] = 0 ; this.sec[j] = 0 ; this.msec[j] = 0 ; } }
catch(Exception e) { e.printStackTrace() ; } }
public void paint(Graphics g) { g.setColor(180,254,243) ; //draw rectangle g.fillRect(0,0,maxX,maxY) ;
//initializing Font Font font = Font.getDefaultFont() ;
//getting width of string this.strWid = font.stringWidth("this.time") ;
//getting hieght of string this.strht = font.getHeight() ; this.ctrY = this.strht ;
for(int j=1 ; j <= current ; j++) { //setting time variable like 00:00:00:00 if(hour[j-1] < 10) { this.time = "0" + String.valueOf(this.hour[j-1]) + ":"; } else { this.time = String.valueOf(this.hour[j-1]) + ":" ; }
if(min[j-1] < 10) { this.time = this.time+ "0"+String.valueOf(this.min[j- 1]) + ":" ; } else { this.time = this.time+ String.valueOf(this.min[j-1]) + ":" ; }
if(sec[j-1] < 10) { this.time = this.time+"0"+String.valueOf(this.sec[j-1]) + ":" ; } else { this.time = this.time+String.valueOf(this.sec[j-1]) + ":" ; }
if(msec[j-1] < 10) { this.time = this.time + "0"+String.valueOf(this.msec[j1]) ; } else { this.time = this.time + String.valueOf(this.msec[j-1]): }
this.time = j + ". " + this.time ;
//Getting width of string this.strWid = font.stringWidth(this.time) ; this.length = this.maxX - this.strWid ;
//Length divided by two for cenrte this.length /=2 ;
//Setting Color and display stored time g.setColor(255,0,128) ; g.drawString(this.time,this.length,this.ctrY- this.offsetY,Graphics.TOP|Graphics.LEFT) ;
//Increment ctrY by gieght of string to draw time in next //line this.ctrY += this.strht ;
}
// Set time variable like 00:00:00:00 if(hour[current] < 10) { this.time = "0" + String.valueOf(this.hour[current])+":" ; } else { this.time = String.valueOf(this.hour[current]) + ":" ; }
if(min[current] < 10) { this.time = this.time + "0"+String.valueOf(this.min[current]) + ":" ; } else { this.time = this.time + String.valueOf(this.min[current]) + ":" ; }
if(sec[current] < 10) { this.time = this.time + "0"+String.valueOf(this.sec[current]) + ":" ; } else { this.time = this.time + String.valueOf(this.sec[current]) + ":" ; }
if(msec[current] < 10) { this.time = this.time + "0"+String.valueOf(this.msec[current]) ; } else { this.time = this.time + String.valueOf(this.msec[current]) ; }
//Getting width of string this.strWid = font.stringWidth(this.time) ; this.length = this.maxX - this.strWid ;
//Length divided by two for display in center this.length /= 2 ;
//Setting Color to rect g.setColor(255,255,255) ;
//Fillrect to background of running watch g.fillRect(0,0,maxX,strht) ; g.fillRect(0,(countpl + 1)*strht,maxX,maxY) ;
//Display time hour:min:sec:msec g.setColor(0,0,0) ; g.drawString(this.time,length,0,Graphics.TOP|Graphics.LEFT) ;
}
private void startTimer() { TimerTask task = new TimerTask() { public void run() { msec[current]++ ;
if(msec[current] == 100) { msec[current] = 0 ;
//sec increment by 1 when msec equal to 100 sec[current]++ ; } else if(sec[current] ==60) { sec[current] = 0 ;
//min increment by 1 when sec equal to 60 min[current]++ ; } else if(min[current] == 60) { min[current] = 0 ;
//hour increment by 1 when min equal to 60 hour[current]++ ; } else if(hour[current] == 24) { hour[current] = 0 ; } repaint() ; } } ;
timer = new Timer() ; timer.scheduleAtFixedRate(task,10,10) ;
}
/** * Called when a key is pressed. */
protected void keyPressed(int keyCode) { int action = getGameAction(keyCode) ;
if(action == Canvas.UP && offsetY >0 ) { offsetY -= strht ; }
if(action == Canvas.DOWN && offsetY < counter * strht && scroll == true) { offsetY += strht ; }
if(keyCode == Canvas.KEY_STAR) { if(this.start == false) { this.start = true ; this.stop = false ; } else if(this.stop == false) { this.start = false ; this.stop = true ; this.timer.cancel() ; } if(start == true) { this.StartTimer() ; } }
if(keyCode == Canvas.KEY_NUM0) { // Cancellling the Timer effect this.timer.cancel() ;
//setting array to zero this.hour[current] =0 ; this.min[current] =0 ; this.sec[current] =0 ; this.msec[current] =0 ; this.start = false ; }
if(keyCode == Canvas.KEY_POUND) { if(start != false) { if(((maxY - ctrY ) < strht || ctrY >= maxY) && offsetY < ((32-countpl) * strht) && current < 32) { offsetY += this.strht ; this.scroll = true ; this.counter++ ; this.yes = false ; } else if(yes) { this.countpl++ ; this.rect += this.ctrY ; } if(current <= 31) { this.current++ ; //store current time in array when pound key pressed this.hour[current] = this.hour[current-1] ; this.min[current] = this.min[current-1] ; this.sec[current] = this.sec[current-1] ; this.msec[current] = this.msec[current-1] ; } } } }
|
Mobile Technology > Java ME (J2ME) > Book - Mobile Phone Programming using Java ME (J2ME) > UNIT II >