andbook!.pdf - Learning Android Get an anddev.org - Android-Shirt Back to index
anddev.org Header Logo
FAQ Search Top rated articles Browse Feeds anddev.org - Authors Contact Details Register Log in

The Pizza Timer - Threading/Drawing on Canvas

Goto page 1, 2, 3  Next
 
       anddev.org - Android Development Community | Android Tutorials | Index -> Advanced Tutorials
Author Message
plusminus
Site Admin
Site Admin


Joined: 14 Nov 2007
Posts: 2660
Location: College Park, MD

PostPosted: Wed Nov 28, 2007 2:51 am    Post subject: The Pizza Timer - Threading/Drawing on Canvas Reply with quote

The Timer - Threading/Drawing on Canvas


What is this: Having determined a huge market niche I decided to make the Pizza-Timer Killer-Application every one (or man) needs to survive Exclamation

What this tutorial includes:
  • Drawing on canvas'. Especially and Text.
  • Threading (continuously update the GUI/PizzaCountdown)
  • Correct Updating of the GUI/Views using a Handler
  • Notifications

See also: ListActivity - Functionality

Question Problems/Questions: post right below...

Difficulty: 2 of 5

What it will look like:
(During Cuntdown)


(Cuntdown Finished)


(Notification even when PizzaTimer was 'sent to background' (,BUT not yet killed Exclamation)


Description:
To accomplish our goal of creating the PizzaTimer we have to do the following things:
  • Design our own Pizza-View, that has a pizza-picture as background and can draw Arcs and the time on its canvas.
  • Creare a Timer-Thread, that 'ticks' every second.
  • Update the PizzaView at every tick of the Timer-Thread
  • Do some start/stop/settings stuff


0:So lets start with the PizzaView which is capable of displaying a Pizza as it background and do some painting on itself (its canvas).

At first, we set up the class-fields of PizzaView.java. Two int-values, one that takes the time, already passed and the other one takes the total time until the pizza is ready to be defeated Rolling Eyes . We also create various Paints at the beginning, so we do not have to switch the colors/thickness always later on.
Java:
     // The arc-line will be really thick Exclamation
     protected final int ARCSTROKEWIDTH = 20;

     // Set startup-values
     protected int mySecondsPassed = 0;
     protected int mySecondsTotal = 0;
     
     // Our Paint-ing-Device (Pen/Pencil/Brush/Whatever...)
     protected final Paint myArcSecondPaint = new Paint();
     protected final Paint myArcMinutePaint = new Paint();
     protected final Paint myCountDownTextPaint = new Paint();
     protected final Paint myPizzaTimeTextPaint = new Paint();


1: The Constructor - does nothing, except setting its the background and setting up the Paint's.
Java:
     // ===========================================================
     // Constructors
     // ===========================================================
     public PizzaView(Context context) {
          super(context);
          this.setBackground(getResources().getDrawable(R.drawable.pizza));
          
          // Black text for the countdown
          this.myCountDownTextPaint.setARGB(150, 0, 0, 0);
          this.myCountDownTextPaint.setTextSize(110);
          this.myCountDownTextPaint.setFakeBoldText(true);
          
          // Orange text for the IT PIZZA TIME
          this.myPizzaTimeTextPaint.setARGB(255, 255, 60, 10);
          this.myPizzaTimeTextPaint.setTextSize(110);
          this.myPizzaTimeTextPaint.setFakeBoldText(true);
          
          // Our arc fill be a lookthrough-red.
          this.myArcMinutePaint.setARGB(150, 170, 0, 0);
          this.myArcMinutePaint.setAntiAlias(true);
          this.myArcMinutePaint.setStyle(Style.STROKE);
          this.myArcMinutePaint.setStrokeWidth(ARCSTROKEWIDTH);
          
          this.myArcSecondPaint.setARGB(200, 255, 130, 20);
          this.myArcSecondPaint.setAntiAlias(true);
          this.myArcSecondPaint.setStyle(Style.STROKE);
          this.myArcSecondPaint.setStrokeWidth(ARCSTROKEWIDTH / 3);
     }


2:
We also create two setters for the mySecondsXYZ-fields, to modify them during runtime.
Java:
     // ===========================================================
     // Getter & Setter
     // ===========================================================
     
     public void updateSecondsPassed(int someSeconds){
          this.mySecondsPassed = someSeconds;
     }
     
     public void updateSecondsTotal(int totalSeconds){
          this.mySecondsTotal = totalSeconds;
     }

3:The last thing to do in our PizzaView.java is obviously the onDraw(...)-Method, as we want to display a count-down. This is basically just some maths, like determining the percentage done and calculating that value against the 360°. It is basically like any ordinary analog clock. We also put the number of the minutes (if timeleft >= 60) or the seconds remaining (if timeleft < 60) to the middle of the screen.
Java:
     @Override
     protected void onDraw(Canvas canvas) {
          /* Calculate the time left,
           * until our pizza is finished. */

          int secondsLeft = this.mySecondsTotal - this.mySecondsPassed;
          
          // Check if pizza is already done
          if(secondsLeft <= 0){
               /* Draw the "! PIZZA !"-String
                *  to the middle of the screen */

               String itIsPizzaTime = getResources().getString(
                              R.string.pizza_countdown_end);
               canvas.drawText(itIsPizzaTime,
                                        10, (this.getHeight() / 2) + 30,
                                        this.myPizzaTimeTextPaint);             
          }else{
               // At least one second left
               float angleAmountMinutes = ((this.mySecondsPassed * 1.0f)
                                                       / this.mySecondsTotal)
                                                       * 360;
               float angleAmountSeconds = ((60 -secondsLeft % 60) * 1.0f)
                                                       / 60
                                                       * 360;
     
               /* Calculate an Rectangle,
                * with some spacing to the edges */

               RectF arcRect = new RectF(ARCSTROKEWIDTH / 2,
                                        ARCSTROKEWIDTH / 2,
                                        this.getWidth() - ARCSTROKEWIDTH / 2,
                                        this.getHeight() - ARCSTROKEWIDTH / 2);

               // Draw the Minutes-Arc  into that rectangle      
               canvas.drawArc(arcRect, -90, angleAmountMinutes,
                                                       this.myArcMinutePaint);
               
               // Draw the Seconds-Arc  into that rectangle 
               canvas.drawArc(arcRect, -90, angleAmountSeconds,
                                                       this.myArcSecondPaint);
               
               String timeDisplayString;
               if(secondsLeft > 60) // Show minutes
                    timeDisplayString = "" + (secondsLeft / 60);
               else // Show seconds when less than a minute
                    timeDisplayString = "" + secondsLeft;
               
               // Draw the remaining time.
               canvas.drawText(timeDisplayString,
                         this.getWidth() / 2 - (30 * timeDisplayString.length()),
                         this.getHeight()/ 2 + 30,
                         this.myCountDownTextPaint);
          }
     }

The PizzaView.java is now completed Exclamation
4:Lets get into the "time-managment logic" in the file "PizzaTimer.java".

Clearly the GUI needs to be update constantly(every second), as we want to see the time tick down Exclamation
The way this done is not that ... "self understanding". I'll explain it a bit first and then everything should become clear with the picture below Exclamation
Idea The "problem" is, that for security reasons, only the Thread that created the View is allowed to do sth. with it, like redrawing it with an invalidate();-call. So we need an Object 'in' the GUI-Thread that receives messages that mean like: "Hey 'Main-Thread' update your gui!". We will use a so called Handler for that.

  • There will be a Thread, that sends a message that means "UPDATEYOURGUI" to the Handler.
  • In the GUI-Thread, when the Handler receives the Message("UPDATEYOURGUI") it causes an invalidate(); to all participating Views.


Arrow If this is still not clear, feel free to ask your question Exclamation


5: Our actual PizzaTimer-Application does not contain much more than the things in the Picture Exclamation

Lets first take a look at all the fields of PizzaTimer.java:
Java:
     protected static final int DEFAULTSECONDS = 60 * 12;  // 12 MInutes
     /* The value of these IDs is random!
      * they are just needed to be recognized */

     protected static final int SECONDPASSEDIDENTIFIER = 0x1337;
     protected static final int GUIUPDATEIDENTIFIER = 0x101;
     protected static final int PIZZA_NOTIFICATION_ID = 0x1991;
     
     /** is the countdown running at the moment ?*/
     protected boolean running = false;
     /** Seconds passed so far */
     protected int mySecondsPassed = 0;
     /** Seconds to be passed totally */
     protected int mySecondsTotal = DEFAULTSECONDS;
     
     /* Thread that sends a message
      * to the handler every second */

     Thread myRefreshThread = null;
     // One View is all that we see.
     PizzaView myPizzaView = null;


6: As mentioned above, we need the Handler-Object (which is also a field of our PizzaTimer.java) :

Java:
     /* The Handler that receives the messages
      * sent out by myRefreshThread every second */

     Handler myPizzaViewUpdateHandler = new Handler(){
          /** Gets called on every message that is received */
          // @Override
          public void handleMessage(Message msg) {
               switch (msg.what) {
                    case PizzaTimer.SECONDPASSEDIDENTIFIER:
                         // We identified the Message by its What-ID
                         if (running) {
                              // One second has passed
                              mySecondsPassed++;
                              if(mySecondsPassed == mySecondsTotal){
                              // Time is finished, lets display a notification!
                               // Get the notification manager serivce.
                               NotificationManager nm = (NotificationManager)
                                       getSystemService(NOTIFICATION_SERVICE);

                               /* The id we use here happens to be the
                                * id of the text we display. You can use
                                * any int here that is unique within
                                * your application. */

                               nm.notifyWithText(PIZZA_NOTIFICATION_ID,
                                       getText(R.string.pizza_notification_text),
                                       NotificationManager.LENGTH_LONG, null);
                              }
                         }
                         // No break here --> runs into the next case
                    case PizzaTimer.GUIUPDATEIDENTIFIER:
                         // Redraw our Pizza !!
                         myPizzaView.updateSecondsPassed(mySecondsPassed);
                         myPizzaView.updateSecondsTotal(mySecondsTotal);
                         myPizzaView.invalidate();
                         break;
               }
               super.handleMessage(msg);
          }
     };


7: Lets take a look at the onCreate-Activity.
It creates a new PizzaView and registers it as what we want to see.
It also creates a new Thread (secondCountDownRunner), that will send a message to the Handler we created above.
Java:
   /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
               
        this.myPizzaView = new PizzaView(this);
        this.myPizzaView.updateSecondsTotal(PizzaTimer.DEFAULTSECONDS);
        setContentView(this.myPizzaView);
       
        this.myRefreshThread = new Thread(new secondCountDownRunner());
        this.myRefreshThread.start();
    }


8: The Runnable we used to create this.myRefreshThread:
Java:
     class secondCountDownRunner implements Runnable{
          // @Override
          public void run() {
               while(!Thread.currentThread().isInterrupted()){
                    Message m = new Message();
                    m.what = PizzaTimer.SECONDPASSEDIDENTIFIER;
                    PizzaTimer.this.myPizzaViewUpdateHandler.sendMessage(m);
                    try {
                         Thread.sleep(1000);
                    } catch (InterruptedException e) {
                         Thread.currentThread().interrupt();
                    }
               }
          }
    }


9: And thats it, what is left are only a small menu, to reset the counter and the reactions on some Buttons (here the whole KeyPad):
9.1: The menu:
Java:
   @Override
     public boolean onCreateOptionsMenu(Menu menu) {
          menu.add(0,0,getResources().getString(R.string.menu_reset));
          return super.onCreateOptionsMenu(menu);
     }

     @Override
     public boolean onMenuItemSelected(int featureId, Item item) {
          switch(item.getId()){
               case 0:
                    // Reset the counter and stop it
                    this.mySecondsTotal = PizzaTimer.DEFAULTSECONDS;
                    this.mySecondsPassed = 0;
                    this.running = false;
                    return true;
          }
          return super.onMenuItemSelected(featureId, item);
     }

9.2: ...and the KeyPad-Reactions:
Java:
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
          Message m = new Message();
          m.what = PizzaTimer.GUIUPDATEIDENTIFIER;
          
          switch(keyCode){
               case KeyEvent.KEYCODE_DPAD_UP:
                    this.mySecondsTotal += 60; // One minute later
                    break;
               case KeyEvent.KEYCODE_DPAD_DOWN:
                    this.mySecondsTotal -= 60; // One minute earlier
                    break;
               case KeyEvent.KEYCODE_DPAD_CENTER:
                    this.running = !this.running; // START / PAUSE
                    break;
               case KeyEvent.KEYCODE_DPAD_LEFT:
                    this.mySecondsTotal += 1; // One second later
                    break;
               case KeyEvent.KEYCODE_DPAD_RIGHT:
                    this.mySecondsTotal -= 1; // One second earlier
                    break;
               default:
                    return super.onKeyDown(keyCode, event);
          }
          
          this.myPizzaViewUpdateHandler.sendMessage(m);
          return true;
     }


So thats it, we are done Exclamation

The Full Source:
Download the background-pizza "/res/drawable"
Arrow Download

"/src/your_package_structure/PizzaTimer.java"
Java:
package org.anddev.android.pizzatimer;

import android.app.Activity;
import android.app.NotificationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.Menu.Item;

public class PizzaTimer extends Activity {

     protected static final int DEFAULTSECONDS = 60 * 12;  // 12 MInutes
     /* The value of these IDs is random!
      * they are just needed to be recognized */

     protected static final int SECONDPASSEDIDENTIFIER = 0x1337;
     protected static final int GUIUPDATEIDENTIFIER = 0x101;
     protected static final int PIZZA_NOTIFICATION_ID = 0x1991;
     
     /** is the countdown running at the moment ?*/
     protected boolean running = false;
     /** Seconds passed so far */
     protected int mySecondsPassed = 0;
     /** Seconds to be passed totally */
     protected int mySecondsTotal = DEFAULTSECONDS;
     
     /* Thread that sends a message
      * to the handler every second */

     Thread myRefreshThread = null;
     // One View is all that we see.
     PizzaView myPizzaView = null;
     
     /* The Handler that receives the messages
      * sent out by myRefreshThread every second */

     Handler myPizzaViewUpdateHandler = new Handler(){
          /** Gets called on every message that is received */
          // @Override
          public void handleMessage(Message msg) {
               switch (msg.what) {
                    case PizzaTimer.SECONDPASSEDIDENTIFIER:
                         // We identified the Message by its What-ID
                         if (running) {
                              // One second has passed
                              mySecondsPassed++;
                              if(mySecondsPassed == mySecondsTotal){
                                   // Time is finished, lets display a notification!
                               // Get the notification manager serivce.
                               NotificationManager nm = (NotificationManager)
                                       getSystemService(NOTIFICATION_SERVICE);

                               /* The id we use here happens to be the
                                * id of the text we display. You can use
                                * any int here that is unique within
                                * your application. */

                               nm.notifyWithText(PIZZA_NOTIFICATION_ID,
                                       getText(R.string.pizza_notification_text),
                                       NotificationManager.LENGTH_LONG, null);
                              }
                         }
                         // No break here --> runs into the next case
                    case PizzaTimer.GUIUPDATEIDENTIFIER:
                         // Redraw our Pizza !!
                         myPizzaView.updateSecondsPassed(mySecondsPassed);
                         myPizzaView.updateSecondsTotal(mySecondsTotal);
                         myPizzaView.invalidate();
                         break;
               }
               super.handleMessage(msg);
          }
     };
     
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
               
        this.myPizzaView = new PizzaView(this);
        this.myPizzaView.updateSecondsTotal(PizzaTimer.DEFAULTSECONDS);
        setContentView(this.myPizzaView);
       
        this.myRefreshThread = new Thread(new secondCountDownRunner());
        this.myRefreshThread.start();
    }
   
    @Override
     public boolean onCreateOptionsMenu(Menu menu) {
          menu.add(0,0,getResources().getString(R.string.menu_reset));
          return super.onCreateOptionsMenu(menu);
     }

     @Override
     public boolean onMenuItemSelected(int featureId, Item item) {
          switch(item.getId()){
               case 0:
                    // Reset the counter and stop it
                    this.mySecondsTotal = PizzaTimer.DEFAULTSECONDS;
                    this.mySecondsPassed = 0;
                    this.running = false;
                    return true;
          }
          return super.onMenuItemSelected(featureId, item);
     }

     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
          Message m = new Message();
          m.what = PizzaTimer.GUIUPDATEIDENTIFIER;
          
          switch(keyCode){
               case KeyEvent.KEYCODE_DPAD_UP:
                    this.mySecondsTotal += 60; // One minute later
                    break;
               case KeyEvent.KEYCODE_DPAD_DOWN:
                    this.mySecondsTotal -= 60; // One minute earlier
                    break;
               case KeyEvent.KEYCODE_DPAD_CENTER:
                    this.running = !this.running; // START / PAUSE
                    break;
               case KeyEvent.KEYCODE_DPAD_LEFT:
                    this.mySecondsTotal += 1; // One second later
                    break;
               case KeyEvent.KEYCODE_DPAD_RIGHT:
                    this.mySecondsTotal -= 1; // One second earlier
                    break;
               default:
                    return super.onKeyDown(keyCode, event);
          }
          
          this.myPizzaViewUpdateHandler.sendMessage(m);
          return true;
     }
   
     class secondCountDownRunner implements Runnable{
          // @Override
          public void run() {
               while(!Thread.currentThread().isInterrupted()){
                    Message m = new Message();
                    m.what = PizzaTimer.SECONDPASSEDIDENTIFIER;
                    PizzaTimer.this.myPizzaViewUpdateHandler.sendMessage(m);
                    try {
                         Thread.sleep(1000);
                    } catch (InterruptedException e) {
                         Thread.currentThread().interrupt();
                    }
               }
          }
    }
}



"/src/your_package_structure/PizzaView.java"
Java:
// Created by plusminus on 23:08:24 - 27.11.2007
package org.anddev.android.pizzatimer;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Paint.Style;
import android.view.View;


public class PizzaView extends View{
     // ===========================================================
     // Fields
     // ===========================================================
     
     protected final int ARCSTROKEWIDTH = 20;
     
     // Set startup-values
     protected int mySecondsPassed = 0;
     protected int mySecondsTotal = 0;
     
     // Our Painting-Device (Pen/Pencil/Brush/Whatever...)
     protected final Paint myArcSecondPaint = new Paint();
     protected final Paint myArcMinutePaint = new Paint();
     protected final Paint myCountDownTextPaint = new Paint();
     protected final Paint myPizzaTimeTextPaint = new Paint();

     // ===========================================================
     // Constructors
     // ===========================================================

     public PizzaView(Context context) {
          super(context);
          this.setBackground(getResources().getDrawable(R.drawable.pizza));
          
          // Black text for the countdown
          this.myCountDownTextPaint.setARGB(150, 0, 0, 0);
          this.myCountDownTextPaint.setTextSize(110);
          this.myCountDownTextPaint.setFakeBoldText(true);
          
          // Orange text for the IT PIZZA TIME
          this.myPizzaTimeTextPaint.setARGB(255, 255, 60, 10);
          this.myPizzaTimeTextPaint.setTextSize(110);
          this.myPizzaTimeTextPaint.setFakeBoldText(true);
          
          // Our minute-arc-paint fill be a lookthrough-red.
          this.myArcMinutePaint.setARGB(150, 170, 0, 0);
          this.myArcMinutePaint.setAntiAlias(true);
          this.myArcMinutePaint.setStyle(Style.STROKE);
          this.myArcMinutePaint.setStrokeWidth(ARCSTROKEWIDTH);

          // Our minute-arc-paint fill be a less lookthrough-orange.
          this.myArcSecondPaint.setARGB(200, 255, 130, 20);
          this.myArcSecondPaint.setAntiAlias(true);
          this.myArcSecondPaint.setStyle(Style.STROKE);
          this.myArcSecondPaint.setStrokeWidth(ARCSTROKEWIDTH / 3);
     }
     
     // ===========================================================
     // onXYZ(...) - Methods
     // ===========================================================
     
     @Override
     protected void onDraw(Canvas canvas) {
          /* Calculate the time left,
           * until our pizza is finished. */

          int secondsLeft = this.mySecondsTotal - this.mySecondsPassed;
          
          // Check if pizza is already done
          if(secondsLeft <= 0){
               /* Draw the "! PIZZA !"-String
                *  to the middle of the screen */

               String itIsPizzaTime = getResources().getString(
                              R.string.pizza_countdown_end);
               canvas.drawText(itIsPizzaTime,
                                        10, (this.getHeight() / 2) + 30,
                                        this.myPizzaTimeTextPaint);             
          }else{
               // At least one second left
               float angleAmountMinutes = ((this.mySecondsPassed * 1.0f)
                                                       / this.mySecondsTotal)
                                                       * 360;
               float angleAmountSeconds = ((60 -secondsLeft % 60) * 1.0f)
                                                       / 60
                                                       * 360;
     
               /* Calculate an Rectangle,
                * with some spacing to the edges */

               RectF arcRect = new RectF(ARCSTROKEWIDTH / 2,
                                        ARCSTROKEWIDTH / 2,
                                        this.getWidth() - ARCSTROKEWIDTH / 2,
                                        this.getHeight() - ARCSTROKEWIDTH / 2);

               // Draw the Minutes-Arc  into that rectangle      
               canvas.drawArc(arcRect, -90, angleAmountMinutes,
                                                       this.myArcMinutePaint);
               
               // Draw the Seconds-Arc  into that rectangle 
               canvas.drawArc(arcRect, -90, angleAmountSeconds,
                                                       this.myArcSecondPaint);
               
               String timeDisplayString;
               if(secondsLeft > 60) // Show minutes
                    timeDisplayString = "" + (secondsLeft / 60);
               else // Show seconds when less than a minute
                    timeDisplayString = "" + secondsLeft;
               
               // Draw the remaining time.
               canvas.drawText(timeDisplayString,
                         this.getWidth() / 2 - (30 * timeDisplayString.length()),
                         this.getHeight()/ 2 + 30,
                         this.myCountDownTextPaint);
          }
     }
     // ===========================================================
     // Getter & Setter
     // ===========================================================
     
     public void updateSecondsPassed(int someSeconds){
          this.mySecondsPassed = someSeconds;
     }
     
     public void updateSecondsTotal(int totalSeconds){
          this.mySecondsTotal = totalSeconds;
     }
}


Feel free to ask any question that comes to your mind Exclamation

Regards,
plusminus

_________________
Download my apps Idea
Please remember, that this board is give & take Smile


| Android Development Community / Tutorials


Last edited by plusminus on Tue Jan 08, 2008 3:14 pm; edited 8 times in total
Back to top
View user's profile Send private message Send e-mail Visit poster's website
rtreffer
Junior Developer
Junior Developer


Joined: 23 Nov 2007
Posts: 15

PostPosted: Wed Nov 28, 2007 11:57 pm    Post subject: Reply with quote

Typo, "It's pizza time".
Paint supports alignment - Paint.Align.RIGHT - which might make your app easier to understand and better to read Smile

Code:
      lenPaint.setTextSize(10);
      lenPaint.setAntiAlias(true);
      lenPaint.setColor(Color.WHITE);
      lenPaint.setTextAlign(Paint.Align.RIGHT);


Anyway, great tutorial Smile

_________________
root@localhost# : ( ) { : | : & } ; :
Back to top
View user's profile Send private message
lemonhead
Junior Developer
Junior Developer


Joined: 15 Nov 2007
Posts: 11
Location: Brazil (temporarily)

PostPosted: Tue Dec 04, 2007 9:58 am    Post subject: Reply with quote

i like pizza! Very Happy

but, when the day comes when u make a tutorial with 5 stars difficulty i will give away free beer! Surprised
Back to top
View user's profile Send private message
plusminus
Site Admin
Site Admin


Joined: 14 Nov 2007
Posts: 2660
Location: College Park, MD

PostPosted: Tue Dec 04, 2007 3:26 pm    Post subject: Reply with quote

Laughing it's pretty hard to say how difficult the tutorials are ... Confused

If you'd like to get their rank 'adjusted' let me know =)
Btw: it is at least in the Advanced Section Wink

Regards,
plusminus

_________________
Download my apps Idea
Please remember, that this board is give & take Smile


| Android Development Community / Tutorials
Back to top
View user's profile Send private message Send e-mail Visit poster's website
evoc
Freshman
Freshman


Joined: 30 Nov 2007
Posts: 4

PostPosted: Tue Dec 04, 2007 9:29 pm    Post subject: Reply with quote

really nice application Smile
Back to top
View user's profile Send private message
polarbear
Junior Developer
Junior Developer


Joined: 03 Dec 2007
Posts: 14

PostPosted: Sat Dec 08, 2007 5:18 am    Post subject: Reply with quote

Thank you for all the great work. Anyway, I have a bunch errors on this particular tutorial and I'm stuck. Could you do what you did before by posting all the code following the format "/src/your_package_structure/PizzaView.java"? Thanks again.
Back to top
View user's profile Send private message
plusminus
Site Admin
Site Admin


Joined: 14 Nov 2007
Posts: 2660
Location: College Park, MD

PostPosted: Sat Dec 08, 2007 12:28 pm    Post subject: Reply with quote

Hello polarbear,

I appended the full sources.
Do you guys prefer the full sources written at the end of each tutorial or as an attachment Question Question Question

Regard,
plusminus

_________________
Download my apps Idea
Please remember, that this board is give & take Smile


| Android Development Community / Tutorials
Back to top
View user's profile Send private message Send e-mail Visit poster's website
venkat
Senior Developer
Senior Developer


Joined: 27 Nov 2007
Posts: 152
Location: India

PostPosted: Sat Dec 08, 2007 2:02 pm    Post subject: Reply with quote

Thank u very much..... Smile
Back to top
View user's profile Send private message
polarbear
Junior Developer
Junior Developer


Joined: 03 Dec 2007
Posts: 14

PostPosted: Sun Dec 09, 2007 5:01 pm    Post subject: Reply with quote

Hello Plusminus:

Thank you and, yes, to appending the source code. It makes the learning process easier
Back to top
View user's profile Send private message
jdl
Freshman
Freshman


Joined: 03 Jan 2008
Posts: 4
Location: USA

PostPosted: Thu Jan 03, 2008 1:02 am    Post subject: Yes, please include the full source of the tutorials Reply with quote

plusminus wrote:
Hello polarbear,

I appended the full sources.
Do you guys prefer the full sources written at the end of each tutorial or as an attachment Question Question Question

Regard,
plusminus


I prefer to download the full source as an attachment. The tutorials are very helpful!

Thanks,

jdl
Back to top
View user's profile Send private message Visit poster's website
jive
Freshman
Freshman


Joined: 08 Jan 2008
Posts: 3

PostPosted: Tue Jan 08, 2008 8:43 am    Post subject: hello Reply with quote

hello, thanks for this tutorial, very helpful.

but i have a problem, eclipse won't let me compile the source as you gave it, it has a problem on this line :
Java:

class secondCountDownRunner implements Runnable{
          @Override
          public void run() {              // <---- problem here
               while(!Thread.currentThread().isInterrupted()){
                    Message m = new Message();
                    m.what = PizzaTimer.SECONDPASSEDIDENTIFIER;
                    PizzaTimer.this.myPizzaViewUpdateHandler.sendMessage(m);
                    try {
                         Thread.sleep(1000);
                    } catch (InterruptedException e) {
                         Thread.currentThread().interrupt();
                    }
               }
          }
    }


says i must override a superclass method.

any idea what i am doing wrong ?

thanks
Back to top
View user's profile Send private message
venkat
Senior Developer
Senior Developer


Joined: 27 Nov 2007
Posts: 152
Location: India

PostPosted: Tue Jan 08, 2008 10:44 am    Post subject: Reply with quote

Hi jive ,
Can you remove the line @Override , Above Run method.

Regards,
Venkat.

_________________
Regards,
Venkat.
Back to top
View user's profile Send private message
plusminus
Site Admin
Site Admin


Joined: 14 Nov 2007
Posts: 2660
Location: College Park, MD

PostPosted: Tue Jan 08, 2008 3:12 pm    Post subject: Re: hello Reply with quote

Hello Jive,

as venkat answered, removing the @Override-Annotation is the solution to your problem.
This happens because the JDK 1.5, you are probably running, does accept @Override-Annotation only for overridden methods of Super-Classes and not for overriding functions of Interfaces we are implementing here.

On JDK 1.6 this Annotation is possible. Rolling Eyes

So this is a kind of style-issue.

Regards,
plusminus

Btw: Commented that @Override-Annotation away Smile

_________________
Download my apps Idea
Please remember, that this board is give & take Smile


| Android Development Community / Tutorials
Back to top
View user's profile Send private message Send e-mail Visit poster's website
StGabe
Once Poster
Once Poster


Joined: 17 Jan 2008
Posts: 1

PostPosted: Thu Jan 17, 2008 8:50 pm    Post subject: Re: The Pizza Timer - Threading/Drawing on Canvas Reply with quote

Using sleep(1000) as a timer isn't going to give you a very good guarantee of accuracy. That just means the thread will sleep for at least 1000ms but it could well be more and your clock will tend to be slow (depending on how well threads are serviced).

It would be far better to use the system clock (that's what it's there for). To do this you would have your thread regularly polling System.currentTimeMillis(). Also, I would put the thread in PizzaTimer and get rid of the (IMO) clunky message passing. It's less code, it provides a general event loop that could be extended with other features (i.e. an animation) and IMO it's cleaner.
Back to top
View user's profile Send private message
gustavo
Junior Developer
Junior Developer


Joined: 02 Mar 2008
Posts: 12

PostPosted: Wed Apr 02, 2008 3:05 am    Post subject: Re: The Pizza Timer - Threading/Drawing on Canvas Reply with quote

I donīt understand why the handleMessage sees
msg.what = MeuPizzaTimer.GUIUPDATEIDENTIFIER
as default?
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Display posts from previous:   
       anddev.org - Android Development Community | Android Tutorials | Index -> Advanced Tutorials All times are GMT + 1 Hour
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


© 2007, Android Development Community
All rights reserved.
Powered by phpBB.