MainActivity 代码

package cn.tedu.music_player_2.activity;

import java.util.List;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;
import cn.tedu.music_player_2.R;
import cn.tedu.music_player_2.adapter.MusicAdapter;
import cn.tedu.music_player_2.app.MusicPlayerApplication;
import cn.tedu.music_player_2.entity.Music;
import cn.tedu.music_player_2.service.PlayMusicService;
import cn.tedu.music_player_2.util.CommonUtils;
import cn.tedu.music_player_2.util.IMusicPlayer;

/**
* MainActivity
*
* @author chengheng
* @version 2.0
*/
public class MainActivity extends Activity implements View.OnClickListener,

OnItemClickListener, OnSeekBarChangeListener {
/**
* ListView:歌曲列表
*/
private ListView lvMusics;
/**
* ImageButton:播放或暂停
*/
private ImageButton ibPlayOrPause;
/**
* ImageButton:播放上一首
*/
private ImageButton ibPrevious;
/**
* ImageButton:播放下一首
*/
private ImageButton ibNext;
/**
* TextView:显示当前播放的歌曲的名称
*/
private TextView tvMusicTitle;
/**
* SeekBar:歌曲的播放进度
*/
private SeekBar sbMusicProgress;
/**
* TextView:歌曲当前播放到的时间
*/
private TextView tvMusicCurrentPosition;
/**
* TextView:当前播放的歌曲的时长
*/
private TextView tvMusicDuration;
/**
* 歌曲数据的List集合
*/
private List musics;
/**
* 歌曲列表的Adapter
*/
private MusicAdapter musicAdapter;
/**
* Application
*/
private MusicPlayerApplication app;
/**
* ServiceConnection:Activity与Service建立的连接
*/
private InnerServiceConnection conn;
/**
* 当Activity与Service连接后,调用Service方法的工具
*/
private IMusicPlayer player;
/**
* 更新歌曲播放信息的线程
*/
private UpdateProgressThread updateProgressThread;
/**
* 播放器是否已经开始运行
*/
private boolean isPlayerWorking;
/**
* 用户是否正在拖拽进度条
*/
private boolean isUserTrackingTouch;

@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    // 绑定Service    Intent intent = new Intent(this, PlayMusicService.class);    conn = new InnerServiceConnection();    bindService(intent, conn, BIND_AUTO_CREATE);    // 初始化控件    lvMusics = (ListView) findViewById(R.id.lv_musics);    ibPlayOrPause = (ImageButton) findViewById

(R.id.ib_play_or_pause);
ibPrevious = (ImageButton) findViewById(R.id.ib_previous);
ibNext = (ImageButton) findViewById(R.id.ib_next);
tvMusicTitle = (TextView) findViewById(R.id.tv_music_title);
sbMusicProgress = (SeekBar) findViewById(R.id.sb_music_progress);
tvMusicCurrentPosition = (TextView) findViewById

(R.id.tv_music_current_position);
tvMusicDuration = (TextView) findViewById

(R.id.tv_music_duration);

    // 获取歌曲列表的数据    app = (MusicPlayerApplication) getApplication();    musics = app.getMusics();    // 显示歌曲列表的ListView    musicAdapter = new MusicAdapter(this, musics);    lvMusics.setAdapter(musicAdapter);    // 为按钮配置监听器    ibPlayOrPause.setOnClickListener(this);    ibPrevious.setOnClickListener(this);    ibNext.setOnClickListener(this);    // 为ListView配置监听器    lvMusics.setOnItemClickListener(this);    // 为SeekBar配置监听器    sbMusicProgress.setOnSeekBarChangeListener(this);}@Overrideprotected void onRestart() {    // 判断是否正在播放    if(player.callIsPlaying()) {        // 开启线程更新播放信息        startUpdateProgressThread();    }    super.onRestart();}@Overrideprotected void onStop() {    // 停止更新播放信息    stopUpdateProgressThread();    super.onStop();}@Overrideprotected void onDestroy() {    // 解除与Service的绑定    if (conn != null) {        unbindService(conn);    }    super.onDestroy();}@Overridepublic void onClick(View v) {    switch (v.getId()) {    case R.id.ib_play_or_pause:        // 判断当前的状态        if (player.callIsPlaying()) {            // 正在播放,则暂停            player.callPause();            // 更换按钮图片:换为“播放”            ibPlayOrPause.setImageResource

(android.R.drawable.ic_media_play);
// 停止更新歌曲播放信息
stopUpdateProgressThread();
} else {
// 没有播放,则播放
player.callPlay();
// 更换按钮图片:换为“暂停”
ibPlayOrPause.setImageResource

(android.R.drawable.ic_media_pause);
// 开启线程,更新播放信息
startUpdateProgressThread();
// 更新标识:播放器开始工作
isPlayerWorking = true;
}
break;

    case R.id.ib_previous:        // 播放上一首        player.callPrevious();        // 更换按钮图片:换为“暂停”        ibPlayOrPause.setImageResource

(android.R.drawable.ic_media_pause);
// 开启线程,更新播放信息
startUpdateProgressThread();
// 更新标识:播放器开始工作
isPlayerWorking = true;
break;

    case R.id.ib_next:        // 播放下一首        player.callNext();        // 更换按钮图片:换为“暂停”        ibPlayOrPause.setImageResource

(android.R.drawable.ic_media_pause);
// 开启线程,更新播放信息
startUpdateProgressThread();
// 更新标识:播放器开始工作
isPlayerWorking = true;
break;
}
}

@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, 

long id) {
// 播放指定的歌曲
player.callPlay(position);
// 更换按钮图片:换为“暂停”
ibPlayOrPause.setImageResource

(android.R.drawable.ic_media_pause);
// 开启线程,更新播放信息
startUpdateProgressThread();
// 更新标识:播放器开始工作
isPlayerWorking = true;
}

@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {    // 标志用户正在拖拽进度条    isUserTrackingTouch = true;}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {    // 标志用户已经停止拖拽进度条    isUserTrackingTouch = false;    // 判断播放器是否已开始工作    if(isPlayerWorking) {        // 获取拖拽后的进度        int progress = sbMusicProgress.getProgress();        // 调用Service中对应的方法        player.callSeekTo(progress);        // 开启线程,更新播放进度        startUpdateProgressThread();        // 设置播放按钮显示的图片为“暂停”        ibPlayOrPause.setImageResource

(android.R.drawable.ic_media_pause);
}
}

/** * 开启线程,更新播放信息 */private void startUpdateProgressThread() {    if(updateProgressThread == null) {        updateProgressThread = new UpdateProgressThread();        updateProgressThread.setRunning(true);        updateProgressThread.start();    }}/** * 停止更新播放信息的线程 */private void stopUpdateProgressThread() {    if(updateProgressThread != null) {        updateProgressThread.setRunning(false);        updateProgressThread = null;    }}/** * 更新播放信息的线程 */private class UpdateProgressThread extends Thread {    private boolean isRunning;    private String musicName;    private int progress;    private String currentPositionString;    private String durationString;    public void setRunning(boolean isRunning) {        this.isRunning = isRunning;    }    private Runnable runner = new Runnable() {        @Override        public void run() {            // 更新控件:歌曲标题            tvMusicTitle.setText(musicName);            // 更新控件:当前歌曲时长            tvMusicDuration.setText(durationString);            // 更新控件:当前播放时间            tvMusicCurrentPosition.setText

(currentPositionString);

            // 判断用户是否正在拖拽进度条            if(!isUserTrackingTouch) {                // 更新控件:进度条                sbMusicProgress.setProgress(progress);            }        }    };    @Override    public void run() {        // 循环        while(isRunning) {            // 日志            Log.d("tedu", "UpdateProgressThread.run()");            // 判断是否正在播放            if(player.callIsPlaying()) {                // 获取所需的数据                int currentMusicIndex = 

player.callGetCurrentMusicIndex();
int currentPosition =

player.callGetCurrentPosition();
int duration = player.callGetDuration();

                // 计算需要被显示的数据                musicName = "正在播放:" + musics.get

(currentMusicIndex).getName();
progress = currentPosition * 100 /

duration;
currentPositionString =

CommonUtils.getFormattedTime(currentPosition);
durationString =

CommonUtils.getFormattedTime(duration);

                // 更新显示                runOnUiThread(runner);            }            // 休眠            try {                Thread.sleep(500);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}/** * ServiceConnection */private class InnerServiceConnection implements ServiceConnection {    @Override    public void onServiceConnected(ComponentName name, IBinder 

service) {
player = (IMusicPlayer) service;
}

    @Override    public void onServiceDisconnected(ComponentName name) {        // (无视)    }}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean 

fromUser) {
// (无视)
}

}

MusicAdapter 代码

package cn.tedu.music_player_2.adapter;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import cn.tedu.music_player_2.R;
import cn.tedu.music_player_2.R.id;
import cn.tedu.music_player_2.R.layout;
import cn.tedu.music_player_2.entity.Music;

/**
* 显示歌曲列表ListView的Adapter
* @author chengheng
* @version 2.0
*/
public class MusicAdapter extends BaseAdapter {
/**
* Context
*/
private Context context;
/**
* 歌曲列表的数据
*/
private List musics;

/** * 构造方法 * @param context 上下文对象 * @param musics 歌曲的数据的List集合 */public MusicAdapter(Context context, List<Music> musics) {    super();    this.context = context;    this.musics = musics;}@Overridepublic int getCount() {    return musics.size();}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {    Music music = musics.get(position);    if (convertView == null) {        LayoutInflater inflater = LayoutInflater.from(context);        convertView = inflater.inflate(R.layout.music_item, null);    }    TextView tvName = (TextView) convertView.findViewById(R.id.tv_music_item_name);    TextView tvPath = (TextView) convertView.findViewById(R.id.tv_music_item_path);    tvName.setText(music.getName());    tvPath.setText(music.getPath());    return convertView;}@Overridepublic Object getItem(int position) {    return null;}@Overridepublic long getItemId(int position) {    return 0;}

}

自定义的application代码

package cn.tedu.music_player_2.app;

import java.util.List;

import android.app.Application;
import android.util.Log;
import cn.tedu.music_player_2.dal.IDao;
import cn.tedu.music_player_2.dal.MusicDaoFactory;
import cn.tedu.music_player_2.entity.Music;

public class MusicPlayerApplication extends Application {
private List musics = null;

@Overridepublic void onCreate() {    // 日志    Log.e("tedu", "MusicPlayerApplication.onCreate()");    // 获取数据    Log.e("tedu", "MusicPlayerApplication. 准备获取歌曲列表!");    // MusicDao dao = new MusicDao();    IDao dao = MusicDaoFactory.newInstance();    musics = dao.getData();    Log.e("tedu", "MusicPlayerApplication. 获取歌曲列表完成!");}/** * 获取歌曲数据的List集合 * @return 歌曲数据的List集合,该返回值永不为null */public List<Music> getMusics() {    return musics;}

}

工具类IDao代码:

package cn.tedu.music_player_2.dal;

import java.util.List;

import cn.tedu.music_player_2.entity.Music;

public interface IDao {

List<Music> getData();

}

工具类InternetMusicDao 代码:

package cn.tedu.music_player_2.dal;

import java.util.ArrayList;
import java.util.List;

import cn.tedu.music_player_2.entity.Music;

public class InternetMusicDao implements IDao {

@Overridepublic List<Music> getData() {    List<Music> musics = new ArrayList<Music>();    Music m1 = new Music();    m1.setName("长城");    m1.setPath("http://mp3.baidu.com/changcheng.mp3");    musics.add(m1);    Music m2 = new Music();    m2.setName("大地");    m2.setPath("http://mp3.baidu.com/dadi.mp3");    musics.add(m2);    Music m3 = new Music();    m3.setName("光辉岁月");    m3.setPath("http://mp3.baidu.com/guanghuisuiyue.mp3");    musics.add(m3);    return musics;}

}

LoadMusicDao 代码;

package cn.tedu.music_player_2.dal;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import android.os.Environment;
import android.util.Log;
import cn.tedu.music_player_2.entity.Music;

/**
* 歌曲数据的访问类
* @author chengheng
* @version 2.0
*/
public class LocalMusicDao implements IDao {
/**
* 扫描sdcard中Music下所有.mp3文件
* @return 扫描到的Music对象的List集合,该返回值永不为null
*/
@Override
public List getData() {
// 准备返回值
List musics = new ArrayList();

    // 扫描sdcard中Music下所有.mp3文件    if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {        File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);        if (dir.exists()) {            File[] files = dir.listFiles();            if (files != null && files.length > 0) {                for (int i = 0; i < files.length; i++) {                    if (files[i].isFile()) {                        if (files[i].getName().toLowerCase(Locale.CHINA).endsWith(".mp3")) {                            Music music = new Music();                            music.setPath(files[i].getAbsolutePath());                            music.setName(files[i].getName().substring(0, files[i].getName().length() - 4));                            Log.v("tedu", "" + music);                            musics.add(music);                        }                    }                }            } else {                Log.w("tedu", "Music文件夹下没有有效的文件!");            }        } else {            Log.w("tedu", "sdcard下Music文件夹不存在!无法扫描到歌曲!");        }    } else {        Log.w("tedu", "sdcard没有正确挂载!无法访问!");    }    // 返回    return musics;}

}

工具类MusicDaoFactory 代码;

package cn.tedu.music_player_2.dal;

public class MusicDaoFactory {
private MusicDaoFactory() {

}public static IDao newInstance() {    return new LocalMusicDao();}

}

实体类 Music 代码

package cn.tedu.music_player_2.entity;

/**
* 歌曲信息的实体类
* @author chengheng
* @version 2.0
*/
public class Music {
/**
* 歌曲名称,用于显示
*/
private String name;
/**
* 歌曲路径
*/
private String path;

public String getName() {    return name;}public void setName(String name) {    this.name = name;}public String getPath() {    return path;}public void setPath(String path) {    this.path = path;}@Overridepublic String toString() {    return "Music [name=" + name + ", path=" + path + "]";}

}

service服务PlayMusicSevice

package cn.tedu.music_player_2.service;

import java.io.IOException;
import java.util.List;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import cn.tedu.music_player_2.app.MusicPlayerApplication;
import cn.tedu.music_player_2.entity.Music;
import cn.tedu.music_player_2.util.IMusicPlayer;

public class PlayMusicService extends Service {
/**
* 播放工具
*/
private MediaPlayer player;
/**
* 歌曲数据的List集合
*/
private List musics;
/**
* Application
*/
private MusicPlayerApplication app;
/**
* 当前播放的歌曲的索引
*/
private int currentMusicIndex;
/**
* 暂停位置
*/
private int pausePosition;

@Overridepublic void onCreate() {    // 创建MediaPlayer    player = new MediaPlayer();    // 获取歌曲列表的数据    app = (MusicPlayerApplication) getApplication();    musics = app.getMusics();    // 为MediaPlayer对象配置监听器    player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {        @Override        public void onCompletion(MediaPlayer mp) {            // 播放下一首            next();        }    });    player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {        @Override        public void onPrepared(MediaPlayer mp) {            // 快进到之前暂停的位置            player.seekTo(pausePosition);            // 播放            player.start();        }    });}@Overridepublic IBinder onBind(Intent intent) {    InnerBinder binder = new InnerBinder();    return binder;}@Overridepublic void onDestroy() {    // 释放播放器相关资源    player.release();    player = null;}/** * Binder */private class InnerBinder extends Binder implements IMusicPlayer {    @Override    public void callPlay() {        PlayMusicService.this.play();    }    @Override    public void callPause() {        PlayMusicService.this.pause();    }    @Override    public void callPrevious() {        PlayMusicService.this.previous();    }    @Override    public void callNext() {        PlayMusicService.this.next();    }    @Override    public boolean callIsPlaying() {        return player.isPlaying();    }    @Override    public void callPlay(int position) {        PlayMusicService.this.play(position);    }    @Override    public int callGetCurrentMusicIndex() {        return currentMusicIndex;    }    @Override    public int callGetCurrentPosition() {        return player.getCurrentPosition();    }    @Override    public int callGetDuration() {        return player.getDuration();    }    @Override    public void callSeekTo(int progress) {        PlayMusicService.this.seekTo(progress);    }}/** * 播放 */private void play() {    try {        // 1. 重置        player.reset();        // 2. 设置歌曲的路径        player.setDataSource(musics.get(currentMusicIndex).getPath());        // 3. 异步加载歌曲数据,必须匹配OnPreparedListener        player.prepareAsync();

// // 3. 加载歌曲数据
// player.prepare();
// // 4. 快进到暂停位置
// player.seekTo(pausePosition);
// // 5. 播放
// player.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

/** * 播放指定的歌曲 *  * @param position *            歌曲的索引 */private void play(int position) {    // 确定需要播放的歌曲的索引    currentMusicIndex = position;    // 清除暂停位置    pausePosition = 0;    // 播放    play();}/** * 暂停 */private void pause() {    // 暂停播放    player.pause();    // 记录当前播放到的位置    pausePosition = player.getCurrentPosition();}/** * 播放上一首 */private void previous() {    // 计算上一首歌曲的索引值    currentMusicIndex--;    if (currentMusicIndex < 0) {        currentMusicIndex = musics.size() - 1;    }    // 清除暂停位置    pausePosition = 0;    // 播放    play();}/** * 播放下一首 */private void next() {    // 计算上一首歌曲的索引值    currentMusicIndex++;    if (currentMusicIndex >= musics.size()) {        currentMusicIndex = 0;    }    // 清除暂停位置    pausePosition = 0;    // 播放    play();}/** * 快进到指定的进度位置开始播放 *  * @param progress *            进度值,假设从60%位置开始播放,则参数值为60 */private void seekTo(int progress) {    // 根据进度计算出需要从??毫秒开始播放,并将值赋给pausePosition    pausePosition = player.getDuration() * progress / 100;    // 播放    play();}

}

commonutils 类代码:

package cn.tedu.music_player_2.util;

import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Locale;
/**
* 通用工具类
*/
public class CommonUtils {
/**
* 格式化时间的工具
*/
private static SimpleDateFormat sdf = new SimpleDateFormat(“mm:ss”, Locale.CHINA);
/**
* 被格式化的时间对象
*/
private static Date date = new Date();

/** * 获取格式化后的时间 *  * @param timeMillis *            时间值,取值为从1970-1-1 0:00:00至今的毫秒数 * @return 格式化为mm:ss格式的字符串 */public static String getFormattedTime(long timeMillis) {    // 设置时间    date.setTime(timeMillis);    // 返回格式化后的结果    return sdf.format(date);}

}

consts工具类

package cn.tedu.music_player_2.util;

/**
* 保存常量
* @author chengheng
* @version 2.0
*/
public interface Consts {
/**
* 指令:播放或暂停
*/
int COMMAND_PLAY_OR_PAUSE = 0;
/**
* 指令:播放上一首
*/
int COMMAND_PREVIOUS = 1;
/**
* 指令:播放下一首
*/
int COMMAND_NEXT = 2;
/**
* 指令:播放指定的歌曲
*/
int COMMAND_PLAY_POSITION = 3;

/** * Intent中封装的数据的key:指令 */String EXTRA_COMMAND = "command";/*** Intent中封装的数据的key:需要播放的歌曲的索引*/String EXTRA_POSITION = "position";

}

IMusicPlayer类代码:

package cn.tedu.music_player_2.util;

public interface IMusicPlayer {
/**
* 播放歌曲
*/
void callPlay();

/** * 暂停播放 */void callPause();/** * 播放上一首 */void callPrevious();/** * 播放下一首 */void callNext();/** * 获取播放状态,即判断是否正在播放 *  * @return 返回true则表示正在播放,返回false则表示没有播放 */boolean callIsPlaying();/** * 播放指定的歌曲 *  * @param position *            歌曲的索引 */void callPlay(int position);/** * 获取当前播放的歌曲的索引 *  * @return 当前播放的歌曲的索引 */int callGetCurrentMusicIndex();/** * 获取当前播放到的位置 *  * @return 当前播放到的位置 */int callGetCurrentPosition();/** * 获取当前播放的歌曲的时长 *  * @return 当前播放的歌曲的时长 */int callGetDuration();/** * 快进到指定的进度位置开始播放 *  * @param progress *            进度值,假设从60%位置开始播放,则参数值为60 */void callSeekTo(int progress);

}

更多相关文章

  1. Android(安卓)handler异步更新
  2. android之动画通过AnimationDrawable控制逐帧动画
  3. Android(安卓)– Video/Music 视频音乐播放
  4. Android(安卓)播放音乐文件与视频文件
  5. Android(安卓)音乐播放器实现歌词显示
  6. Android中数据库升级
  7. android 简单的音乐播放
  8. Android(安卓)Exception异常汇集【不定时更新】
  9. Google Android's Gingerbread Update Coming Soon

随机推荐

  1. android tab上显示数字
  2. Android 系统广播机制
  3. [置顶] android应用框架系列三,兼容性
  4. Android获取WIFI状态下的IP地址以及MAC地
  5. android 环境变量搭建
  6. android 内存使用
  7. android studio下ndk开发
  8. android sdk api的层次结构
  9. Android Things之---Android Things专题
  10. 一行命令得到签名SHA1(Android Studio)