編輯:Android開發教程
我們需要讀取以上歌詞文件的每一行轉換成成一個個歌詞實體:
public class LyricObject { public int begintime; // 開始時間 public int endtime; // 結束時間 public int timeline; // 單句歌詞用時 public String lrc; // 單句歌詞 }
可根據當前播放器的播放進度與每句歌詞的開始時間,得到當前屏幕中央高亮顯示的那句歌詞。在 UI線程中另起線程,通過回調函數 onDraw() 每隔100ms重新繪制屏幕,實現歌詞平滑滾動的動畫效果。 MainActivity代碼如下:
import java.io.IOException; import android.app.Activity; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; public class MainActivity extends Activity { /** Called when the activity is first created. */ private LyricView lyricView; private MediaPlayer mediaPlayer; private Button button; private SeekBar seekBar; private String mp3Path; private int INTERVAL=45;//歌詞每行的間隔 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // this.requestWindowFeature(Window.FEATURE_NO_TITLE); // getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.main); mp3Path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/LyricSync/1.mp3"; lyricView = (LyricView) findViewById(R.id.mylrc); mediaPlayer = new MediaPlayer(); // this.requestWindowFeature(Window.FEATURE_NO_TITLE); ResetMusic(mp3Path); SerchLrc(); lyricView.SetTextSize(); button = (Button) findViewById(R.id.button); button.setText("播放"); seekBar = (SeekBar) findViewById(R.id.seekbarmusic); seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // TODO Auto-generated method stub if (fromUser) { mediaPlayer.seekTo(progress); lyricView.setOffsetY(220 - lyricView.SelectIndex(progress) * (lyricView.getSIZEWORD() + INTERVAL-1)); } } }); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub if (mediaPlayer.isPlaying()) { button.setText("播放"); mediaPlayer.pause(); } else { button.setText("暫停"); mediaPlayer.start(); lyricView.setOffsetY(220 - lyricView.SelectIndex(mediaPlayer.getCurrentPosition()) * (lyricView.getSIZEWORD() + INTERVAL-1)); } } }); mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { ResetMusic(mp3Path); lyricView.SetTextSize(); lyricView.setOffsetY(200); mediaPlayer.start(); } }); seekBar.setMax(mediaPlayer.getDuration()); new Thread(new runable()).start(); } public void SerchLrc() { String lrc = mp3Path; lrc = lrc.substring(0, lrc.length() - 4).trim() + ".lrc".trim(); LyricView.read(lrc); lyricView.SetTextSize(); lyricView.setOffsetY(350); } public void ResetMusic(String path) { mediaPlayer.reset(); try { mediaPlayer.setDataSource(mp3Path); mediaPlayer.prepare(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } class runable implements Runnable { @Override public void run() { // TODO Auto-generated method stub while (true) { try { Thread.sleep(100); if (mediaPlayer.isPlaying()) { lyricView.setOffsetY(lyricView.getOffsetY() - lyricView.SpeedLrc()); lyricView.SelectIndex(mediaPlayer.getCurrentPosition()); seekBar.setProgress(mediaPlayer.getCurrentPosition()); mHandler.post(mUpdateResults); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } Handler mHandler = new Handler(); Runnable mUpdateResults = new Runnable() { public void run() { lyricView.invalidate(); // 更新視圖 } }; }
上節openfire服務器已經搭建完成,這節看看,怎麼使用smack基於xmpp協議登錄openfire服務器,在服務器中創建好測試的賬號下面看android客戶端的代碼
一 相關下載(1) java JDK下載:進入該網頁: http://java.sun.com/javase/downloads/index.jsp (或者直接點擊下載)
又到了再一次審視Google家的移動操作系統"碎片化"到如何程度的時候了。OpenSignal背後的開發人員們,通過他們從用戶所下載的應用那裡收集來的
Android Service是分為兩種:本地服務(Local Service): 同一個apk內被調用遠程服 務(Remote Service):被另一個apk調用遠程