简体   繁体   中英

Android - How To Run Multiple Timers In Background

I am currently building an app that plays music on a wifi speaker. The app can connect to multiple speakers, and each speaker plays different music.

Due to frequent loss in receiving the song playing progress sent by the speakers to the app, I have to run one timer for each speaker that is playing a music in order to keep track of the song progress continuously. So that every time I receive a song progress, I will just update the timer, and then the timer will start counting from the updated song progress.

This is the code that runs a timer.

public class SongTimer
{
     Timer mTimer;
     int count;
     long duration;
     int groupAddress;
     SongTimerListener listener;

     boolean timer;

     private Handler mHandler = new Handler();

     public interface SongTimerListener
     {
         public void onPositionCounted(int position);
         public void onFinishCounting();
     }

     public SongTimer(int position, long duration, int groupAddress, SongTimerListener listener)
     {
         this.listener = listener;
         this.count = position;
         this.duration = duration;
         this.groupAddress = groupAddress;

         timer = true;
     }

     public void startTimer() 
     {      
         mTimer = new Timer();
         mTimer.schedule(new TimerTask()
         {
             @Override  
             public void run()
             {
                 if (timer)
                 {
                    if(count<=(duration/1000))
                    {
                        mHandler.post(new Runnable()
                        {
                            public void run(){

                                if (DataHolder.PlayProgress.containsKey(DataHolder.tSpeaker.mAddress))
                                {
                                    long progress = DataHolder.PlayProgress.get(DataHolder.tSpeaker.mAddress);
                                    count=(int)progress;
                                }
                            }
                         });

                     }

                    else
                    {
                        mHandler.post(new Runnable()
                        {
                            public void run()
                            {
                                count = 0; 
                            }
                        });
                    }
                }

                else
                {
                    mHandler.post(new Runnable()
                    {
                        public void run()
                        {
                            mTimer.cancel();
                            mTimer = null;

                            if(SongTimer.this.listener != null)
                            {
                                SongTimer.this.listener.onFinishCounting();
                            }
                        }
                    });
                }

                count++;

                if(SongTimer.this.listener != null)
                {
                    SongTimer.this.listener.onPositionCounted(count);
                }
            }

         }, 1000, 1000);
    } 

    public void stopTimer()
    {
        timer = false;
        DataHolder.PlayProgress.put(this.groupAddress, (long)count);
    }
}

The user chooses a speaker and then one timer will be started when user plays a music with the speaker. When the user switches to another speaker and plays a song with it, a new timer will be started again. All the timers that were started will be stored in a HashMap using the groupAddress as the key for the object, timer.

When user taps pause, timer will be fetch from the HashMap and then terminate it, but the last position counted will be remembered.

When user taps resume time will be started again (new Timer()) and then starts counting from the last position stored.

Here comes the problem:

When multiple timers start to run, they work fine. But when the user taps pause, one timer will be fetch from the HashMap and then terminate it. But unfortunately all timers were terminated at the same time. I checked the Log for the object ID of the timers, they were all different. So I don't understand what is wrong here.

Please help. Many Thanks!

try this one

public class SongTimer{
 int count;
 long duration;
 int groupAddress;
 SongTimerListener listener;
 boolean timer,run;
 View user; //the view who this is going to be attached to

 public interface SongTimerListener {
     public void onPositionCounted(int position);
     public void onFinishCounting();
 }
 //your constructor
 public SongTimer(int position, long duration, int groupAddress,
           SongTimerListener listener, View viewToAttach){  //added new parameter
     this.listener = listener;
     this.count = position;
     this.duration = duration;
     this.groupAddress = groupAddress;
     timer = run = true;
     user = viewToAttach;
     new Thread(new Runnable() { // your timer 

        @Override
        public void run() {
            while(run){
              if(!timer)
                 continue;
               //now add your implementation here, (its too late here)
       //put your code that you already have here, but minor changes
       //if you need to call a Ui method use the user.post(runnable); it
       // the same as handler.post(runnable), also with this you have 
      // reference to your view to which you want to alter, so all you
      // to do is do what you want to do easily without actually needing
     // your interface call. and all Views that they rely on the music
     //mechanism that you talked about will each have an instance of this
    //class. your pausing mechanism has already being implemented so 
   //maintain your old pausing mechanism. Also if you are done and want 
   // totally stop the thread or kill this class set the boolean run 
   //variable to false.

        }
    }).start();
 }

hope it helps

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM