MP3播放器

自制MP3播放器

自己做的一个MP3播放器

Tomcat下载列表文件

resources.xml

<?xml version="1.0" encoding="UTF-8"?>
<resources>
	<resource>
		<id>001</id>
		<music.name>这,就是爱</music.name>
		<music.artist>张杰</music.artist>
		<music.type>mp3</music.type>
		<music.size>4700288</music.size>
		<lrc.name>这,就是爱</lrc.name>
		<lrc.type>lrc</lrc.type>
		<lrc.size>1188</lrc.size>
	</resource>
	<resource>
		<id>002</id>
		<music.name>思念是一种病</music.name>
		<music.artist>张震岳</music.artist>
		<music.type>mp3</music.type>
		<music.size>4095396</music.size>
		<lrc.name>思念是一种病</lrc.name>
		<lrc.type>lrc</lrc.type>
		<lrc.size>2108</lrc.size>
	</resource>
	<resource>
		<id>003</id>
		<music.name>稻香</music.name>
		<music.artist>周杰伦</music.artist>
		<music.type>mp3</music.type>
		<music.size>3578366</music.size>
		<lrc.name>稻香</lrc.name>
		<lrc.type>lrc</lrc.type>
		<lrc.size>1627</lrc.size>
	</resource>
	<resource>
		<id>004</id>
		<music.name>简单爱</music.name>
		<music.artist>周杰伦</music.artist>
		<music.type>mp3</music.type>
		<music.size>6609364</music.size>
		<lrc.name>简单爱</lrc.name>
		<lrc.type>lrc</lrc.type>
		<lrc.size>1315</lrc.size>
	</resource>
	<resource>
		<id>005</id>
		<music.name>听妈妈的话</music.name>
		<music.artist>周杰伦</music.artist>
		<music.type>mp3</music.type>
		<music.size>7218980</music.size>
		<lrc.name>听妈妈的话</lrc.name>
		<lrc.type>lrc</lrc.type>
		<lrc.size>2266</lrc.size>
	</resource>
</resources>

org.wp.activity

 

MainActivity

package org.wp.activity;

import android.app.TabActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;

public class MainActivity extends TabActivity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// 取得TabHost对象
		TabHost tabHost = getTabHost();
		// 去除TabHost横线
		tabHost.setPadding(0, 0, 0, -6);

		Intent remoteIntent = new Intent(MainActivity.this,
				RemoteListActivity.class);
		// 新建一个newTabSpec(newTabSpec);
		TabHost.TabSpec remoteTabSpec = tabHost.newTabSpec("下载列表");
		// 设置其标签和图表(setIndicator)
		remoteTabSpec.setIndicator("下载列表");
		// 设置内容(setContent)
		remoteTabSpec.setContent(remoteIntent);
		tabHost.addTab(remoteTabSpec);

		Intent localIntent = new Intent(MainActivity.this,
				LocalListActivity.class);
		TabHost.TabSpec localTabSpec = tabHost.newTabSpec("本地音乐");
		localTabSpec.setIndicator("本地音乐");
		localTabSpec.setContent(localIntent);
		tabHost.addTab(localTabSpec);

		TabWidget tabWidget = tabHost.getTabWidget();
		for (int i = 0; i < tabWidget.getChildCount(); i++) {
			// 设置高度
			tabWidget.getChildAt(i).getLayoutParams().height = 35;
			// 设置字体
			((TextView) getTabWidget().getChildAt(i).findViewById(
					android.R.id.title)).setTextSize(20);
		}
	}
}

 

RemoteListActivity

package org.wp.activity;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.wp.activity.service.DownloadService;
import org.wp.domain.MusicInfo;
import org.wp.utils.HttpDownloadUtil;
import org.wp.utils.SAXMusicInfo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

public class RemoteListActivity extends Activity {
	private static final int UPDATE = 1;
	private static final int MANAGE = 2;
	private static final int ABOUT = 3;
	private ListView listView;
	private List<MusicInfo> musicInfos;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.remote);
		listView = (ListView) this.findViewById(R.id.remoteListView);
	}

	@Override
	public void onResume() {
		// 载入下载列表
		loadMusicList();
		listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				if (Environment.getExternalStorageState().equals(
						Environment.MEDIA_MOUNTED)) {
					MusicInfo musicInfo = musicInfos.get(position);
					Intent intent = new Intent();
					intent.putExtra("musicInfo", musicInfo);
					intent.setClass(RemoteListActivity.this,
							DownloadService.class);
					startService(intent);
				} else {
					Toast.makeText(RemoteListActivity.this,
							R.string.externalStorageState, Toast.LENGTH_LONG)
							.show();
				}
			}
		});
		super.onResume();
	}

	// 当客户点击MENU按钮的时候,调用该方法
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// groupId,itemId,order,title
		menu.add(0, UPDATE, 1, R.string.musiclist_update);
		menu.add(0, MANAGE, 2, R.string.musiclist_manage);
		menu.add(0, ABOUT, 3, R.string.musiclist_about);
		return super.onCreateOptionsMenu(menu);
	}

	// 当客户点击菜单当中的某一个选项时,会调用该方法
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (item.getItemId() == UPDATE) {
			loadMusicList();
		} else if (item.getItemId() == MANAGE) {
			Intent intent = new Intent();
			intent.setClass(RemoteListActivity.this, DownloadListActivity.class);
			startActivity(intent);
		} else if (item.getItemId() == ABOUT) {
		}
		return super.onOptionsItemSelected(item);
	}

	private void loadMusicList() {
		try {
			HttpDownloadUtil httpDownloadUtil = new HttpDownloadUtil();
			InputStream inStream = httpDownloadUtil.getConnectionFormUrl(
					"http://192.168.1.105:8080/music/resources.xml")
					.getInputStream();
			listView.setAdapter(getSimpleAdapter(inStream));
			inStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private SimpleAdapter getSimpleAdapter(InputStream inStream) {
		SimpleAdapter simpleAdapter = null;
		try {
			musicInfos = SAXMusicInfo.readXml(inStream);
			List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
			for (MusicInfo musicInfo : musicInfos) {
				HashMap<String, String> map = new HashMap<String, String>();
				map.put("musicName", musicInfo.getMusicName());
				map.put("musicArtist", musicInfo.getMusicArtist());
				map.put("musicSize", musicInfo.getMusicSize());
				data.add(map);
			}
			simpleAdapter = new SimpleAdapter(RemoteListActivity.this, data,
					R.layout.musicitem, new String[] { "musicName",
							"musicArtist", "musicSize" }, new int[] {
							R.id.musicName, R.id.musicArtist, R.id.musicSize });
			inStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return simpleAdapter;
	}
}

 

LocalListActivity

package org.wp.activity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.wp.domain.MusicInfo;
import org.wp.utils.FileUtil;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

public class LocalListActivity extends Activity {
	private ListView listView;
	private List<MusicInfo> musicInfos;
	private static final int PLAY = 1;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.local);
		listView = (ListView) this.findViewById(R.id.localListView);
	}

	@Override
	public void onResume() {
		if (Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED)) {
			loadMusicList();
			listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
				@Override
				public void onItemClick(AdapterView<?> parent, View view,
						int position, long id) {
					String[] names = new String[musicInfos.size()];
					for (int i = 0; i < musicInfos.size(); i++) {
						names[i] = musicInfos.get(i).getMusicName();
					}
					Bundle bundle = new Bundle();
					bundle.putStringArray("names", names);
					bundle.putInt("position", position);
					Intent intent = new Intent();
					intent.putExtras(bundle);
					intent.setClass(LocalListActivity.this,
							PlayMusicActivity.class);
					startActivity(intent);
				}
			});
		} else {
			Toast.makeText(LocalListActivity.this,
					R.string.externalStorageState, Toast.LENGTH_LONG).show();
		}
		super.onResume();
	}

	private void loadMusicList() {
		try {
			FileUtil fileUtil = new FileUtil();
			musicInfos = fileUtil.getLocalMusicFiles("music");
			List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
			for (MusicInfo musicInfo : musicInfos) {
				HashMap<String, String> map = new HashMap<String, String>();
				map.put("musicName", musicInfo.getMusicName());
				map.put("musicArtist", musicInfo.getMusicArtist());
				map.put("musicSize", musicInfo.getMusicSize());
				data.add(map);
			}
			SimpleAdapter simpleAdapter = new SimpleAdapter(
					LocalListActivity.this, data, R.layout.musicitem,
					new String[] { "musicName", "musicArtist", "musicSize" },
					new int[] { R.id.musicName, R.id.musicArtist,
							R.id.musicSize });
			listView.setAdapter(simpleAdapter);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(0, PLAY, 1, R.string.musiclist_play);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (item.getItemId() == PLAY) {
			Intent intent = new Intent();
			intent.setClass(LocalListActivity.this, PlayMusicActivity.class);
			startActivity(intent);
		}
		return super.onOptionsItemSelected(item);
	}
}

 

DownloadListActivity

package org.wp.activity;

import java.util.ArrayList;
import java.util.List;
import org.wp.domain.DownloadInfo;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Gravity;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.LinearLayout.LayoutParams;

public class DownloadListActivity extends Activity {
	private static List<DownloadInfo> list = new ArrayList<DownloadInfo>();
	private static int ID_INCRNUM = 10000;
	private DownloadReceiver downloadReceiver;
	private LinearLayout mLayout;
	private ProgressBar pgb;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.download);
	}

	// 接收下载百分比信息
	public Handler handler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			String name = msg.getData().getString("name");
			String percent = msg.getData().getString("percent");
			boolean flag = false;
			if (list == null) {
				DownloadInfo downloadInfo = new DownloadInfo();
				downloadInfo.setName(name);
				downloadInfo.setPercent(percent);
				list.add(downloadInfo);
			} else {
				for (DownloadInfo downloadInfo : list) {
					if (downloadInfo.getName().equals(name)) {
						downloadInfo.setPercent(percent);
						flag = true;
					}
				}
				if (!flag) {
					DownloadInfo downloadInfo = new DownloadInfo();
					downloadInfo.setName(name);
					downloadInfo.setPercent(percent);
					list.add(downloadInfo);
				}
			}
		}
	};

	@Override
	protected void onResume() {
		super.onResume();
		mLayout = (LinearLayout) this.findViewById(R.id.downloadList);
		for (int i = 0; i < list.size(); i++) {
			DownloadInfo downloadInfo = list.get(i);
			LinearLayout ll = new LinearLayout(DownloadListActivity.this);
			ll.setOrientation(LinearLayout.HORIZONTAL);
			LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
					LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
			lp.topMargin = 10;
			mLayout.addView(ll, lp);

			lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
					LayoutParams.WRAP_CONTENT);
			lp.weight = 1;
			TextView textView1 = new TextView(DownloadListActivity.this);
			textView1.setText(downloadInfo.getName());
			ll.addView(textView1, lp);

			lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
					LayoutParams.WRAP_CONTENT);
			lp.weight = 1;
			TextView textView2 = new TextView(DownloadListActivity.this);
			textView2.setText(downloadInfo.getPercent());
			textView2.setGravity(Gravity.RIGHT);
			textView2.setId(i + ID_INCRNUM);
			ll.addView(textView2, lp);

			lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
					LayoutParams.WRAP_CONTENT);
			pgb = new ProgressBar(DownloadListActivity.this, null,
					android.R.attr.progressBarStyleHorizontal);
			pgb.setMax(100);
			pgb.setId(i);
			mLayout.addView(pgb, lp);
		}

		for (int i = 0; i < list.size(); i++) {
			updateUI(i);
		}

		downloadReceiver = new DownloadReceiver();
		IntentFilter filter = new IntentFilter();
		filter.addAction("DownloadService.DownloadMusic");
		DownloadListActivity.this.registerReceiver(downloadReceiver, filter);
	}

	@Override
	protected void onPause() {
		super.onPause();
		DownloadListActivity.this.unregisterReceiver(downloadReceiver);
		// 删除已经下载完成的信息
		for (int i = 0; i < list.size(); i++) {
			String str = list.get(i).getPercent();
			int percent = Integer.parseInt(str.substring(0, str.indexOf(".")));
			if (percent == 100) {
				list.remove(i);
			}
		}
	}

	class DownloadReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			for (int i = 0; i < list.size(); i++) {
				updateUI(i);
			}
		}
	}

	private void updateUI(int i) {
		String str = list.get(i).getPercent();
		ProgressBar pb = (ProgressBar) DownloadListActivity.this
				.findViewById(i);
		TextView textView = (TextView) DownloadListActivity.this.findViewById(i
				+ ID_INCRNUM);
		textView.setText(str);
		int percent = Integer.parseInt(str.substring(0, str.indexOf(".")));
		pb.setProgress(percent);
	}
}

 

PlayMusicActivity

package org.wp.activity;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Vector;
import org.wp.activity.service.PlayMusicService;
import org.wp.domain.LrcInfo;
import org.wp.utils.ParseLrcUtil;
import org.wp.utils.PlayConstant;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ScrollView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

public class PlayMusicActivity extends Activity {
	private ImageButton startMusicButton;
	private ImageButton stopMusicButton;
	private ImageButton lastMusicButton;
	private ImageButton nextMusicButton;
	private SeekBar seekBar;
	private ScrollView scrollView;
	private SeekBarReceiver seekBarReceiver;
	private LinearLayout ll;
	private static String names[] = null;
	private static int position = -1;
	private Vector<LrcInfo> lrcInfos;
	private long lrcTime;
	private int i = 0;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.play);

		startMusicButton = (ImageButton) this.findViewById(R.id.startMusic);
		stopMusicButton = (ImageButton) this.findViewById(R.id.stopMusic);
		lastMusicButton = (ImageButton) this.findViewById(R.id.lastMusic);
		nextMusicButton = (ImageButton) this.findViewById(R.id.nextMusic);
		seekBar = (SeekBar) this.findViewById(R.id.seekBarId);
		scrollView = (ScrollView) this.findViewById(R.id.scrollViewId);

		startMusicButton.setOnClickListener(new ImageButton.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (warn()) {
					ImageButton button = (ImageButton) v;
					if (!PlayConstant.FLAG) {
						Intent intent = new Intent();
						intent.putExtra("msg", PlayConstant.START_MSG);
						intent.putExtra("name", names[position]);
						intent.setClass(PlayMusicActivity.this,
								PlayMusicService.class);
						startService(intent);
						button.setImageResource(R.drawable.pause);
						PlayConstant.FLAG = true;
					} else {
						Intent intent = new Intent();
						intent.putExtra("msg", PlayConstant.PAUSE_MSG);
						intent.setClass(PlayMusicActivity.this,
								PlayMusicService.class);
						startService(intent);
						button.setImageResource(R.drawable.start);
						PlayConstant.FLAG = false;
					}
				}
			}
		});

		stopMusicButton.setOnClickListener(new ImageButton.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (warn()) {
					Intent intent = new Intent();
					intent.putExtra("msg", PlayConstant.STOP_MSG);
					intent.setClass(PlayMusicActivity.this,
							PlayMusicService.class);
					startService(intent);
					startMusicButton.setImageResource(R.drawable.start);
					PlayConstant.FLAG = false;
					seekBar.setProgress(0);
				}
			}
		});

		lastMusicButton.setOnClickListener(new ImageButton.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (warn()) {
					position--;
					if (position < 0) {
						Toast.makeText(PlayMusicActivity.this,
								R.string.musiclist_last, Toast.LENGTH_SHORT)
								.show();
						position = 0;
					} else {
						scrollView.removeView(ll);
						// 重新载入歌词
						prepareLrc(names[position]);
						Intent intent = new Intent();
						intent.putExtra("msg", PlayConstant.LAST_MSG);
						intent.putExtra("name", names[position]);
						intent.setClass(PlayMusicActivity.this,
								PlayMusicService.class);
						startService(intent);
						startMusicButton.setImageResource(R.drawable.pause);
						PlayConstant.FLAG = true;
						seekBar.setProgress(0);
					}
				}
			}
		});

		nextMusicButton.setOnClickListener(new ImageButton.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (warn()) {
					position++;
					if (position >= names.length) {
						Toast.makeText(PlayMusicActivity.this,
								R.string.musiclist_next, Toast.LENGTH_SHORT)
								.show();
						position = names.length - 1;
					} else {
						scrollView.removeView(ll);
						// 重新载入歌词
						prepareLrc(names[position]);
						Intent intent = new Intent();
						intent.putExtra("msg", PlayConstant.NEXT_MSG);
						intent.putExtra("name", names[position]);
						intent.setClass(PlayMusicActivity.this,
								PlayMusicService.class);
						startService(intent);
						startMusicButton.setImageResource(R.drawable.pause);
						PlayConstant.FLAG = true;
						seekBar.setProgress(0);
					}
				}
			}
		});

		seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
			}

			public void onStartTrackingTouch(SeekBar seekBar) {
			}

			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
				Intent intent = new Intent();
				int progress = seekBar.getProgress();
				intent.putExtra("msg", PlayConstant.ALTER_MSG);
				intent.putExtra("progress", progress);
				intent.setClass(PlayMusicActivity.this, PlayMusicService.class);
				startService(intent);
			}
		});
	}

	@Override
	protected void onResume() {
		Intent intent = getIntent();
		Bundle bundle = intent.getExtras();
		if (bundle != null) {
			names = bundle.getStringArray("names");
			position = bundle.getInt("position");
		}

		// 修改播放按钮图片
		if (PlayConstant.FLAG) {
			startMusicButton.setImageResource(R.drawable.pause);
		}

		// 初始化歌词
		if (names != null && position != -1) {
			prepareLrc(names[position]);
			lrcTime = lrcInfos.get(0).getTime();
		}

		// 注册广播
		seekBarReceiver = new SeekBarReceiver();
		IntentFilter filter = new IntentFilter();
		filter.addAction("PlayMusicService.UpdateSeekBar");
		PlayMusicActivity.this.registerReceiver(seekBarReceiver, filter);
		super.onResume();
	}

	@Override
	protected void onPause() {
		// 撤销广播
		PlayMusicActivity.this.unregisterReceiver(seekBarReceiver);
		super.onPause();
	}

	// 判断是否选择了音乐文件
	private boolean warn() {
		if (names == null || position == -1) {
			Toast.makeText(PlayMusicActivity.this, R.string.musiclist_warn,
					Toast.LENGTH_SHORT).show();
			return false;
		}
		return true;
	}

	// 载入歌词文件
	private void prepareLrc(String lrcName) {
		try {
			InputStream inStream = new FileInputStream(Environment
					.getExternalStorageDirectory().getAbsoluteFile()
					+ File.separator + "music/" + lrcName + ".lrc");
			ParseLrcUtil parseLrcUtil = new ParseLrcUtil();
			lrcInfos = parseLrcUtil.parseLrc(inStream);
			ll = new LinearLayout(PlayMusicActivity.this);
			ll.setOrientation(LinearLayout.VERTICAL);
			LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
					LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
			lp.topMargin = 50;
			scrollView.addView(ll, lp);
			// 添加歌词
			for (int i = 0; i < lrcInfos.size(); i++) {
				lp = new LinearLayout.LayoutParams(
						LinearLayout.LayoutParams.FILL_PARENT,
						LinearLayout.LayoutParams.WRAP_CONTENT);
				TextView textView = new TextView(PlayMusicActivity.this);
				String str = lrcInfos.get(i).getLrcStr();
				textView.setText(str);
				textView.setId(i);
				textView.setGravity(Gravity.CENTER_HORIZONTAL);
				ll.addView(textView, lp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	class SeekBarReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			int duration = intent.getIntExtra("duration", 0);
			int currentPosition = intent.getIntExtra("currentPosition", 0);
			System.out.println("duration" + duration + "  currentPosition"
					+ currentPosition);
			if ((duration < currentPosition) && duration != 0) {
				Intent inte = new Intent();
				inte.putExtra("msg", PlayConstant.STOP_MSG);
				inte.setClass(PlayMusicActivity.this, PlayMusicService.class);
				startService(inte);
				startMusicButton.setImageResource(R.drawable.start);
				PlayConstant.FLAG = false;
				seekBar.setProgress(0);
			}
			seekBar.setMax(duration);
			seekBar.setProgress(currentPosition);
			if (lrcTime <= currentPosition) {
				synchlrc();
			}
		}
	}

	// 同步歌词
	private void synchlrc() {
		if (lrcInfos != null) {
			i++;
			if (i < lrcInfos.size()) {
				// 获得下一次更新的时间
				lrcTime = lrcInfos.get(i).getTime();
				// 高亮显示当前歌词
				TextView textView = (TextView) this.findViewById(i - 1);
				String str = textView.getText().toString();
				SpannableString sp = new SpannableString(str);
				sp.setSpan(new ForegroundColorSpan(Color.YELLOW), 0,
						str.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
				textView.setText(sp);
				// 实现滚动
				int j = i + 8 >= lrcInfos.size() - 1 ? lrcInfos.size() - 1
						: i + 8;
				textView = (TextView) this.findViewById(j);
				scrollView.requestChildFocus(textView, textView);
				// 恢复已经高亮显示的歌词
				if (i >= 2) {
					TextView tempView = (TextView) this.findViewById(i - 2);
					tempView.setText(lrcInfos.get(i - 2).getLrcStr());
				}
			}
		}
	}
}

  

 

org.wp.activity.service

 

DownloadService

package org.wp.activity.service;

import java.net.URLEncoder;
import org.wp.activity.DownloadListActivity;
import org.wp.activity.R;
import org.wp.domain.MusicInfo;
import org.wp.utils.HttpDownloadUtil;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;

public class DownloadService extends Service {
	private NotificationManager notificationManager = null;
	private Notification notification = null;

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		MusicInfo musicInfo = (MusicInfo) intent
				.getSerializableExtra("musicInfo");
		DownloadListActivity downloadListActivity = new DownloadListActivity();
		notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		new DownloadLrc(musicInfo).start();
		new DownloadMusic(musicInfo, downloadListActivity.handler).start();
		return super.onStartCommand(intent, flags, startId);
	}

	class DownloadLrc extends Thread {
		private MusicInfo musicInfo;
		private int i = -1;

		public DownloadLrc(MusicInfo musicInfo) {
			this.musicInfo = musicInfo;
		}

		@Override
		public void run() {
			String lrcName = URLEncoder.encode(musicInfo.getLrcName());
			String urlStr = "http://192.168.1.105:8080/music/" + lrcName + "."
					+ musicInfo.getLrcType();
			HttpDownloadUtil httpDownloadUtil = new HttpDownloadUtil();
			i = httpDownloadUtil.downloadLrc(urlStr, "music",
					musicInfo.getLrcName() + "." + musicInfo.getLrcType());
			notification = new Notification();
			notification.when = System.currentTimeMillis();
			PendingIntent pIntent = PendingIntent.getService(
					DownloadService.this, 0, null, 0);
			getTickerStr(notification, musicInfo.getLrcName() + "歌词", i,
					pIntent);
			notificationManager.notify(0, notification);
		}
	}

	class DownloadMusic extends Thread {
		private MusicInfo musicInfo;
		private Handler handler;
		private int i = -1;

		public DownloadMusic(MusicInfo musicInfo, Handler handler) {
			this.musicInfo = musicInfo;
			this.handler = handler;
		}

		@Override
		public void run() {
			try {
				String musicName = URLEncoder.encode(musicInfo.getMusicName(),
						"UTF-8");
				String urlStr = "http://192.168.1.105:8080/music/" + musicName
						+ "." + musicInfo.getMusicType();
				HttpDownloadUtil httpDownloadUtil = new HttpDownloadUtil();
				i = httpDownloadUtil.downloadMusic(urlStr, "music", musicInfo.getMusicName() 
						+ "." + musicInfo.getMusicType(), DownloadService.this, handler);
				notification = new Notification();
				notification.when = System.currentTimeMillis();
				PendingIntent pIntent = PendingIntent.getService(
						DownloadService.this, 0, null, 0);
				getTickerStr(notification, musicInfo.getLrcName() + "音乐", i,
						pIntent);
				notificationManager.notify(1, notification);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private void getTickerStr(Notification notification, String name, int i,
			PendingIntent pIntent) {
		if (i == HttpDownloadUtil.ERROR) {
			notification.icon = R.drawable.error;
			notification.tickerText = name + "文件下载错误";
			notification.setLatestEventInfo(DownloadService.this, name
					+ "文件下载信息", name + "文件下载错误", pIntent);
		} else if (i == HttpDownloadUtil.EXIST) {
			notification.icon = R.drawable.exist;
			notification.tickerText = name + "文件已经存在";
			notification.setLatestEventInfo(DownloadService.this, name
					+ "文件下载信息", name + "文件已经存在", pIntent);
		} else if (i == HttpDownloadUtil.SUCCEE) {
			notification.icon = R.drawable.succee;
			notification.tickerText = name + "文件下载成功";
			notification.setLatestEventInfo(DownloadService.this, name
					+ "文件下载信息", name + "文件下载成功", pIntent);
		} else if (i == HttpDownloadUtil.WORKING) {
			notification.icon = R.drawable.working;
			notification.tickerText = name + "文件正在下载中...";
			notification.setLatestEventInfo(DownloadService.this, name
					+ "文件下载信息", name + "文件正在下载中...", pIntent);
		}
	}
}

 

PlayMusicService

package org.wp.activity.service;

import org.wp.utils.PlayConstant;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.IBinder;

public class PlayMusicService extends Service {
	private boolean isPlaying = false;
	private boolean isPause = false;
	private boolean isReleased = false;
	private static boolean flag = true;
	private MediaPlayer mediaPlayer = null;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		int msg = intent.getIntExtra("msg", 0);
		if (PlayConstant.COUNT == 0) {
			new UpdateSeekBar().start();
		}
		if (msg == PlayConstant.START_MSG) {
			String name = intent.getStringExtra("name");
			play(name);
		} else if (msg == PlayConstant.PAUSE_MSG) {
			pause();
		} else if (msg == PlayConstant.STOP_MSG) {
			stop();
		} else if (msg == PlayConstant.LAST_MSG) {
			String name = intent.getStringExtra("name");
			last(name);
		} else if (msg == PlayConstant.NEXT_MSG) {
			String name = intent.getStringExtra("name");
			next(name);
		} else if (msg == PlayConstant.ALTER_MSG) {
			int progress = intent.getIntExtra("progress", 0);
			alter(progress);
		}
		PlayConstant.COUNT++;
		return super.onStartCommand(intent, flags, startId);
	}

	private void play(String name) {
		if (isPause) {
			mediaPlayer.start();
			updateState(true, false, false);
		} else {
			init(name);
			mediaPlayer.start();
			updateState(true, false, false);
		}
	}

	private void pause() {
		if (isPlaying && !isReleased) {
			mediaPlayer.pause();
			updateState(false, true, false);
		}
	}

	private void stop() {
		if ((isPlaying || isPause) && !isReleased) {
			mediaPlayer.stop();
			mediaPlayer.release();
			updateState(false, false, true);
		}
	}

	private void last(String name) {
		if ((isPlaying || isPause) && !isReleased) {
			mediaPlayer.stop();
			mediaPlayer.release();
			init(name);
			mediaPlayer.start();
			updateState(true, false, false);
		} else {
			init(name);
			mediaPlayer.start();
			updateState(true, false, false);
		}
	}

	private void next(String name) {
		if ((isPlaying || isPause) && !isReleased) {
			mediaPlayer.stop();
			mediaPlayer.release();
			init(name);
			mediaPlayer.start();
			updateState(true, false, false);
		} else {
			init(name);
			mediaPlayer.start();
			updateState(true, false, false);
		}
	}

	private void init(String name) {
		String path = PlayConstant.BASE_URL + name + PlayConstant.TYPE;
		mediaPlayer = MediaPlayer.create(this, Uri.parse("file://" + path));
		mediaPlayer.setLooping(false);
	}

	private void updateState(boolean b1, boolean b2, boolean b3) {
		this.isPlaying = b1;
		this.isPause = b2;
		this.isReleased = b3;
	}

	private void alter(int progress) {
		if ((isPlaying || isPause) && !isReleased) {
			mediaPlayer.seekTo(progress);
		}
	}

	public void shutDown() {
		flag = false;
	}

	// 更新播放的进度
	class UpdateSeekBar extends Thread {
		@Override
		public void run() {
			while (flag) {
				try {
					if ((isPlaying || isPause) && !isReleased) {
						Intent intent = new Intent();
						intent.putExtra("duration", mediaPlayer.getDuration());
						intent.putExtra("currentPosition",
								mediaPlayer.getCurrentPosition());
						intent.setAction("PlayMusicService.UpdateSeekBar");
						sendBroadcast(intent);
					} else {
						Intent intent = new Intent();
						intent.putExtra("duration", 0);
						intent.putExtra("currentPosition", 0);
						intent.setAction("PlayMusicService.UpdateSeekBar");
						sendBroadcast(intent);
					}
					Thread.sleep(100);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
}

 

 

org.wp.domain

 

MusicInfo

package org.wp.domain;

import java.io.Serializable;

public class MusicInfo implements Serializable {
	private static final long serialVersionUID = 1L;

	private Integer id;
	private String musicName;
	private String musicArtist;
	private String musicType;
	private String musicSize;
	private String lrcName;
	private String lrcType;
	private String lrcSize;

	public MusicInfo() {
	}

	public MusicInfo(Integer id, String musicName, String musicArtist,
			String musicType, String musicSize, String lrcName, String lrcType,
			String lrcSize) {
		this.id = id;
		this.musicName = musicName;
		this.musicArtist = musicArtist;
		this.musicType = musicType;
		this.musicSize = musicSize;
		this.lrcName = lrcName;
		this.lrcType = lrcType;
		this.lrcSize = lrcSize;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getMusicName() {
		return musicName;
	}

	public void setMusicName(String musicName) {
		this.musicName = musicName;
	}

	public String getMusicArtist() {
		return musicArtist;
	}

	public void setMusicArtist(String musicArtist) {
		this.musicArtist = musicArtist;
	}

	public String getMusicType() {
		return musicType;
	}

	public void setMusicType(String musicType) {
		this.musicType = musicType;
	}

	public String getMusicSize() {
		return musicSize;
	}

	public void setMusicSize(String musicSize) {
		this.musicSize = musicSize;
	}

	public String getLrcName() {
		return lrcName;
	}

	public void setLrcName(String lrcName) {
		this.lrcName = lrcName;
	}

	public String getLrcType() {
		return lrcType;
	}

	public void setLrcType(String lrcType) {
		this.lrcType = lrcType;
	}

	public String getLrcSize() {
		return lrcSize;
	}

	public void setLrcSize(String lrcSize) {
		this.lrcSize = lrcSize;
	}

	@Override
	public String toString() {
		return "MusicInfo [id=" + id + ", musicName=" + musicName
				+ ", musicArtist=" + musicArtist + ", musicType=" + musicType
				+ ", musicSize=" + musicSize + ", lrcName=" + lrcName
				+ ", lrcType=" + lrcType + ", lrcSize=" + lrcSize + "]";
	}
}

 

DownloadInfo

package org.wp.domain;

public class DownloadInfo {
	private String name;
	private String percent;

	public DownloadInfo() {
	}

	public DownloadInfo(String name, String percent) {
		this.name = name;
		this.percent = percent;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPercent() {
		return percent;
	}

	public void setPercent(String percent) {
		this.percent = percent;
	}

	@Override
	public String toString() {
		return "DownloadInfo [name=" + name + ", percent=" + percent + "]";
	}
}

 

LrcInfo

package org.wp.domain;

@SuppressWarnings("rawtypes")
public class LrcInfo implements Comparable {
	private Long time;
	private String lrcStr;

	public LrcInfo() {
	}

	public LrcInfo(Long time, String lrcStr) {
		this.time = time;
		this.lrcStr = lrcStr;
	}

	public Long getTime() {
		return time;
	}

	public void setTime(String time) {
		String str[] = time.split(":|\\.");
		this.time = (long) (Integer.parseInt(str[0]) * 60 * 1000
				+ Integer.parseInt(str[1]) * 1000 + Integer.parseInt(str[2]) * 10);
	}

	public String getLrcStr() {
		return lrcStr;
	}

	public void setLrcStr(String lrcStr) {
		this.lrcStr = lrcStr;
	}

	@Override
	public String toString() {
		return "LrcInfo [time=" + time + ", lrcStr=" + lrcStr + "]";
	}

	@Override
	public int compareTo(Object another) {
		LrcInfo li = (LrcInfo) another;
		if (this.time > li.getTime())
			return 1;
		if (this.time < li.getTime()) {
			return -1;
		}
		return 0;
	}
}

 

 

org.wp.utils

 

SAXMusicInfo

package org.wp.utils;

import java.io.InputStream;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.wp.domain.MusicInfo;

public class SAXMusicInfo {
	public static List<MusicInfo> readXml(InputStream inStream) throws Exception {
		// 得到SAX解析器的工厂实例
		SAXParserFactory spf = SAXParserFactory.newInstance();
		// 从SAX工厂实例中获得SAX解析器
		SAXParser saxParser = spf.newSAXParser();
		XMLContentHandler handler = new XMLContentHandler();
		saxParser.parse(inStream, handler);
		inStream.close();
		return handler.getMusicInfos();
	}
}

 

XMLContentHandler

package org.wp.utils;

import java.util.ArrayList;
import java.util.List;
import org.wp.domain.MusicInfo;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class XMLContentHandler extends DefaultHandler {
	private List<MusicInfo> musicInfos;
	private MusicInfo musicInfo;
	private String preTAG;

	@Override
	public void startDocument() throws SAXException {
		musicInfos = new ArrayList<MusicInfo>();
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		if ("resource".equals(localName)) {
			musicInfo = new MusicInfo();
		}
		preTAG = localName;
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		String data = new String(ch, start, length);
		if ("id".equals(preTAG)) {
			musicInfo.setId(Integer.parseInt(data));
		} else if ("music.name".equals(preTAG)) {
			musicInfo.setMusicName(data);
		} else if ("music.artist".equals(preTAG)) {
			musicInfo.setMusicArtist(data);
		} else if ("music.type".equals(preTAG)) {
			musicInfo.setMusicType(data);
		} else if ("music.size".equals(preTAG)) {
			musicInfo.setMusicSize(data);
		} else if ("lrc.name".equals(preTAG)) {
			musicInfo.setLrcName(data);
		} else if ("lrc.type".equals(preTAG)) {
			musicInfo.setLrcType(data);
		} else if ("lrc.size".equals(preTAG)) {
			musicInfo.setLrcSize(data);
		}
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if (musicInfo != null && "resource".equals(localName)) {
			musicInfos.add(musicInfo);
		}
		preTAG = null;
	}

	public List<MusicInfo> getMusicInfos() {
		return musicInfos;
	}
}

 

HttpDownloadUtil

package org.wp.utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.wp.activity.service.DownloadService;
import android.os.Handler;

public class HttpDownloadUtil {
	private URL url = null;
	public static final int ERROR = -1;
	public static final int SUCCEE = 0;
	public static final int EXIST = 1;
	public static final int WORKING = 2;

	/**
	 *  根据URL下载歌词文件 
	 * -1:代表下载文件出错 
	 *  0:代表下载文件成功 
	 *  1:代表文件已经存在
	 * 
	 * @param urlStr
	 * @param path
	 * @param fileName
	 * @return int
	 */
	public int downloadLrc(String urlStr, String path, String fileName) {
		InputStream inStream = null;
		try {
			HttpURLConnection conn = getConnectionFormUrl(urlStr);
			inStream = conn.getInputStream();
			FileUtil fileUtil = new FileUtil();
			if (fileUtil.isFileExist(fileName, path)) {
				return EXIST;
			} else {
				File resultFile = fileUtil.writeLrcToSDFromInput(path,
						fileName, inStream);
				if (resultFile == null) {
					return ERROR;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return ERROR;
		} finally {
			try {
				inStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return SUCCEE;
	}

	/**
	 *  根据URL下载音乐文件 
	 * -1:代表下载文件出错 
	 *  0:代表下载文件成功 
	 *  1:代表文件已经存在 
	 *  2: 代表文件正在下载中
	 * 
	 * @param urlStr
	 * @param path
	 * @param fileName
	 * @param downloadService
	 * @param handler
	 * @return int
	 */
	public int downloadMusic(String urlStr, String path, String fileName,
			DownloadService downloadService, Handler handler) {
		InputStream inStream = null;
		try {
			HttpURLConnection conn = getConnectionFormUrl(urlStr);
			inStream = conn.getInputStream();
			FileUtil fileUtil = new FileUtil();
			if (fileUtil.isFileExist(fileName, path)) {
				return EXIST;
			} else if (fileUtil.isFileDownloading(fileName, path)) {
				return WORKING;
			} else {
				File resultFile = fileUtil.writeMusicToSDFromInput(path,
						fileName, inStream, (long) conn.getContentLength(),
						downloadService, handler);
				if (resultFile == null) {
					return ERROR;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return ERROR;
		} finally {
			try {
				inStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return SUCCEE;
	}

	/**
	 * 根据URL得到Connection连接
	 * 
	 * @param urlStr
	 * @return HttpURLConnection
	 * @throws Exception
	 */
	public HttpURLConnection getConnectionFormUrl(String urlStr)
			throws Exception {
		url = new URL(urlStr);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("POST");
		conn.setReadTimeout(6 * 1000);
		if (conn.getResponseCode() == 200) {
			return conn;
		}
		return null;
	}
}

 

FileUtil

package org.wp.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import org.wp.activity.service.DownloadService;
import org.wp.domain.MusicInfo;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;

public class FileUtil {
	private String SDCardPath;
	private String tempFileName = "tempFileName";
	private static int TEMP_INCRNUM = 1;

	/**
	 * 得到当前外部存储设备的目录 SDCARD
	 */
	public FileUtil() {
		SDCardPath = Environment.getExternalStorageDirectory()
				.getAbsolutePath() + File.separator;
	}

	/**
	 * 创建此抽象路径名指定的目录
	 * 
	 * @param dirPath
	 * @return dir
	 */
	public File createSDDir(String dirPath) {
		File dir = new File(SDCardPath + dirPath + File.separator);
		dir.mkdir();
		return dir;
	}

	/**
	 * 在SD卡上创建文件
	 * 
	 * @param fileName
	 * @param dirPath
	 * @return file
	 * @throws IOException
	 */
	public File createSDFile(String fileName, String dirPath)
			throws IOException {
		File file = new File(SDCardPath + dirPath + File.separator + fileName);
		file.createNewFile();
		return file;
	}

	/**
	 * 判断SD卡上的文件是否存在
	 * 
	 * @param fileName
	 * @param dirPath
	 * @return boolean
	 */
	public boolean isFileExist(String fileName, String dirPath) {
		File file = new File(SDCardPath + dirPath + File.separator + fileName);
		return file.exists();
	}

	/**
	 * 判断文件是否正在下载中
	 * 
	 * @param fileName
	 * @param dirPath
	 * @return boolean
	 */
	public boolean isFileDownloading(String fileName, String dirPath) {
		File file = new File(SDCardPath + dirPath);
		File[] files = file.listFiles();
		for (File f : files) {
			if (f.getName().contains(fileName)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 将一个音乐文件里面的数据写入到SD卡中
	 * 
	 * @param path
	 * @param fileName
	 * @param inputStream
	 * @param contentLength
	 * @param downloadService
	 * @param handler
	 * @return file
	 */
	public File writeMusicToSDFromInput(String path, String fileName,
			InputStream inputStream, Long contentLength,
			DownloadService downloadService, Handler handler) {
		File file = null;
		File tempFile = null;
		OutputStream outputStream = null;
		long sum = 0;
		DecimalFormat decf = new DecimalFormat("0.00");
		try {
			createSDDir(path);
			tempFile = createSDFile(fileName + tempFileName + TEMP_INCRNUM,
					path);
			TEMP_INCRNUM++;
			outputStream = new FileOutputStream(tempFile);
			int length = -1;
			byte[] buffer = new byte[5 * 1024];
			while ((length = inputStream.read(buffer)) != -1) {
				outputStream.write(buffer, 0, length);
				sum += length;
				sendMessage(handler, downloadService, decf, contentLength, sum,
						fileName);
			}
			outputStream.flush();
			file = createSDFile(fileName, path);
			tempFile.renameTo(file);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				inputStream.close();
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return file;
	}

	/**
	 * 发送文件下载信息
	 * 
	 * @param handler
	 * @param downloadService
	 * @param decf
	 * @param contentLength
	 * @param sumLength
	 * @param fileName
	 */
	private void sendMessage(Handler handler, DownloadService downloadService,
			DecimalFormat decf, Long contentLength, Long sumLength,
			String fileName) {
		// 下载百分比
		double percent = (double) sumLength * 100 / contentLength;
		Bundle bundle = new Bundle();
		bundle.putString("name", fileName);
		bundle.putString("percent", decf.format(percent) + "%");
		Message message = handler.obtainMessage();
		message.setData(bundle);
		handler.sendMessage(message);
		Intent intent = new Intent();
		intent.setAction("DownloadService.DownloadMusic");
		downloadService.sendBroadcast(intent);
	}

	/**
	 * 将一个歌词文件里面的数据写入到SD卡中
	 * 
	 * @param path
	 * @param fileName
	 * @param inputStream
	 * @return file
	 */
	public File writeLrcToSDFromInput(String path, String fileName,
			InputStream inputStream) {
		File file = null;
		OutputStream outputStream = null;
		try {
			createSDDir(path);
			file = createSDFile(fileName, path);
			outputStream = new FileOutputStream(file);
			int length = -1;
			byte[] buffer = new byte[5 * 1024];
			while ((length = inputStream.read(buffer)) != -1) {
				outputStream.write(buffer, 0, length);
			}
			outputStream.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				inputStream.close();
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return file;
	}

	/**
	 * 获取SD卡中music目录下的音乐文件
	 * 
	 * @param path
	 * @return List<MusicInfo>
	 */
	public List<MusicInfo> getLocalMusicFiles(String path) {
		List<MusicInfo> musicInfos = new ArrayList<MusicInfo>();
		File file = new File(SDCardPath + path);
		if (!file.isDirectory()) {
			file.mkdir();
			return null;
		} else {
			File[] files = file.listFiles();
			for (File f : files) {
				if (f.getName().endsWith("mp3")) {
					MusicInfo musicInfo = new MusicInfo();
					musicInfo.setMusicName(getMusicName(f));
					musicInfo.setMusicArtist(getMusicArtist(f, f.length()));
					musicInfo.setMusicType(getMusicType(f));
					musicInfo.setMusicSize(f.length() + "");
					musicInfos.add(musicInfo);
				}
			}
		}
		return musicInfos;
	}

	/**
	 * 获得文件名称
	 * 
	 * @param file
	 * @return String
	 */
	private String getMusicName(File file) {
		String fileName = file.getName();
		return fileName.substring(0, fileName.lastIndexOf("."));
	}

	/**
	 * 获得文件艺术家
	 * 
	 * @param file
	 * @param size
	 * @return String
	 */
	private String getMusicArtist(File file, Long size) {
		byte[] buffer = new byte[1024];
		String str = null;
		try {
			RandomAccessFile raf = new RandomAccessFile(file, "r");
			raf.seek(size - 95);
			raf.read(buffer, 0, 30);
			raf.close();
			str = new String(buffer, 0, 30, "GB2312").trim();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return str;
	}

	/**
	 * 获得文件类型
	 * 
	 * @param file
	 * @return String
	 */
	private String getMusicType(File file) {
		String fileName = file.getName();
		return fileName.substring(fileName.lastIndexOf(".") + 1,
				fileName.length());
	}
}

 

ParseLrcUtil

package org.wp.utils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Vector;
import org.wp.domain.LrcInfo;

public class ParseLrcUtil {
	private Vector<LrcInfo> lrcInfos = new Vector<LrcInfo>();

	/**
	 * 解析Lrc歌词文件
	 * 
	 * @param inStream
	 * @return Vector<T>
	 */
	@SuppressWarnings("unchecked")
	public Vector<LrcInfo> parseLrc(InputStream inStream) {
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(
					inStream, "GB2312"));
			String str = null;
			while ((str = br.readLine()) != null) {
				// 本行含时间个数
				int timeNum = 0;
				// 以]分隔
				String str1[] = str.split("\\]");
				for (int i = 0; i < str1.length; i++) {
					// 以[分隔
					String str2[] = str1[i].split("\\[");
					str1[i] = str2[str2.length - 1];
					if (isTime(str1[i])) {
						timeNum++;
					}
				}
				// 处理歌词复用的情况
				for (int i = 0; i < timeNum; i++) {
					LrcInfo lrcInfo = new LrcInfo();
					lrcInfo.setTime(str1[i]);
					// 如果有歌词
					if (timeNum < str1.length) {
						lrcInfo.setLrcStr(str1[str1.length - 1]);
					}
					lrcInfos.add(lrcInfo);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 将读取的歌词按时间排序
		Collections.sort(lrcInfos);

		return lrcInfos;
	}

	/**
	 * 判断给定的字符串是否表示时间.
	 * 
	 * @param string
	 * @return boolean
	 */
	public boolean isTime(String string) {
		String str[] = string.split(":|\\.");
		if (str.length != 3) {
			return false;
		}
		for (int i = 0; i < str.length; i++) {
			try {
				Integer.parseInt(str[i]);
			} catch (NumberFormatException e) {
				return false;
			}
		}
		return true;
	}
}

 

PlayConstant

package org.wp.utils;

import java.io.File;
import android.os.Environment;

public class PlayConstant {
	public static final String BASE_URL = Environment.getExternalStorageDirectory().getAbsoluteFile()
			+ File.separator + "music/";
	public static final String TYPE = ".mp3";
	public static final int START_MSG = 1;
	public static final int PAUSE_MSG = 2;
	public static final int STOP_MSG = 3;
	public static final int LAST_MSG = 4;
	public static final int NEXT_MSG = 5;
	public static final int ALTER_MSG = 6;
	public static boolean FLAG = false;
	public static int COUNT = 0;
}

 

 

layout

 

main.xml

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:id="@android:id/tabhost"
	>
	<RelativeLayout
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:padding="3dip"
		>
		<TabWidget
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:layout_alignParentBottom="true"
			android:id="@android:id/tabs"
			/>
		<FrameLayout
			android:layout_width="fill_parent"
			android:layout_height="fill_parent"
			android:id="@android:id/tabcontent"
			/>
	</RelativeLayout>
</TabHost>

 

remote.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
    >
	<LinearLayout
		android:orientation="horizontal"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:padding="7dip"
		>
		<TextView
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:text="@string/musicNameTitle"
			android:layout_weight="1"
			/>
		<TextView
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:text="@string/musicArtistTitle"
			android:layout_weight="1"
			/>
		<TextView
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:text="@string/musicSizeTitle"
			android:layout_weight="1"
			/>		
	</LinearLayout>
	
	<ListView
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:id="@+id/remoteListView"
		/>
</LinearLayout>

 

local.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
    >
	<LinearLayout
		android:orientation="horizontal"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:padding="7dip"
		>
		<TextView
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:text="@string/musicNameTitle"
			android:layout_weight="1"
			/>
		<TextView
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:text="@string/musicArtistTitle"
			android:layout_weight="1"
			/>
		<TextView
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:text="@string/musicSizeTitle"
			android:layout_weight="1"
			/>		
	</LinearLayout>
	
	<ListView
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:id="@+id/localListView"
		/>
</LinearLayout>

 

musicitem.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="horizontal"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:padding="7dip"
	>
	<TextView
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout_weight="1"
		android:id="@+id/musicName"
		/>
	<TextView
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout_weight="1"
		android:id="@+id/musicArtist"
		/>
	<TextView
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout_weight="1"
		android:id="@+id/musicSize"
		/>		
</LinearLayout>

 

download.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical"
	android:layout_width="fill_parent"
  	android:layout_height="fill_parent"
  	android:padding="10dip"
  	android:id="@+id/downloadList"
  	>
	<TextView
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:textSize="20px"
		android:text="@string/downloadList"
		/>
</LinearLayout>

 

play.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent" 
	android:layout_height="fill_parent"
	android:padding="10dip"
	>
	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_alignParentBottom="true"
		android:layout_centerHorizontal="true"
		android:id="@+id/centerTextView"
		/>	
	<ImageButton
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_alignParentBottom="true"
		android:layout_toLeftOf="@id/centerTextView"
		android:layout_marginRight="5dip"
		android:src="@drawable/start"
		android:id="@+id/startMusic"
		/>
	<ImageButton
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_alignParentBottom="true"
		android:layout_toRightOf="@id/centerTextView"
		android:layout_marginLeft="5dip"
		android:src="@drawable/stop"
		android:id="@+id/stopMusic"
		/>
	<ImageButton
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_alignParentBottom="true"
		android:layout_toLeftOf="@id/startMusic"
		android:layout_marginRight="10dip"
		android:src="@drawable/last"
		android:id="@+id/lastMusic"
		/>
	<ImageButton
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_alignParentBottom="true"
		android:layout_toRightOf="@id/stopMusic"
		android:layout_marginLeft="10dip"
		android:src="@drawable/next"
		android:id="@+id/nextMusic"
		/>
	<SeekBar
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout_above="@id/startMusic"
		android:id="@+id/seekBarId"
		/>
	<ScrollView
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout_above="@id/seekBarId"
		android:scrollbars="none"
		android:id="@+id/scrollViewId"
		/>			
</RelativeLayout>

values

 

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
	<string name="app_name">MusicPlayer</string>
	<string name="musicNameTitle">歌曲名</string>
	<string name="musicArtistTitle">歌手名</string>
	<string name="musicSizeTitle">文件大小</string>
	<string name="downloadList">下载列表</string>
	<string name="musiclist.update">更新下载列表</string>
	<string name="musiclist.manage">下载管理</string>
	<string name="musiclist.about">关于</string>
	<string name="musiclist.play">音乐播放</string>
	<string name="musiclist.warn">请先选择要播放的歌曲</string>
	<string name="musiclist.last">已经没有上一首了</string>
	<string name="musiclist.next">已经没有下一首了</string>
	<string name="externalStorageState">SDCard不存在或者写保护</string>
</resources>

 

 

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="org.wp.activity" android:versionCode="1" android:versionName="1.0">
	<application android:icon="@drawable/icon" android:label="@string/app_name">
		<activity android:name=".MainActivity" android:label="@string/app_name">
			<intent-filter>
				<action android:name="android.intent.action.MAIN" />
				<category android:name="android.intent.category.LAUNCHER" />
			</intent-filter>
		</activity>
		<activity android:name=".LocalListActivity" android:label="@string/app_name" />
		<activity android:name=".RemoteListActivity" android:label="@string/app_name" />
		<activity android:name=".PlayMusicActivity" android:label="@string/app_name" />
		<activity android:name=".DownloadListActivity" android:label="@string/app_name" />
		<service android:name=".service.DownloadService" />
		<service android:name=".service.PlayMusicService" />
	</application>
	<!-- Allows applications to open network sockets -->
	<uses-permission android:name="android.permission.INTERNET" />
	<!-- Allows an application to write to external storage -->
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<!-- Allows mounting and unmounting file systems for removable storage -->
	<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
	<uses-sdk android:minSdkVersion="8" />
</manifest>

 

 

 

内容概要:本文详细介绍了“秒杀商城”微服务架构的设计与实战全过程,涵盖系统从需求分析、服务拆分、技术选型到核心功能开发、分布式事务处理、容器化部署及监控链路追踪的完整流程。重点解决了高并发场景下的超卖问题,采用Redis预减库存、消息队列削峰、数据库乐观锁等手段保障数据一致性,并通过Nacos实现服务注册发现与配置管理,利用Seata处理跨服务分布式事务,结合RabbitMQ实现异步下单,提升系统吞吐能力。同时,项目支持Docker Compose快速部署和Kubernetes生产级编排,集成Sleuth+Zipkin链路追踪与Prometheus+Grafana监控体系,构建可观测性强的微服务系统。; 适合人群:具备Java基础和Spring Boot开发经验,熟悉微服务基本概念的中高级研发人员,尤其是希望深入理解高并发系统设计、分布式事务、服务治理等核心技术的开发者;适合工作2-5年、有志于转型微服务或提升架构能力的工程师; 使用场景及目标:①学习如何基于Spring Cloud Alibaba构建完整的微服务项目;②掌握秒杀场景下高并发、超卖控制、异步化、削峰填谷等关键技术方案;③实践分布式事务(Seata)、服务熔断降级、链路追踪、统一配置中心等企业级中间件的应用;④完成从本地开发到容器化部署的全流程落地; 阅读建议:建议按照文档提供的七个阶段循序渐进地动手实践,重点关注秒杀流程设计、服务间通信机制、分布式事务实现和系统性能优化部分,结合代码调试与监控工具深入理解各组件协作原理,真正掌握高并发微服务系统的构建能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值