Android MP3 Player Development Example (3) progress bar and Lyrics update implementation

Source: Internet
Author: User
Tags message queue

The last time we talked about the realization of music playback, this time the most complicated progress bar and lyrics update. Because of the need to interact between the playing activity and the service being played, it involves the binding of the activity to the service and the transfer of the data after the binding, which needs to be familiar with the service bindings. The principle is not complicated, but the steps are a little cumbersome and the code may be confusing.

The progress bar and lyrics put together to say better, or more chaotic. Progress bar Adjustment We all know, is the progress of the tune to where the song play to follow where, lyrics also have to follow where. First look at the binding code of the service in the previous Read Start button listener event:

Bind Play Service Bindservice (intent, conn,bind_auto_create); The Runnable object joins the message queue, executes in the handler bound thread, and is used for the lyrics update handler.post (updatetimecallback); start = System.currenttimemillis ();
Bindservice (Intent, conn,bind_auto_create); In the conn is a callback interface after the binding service, let's look at the code:

/** * Callback interface in Bindservice () */serviceconnection  conn = new Serviceconnection () {@Overridepublic void Onserviceconnected (componentname arg0, IBinder binder) {//bind successfully after the method is called PlayActivity.this.binder = (binder) Binder;} @Overridepublic void onservicedisconnected (ComponentName arg0) {}};
is actually a statement, the function is to assign the IBinder object reference returned by the playback service to play the activity, so that the activity can get the data returned from the service, we are here to get the progress data played at this time.

Handler.post (updatetimecallback); is to add a Runnable object to the queue, the runnable object updatetimecallback

Is the core implementation code that implements the progress bar and the lyrics update, but before we look at this class, we'll look at the progress bar's listening events:

/** * After the test if the progress bar transfer before and after the merger into a way to achieve the lyrics of the update, the reason may be the synchronization of resources between different threads, had to be broken into * before the progress bar transfer (change = False) and after the transfer (change = = True) Two parts executed in the lyrics update thread * @author Yan * */class Seekbarlistener implements onseekbarchangelistener{  @Overridepublic void Onprogresschanged (SeekBar SeekBar, int progress, Boolean fromuser) {        } @Overridepublic void Onstarttrackingtouch ( SeekBar arg0) {log.d ("Yinan", "Start--------" +seekbar.getprogress ());} @Overridepublic void Onstoptrackingtouch (SeekBar arg0) {if (Stopmusic = = False) {change = true;//progress bar Progress artificially changed, Send the changed progress to the playback service Intent intent = new Intent () Intent.setclass (Playactivity.this, Playservice.class); Intent.putextra (" Progress ", seekbar.getprogress ()); StartService (intent);} Else{seekbar.setprogress (0);}}
after adjusting the position of the progress bar, StartService (intent) is still used to pass the intent object that encapsulates the progress bar to the service's Onstartcommand method.

Now let's take a look at the implementation of the core code runnable object updatetimecallback class:

/** * Asynchronously adjusts the progress bar position consistent with the song progress and displays the lyrics class * @author Yinan * */class Updatetimecallback implements runnable{queue times = null; Queue messages = null; arraylist<queue> queues = Null;public updatetimecallback (arraylist<queue> queues) {times = Queues.get (0); Messages = Queues.get (1); this.queues = queues;} /** * The Run method does not open a child thread because there is no bar with start, so the child thread is opened inside/@Overridepublic void run () {total = Playservice.totallength;if  true) {Parcel data = Parcel.obtain (); Parcel reply = Parcel.obtain ();d ata.writestring ("change"), try {binder.transact (0, data, reply, 0);} catch ( RemoteException e) {e.printstacktrace ();} This sentence is not executed until the service returns float s = reply.readfloat ();//s time for song playback float f = s*100;seekbar.setprogress ((int) f);//conversion to progress bar progress// At this point the corresponding playback time point is final long T = (long) (s*total);p REPARELRC (Mp3info.getlrcname ()); times = Queues.get (0); messages = Queues.get ( 1); System.out.println ("Times" +times.size ()); SYSTEM.OUT.PRINTLN ("Messages" +messages.size ()), if (Stopmusic = = False) {new Thread () {public void run () {while (nextTime < T) {//traverse the lyrics from the beginning, until the time queue is more than the current time System.out.println ("Nexttime" +nexttime);///////////////////////////////    lyric = message; if ((Times.size () >0) | |    Messages.size () >0) {nexttime = (Long) times.poll (); message = (String) messages.poll ();        }else{lyric = null;        Stopmusic = true; }//Save the time point just above the current time of the previous lyrics, that is closest to the current lyrics System.out.println ("Nexttime" +nexttime);}}. Start (); System.out.println ("lyric" +lyric); if (lyric! = null) {lrctext.settext (lyric);}}}   if (!change) {nowtime = System.currenttimemillis ()-start;seekbar.setprogress ((int) (nowtime*100/total)); if (Stopmusic = = False) {new Thread () {public void run () {while (Nexttime < nowtime) {//traverse the lyrics from the beginning, the time queue until the point of time is less than the current time System.ou    T.println ("Nexttime" +nexttime); Lyric = message;//Save point just above the previous lyrics of the current time, which is closest to the current lyrics if ((Times.size () >0) | |    Messages.size () >0) {nexttime = (Long) times.poll (); message = (String) messages.poll ();    }else{lyric = null;    Stopmusic = true; }}}}.start (); if (lyric! = null) {Lrctext.settext (Lyric);} }}if (Stopmusic = = True) {handler.removecallbacks (updatetimecallback);} Handler.postdelayed (Updatetimecallback, 200);//execute thread every 20 milliseconds}}
This code is roughly when you get the data for the real-time progress of the songs returned by the service, adjust the position of the progress bar to the corresponding child's processing, and then update the lyrics to the corresponding section. since the progress bar should be followed up in real time, allthe Run method of the Updatetimecallback class is executed every 200 milliseconds and gets the return value in the service.

Here is the situation where the processing is divided into the progress bar has been changed and not changed in two cases, with the flag bit change (once the progress bar has been changed on the implementation of the changes to true that section of code). Threads are opened because the processing of the lyrics is time-consuming and inappropriate for the UI thread.

The specific process is:

First, Parcel data = Parcel.obtain ();
Parcel reply = Parcel.obtain ();
Data.writestring ("Change");
Binder.transact (0, data, reply, 0);

Binder is the IBinder object that was previously bound to the service,binder.transact A Parcel object (incoming"Change" Just a sign) to the service, and then the service returns the song progress, received in float s = reply.readfloat (), S is a percentage of the current progress to the total progress, then set the progress bar position.

The lyrics update is then processed. The first is to prepare the lyrics for processing,PREPARELRC (Mp3info.getlrcname ()), the LRC format lyrics in the time and corresponding specific lyrics split into two queues. (see source code for specific codes) then traverse through the two queues based on the progress of the songs returned by the service. When there is a point in time that exceeds the time point of the schedule, the lyrics that correspond to that point of time are taken out and displayed on the activity.

The front always says that the service returns the song in real-time progress, and we look at the processing of the data return in the service.

When the progress bar is adjusted, it enters the service's Onstartcommand method and enters into the following if statement:

if (Intent.getintextra ("Progress", 0)! = 0) {///////////////////////if (isplay) {//progress bar Progress int progress = Intent.getintextra ("Progress", 0); if (progress! = 0)//Adjust the music progress to the corresponding position mediaplayer.seekto (progress*totallength/100);}}
How does the service return the progress of the song in real time? There is a binder class in the service, which is a subclass of IBinder:

/* * Execute binder.transact () after executing */class firstbinder extends binder{   @Overrideprotected boolean ontransact (int code, Parcel data, Parcel Reply,int flags) throws RemoteException {String str = data.readstring (); int currentposition = Mediapla Yer.getcurrentposition (); float s = (float) currentposition/mediaplayer.getduration (); if (Isplay) reply.writefloat (s) ; return Super.ontransact (Code, data, reply, flags);}    
Yes, it is the IBinder object that was obtained before the activity was bound to the service. whenever the activitybinder.transact (0, data, reply, 0); When invoked, the service invokes the Ontransact method, loads the obtained data into the parcel object reply, and then the entire The IBinder object returns activity.

MP3 player This is finished, may be very messy, I hope to help you, source code download Link: http://download.csdn.net/detail/sinat_23092639/8933995

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Android MP3 Player Development Example (3) progress bar and Lyrics update implementation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.