Android应用开发--MP3音乐播放器代码实现(二)

Android应用开发--MP3音乐播放器代码实现(二)

 

2013年5月25日 简、美音乐播放器开发

小巫在这里罗列这个播放器已经实现的功能:

1.   自动显示音乐列表

2.   点击列表播放音乐

3.   长按列表弹出对话框

4.   暂停音乐

5.   上一首音乐

6.   下一首音乐

7.   自动播放下一首歌曲

8.   单曲循环

9.   全部循环

10.  随机播放

 

以上所有功能将会分为两篇博文来讲解,首先是主界面的,接着是播放界面的。在这里要说明一点,以上功能是小巫自己一点一点调试才实现的,并不能完全排除考虑不周的地方,原本这个软件实现起来并不太难,但确实要考虑到很多细节的地方,播放状态的切换和控制就是一块,也花了我不少实现,之前还很苦恼实现自己想要的效果,但后来还是经过思考和调试把功能实现。所以说,开发是一个需要很耐心的过程,各位童鞋,如果真正喜欢编程的话,想要做出一些小作品的话,那就好好掂量自己的耐心吧,好了,废话不多说,先贴一大段代码,后面在慢慢把需要注意的地方说一下。

主界面效果图:

            

以上界面的效果怎么实现的?

很简单的,就是ListView的数据填充,但要填的的东西就要考虑了,怎么把数据从SQLite中获取,小巫封装了一个工具类,用来获取与MP3相关的数据。

==>MediaUtils

package com.wwj.sb.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import android.content.Context;
import android.database.Cursor;
import android.provider.MediaStore;

import com.wwj.sb.domain.Mp3Info;

public class MediaUtil {
	/**
	 * 用于从数据库中查询歌曲的信息,保存在List当中
	 * 
	 * @return
	 */
	public static List<Mp3Info> getMp3Infos(Context context) {
		Cursor cursor = context.getContentResolver().query(
				MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
				MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
		List<Mp3Info> mp3Infos = new ArrayList<Mp3Info>();
		for (int i = 0; i < cursor.getCount(); i++) {
			cursor.moveToNext();
			Mp3Info mp3Info = new Mp3Info();
			long id = cursor.getLong(cursor
					.getColumnIndex(MediaStore.Audio.Media._ID));				//音乐id
			String title = cursor.getString((cursor	
					.getColumnIndex(MediaStore.Audio.Media.TITLE)));			//音乐标题
			String artist = cursor.getString(cursor
					.getColumnIndex(MediaStore.Audio.Media.ARTIST));			//艺术家
			long duration = cursor.getLong(cursor
					.getColumnIndex(MediaStore.Audio.Media.DURATION));			//时长
			long size = cursor.getLong(cursor
					.getColumnIndex(MediaStore.Audio.Media.SIZE));				//文件大小
			String url = cursor.getString(cursor
					.getColumnIndex(MediaStore.Audio.Media.DATA));				//文件路径
			int isMusic = cursor.getInt(cursor
					.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));			//是否为音乐
			if (isMusic != 0) {		//只把音乐添加到集合当中
				mp3Info.setId(id);
				mp3Info.setTitle(title);
				mp3Info.setArtist(artist);
				mp3Info.setDuration(duration);
				mp3Info.setSize(size);
				mp3Info.setUrl(url);
				mp3Infos.add(mp3Info);
			}
		}
		return mp3Infos;
	}
	
	/**
	 * 往List集合中添加Map对象数据,每一个Map对象存放一首音乐的所有属性
	 * @param mp3Infos
	 * @return
	 */
	public static List<HashMap<String, String>> getMusicMaps(
			List<Mp3Info> mp3Infos) {
		List<HashMap<String, String>> mp3list = new ArrayList<HashMap<String, String>>();
		for (Iterator iterator = mp3Infos.iterator(); iterator.hasNext();) {
			Mp3Info mp3Info = (Mp3Info) iterator.next();
			HashMap<String, String> map = new HashMap<String, String>();
			map.put("title", mp3Info.getTitle());
			map.put("Artist", mp3Info.getArtist());
			map.put("duration", formatTime(mp3Info.getDuration()));
			map.put("size", String.valueOf(mp3Info.getSize()));
			map.put("url", mp3Info.getUrl());
			mp3list.add(map);
		}
		return mp3list;
	}
	
	/**
	 * 格式化时间,将毫秒转换为分:秒格式
	 * @param time
	 * @return
	 */
	public static String formatTime(long time) {
		String min = time / (1000 * 60) + "";
		String sec = time % (1000 * 60) + "";
		if (min.length() < 2) {
			min = "0" + time / (1000 * 60) + "";
		} else {
			min = time / (1000 * 60) + "";
		}
		if (sec.length() == 4) {
			sec = "0" + (time % (1000 * 60)) + "";
		} else if (sec.length() == 3) {
			sec = "00" + (time % (1000 * 60)) + "";
		} else if (sec.length() == 2) {
			sec = "000" + (time % (1000 * 60)) + "";
		} else if (sec.length() == 1) {
			sec = "0000" + (time % (1000 * 60)) + "";
		}
		return min + ":" + sec.trim().substring(0, 2);
	}
}


好吧,来重头戏了,一大段代码来袭。

HomeActivity.Java

package com.wwj.sb.activity;

import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Vibrator;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

import com.wwj.sb.domain.AppConstant;
import com.wwj.sb.domain.Mp3Info;
import com.wwj.sb.service.PlayerService;
import com.wwj.sb.utils.ConstantUtil;
import com.wwj.sb.utils.CustomDialog;
import com.wwj.sb.utils.MediaUtil;

/**
 * 2013/5/7
 * 简、美音乐播放器
 * @author wwj
 * 
 */
public class HomeActivity extends Activity {
	private ListView mMusiclist; // 音乐列表
	private List<Mp3Info> mp3Infos = null;
	private SimpleAdapter mAdapter; // 简单适配器
	private Button previousBtn; // 上一首
	private Button repeatBtn; // 重复(单曲循环、全部循环)
	private Button playBtn; // 播放(播放、暂停)
	private Button shuffleBtn; // 随机播放
	private Button nextBtn; // 下一首
	private TextView musicTitle;//歌曲标题
	private TextView musicDuration;	//歌曲时间
	private Button musicPlaying;	//歌曲专辑

	private int repeatState;		//循环标识
	private final int isCurrentRepeat = 1; // 单曲循环
	private final int isAllRepeat = 2; // 全部循环
	private final int isNoneRepeat = 3; // 无重复播放
	private boolean isFirstTime = true; 
	private boolean isPlaying; // 正在播放
	private boolean isPause; // 暂停
	private boolean isNoneShuffle = true; // 顺序播放
	private boolean isShuffle = false; // 随机播放
	
	
	private int listPosition = 0;	//标识列表位置
	private HomeReceiver homeReceiver;	//自定义的广播接收器
	//一系列动作
	public static final String UPDATE_ACTION = "com.wwj.action.UPDATE_ACTION";
	public static final String CTL_ACTION = "com.wwj.action.CTL_ACTION";
	public static final String MUSIC_CURRENT = "com.wwj.action.MUSIC_CURRENT";
	public static final String MUSIC_DURATION = "com.wwj.action.MUSIC_DURATION";
	public static final String REPEAT_ACTION = "com.wwj.action.REPEAT_ACTION";
	public static final String SHUFFLE_ACTION = "com.wwj.action.SHUFFLE_ACTION";
	
	
	private int currentTime;
	private int duration;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.home_activity_layout);

		mMusiclist = (ListView) findViewById(R.id.music_list);
		mMusiclist.setOnItemClickListener(new MusicListItemClickListener());
		mMusiclist.setOnCreateContextMenuListener(new MusicListItemContextMenuListener());
		mp3Infos = MediaUtil.getMp3Infos(getApplicationContext());	//获取歌曲对象集合
		setListAdpter(MediaUtil.getMusicMaps(mp3Infos));	//显示歌曲列表
		findViewById();				//找到界面上的每一个控件
		setViewOnclickListener();	//为一些控件设置监听器
		repeatState = isNoneRepeat; // 初始状态为无重复播放状态
		
		
		homeReceiver = new HomeReceiver();
		// 创建IntentFilter
		IntentFilter filter = new IntentFilter();
		// 指定BroadcastReceiver监听的Action
		filter.addAction(UPDATE_ACTION);
		filter.addAction(MUSIC_CURRENT);
		filter.addAction(MUSIC_DURATION);
		filter.addAction(REPEAT_ACTION);
		filter.addAction(SHUFFLE_ACTION);
		// 注册BroadcastReceiver
		registerReceiver(homeReceiver, filter);
		

	}

	/**
	 * 从界面上根据id获取按钮
	 */
	private void findViewById() {
		previousBtn = (Button) findViewById(R.id.previous_music);
		repeatBtn = (Button) findViewById(R.id.repeat_music);
		playBtn = (Button) findViewById(R.id.play_music);
		shuffleBtn = (Button) findViewById(R.id.shuffle_music);
		nextBtn = (Button) findViewById(R.id.next_music);
		musicTitle = (TextView) findViewById(R.id.music_title);
		musicDuration = (TextView) findViewById(R.id.music_duration);
		musicPlaying = (Button) findViewById(R.id.playing);
	}

	/**
	 * 给每一个按钮设置监听器
	 */
	private void setViewOnclickListener() {
		ViewOnClickListener viewOnClickListener = new ViewOnClickListener();
		previousBtn.setOnClickListener(viewOnClickListener);
		repeatBtn.setOnClickListener(viewOnClickListener);
		playBtn.setOnClickListener(viewOnClickListener);
		shuffleBtn.setOnClickListener(viewOnClickListener);
		nextBtn.setOnClickListener(viewOnClickListener);
		musicPlaying.setOnClickListener(viewOnClickListener);
	}

	private class ViewOnClickListener implements OnClickListener {
		Intent intent = new Intent();
		@Override
		public void onClick(View v) {
			switch (v.getId()) {
			case R.id.previous_music: // 上一首
				playBtn.setBackgroundResource(R.drawable.play_selector);
				isFirstTime = false;
				isPlaying = true;
				isPause = false;
				previous();
				break;
			case R.id.repeat_music: // 重复播放
				if (repeatState == isNoneRepeat) {
					repeat_one();
					shuffleBtn.setClickable(false);
					repeatState = isCurrentRepeat;
				} else if (repeatState == isCurrentRepeat) {
					repeat_all();
					shuffleBtn.setClickable(false);
					repeatState = isAllRepeat;
				} else if (repeatState == isAllRepeat) {
					repeat_none();
					shuffleBtn.setClickable(true);
					repeatState = isNoneRepeat;
				}
				switch (repeatState) {
				case isCurrentRepeat: // 单曲循环
					repeatBtn
							.setBackgroundResource(R.drawable.repeat_current_selector);
					Toast.makeText(HomeActivity.this, R.string.repeat_current,
							Toast.LENGTH_SHORT).show();
					break;
				case isAllRepeat: // 全部循环
					repeatBtn
							.setBackgroundResource(R.drawable.repeat_all_selector);
					Toast.makeText(HomeActivity.this, R.string.repeat_all,
							Toast.LENGTH_SHORT).show();
					break;
				case isNoneRepeat: // 无重复
					repeatBtn
							.setBackgroundResource(R.drawable.repeat_none_selector);
					Toast.makeText(HomeActivity.this, R.string.repeat_none,
							Toast.LENGTH_SHORT).show();
					break;
				}

				break;
			case R.id.play_music: // 播放音乐
				if(isFirstTime) {
					play();
					isFirstTime = false;
					isPlaying = true;
					isPause = false;
				} else {
					if (isPlaying) {
						playBtn.setBackgroundResource(R.drawable.pause_selector);
						intent.setAction("com.wwj.media.MUSIC_SERVICE");
						intent.putExtra("MSG", AppConstant.PlayerMsg.PAUSE_MSG);
						startService(intent);
						isPlaying = false;
						isPause = true;
						
					} else if (isPause) {
						playBtn.setBackgroundResource(R.drawable.play_selector);
						intent.setAction("com.wwj.media.MUSIC_SERVICE");
						intent.putExtra("MSG", AppConstant.PlayerMsg.CONTINUE_MSG);
						startService(intent);
						isPause = false;
						isPlaying = true;
					}
				}
				break;
			case R.id.shuffle_music: // 随机播放
				if (isNoneShuffle) {
					shuffleBtn
							.setBackgroundResource(R.drawable.shuffle_selector);
					Toast.makeText(HomeActivity.this, R.string.shuffle,
							Toast.LENGTH_SHORT).show();
					isNoneShuffle = false;
					isShuffle = true;
					shuffleMusic();
					repeatBtn.setClickable(false);
				} else if (isShuffle) {
					shuffleBtn
							.setBackgroundResource(R.drawable.shuffle_none_selector);
					Toast.makeText(HomeActivity.this, R.string.shuffle_none,
							Toast.LENGTH_SHORT).show();
					isShuffle = false;
					isNoneShuffle = true;
					repeatBtn.setClickable(true);
				}
				break;
			case R.id.next_music: // 下一首
				playBtn.setBackgroundResource(R.drawable.play_selector);
				isFirstTime = false;
				isPlaying = true;
				isPause = false;
				next();
				break;
			case R.id.playing:	//正在播放
				Mp3Info mp3Info = mp3Infos.get(listPosition);
				Intent intent = new Intent(HomeActivity.this, PlayerActivity.class);
				intent.putExtra("title", mp3Info.getTitle());	
				intent.putExtra("url", mp3Info.getUrl());
				intent.putExtra("artist", mp3Info.getArtist());
				intent.putExtra("listPosition", listPosition);
				intent.putExtra("currentTime", currentTime);
				intent.putExtra("duration", duration);
				intent.putExtra("MSG", AppConstant.PlayerMsg.PLAYING_MSG);
				startActivity(intent);
				break;
			}
		}
	}

	private class MusicListItemClickListener implements OnItemClickListener {
		/**
		 * 点击列表播放音乐
		 */
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position,
				long id) {
			listPosition = position;
			playMusic(listPosition);		
		}

	}
	
	public class MusicListItemContextMenuListener implements OnCreateContextMenuListener {

		@Override
		public void onCreateContextMenu(ContextMenu menu, View v,
				ContextMenuInfo menuInfo) {
			Vibrator vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);
			vibrator.vibrate(50); 		//长按振动
			musicListItemDialog();		//长按后弹出的对话框
		}

	}

	/**
	 * 填充列表
	 * 
	 * @param mp3Infos
	 */
	public void setListAdpter(List<HashMap<String, String>> mp3list) {
		mAdapter = new SimpleAdapter(this, mp3list,
				R.layout.music_list_item_layout, new String[] { "title",
						"Artist", "duration" }, new int[] { R.id.music_title,
						R.id.music_Artist, R.id.music_duration });
		mMusiclist.setAdapter(mAdapter);
	}
	
	
	/**
	 * 下一首歌曲
	 */
	public void next() {
		listPosition = listPosition + 1;
		if(listPosition <= mp3Infos.size() - 1) {
			Mp3Info mp3Info = mp3Infos.get(listPosition);
			musicTitle.setText(mp3Info.getTitle());
			Intent intent = new Intent();
			intent.setAction("com.wwj.media.MUSIC_SERVICE");
			intent.putExtra("listPosition", listPosition);
			intent.putExtra("url", mp3Info.getUrl());
			intent.putExtra("MSG", AppConstant.PlayerMsg.NEXT_MSG);
			startService(intent);
		} else {
			Toast.makeText(HomeActivity.this, "没有下一首了", Toast.LENGTH_SHORT).show();
		}
	}

	/**
	 * 上一首歌曲
	 */
	public void previous() {
		listPosition = listPosition - 1;
		if(listPosition >= 0) {
			Mp3Info mp3Info = mp3Infos.get(listPosition);
			musicTitle.setText(mp3Info.getTitle());
			Intent intent = new Intent();
			intent.setAction("com.wwj.media.MUSIC_SERVICE");
			intent.putExtra("listPosition", listPosition);
			intent.putExtra("url", mp3Info.getUrl());
			intent.putExtra("MSG", AppConstant.PlayerMsg.PRIVIOUS_MSG);
			startService(intent);
		}else {
			Toast.makeText(HomeActivity.this, "没有上一首了", Toast.LENGTH_SHORT).show();
		}
	}

	public void play() {
		playBtn.setBackgroundResource(R.drawable.play_selector);
		Mp3Info mp3Info = mp3Infos.get(listPosition);
		musicTitle.setText(mp3Info.getTitle());
		Intent intent = new Intent();
		intent.setAction("com.wwj.media.MUSIC_SERVICE");
		intent.putExtra("listPosition", 0);
		intent.putExtra("url", mp3Info.getUrl());
		intent.putExtra("MSG", AppConstant.PlayerMsg.PLAY_MSG);
		startService(intent);
	}
	
	/**
	 * 单曲循环
	 */
	public void repeat_one() {
		Intent intent = new Intent(CTL_ACTION);
		intent.putExtra("control", 1);
		sendBroadcast(intent);
	}
	
	/**
	 * 全部循环
	 */
	public void repeat_all() {
		Intent intent = new Intent(CTL_ACTION);
		intent.putExtra("control", 2);
		sendBroadcast(intent);
	}

	/**
	 * 顺序播放
	 */
	public void repeat_none() {
		Intent intent = new Intent(CTL_ACTION);
		intent.putExtra("control", 3);
		sendBroadcast(intent);
	}
	
	/**
	 * 随机播放
	 */
	public void shuffleMusic() {
		Intent intent = new Intent(CTL_ACTION);
		intent.putExtra("control", 4);
		sendBroadcast(intent);
	}

	public void musicListItemDialog() {
		String[] menuItems = new String[]{"播放音乐","设为铃声","查看详情"};
		ListView menuList = new ListView(HomeActivity.this);
		menuList.setCacheColorHint(Color.TRANSPARENT);
		menuList.setDividerHeight(1);
		menuList.setAdapter(new ArrayAdapter<String>(HomeActivity.this, R.layout.context_dialog_layout, R.id.dialogText, menuItems));
		menuList.setLayoutParams(new LayoutParams(ConstantUtil.getScreen(HomeActivity.this)[0] / 2, LayoutParams.WRAP_CONTENT));
		
		
		final CustomDialog customDialog = new CustomDialog.Builder(HomeActivity.this).setTitle(R.string.operation).setView(menuList).create();
		customDialog.show();
		
		menuList.setOnItemClickListener( new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				customDialog.cancel();
				customDialog.dismiss();
			}
			
		});
	}
	public void playMusic(int listPosition) {
		if (mp3Infos != null) {
			Mp3Info mp3Info = mp3Infos.get(listPosition);
			musicTitle.setText(mp3Info.getTitle());
			Intent intent = new Intent(HomeActivity.this, PlayerActivity.class);
			intent.putExtra("title", mp3Info.getTitle());	
			intent.putExtra("url", mp3Info.getUrl());
			intent.putExtra("artist", mp3Info.getArtist());
			intent.putExtra("listPosition", listPosition);
			intent.putExtra("currentTime", currentTime);
			intent.putExtra("repeatState", repeatState);
			intent.putExtra("shuffleState", isShuffle);
			intent.putExtra("MSG", AppConstant.PlayerMsg.PLAY_MSG);
			startActivity(intent);
		}
	}
	
	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
	}
	
	
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}
	
	/**
	 * 按返回键弹出对话框确定退出
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK
				&& event.getAction() == KeyEvent.ACTION_DOWN) {

			new AlertDialog.Builder(this)
					.setIcon(R.drawable.ic_launcher)
					.setTitle("退出")
					.setMessage("您确定要退出?")
					.setNegativeButton("取消", null)
					.setPositiveButton("确定",
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									finish();
									Intent intent = new Intent(
											HomeActivity.this,
											PlayerService.class);
									unregisterReceiver(homeReceiver);
									stopService(intent); // 停止后台服务
								}
							}).show();

		}
		return super.onKeyDown(keyCode, event);
	}
	
	
	//自定义的BroadcastReceiver,负责监听从Service传回来的广播
	public class HomeReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();	
			if(action.equals(MUSIC_CURRENT)){
				//currentTime代表当前播放的时间
				currentTime = intent.getIntExtra("currentTime", -1);
				musicDuration.setText(MediaUtil.formatTime(currentTime));
			} else if (action.equals(MUSIC_DURATION)) {
				duration = intent.getIntExtra("duration", -1);
			}
			else if(action.equals(UPDATE_ACTION)) {
				//获取Intent中的current消息,current代表当前正在播放的歌曲
				listPosition = intent.getIntExtra("current", -1);
				if(listPosition >= 0) {
					musicTitle.setText(mp3Infos.get(listPosition).getTitle());
				}
			}else if(action.equals(REPEAT_ACTION)) {
				repeatState = intent.getIntExtra("repeatState", -1);
				switch (repeatState) {
				case isCurrentRepeat: // 单曲循环
					repeatBtn
							.setBackgroundResource(R.drawable.repeat_current_selector);
					shuffleBtn.setClickable(false);
					break;
				case isAllRepeat: // 全部循环
					repeatBtn
							.setBackgroundResource(R.drawable.repeat_all_selector);
					shuffleBtn.setClickable(false);
					break;
				case isNoneRepeat: // 无重复
					repeatBtn
							.setBackgroundResource(R.drawable.repeat_none_selector);
					shuffleBtn.setClickable(true);
					break;
				}
			}
			else if(action.equals(SHUFFLE_ACTION)) {
				isShuffle = intent.getBooleanExtra("shuffleState", false);
				if(isShuffle) {
					isNoneShuffle = false;
					shuffleBtn.setBackgroundResource(R.drawable.shuffle_selector);
					repeatBtn.setClickable(false);
				} else {
					isNoneShuffle = true;
					shuffleBtn.setBackgroundResource(R.drawable.shuffle_none_selector);
					repeatBtn.setClickable(true);
				}
			}
		}
		
	}
}


到这里,要开讲啦。

以下是需要注意的几点:

1. 音乐是通过Service来播放的,Activity通过启动服务来实现在后台播放音乐。

2. Activity中自定义了一个广播接收器,需要进行intent过滤器的定义,动作的添加,注册广播接收器:

		homeReceiver = new HomeReceiver();
		// 创建IntentFilter
		IntentFilter filter = new IntentFilter();
		// 指定BroadcastReceiver监听的Action
		filter.addAction(UPDATE_ACTION);
		filter.addAction(MUSIC_CURRENT);
		filter.addAction(MUSIC_DURATION);
		filter.addAction(REPEAT_ACTION);
		filter.addAction(SHUFFLE_ACTION);
		// 注册BroadcastReceiver
		registerReceiver(homeReceiver, filter);
		


3. 在广播接收器类当中对动作进行处理,比如实现时间的更新和标题的更新等。

4. 这里还要注意按钮触发,播放状态的改变,比如音乐循环,有三种状态:单曲、全部循环、顺序,每切换一个状态都要向服务发送一条广播,通知它要改变状态。

5. 点击列表的时候,会跳入到播放界面的Activity中,要注意用intent来传递参数,注意每个参数的用途,比如title、url、MSG,就分别代表标题、路径、播放状态。

6. 长按列表会弹出自定义对话框,也会有短暂的震动效果,自定义对话框需要自行实现。这里我也贴一下实现代码吧。

package com.wwj.sb.utils;


import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.wwj.sb.activity.R;

/**
 * 自定义对话框类
 * 
 * @author wwj
 * 
 */
public class CustomDialog extends Dialog {

	public CustomDialog(Context context) {
		super(context);
	}

	public CustomDialog(Context context, int theme) {
		super(context, theme);
	}

	public static class Builder {

		private Context context;
		private int mIcon = -1; // 提示图标
		private CharSequence mTitle; // 提示标题
		private CharSequence mMessage; // 提示内容
		private CharSequence mPositiveButtonText; // 确定按钮文本
		private CharSequence mNegativeButtonText; // 取消按钮文本
		private CharSequence mNeutralButtonText; // 中间按钮文本
		private boolean mCancelable = true; // 是否启用取消键

		private int mViewSpacingLeft;
		private int mViewSpacingTop;
		private int mViewSpacingRight;
		private int mViewSpacingBottom;
		private boolean mViewSpacingSpecified = false;

		// 提示内容View
		private View mView;

		// 各种触发事件
		private OnClickListener mPositiveButtonClickListener,
				mNegativeButtonClickListener, mNeutralButtonClickListener;
		private OnCancelListener mCancelListener; // 取消键事件
		private OnKeyListener mKeyListener; // 按键处理

		public Builder(Context context) {
			this.context = context;
		}

		public Builder setMessage(CharSequence message) {
			this.mMessage = message;
			return this;
		}

		public Builder setMessage(int message) {
			this.mMessage = context.getText(message);
			return this;
		}

		public Builder setTitle(int title) {
			this.mTitle = context.getText(title);
			return this;
		}

		public Builder setTitle(CharSequence title) {
			this.mTitle = title;
			return this;
		}

		public Builder setIcon(int icon) {
			this.mIcon = icon;
			return this;
		}

		public Builder setView(View view) {
			this.mView = view;
			mViewSpacingSpecified = false;
			return this;
		}

		public Builder setView(View view, int left, int top, int right,
				int bottom) {
			this.mView = view;
			this.mViewSpacingLeft = left;
			this.mViewSpacingTop = top;
			this.mViewSpacingRight = right;
			this.mViewSpacingBottom = bottom;
			mViewSpacingSpecified = true;
			return this;
		}

		public Builder setPositonButton(int textId,
				final OnClickListener listener) {
			this.mPositiveButtonText = context.getText(textId);
			this.mPositiveButtonClickListener = listener;
			return this;
		}

		public Builder setPostionButton(String text,
				final OnClickListener listener) {
			this.mPositiveButtonText = text;
			this.mPositiveButtonClickListener = listener;
			return this;
		}

		public Builder setNeutralButton(int textId,
				final OnClickListener listener) {
			this.mNeutralButtonText = context.getText(textId);
			this.mNeutralButtonClickListener = listener;
			return this;
		}
		
		public Builder setNeutralButton(String text, final OnClickListener listener) {
			this.mNeutralButtonText = text;
			this.mNeutralButtonClickListener = listener;
			return this;
		}
		public Builder setNegativeButton(int textId,
				final OnClickListener listener) {
			this.mNegativeButtonText = context.getText(textId);
			this.mNegativeButtonClickListener = listener;
			return this;
		}

		public Builder setNegativeButton(String text,
				final OnClickListener listener) {
			this.mNegativeButtonText = text;
			this.mNegativeButtonClickListener = listener;
			return this;
		}
		
		
		public Builder setCancelable(boolean cancelable) {
			this.mCancelable = cancelable;
			return this;
		}
		
		public Builder setOnCancelListener(OnCancelListener listener) {
			this.mCancelListener = listener;
			return this;
		}
		
		public Builder setOnKeyListener(OnKeyListener listener) {
			this.mKeyListener = listener;
			return this;
		}
		
		public CustomDialog create() {
			LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			final CustomDialog dialog = new CustomDialog(context, R.style.CustomDialog);
			dialog.setCancelable(mCancelable);
			//设置取消键事件
			if(mCancelListener != null) {
				dialog.setOnCancelListener(mCancelListener);
			}
			//设置键盘监听事件
			if(mKeyListener != null) {
				dialog.setOnKeyListener(mKeyListener);
			}
			//获取对话框布局
			View layout = inflater.inflate(R.layout.alert_dialog, (ViewGroup)(((Activity)context).findViewById(R.id.parentPanel)));
			layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
			
			//设置标题
			((TextView) layout.findViewById(R.id.alertTitle)).setText(mTitle);
			//设置图标
			if(mIcon != -1) {
				((ImageView) layout.findViewById(R.id.icon))
				.setBackgroundResource(mIcon);
			}
			
			int count = 0;
			//设置确定按钮
			if(setButton(layout, mPositiveButtonText, R.id.button1, dialog, mPositiveButtonClickListener)) count++;
			// 设置拒绝按钮
			if(setButton(layout, mNegativeButtonText, R.id.button2, dialog, mNegativeButtonClickListener)) count++;
			// 设置中间按钮
			if(setButton(layout, mNeutralButtonText, R.id.button3, dialog, mNeutralButtonClickListener)) count++;
			
			if(count == 0) {
				layout.findViewById(R.id.buttonPanel).setVisibility(View.GONE);
			}
			//一个按钮时,显示两边空间
			if(count == 1) {
				layout.findViewById(R.id.leftSpacer)
					.setVisibility(View.INVISIBLE);
				layout.findViewById(R.id.rightSpacer).setVisibility(View.INVISIBLE);
			}
			//设置提示消息
			if(!TextUtils.isEmpty(mMessage)) {
				((TextView)layout.findViewById(R.id.message))
					.setText(mMessage);
			} else {
				((LinearLayout) layout.findViewById(R.id.contentPanel))
					.setVisibility(View.GONE);
			}
			//设置提示内容布局
			if(mView != null) {
				final FrameLayout customPanel = (FrameLayout) layout
						.findViewById(R.id.customPanel);
				if(mViewSpacingSpecified) {
					customPanel.setPadding(mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight, mViewSpacingBottom);
				}
				customPanel.addView(mView);
			} else {
				((FrameLayout) layout.findViewById(R.id.customPanel))
							.setVisibility(View.GONE);
			}
			dialog.setContentView(layout);
			return dialog;
				
		}
		
		public CustomDialog show() {
			CustomDialog dialog = create();
			dialog.show();
			return dialog;
		}
		
		private boolean setButton(View layout, CharSequence mPositiveButtonText, int id, final Dialog dialog, final OnClickListener listener) {
			if(!TextUtils.isEmpty(mPositiveButtonText)) {
				final Button button = (Button) layout.findViewById(id);
				button.setText(mPositiveButtonText);
				if(listener != null) {
					button.setOnClickListener(new View.OnClickListener() {
						
						@Override
						public void onClick(View v) {
							listener.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
						}
					});
				} else {
					//默认事件为关闭对话框
					button.setOnClickListener(new View.OnClickListener() {
						
						@Override
						public void onClick(View v) {
							dialog.cancel();
							dialog.dismiss();
						}
					});
				}
				return true;
			} else {
				layout.findViewById(id).setVisibility(View.GONE);
				return false;
			}
		}
	}
}

关于主界面的业务逻辑具体实现和需要注意的地方,小巫已经说完了。其实最重要的是要写好服务类,下一篇播放将会给童鞋们介绍服务类的实现。最后感谢大家的关注。


  • 53
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 50
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 50
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小巫技术博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值