Android music player development SweetMusicPlayer intelligently matches local lyrics, android player

Source: Internet
Author: User
Tags drawtext

Android music player development SweetMusicPlayer intelligently matches local lyrics, android player

In the previous article, I used MediaPlayer to play music. Well, use that image.


I. Match the lyrics from the memory card

Will match from the following path

1) SweetMusicPlayer/Lyrics/

2) under the same category of songs

3) Song parent directory/lryics)


LrcContent

Package com. huwei. sweetmusicplayer. models; public class LrcContent {private String lrcStr; // The lyrics are private int lrcTime; // The current lyrics are public String getLrcStr () {return lrcStr;} public void setLrcStr (String lrcStr) {this. lrcStr = lrcStr;} public int getLrcTime () {return lrcTime;} public void setLrcTime (int lrcTime) {this. lrcTime = lrcTime ;}}
LrcProcess

Package com. huwei. sweetmusicplayer. models; import java. io. bufferedReader; import java. io. file; import java. io. fileInputStream; import java. io. fileNotFoundException; import java. io. IOException; import java. io. inputStreamReader; import java. io. unsupportedEncodingException; import java. util. arrayList; import java. util. collections; import java. util. list; import android. util. log; import com. huwei. sweetmusicplayer. c Omparator. lrcComparator; import com. huwei. sweetmusicplayer. datamanager. musicManager; import com. huwei. sweetmusicplayer. util. onlineLrcUtil; import com. huwei. sweetmusicplayer. util. timeUtil; public class LrcProcess {private List <LrcContent> lrclists; public LrcProcess () {super (); lrclists = new ArrayList <LrcContent> (); lrclists. clear ();} public String loadLrc (Song song) {String path = song. getPath (); StringBu Ffer stringBuffer = new StringBuffer (); // obtain the lyrics file path String lrcPathString = path. substring (0, path. lastIndexOf (". ") + ". lrc "; int index = lrcPathString. lastIndexOf ("/"); String parentPath; String lrcName; // if (index! =-1) {parentPath = lrcPathString. substring (0, index); lrcName = lrcPathString. substring (index); //} File file = new File (lrcPathString); // match SweetMusicPlayer/Lyricsif (! File. exists () {file = new File (OnlineLrcUtil. getInstance (). getLrcPath (song. getTitle (), song. getArtist ();} Log. I ("Path", file. getAbsolutePath (). toString (); // match Lyricsif (! File. exists () {file = new File (parentPath + "/.. /"+" Lyrics/"+ lrcName);} Log. I ("Path", file. getAbsolutePath (). toString (); // match lyricif (! File. exists () {file = new File (parentPath + "/.. /"+" lyric/"+ lrcName);} Log. I ("Path", file. getAbsolutePath (). toString (); // match Lyricif (! File. exists () {file = new File (parentPath + "/.. /"+" Lyric/"+ lrcName);} Log. I ("Path", file. getAbsolutePath (). toString (); // match lyricsif (! File. exists () {file = new File (parentPath + "/.. /"+" lyrics/"+ lrcName);} Log. I ("Path", file. getAbsolutePath (). toString (); if (! File. exists () {stringBuffer. append (MusicManager. operateState. READLRCFILE_FAIL); return stringBuffer. toString () ;}try {FileInputStream fin = new FileInputStream (file); InputStreamReader isr = new InputStreamReader (fin, "UTF-8"); BufferedReader br = new BufferedReader (isr ); string s; boolean isLrc = false; while (s = br. readLine ())! = Null) {// if (isLrc) {s = s. replace ("[", ""); // remove the left bracket String lrcData [] = s. split ("]"); // The lyrics if (lrcData [0]. matches ("^ \ d {2 }:\\ d {2 }. \ d + $ ") {int len = lrcData. length; int end = lrcData [len-1]. matches ("^ \ d {2 }:\\ d {2 }. \ d + $ ")? Len: len-1; for (int I = 0; I <end; I ++) {LrcContent lrcContent = new LrcContent (); int lrcTime = TimeUtil. getLrcMillTime (lrcData [I]); lrcContent. setLrcTime (lrcTime); if (lrcData. length = end) lrcContent. setLrcStr (""); // blank line elselrcContent. setLrcStr (lrcData [len-1]); lrclists. add (lrcContent) ;}}// sort Collections by time. sort (lrclists, new LrcComparator (); if (lrclists. size () = 0) {stringBuffer. append (MusicManager. operateState. READLRC_LISTNULL);} else {stringBuffer. append (MusicManager. operateState. READLRC_SUCCESS) ;}} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke. printStackTrace (); // stringBuffer. append ("no lyrics file found");} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke. printStackTrace (); // stringBuffer. append ("unsupported encoding");} catch (IOException e) {// TODO Auto-generated catch blocke. printStackTrace (); // stringBuffer. append ("IO error");} return stringBuffer. toString () ;}public List <LrcContent> getLrclists () {return lrclists ;}}

2. Extract A Piece Of lyrics first

Ti: Quiet]
[Ar: Jay Chou]
[Al: fantasy]
[By: Midas]
[00:03. 16]
[00:04. 50] Jay Chou-quiet
[. 50] word: Jay Chou Qu: Jay Chou: Zhong xingmin
[00: 25. 17]
[. 48] [. 02] only the piano left for me to talk for a day.
[. 76] [. 51] sleeping cello quiet old
[. 60] [. 67]
[. 74] [. 48]
[. 04] [. 7] I understand and know that you are not reluctant
[. 23] [. 53]
[. 04] [. 76] You said you would be sad, too. I don't believe it.
[. 59] [. 36] with you, I was just
[. 63] [. 24] I hope he really loves you more than I do.
[. 29] [. 96] I will force myself to leave


To traverse a row, replace "[" with "" to match the time part. The regular expression matches "^ \ d {2 }:\\ d {2 }. \ d + $ ", then split ("] ") to get an array of data [], the last one is the content, followed by the lyrics, traversing the array, loading the time lyrics to the list.


Time Processing: converted to milliseconds


After traversing all rows, sort the list by time.


The code is above LrcProgress.

3. The LrcView control is divided into the following states:

Public static String READLRC_SUCCESS = "READLRC_SUCCESS"; // The local lyrics are successfully read.
Public static String READLRC_LISTNULL = "READLRC_LISTNULL"; // The list of read lyrics is null.
Public static String READLRC_ONLINE = "READLRC_ONLINE"; // loading the lyrics from the network
Public static String READLRCFILE_FAIL = "READLRCFILE_FAIL"; // An error occurred while reading the lyrics file.
Public static String READLRCONLINE_FAIL = "READLRCONLINE_FAIL"; // An error occurred while loading the lyrics from the network.


Draw different content based on different states.

LrcView inherits from ScrollView, and adds a LinearLayout layer. The lyrics are drawn on TextView. By scrolling by playback time, you can ensure that the current playback lyrics are in the middle of the screen.

For custom controls, pay attention to understanding onMeasure (), onLayout (), and onDraw (). Sometimes onDraw () cannot be executed. Remember to add setWillNotDraw (false ), it is directly inherited from ScrollView, so you do not need to consider that much.


Here, you need to calculate the current playback position and the line of the lyrics based on the playback time. Then, you can update the lyrics page when different times are involved.



Adjust the lyrics progress:

When you touch the listener, ACTION_MOVE will draw the lyrics progress Preview (including the time to be adjusted), and ACTION_UP will be adjusted to the corresponding progress.



Package com. huwei. sweetmusicplayer. ui. widgets; import java. util. list; import com. huwei. sweetmusicplayer. datamanager. musicManager; import com. huwei. sweetmusicplayer. models. lrcContent; import com. huwei. sweetmusicplayer. util. timeUtil; import android. content. context; import android. content. intent; import android. graphics. canvas; import android. graphics. color; import android. graphics. paint; import android. graph Ics. typeface; import android. OS. handler; import android. OS. message; import android. util. attributeSet; import android. util. log; import android. view. motionEvent; import android. view. view; import android. view. viewTreeObserver. onScrollChangedListener; import android. widget. scrollView; import android. widget. textView; import android. view. view. onTouchListener; public class LrcView extends ScrollView implements OnSc RollChangedListener, OnTouchListener {private float width; // private float height of the lyrics view; // private Paint currentPaint of the lyrics view height; // private Paint notCurrentPaint of the current Paint object; // non-current paint brush object private final float textHeight = 40; // text height private final float textSize = 36; // highlight text size private final float notTextSize = 30; // private int index of non-highlighted text; // subscripts of the lyrics list set private String lrcState; private LrcTextView lrcTextView; private List <LrcContent> LrcLists; private int scrollY; private boolean canDrawLine = false; private int pos =-1; // private Paint linePaint; private boolean canTouchLrc = false; // can I touch and adjust the lyrics private int count = 0; // draw the number of times of loading points private Context mContext; public LrcView (Context context) {this (context, null ); // TODO Auto-generated constructor stub} public LrcView (Context context, AttributeSet attrs) {this (context, attrs, 0); // Todd O Auto-generated constructor stub} public LrcView (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); // TODO Auto-generated constructor stubmContext = context; this. setOnTouchListener (this); init ();} public List <LrcContent> getLrcLists () {return lrcLists;} public void setLrcLists (List <LrcContent> lrcLists) {this. lrcLists = lrcLists; // determines whether the lyrics interface can touch if (lrcLists = null | lrcLi Sts. size () = 0) canTouchLrc = false; else canTouchLrc = true; // SET index =-1this. index =-1; LayoutParams params1 = new LayoutParams (LayoutParams. MATCH_PARENT, LayoutParams. MATCH_PARENT); lrcTextView = new LrcTextView (this. getContext (); lrcTextView. setLayoutParams (params1); this. removeAllViews (); this. addView (lrcTextView);} public int getIndex () {return index;} public void setIndex (int index) {// The Position of the song changes, and the finger does not adjust the position of the lyrics Status if (this. index! = Index & pos =-1) {this. scrollTo (0, (int) (index * textHeight);} this. index = index ;}@ Overrideprotected void onSizeChanged (int w, int h, int oldw, int oldh) {// TODO Auto-generated method stubsuper. onSizeChanged (w, h, oldw, oldh); this. width = w; this. height = h;} public int getIndexByLrcTime (int currentTime) {for (int I = 0; I <lrcLists. size (); I ++) {if (currentTime <lrcLists. get (I ). getLrcTime () {return I-1 ;}} return l RcLists. size ()-1;} public void clear () {lrcLists = null;} public String getLrcState () {return lrcState;} public void setLrcState (String lrcState) {this. lrcState = lrcState; this. invalidate ();} class LrcTextView extends TextView {public LrcTextView (Context context) {this (context, null); // TODO Auto-generated constructor stub} public LrcTextView (Context context, attributeSet attrs) {this (context, attrs, 0 );// TODO Auto-generated constructor stub} public LrcTextView (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); // TODO Auto-generated constructor stubthis. setWillNotDraw (false);} // draw the lyrics @ Overrideprotected void onDraw (Canvas canvas) {// TODO Auto-generated method stubsuper. onDraw (canvas); Log. I ("LrcTextView onDraw", "LrcTextView onDraw"); if (canvas = null) return; int tempY = (Int) height/2; if (MusicManager. operateState. READLRC_LISTNULL.equals (lrcState) {canvas. drawText ("the lyrics are empty", width/2, tempY, notCurrentPaint); return;} else if (MusicManager. operateState. READLRCFILE_FAIL.equals (lrcState) {canvas. drawText ("no lyrics file found", width/2, tempY, notCurrentPaint); return;} else if (MusicManager. operateState. READLRC_SUCCESS.equals (lrcState) {// draw the lyrics for (int I = 0; I <lrcLists. size (); I ++, TempY + = textHeight) {if (I = index) {canvas. drawText (lrcLists. get (I ). getLrcStr (), width/2, tempY, currentPaint);} else if (I = pos) {canvas. drawText (lrcLists. get (I ). getLrcStr (), width/2, tempY, linePaint);} else {canvas. drawText (lrcLists. get (I ). getLrcStr (), width/2, tempY, notCurrentPaint) ;}} return;} else if (MusicManager. operateState. READLRC_ONLINE.equals (lrcState) {String drawContentStr = "Online Matching lyrics "; For (int I = 0; I <count; I ++) {drawContentStr + = ". ";}count ++; if (count> = 6) count = 0; canvas. drawText (drawContentStr, width/2, tempY, notCurrentPaint); handler. sendEmptyMessageDelayed (1,500); return;} else if (MusicManager. operateState. READLRCONLINE_FAIL.equals (lrcState) {canvas. drawText ("failed to load lyrics from the network", width/2, tempY, notCurrentPaint); return ;}@ Overrideprotected void onMeasure (int widthMeasureSpec, I Nt heightMeasureSpec) {// TODO Auto-generated method stubsuper. onMeasure (widthMeasureSpec, heightMeasureSpec); heightMeasureSpec = (int) (height + textHeight * (lrcLists. size ()-1); setMeasuredDimension (widthMeasureSpec, heightMeasureSpec) ;};@ Overrideprotected void onDraw (Canvas canvas) {// TODO Auto-generated method stubsuper. onDraw (canvas); if (canDrawLine) {canvas. drawLine (0, scrollY + height/2, width, scr OllY + height/2, linePaint); canvas. drawText (TimeUtil. toTime (lrcLists. get (pos ). getLrcTime (), 42, scrollY + height/2-2, linePaint);} private void init () {setFocusable (true ); // set this control to have focus this. setWillNotDraw (false); // The highlighted lyrics section currentPaint = new Paint (); currentPaint. setAntiAlias (true); // you can specify the value of currentPaint. setTextAlign (Paint. align. CENTER); // set text CENTER // notCurrentPaint = new Paint (); notCurrentPaint for non-highlighted lyrics. setAntiAlias (t Rue); notCurrentPaint. setTextAlign (Paint. align. CENTER); // linePaint = new Paint (); linePaint. setAntiAlias (true); linePaint. setTextAlign (Paint. align. CENTER); // set the paint brush color currentPaint. setColor (Color. argb (210,251,248, 29); notCurrentPaint. setColor (Color. argb (140,255,255,255); linePaint. setColor (Color. RED); currentPaint. setTextSize (textSize); currentPaint. setTypeface (Typeface. SERIF); notCurrentPaint. setTe XtSize (notTextSize); notCurrentPaint. setTypeface (Typeface. DEFAULT); linePaint. setTextSize (textSize); linePaint. setTypeface (Typeface. SERIF) ;}@ Overridepublic void invalidate () {// TODO Auto-generated method stubsuper. invalidate (); lrcTextView. invalidate () ;}@ Overridepublic void onScrollChanged () {// TODO Auto-generated method stub} @ Overridepublic boolean onTouch (View v, MotionEvent event) {// TODO Auto-generated method stub // The interface cannot be touched if (! CanTouchLrc) return true; switch (event. getAction () {case MotionEvent. ACTION_MOVE: scrollY = this. getScrollY (); pos = (int) (this. getScrollY ()/textHeight); canDrawLine = true; this. invalidate (); Log. I ("LrcView", "ACTION_DOWN"); break; caseMotionEvent. ACTION_UP: MusicManager. getInstance (). setProgress (lrcLists. get (pos ). getLrcTime (); canDrawLine = false; pos =-1; this. invalidate (); break;} return false;} private Handler handler = new Handler () {@ Overridepublic void handleMessage (Message msg) {// TODO Auto-generated method stubinvalidate ();}};}


Next intelligent match online lyrics: http://blog.csdn.net/huweigoodboy/article/details/39878063



How can I match the lyrics to music exactly as the android codoy music player does?

Cool's lyrics match word by word because cool's lyrics have you ever used cool's lyrics? If you want to make the same one, I suggest you make a lyrics to understand it... Writing with only LRC will definitely affect the appearance even if you add some space or something. If you can write the algorithms in the program based on the cool dog's lyrics creation steps, you can write them well...


Which music player can display the local LRC lyrics?

Right-click and choose notepad to open... However, there will be a time display ....
 

Related Article

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.