该文章主要针对 android 的音乐播放器软件进行简单的功能添加:播放、断点播放、停止、上一曲、下一曲、随机播放、显示当前播放歌曲(后续会为当前显示的播放添加动画);
软件开发流程:
1、先向内存卡导入音乐文件(文件的导入方法可以自己查找,文章类较多);
2、获取内存卡中的音乐文件;
3、将音乐文件存入集合中,便于调用,并将需要播放的文件显示在 ListView 中(点击 ListView 中的文件也可播放);
4、运用 MediaPlayer的方法实现播放、暂停、断点播放、连续播放文件;
5、通过调用写好的方法实现手动的下一曲、上一曲、随机播放、显示当前播放的音乐名;
<pre name="code" class="java">package com.wangban.yzbbanban.v10;

import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.media.MediaPlayer;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;

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

public class MainActivity extends AppCompatActivity {
    //声明各个组件,集合
    private List<Music> musics;
    private ListView lvMusicList;
    private ImageButton ibtnPlayOrPause;
    private ImageButton ibtnNext;
    private ImageButton ibtnprevious;
    private ImageButton ibtnGetPosition;
    private RadioButton rbtnPlayRandown;
    private RadioButton rbtnPlaySequence;
    private RadioButton rbtnPlaySingle;
    private MusicAdapter adapter;
    private TextView tvTip;
    private Context context;

    //声明 MediaPla
    private MediaPlayer player;
    // 记录的暂停时的播放位置
    private int pausePosition;
    // 当前播放的歌曲的索引
    private int currentMusicIndex;

    @Override
    //主函数
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //设置布局为 activity_main
        setContentView(R.layout.activity_main);

        //初始化控件
        initView();
        //获取歌曲列表
        loadData();
        //列出列表
        initListView();
        //配置监听器
        setListener();


        //重置(设置 MediaPlayer必须步骤)
        player.reset();


    }

    //设置各种监听器
    private void setListener() {
        InnerOnclickListener listener = new InnerOnclickListener();
        //暂停播放
        ibtnPlayOrPause.setOnClickListener(listener);
        //下一首
        ibtnNext.setOnClickListener(listener);
        //上一首
        ibtnprevious.setOnClickListener(listener);
        //获取当前播放音乐
        ibtnGetPosition.setOnClickListener(listener);

        InnerItemOnCLickListener listener2 = new InnerItemOnCLickListener();
        //给 ListView 添加点击(点击音乐即可播放)
        lvMusicList.setOnItemClickListener(listener2);
        // MediaPlay 自动播放(因为就一条,无需加变量)
        player.setOnCompletionListener(new InnerOnCompletionListener());


    }

    //播放ListView 点击的音乐
    private class InnerItemOnCLickListener implements AdapterView.OnItemClickListener {


        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            //获取点击的列表的中音乐的位置,赋值给当前播放音乐
            currentMusicIndex = position;
            //令暂停的进度为0(即为从头播放)
            pausePosition = 0;
            //播放
            play();
        }
    }

    //主要按钮的播放监听器
    private class InnerOnclickListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                // 播放/暂停按钮即执行的方法
                case R.id.ibtn_playorpause:
                    //当音乐在播放时
                    if (player.isPlaying()) {
                        //暂停
                        pause();
                    } else {
                        //不在播放,则播放
                        play();
                    }
                    break;
                //下一首按钮即执行方法
                case R.id.ibtn_next:
                    next();
                    break;
                //上一首按钮即执行方法
                case R.id.ibtn_previous:
                    previous();
                    break;
                //获取当前播放音乐即执行方法
                case R.id.ibtn_getposition:
                    getPosition();
                    break;


            }

        }
    }

    //单曲循环
    private void single() {
        currentMusicIndex++;
        currentMusicIndex--;
        pausePosition = 0;
        play();
    }

    //随机播放方法
    private void randown() {
        currentMusicIndex = new Random().nextInt(musics.size());
        Toast.makeText(MainActivity.this, "随机", Toast.LENGTH_SHORT).show();
        pausePosition = 0;
        play();

    }

    //列表循环
    private void sequence() {
        currentMusicIndex++;
        if (currentMusicIndex >= musics.size()) {
            currentMusicIndex = 0;
        }
        pausePosition = 0;
        play();


    }

    //获取当前播放的音乐文件的名字,必先是在另一个布局中;
    private void getPosition() {
        //声明一个意图,用来切换布局和传递数据
        Intent intent = new Intent();
        //定义要传递的数据
        String extra = musics.get(currentMusicIndex).getName() + "";
        //传递数据
        intent.putExtra("currentMusic", extra);
        //切换布局
        intent.setClass(MainActivity.this, Main2Activity.class);
        //执行此系列活动
        MainActivity.this.startActivity(intent);


    }

    //暂停
    private void pause() {
        //直接调用MediaPlay 中的暂停方法
        player.pause();
        //获取暂停的位置(音乐进度)
        pausePosition = player.getCurrentPosition();
        //切换为播放的按钮(按钮为android系统自带的按钮,可直接用)
        ibtnPlayOrPause.setImageResource(android.R.drawable.ic_media_play);
    }

    //播放上一曲
    private void previous() {


        //判断是否为第一首歌曲,若为第一首歌曲,则播放最后一首
        if (rbtnPlaySingle.isChecked()) {
            single();
        } else {
            //当前音乐播放位置--(上一曲)
            currentMusicIndex--;
            if (currentMusicIndex <= 0) {
                Toast.makeText(MainActivity.this, "已经是第一首了", Toast.LENGTH_SHORT).show();
                return;
            } else {

                //音乐进度置为0
                pausePosition = 0;
                //播放
                play();
            }
        }
    }

    //播放下一曲(与上一曲类似)
    private void next() {
        if (rbtnPlayRandown.isChecked()) {
            randown();

        } else if (rbtnPlaySingle.isChecked()) {
            single();

        } else if (rbtnPlaySequence.isChecked()) {
            sequence();

        } else {
            currentMusicIndex++;
            if (currentMusicIndex >= musics.size()) {
                Toast.makeText(MainActivity.this, "已经是最后一首了", Toast.LENGTH_SHORT).show();
                return;
            } else {
                pausePosition = 0;
                play();
            }
        }
    }


    //播放音乐
    private void play() {
        //重置
        player.reset();

        try {
            //设置音乐文件来源
            player.setDataSource(musics.get(currentMusicIndex).getPath());
            //准备(缓冲文件)
            player.prepare();
            //将进度设置到“音乐进度”
            player.seekTo(pausePosition);
            //获取音乐进度
            player.getCurrentPosition();
            //播放开始
            player.start();
            //用当前界面的 TextView显示当前播放的音乐
            tvTip.setText(musics.get(currentMusicIndex).getName() + "");
            //设置按钮图片为暂停图标
            ibtnPlayOrPause.setImageResource(android.R.drawable.ic_media_pause);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private final class InnerOnCompletionListener implements MediaPlayer.OnCompletionListener {

        @Override
        public void onCompletion(MediaPlayer mp) {
            next();

        }
    }

    private void initListView() {
        adapter = new MusicAdapter(getApplicationContext(), musics);
        lvMusicList.setAdapter(adapter);

    }

    private void loadData() {
        //获取音乐文件的内容
        Cursor cursor = context.getContentResolver().query(
                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
                MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
        // 获取歌曲列表
        musics = new ArrayList<>();
        // 1. 检查sdcard是否可用
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            // 2. 获取sdcard下Music文件夹的File对象
            File musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
            // 3. 检查Music文件夹是否存在
            if (musicDir.exists()) {
                // 4. 通过File类的listFiles()方法,获取Music文件夹下所有子级File对象
                File[] files = musicDir.listFiles();
                // 5. 检查获取到的File列表是否有效(数组是否为null,或数组长度是否为0)
                if (files != null && files.length > 0) {
                    // 6. 遍历File列表
                    for (int i = 0; i < files.length; i++) {
                        //下一个文件
                        cursor.moveToNext();
                        //获取艺术家内容
                        String artist = cursor.getString(cursor
                                .getColumnIndex(MediaStore.Audio.Media.ARTIST));
                        // 6.1. 通过File类的isFile()方法,检查是否是文件
                        if (files[i].isFile()) {
                            // 6.2. 通过File类的getName()方法获取文件名,
                            // 结合String类的endsWith()方法,检查是否是mp3文件
                            String fileName = files[i].getName();
                            if (fileName.toUpperCase(Locale.CHINA).endsWith(".MP3")) {


                                // 6.3. 创建Music对象,并封装必要的属性
                                Music music = new Music();
                                music.setName(fileName.substring(0, fileName.length() - 4));
                                music.setArtist(artist);
                                music.setPath(files[i].getAbsolutePath());
                                // 6.4. 将新创建的Music对象添加到集合中
                                musics.add(music);

                            }

                        }

                    }
                }
            }


        }
    }

    //初始化控件级布局文件等
    private void initView() {
        player = new MediaPlayer();
        lvMusicList = (ListView) findViewById(R.id.lv_musiclist);
        ibtnPlayOrPause = (ImageButton) findViewById(R.id.ibtn_playorpause);
        ibtnNext = (ImageButton) findViewById(R.id.ibtn_next);
        ibtnprevious = (ImageButton) findViewById(R.id.ibtn_previous);
        ibtnGetPosition = (ImageButton) findViewById(R.id.ibtn_getposition);
        rbtnPlayRandown = (RadioButton) findViewById(R.id.rbtn_playrandowm);
        rbtnPlaySequence = (RadioButton) findViewById(R.id.rbtn_playsequence);
        rbtnPlaySingle = (RadioButton) findViewById(R.id.rbtn_playsingle);
        tvTip = (TextView) findViewById(R.id.tv_musictip);
        context = MainActivity.this;
    }
}




<pre name="code" class="java">package com.wangban.yzbbanban.v10;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

//实现显示当前播放的音乐
public class Main2Activity extends AppCompatActivity {
    private TextView tvCurrentMusic;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //设置当前布局为activity_main2
        setContentView(R.layout.activity_main2);
        //声明 TextView 控件
        tvCurrentMusic = (TextView) findViewById(R.id.tv_current_music);
        //获取主程序传出的“当前播放文件名字”的值
        Intent intent= this.getIntent();
        String stringValue=intent.getStringExtra("currentMusic");
        tvCurrentMusic.setText(stringValue);


    }
}



package com.wangban.yzbbanban.v10;

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 java.util.List;

//集合:显示音乐文件的名称、路径,显示在 ListView 中
public class MusicAdapter extends BaseAdapter{
    private Context context;
    private List<Music> musics;

    public MusicAdapter(Context context, List<Music> musics) {
        this.context = context;
        this.musics = musics;
    }

    @Override
    public int getCount() {
        return musics.size();
    }

    @Override
    public 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_title);
        TextView tvArtist= (TextView) convertView.findViewById(R.id.tv_music_path);
        //TextView tvPath= (TextView) convertView.findViewById(R.id.tv_music_path);
        //显示文件内容
        //显示歌曲名
        tvName.setText(music.getName());
        //tvPath.setText(music.getPath());
        //显示艺术家名字
        tvArtist.setText(music.getArtist());
        return convertView;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }
}



package com.wangban.yzbbanban.v10;

//Music 类型文件,用于集合musics,声明一个类型,获取集合中的名字、路径
public class Music {
    //name 类型
    private String name;
    //path 类型
    private String path;
    //获取艺术家
    private String artist;

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    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;
    }

    @Override
    public String toString() {
        return "Music{" +
                "name='" + name + '\'' +
                ", path='" + path + '\'' +
                '}';
    }
}



<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="当前播放的歌曲:"
        android:textSize="20sp"
        android:background="@color/colorPrimary"
        />

    <ImageView
        android:id="@+id/iv_current_player"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:src="@drawable/default_play_activity_bg1" />

    <TextView
        android:id="@+id/tv_current_music"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="50dp"
        android:layout_below="@id/iv_current_player"
        android:text="" />

</RelativeLayout>



<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/ic_launcher_app"
    android:padding="5dp"
    tools:context="com.wangban.yzbbanban.v10.MainActivity">


    <RelativeLayout
        android:id="@+id/rl_music"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">
        <ImageButton
            android:id="@+id/ibtn_previous"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@android:drawable/ic_media_previous" />

        <ImageButton
            android:id="@+id/ibtn_playorpause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/ibtn_previous"
            android:src="@android:drawable/ic_media_play" />

        <ImageButton
            android:id="@+id/ibtn_next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/ibtn_playorpause"
            android:src="@android:drawable/ic_media_next" />



        <ImageButton
            android:id="@+id/ibtn_getposition"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:src="@android:drawable/ic_menu_mylocation"

            />


    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/rl_playstate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_above="@id/rl_music"
        android:orientation="horizontal">

        <RadioGroup
            android:id="@+id/rg_playstate"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:orientation="horizontal"
            >

            <RadioButton
                android:id="@+id/rbtn_playsequence"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerInParent="true"
                android:background="@drawable/selector_sequence"
                android:button="@null" />

            <RadioButton
                android:id="@+id/rbtn_playrandowm"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_toLeftOf="@id/rbtn_playsequence"
                android:background="@drawable/selector_randowm"
                android:button="@null" />

            <RadioButton
                android:id="@+id/rbtn_playsingle"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_toRightOf="@id/rbtn_playsequence"
                android:background="@drawable/selector_single"
                android:button="@null" />


        </RadioGroup>


    </RelativeLayout>

    <TextView
        android:id="@+id/tv_musictip"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/rl_playstate"
        android:padding="10dp"
        android:text="您播放的歌为"
        android:textColor="#ffdfce"
        android:textSize="17sp" />

    <ListView
        android:id="@+id/lv_musiclist"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/tv_musictip"

        />


</RelativeLayout>



<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="5dp">

    <ImageView
        android:id="@+id/iv_artist"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:background="@drawable/ic_luancher_app"

        />

    <TextView
        android:id="@+id/tv_music_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_toRightOf="@id/iv_artist"
        android:text="歌名"
        android:textColor="#eeeeee"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/tv_music_path"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_music_title"
        android:layout_marginLeft="10dp"
        android:layout_toRightOf="@id/iv_artist"
        android:text="路径"
        android:textColor="#999999"
        android:textSize="14sp" />

</RelativeLayout>

//随机图标的选择


<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true" android:drawable="@drawable/play_list_mode_shuffle"
        ></item>
    <item android:drawable="@drawable/playmode_repeate_random_hover"></item>
</selector>
//顺序播放的图标的选择



<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true" android:drawable="@drawable/play_list_mode_sequent"
        ></item>
    <item android:drawable="@drawable/playmode_repeate_all_hover"></item>
</selector>
//单曲循环的图标的选择



<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true" android:drawable="@drawable/play_list_mode_repeat_one"
        ></item>
    <item android:drawable="@drawable/playmode_repeate_single_hover"></item>
</selector>