实体类Music
package cn.tedu.music_player_1;

public class Music {

private String name;private String path;public String getPath() {    return path;}public void setPath(String path) {    this.path = path;}public String getName() {    return name;}public void setName(String name) {    this.name = name;}

}

Activity代码,带注释

package cn.tedu.music_player_1;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Random;

import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {
// 歌曲的数据
private List musics;
// ListView
private ListView lvMusics;
// Adapter
private MusicAdapter musicAdapter;
// MediaPlayer
private MediaPlayer player;
// ImageButton:播放/暂停
private ImageButton ibPlayOrPause;
// ImageButton:上一首
private ImageButton ibPrevious;
// ImageButton:下一首
private ImageButton ibNext;
// Button:播放模式
private Button btnPlayMode;
// TextView:当前播放的歌曲名称
private TextView tvMusicTitle;
// TextView:当前播放的歌曲的时长
private TextView tvMusicDuration;
// TextView:当前播放到的时间(播放过程中)
private TextView tvMusicCurrentPosition;
// SeekBar:歌曲的播放进度
private SeekBar sbMusicProgress;
// 暂停时播放到的位置
private int pausePosition;
// 当前播放的歌曲的索引
private int currentMusicIndex;
// 格式化时间的工具
private SimpleDateFormat sdf = new SimpleDateFormat(“mm:ss”, Locale.CHINA);
// 被格式化的时间对象
private Date date = new Date();
// 更新进度的线程
private UpdateProgressThread updateProgressThread;
// 是否是第1次点击列表项
private boolean isFirstClickListItem = true;
// 用户是否正在拖拽进度条
private boolean isUserTrackingTouch;
// 生成随机数据的工具
private Random random = new Random();
// 播放模式
private int playMode;
// 播放模式对应的字符串,用于显示在Button中
public static final String[] PLAY_MODE_TEXT = { “顺”, “随”, “单” };
// 播放模式 – 顺序播放
private static final int PLAY_MODE_ORDER = 0;
// 播放模式 – 随机播放
private static final int PLAY_MODE_RANDOM = 1;
// 播放模式 – 单曲循环
private static final int PLAY_MODE_SINGLE = 2;

@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    // 设置歌曲数据    setMusicData();    // 初始化播放工具    player = new MediaPlayer();    // 为MediaPlayer配置监听器    player.setOnCompletionListener(new OnCompletionListener() {        @Override        public void onCompletion(MediaPlayer mp) {            next();        }    });    // 初始化控件    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);    tvMusicDuration = (TextView) findViewById(R.id.tv_music_duration);    tvMusicCurrentPosition = (TextView) findViewById(R.id.tv_music_current_position);    sbMusicProgress = (SeekBar) findViewById(R.id.sb_music_progress);    btnPlayMode = (Button) findViewById(R.id.btn_play_mode);    // 创建Adapter    musicAdapter = new MusicAdapter(this, musics);    // 为ListView配置Adapter    lvMusics.setAdapter(musicAdapter);    // 为按钮配置监听器    InnerOnClickListener listener1 = new InnerOnClickListener();    ibPlayOrPause.setOnClickListener(listener1);    ibPrevious.setOnClickListener(listener1);    ibNext.setOnClickListener(listener1);    btnPlayMode.setOnClickListener(listener1);    // 为ListView配置监听器    InnerOnItemClickListener listener2 = new InnerOnItemClickListener();    lvMusics.setOnItemClickListener(listener2);    // 为SeekBar配置监听器    InnerOnSeekBarChangeListener listener3 = new InnerOnSeekBarChangeListener();    sbMusicProgress.setOnSeekBarChangeListener(listener3);}@Overrideprotected void onDestroy() {    // 线程运行结束    stopUpdateProgressThread();    // 释放播放器资源    player.release();    player = null;    super.onDestroy();}private class UpdateProgressThread extends Thread {    // 播放的进度值    private int progress;    // 当前播放到的时间的字符串    private String timeString;    // 线程的运行控制变量    private boolean isRunning;    // 运行在主线程更新UI的对象    private Runnable runner = new Runnable() {        @Override        public void run() {            // 判断用户是否正在拖拽进度条            if (!isUserTrackingTouch) {                // 更新SeekBar                sbMusicProgress.setProgress(progress);            }            // 更新TextView            tvMusicCurrentPosition.setText(timeString);        }    };    // 设置线程是否循环    public void setRunning(boolean isRunning) {        this.isRunning = isRunning;    }    @Override    public void run() {        while (isRunning) {            // 日志            Log.i("tedu", "Thread(" + Thread.currentThread().getId() + ")尝试更新进度 ... ...");            // 判断当前是否处于播放状态            if (player.isPlaying()) {                // 获取当前歌曲播放到的位置,计算得到显示的数据                progress = player.getCurrentPosition() * 100 / player.getDuration();                date.setTime(player.getCurrentPosition());                timeString = sdf.format(date);                // 执行更新                runOnUiThread(runner);            }            // 休眠            try {                Thread.sleep(450);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}private class InnerOnSeekBarChangeListener implements OnSeekBarChangeListener {    @Override    public void onStartTrackingTouch(SeekBar seekBar) {        // 当开始拖拽时,标识用户开始拖拽进度条        isUserTrackingTouch = true;    }    @Override    public void onStopTrackingTouch(SeekBar seekBar) {        // 获取进度        int progress = sbMusicProgress.getProgress();        // 计算播放的时间点        pausePosition = player.getDuration() * progress / 100;        // 播放        play();        // 标识用户已经停止拖拽进度条        isUserTrackingTouch = false;    }    @Override    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {        // 当进度值发生变化时:可能由于程序更新了进度,或者用户正在拖拽的过程中    }}private class InnerOnItemClickListener implements OnItemClickListener {    @Override    public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {        // 判断点击的列表项的position是否匹配当前播放的歌曲的索引        if (isFirstClickListItem || position != currentMusicIndex) {            // 确定需要播放的歌曲的索引,直接对应点击的列表项的position            currentMusicIndex = position;            // 清除暂停位置            pausePosition = 0;            // 执行播放            play();            // 清除记录第1次点击            isFirstClickListItem = false;        }    }}private class InnerOnClickListener implements OnClickListener {    @Override    public void onClick(View v) {        switch (v.getId()) {        case R.id.btn_play_mode:            // 计算播放模式变量的值            playMode++;            playMode = playMode % 3;            // 设置按钮上显示的文字            btnPlayMode.setText(PLAY_MODE_TEXT[playMode]);            break;        case R.id.ib_play_or_pause:            // 判断当前是否正在播放            if (player.isPlaying()) {                // 正在播放,则暂停                pause();            } else {                // 没有播放,则播放                play();            }            break;        case R.id.ib_previous:            // 播放上一首            previous();            break;        case R.id.ib_next:            // 播放下一首            next();            break;        }    }}// 开启线程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 void play() {    try {        // 1. 重置        player.reset();        // 2. 设置歌曲路径        player.setDataSource(musics.get(currentMusicIndex).getPath());        // 3. 缓冲        player.prepare();        // 4. 快进        player.seekTo(pausePosition);        // 5. 播放        player.start();        // 6. 将按钮显示为“暂停”        ibPlayOrPause.setImageResource(android.R.drawable.ic_media_pause);        // 7. 显示歌曲的名称        tvMusicTitle.setText("当前播放:" + musics.get(currentMusicIndex).getName());        // 8. 显示歌曲的时长        date.setTime(player.getDuration()); // 设置需要被格式化的时间        tvMusicDuration.setText(sdf.format(date)); // 显示        // 9. 开启线程,更新进度        startUpdateProgressThread();    } catch (IllegalArgumentException e) {        e.printStackTrace();    } catch (SecurityException e) {        e.printStackTrace();    } catch (IllegalStateException e) {        e.printStackTrace();    } catch (IOException e) {        e.printStackTrace();    }}// 暂停播放private void pause() {    // 执行暂停    player.pause();    // 记录当前播放到的位置    pausePosition = player.getCurrentPosition();    // 将按钮显示为“播放”    ibPlayOrPause.setImageResource(android.R.drawable.ic_media_play);    // 停止更新进度的线程    stopUpdateProgressThread();}// 播放上一首private void previous() {    // 计算上一首歌曲的索引    currentMusicIndex--;    if (currentMusicIndex < 0) {        currentMusicIndex = musics.size() - 1;    }    // 清除记录的暂停位置    pausePosition = 0;    // 执行播放    play();}// 播放下一首private void next() {    switch (playMode) {    case PLAY_MODE_ORDER:        // 计算下一首歌曲的索引        currentMusicIndex++;        if (currentMusicIndex >= musics.size()) {            currentMusicIndex = 0;        }        break;    case PLAY_MODE_RANDOM:        // 随机生成需要播放的歌曲的索引        int i;        while ((i = random.nextInt(musics.size())) == currentMusicIndex) {        }        currentMusicIndex = i;        break;    case PLAY_MODE_SINGLE:        break;    }    // 清除记录的暂停位置    pausePosition = 0;    // 执行播放    play();}// 设置歌曲数据private void setMusicData() {    // 初始化List集合    musics = new ArrayList<Music>();    // 检查sdcard的状态,即是否可用    if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {        // 获取sdcard下Music文件夹的File对象        File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);        // 通过exists()方法检查Music文件夹是否存在        if (dir.exists()) {            // 通过listFiles()方法获取Music文件夹下所有文件的File对象,获取的结果是File[]            File[] files = dir.listFiles();            // 判断数组是否为null            if (files != null) {                // 遍历数组                for (int i = 0; i < files.length; i++) {                    // 检查遍历到的是否是文件,而不是文件夹                    if (files[i].isFile()) {                        // 检查遍历到的是否是mp3文件                        if (files[i].getName().toLowerCase(Locale.CHINA).endsWith(".mp3")) {                            // 如果是mp3文件,则创建Music对象,并添加到List集合中                            Music music = new Music();                            music.setPath(files[i].getAbsolutePath());                            music.setName(files[i].getName().substring(0, files[i].getName().length() - 4));                            musics.add(music);                            Log.i("tedu", "扫描到MP3文件:" + music.getName() + ",路径:" + music.getPath());                        } else {                            Log.w("tedu", "遍历到File对象" + files[i] + "不是MP3文件!忽略!");                        }                    } else {                        Log.w("tedu", "遍历到File对象" + files[i] + "是文件夹!忽略!");                    }                }            } else {                Log.w("tedu", "获取Music文件夹的内容失败!");            }        } else {            Log.w("tedu", "sdcard下Music文件夹不存在!");        }    } else {        Log.w("tedu", "sdcard不可用!");    }}

}

适配器adapter 具体代码

package cn.tedu.music_player_1;

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;

public class MusicAdapter extends BaseAdapter {
private Context context;
private List musics;

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) {    // 1. 获取需要显示的数据    Music music = musics.get(position);    // 2. 判断有没有可以直接使用的convertView    if(convertView == null) {        // 2.1 如果没有,则通过XML加载得到        LayoutInflater inflater = LayoutInflater.from(context);        convertView = inflater.inflate(R.layout.music_item, null);    } else {        // 2.2 如果有,则直接使用    }    // 3. 组装数据与模板    TextView tvName = (TextView) convertView.findViewById(R.id.tv_music_item_name);    tvName.setText(music.getName());    TextView tvPath = (TextView) convertView.findViewById(R.id.tv_music_item_path);    tvPath.setText(music.getPath());    // 4. 返回convertView    return convertView;}@Overridepublic Object getItem(int position) {    return null;}@Overridepublic long getItemId(int position) {    return 0;}

}

activity_main.XML布局文件

更多相关文章

  1. android 调用本地音乐播放器
  2. Android模仿jquery异步请求
  3. android之seekBar
  4. Android(安卓)播放音乐文件与视频文
  5. Android(安卓)判断是否为Wifi网络
  6. android 判断当前网络是否可用
  7. android 如何判断当前进程在主页面
  8. Android(安卓)Asynchronous Http Client
  9. Android(安卓)BaseAdapter如何获得每一项并添加按钮事件

随机推荐

  1. Android手机定位案例代码
  2. Android(安卓)优秀开源框架集合
  3. SharedPreferences保存少量的数据
  4. android 静默安装并自启
  5. [Android(安卓)Pro] AES加密
  6. Android(安卓)应用界面开发笔记 Service
  7. 多条柱状图图
  8. Mediacodec
  9. android存储对象到本地
  10. Android学习笔记(21)————利用JDBC连