最近在学android开发,最近写了一个简易的音乐播放器,主要参考了《第一行代码》以及别人的博客。这里贴出代码,供大家交流分享,如有错误或疑问,欢迎批评或者交流探讨。本人使用的开发工具是android studio 2.1.2。

首先是MainActivity.java

package handsome.musicplayer;

import android.database.Cursor;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Layout;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

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

public class MainActivity extends AppCompatActivity {
    private ListView songView;
    private List<Song> songList;
    private MediaPlayer mediaPlayer;
    private Button mainPlay,mainNext;
    private SeekBar playTime;
    private TextView nowPlaying;
    private int playType;
    private static int ICON_PLAY=R.drawable.bfzn_004;
    private static int ICON_PAUSE=R.drawable.bfzn_003;
    private static final int UPDATE_PLAYTIME=1;
    private static final int PLAY_ORDER=0;
    private static final int PLAY_RANDOM=1;
    private static final int PLAY_SINGLE=2;
    private int previousSong,totalSong;
    private ImageView bgImage;
    private Handler handler=new Handler(){
        public void handleMessage(Message msg){
            switch (msg.what){
                case UPDATE_PLAYTIME:
                    try {
                        playTime.setProgress(mediaPlayer.getCurrentPosition());
                    }catch(Exception e){

                    }
                    break;
                default:break;
            }
        }
    };

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

        /*musicList=new ArrayList<>();
        musicView=(ListView)findViewById(R.id.musicView);
        adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,musicList);
        musicView.setAdapter(adapter);*/
        //初始化
        songList=new ArrayList<>();
        mediaPlayer=new MediaPlayer();
        totalSong=0;
        previousSong=-1;
        playType=PLAY_ORDER;

        //控件初始化
        songView=(ListView)findViewById(R.id.songView);
        mainPlay=(Button)findViewById(R.id.mainPlay);
        mainNext=(Button)findViewById(R.id.mainNext);
        playTime=(SeekBar)findViewById(R.id.playTime);
        nowPlaying=(TextView)findViewById(R.id.nowPlaying);
        bgImage=(ImageView)findViewById(R.id.bgImage);

        nowPlaying.setBackgroundColor(Color.WHITE);
        bgImage.setImageResource(R.drawable.setsuna);
        bgImage.setImageAlpha(0x77);

        Cursor cursor=getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,null,null,null,null);
        while(cursor.moveToNext()){
            String title=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));//标题
            String artist=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));//艺术家
            String url=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));//文件路径
            int duration=cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));//时长
            if(artist.compareTo("<unknown>")==0)
                artist="";
            songList.add(new Song(title,artist,url,duration));totalSong++;
        }
        if(cursor!=null)
            cursor.close();
        final SongAdapter adapter=new SongAdapter(this,R.layout.song,songList);

        songView.setAdapter(adapter);
        songView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                playSong(i);
            }
        });

        mainPlay.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(mediaPlayer.isPlaying()){
                    mainPlay.setBackground(getResources().getDrawable(ICON_PLAY));
                    mediaPlayer.pause();
                }else {
                    mainPlay.setBackground(getResources().getDrawable(ICON_PAUSE));
                    mediaPlayer.start();
                }
            }
        });

        mainNext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                switch (playType){
                    case PLAY_ORDER:
                        if(previousSong==totalSong-1)
                            previousSong=-1;
                        playSong(previousSong+1);
                        break;
                    case PLAY_RANDOM:
                        playSong((int)(Math.random()*songList.size()));
                        break;
                    case PLAY_SINGLE:
                        playSong((int)(Math.random()*songList.size()));
                        break;
                }
            }
        });

        playTime.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                mediaPlayer.seekTo(playTime.getProgress());
            }
        });

        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mediaPlayer) {
                switch (playType){
                    case PLAY_ORDER:
                        if(previousSong==totalSong-1)
                            previousSong=-1;
                        playSong(previousSong+1);
                        break;
                    case PLAY_RANDOM:
                        playSong((int)(Math.random()*songList.size()));
                        break;
                    case PLAY_SINGLE:
                        mediaPlayer.start();
                        break;
                }
            }
        });
    }

    @Override
    protected void onDestroy(){
        super.onDestroy();
        if(mediaPlayer!=null) {
            mediaPlayer.stop();
            mediaPlayer.release();
        }
    }

    void playSong(int i){
        Song song=songList.get(i);
        try {
            Log.e("url",song.getUrl());
            mediaPlayer.reset();
            mediaPlayer.setDataSource(song.getUrl());
            mediaPlayer.prepare();
            mediaPlayer.start();
            mainPlay.setBackground(getResources().getDrawable(ICON_PAUSE));
            previousSong=i;
            playTime.setMax(song.getDuration());
            nowPlaying.setText("正在播放:"+song.getTitle());

            new Thread(new Runnable() {
                @Override
                public void run() {
                    Message message=new Message();
                    message.what=UPDATE_PLAYTIME;
                    handler.sendMessage(message);
                    handler.postDelayed(this,1000);
                }
            }).start();
        }catch (Exception e){
            String errorInformation="Play failed!";
            Toast.makeText(MainActivity.this,errorInformation,Toast.LENGTH_SHORT).show();
        }
    }

    public boolean onCreateOptionsMenu(Menu menu){
        getMenuInflater().inflate(R.menu.main_menu,menu);
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item){
        switch (item.getItemId()){
            case R.id.playOrder:
                playType=PLAY_ORDER;break;
            case R.id.playRandom:
                playType=PLAY_RANDOM;break;
            case R.id.playSingle:
                playType=PLAY_SINGLE;break;
            default:break;
        }
        return true;
    }
}

然后是Song.java

package handsome.musicplayer;

/**
 * Created by Administrator on 2016/7/17.
 */
public class Song {
    private String title;
    private String artist;
    private String url;
    private int duration;
    public Song(String title,String artist,String url,int duration){
        this.title=title;
        this.artist=artist;
        this.url=url;
        this.duration=duration;
    }
    public String getTitle(){
        return title;
    }
    public String getArtist(){
        return artist;
    }
    public String getUrl(){
        return url;
    }
    public int getDuration(){
        return duration;
    }
}

最后是SongAdapter.java

package handsome.musicplayer;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.util.List;

/**
 * Created by Administrator on 2016/7/17.
 */
public class SongAdapter extends ArrayAdapter<Song> {
    private int resourceId;

    public SongAdapter(Context context,int textViewResourceId,List<Song> objects){
        super(context,textViewResourceId,objects);
        resourceId=textViewResourceId;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        Song song=getItem(position);
        View view= LayoutInflater.from(getContext()).inflate(resourceId,null);
        TextView title=(TextView)view.findViewById(R.id.title);
        TextView artist=(TextView)view.findViewById(R.id.artist);
        title.setText(song.getTitle());
        artist.setText(song.getArtist());
        return view;
    }
}

这里简要分析一下,界面部分:首先调用 Cursor cursor=getContentResolver().query(MediaStore.Audio.Media. EXTERNAL_CONTENT_URI , null , null , null , null )函数提取出手机当中所有的音频文件(这里由于个人水平原因,处理得比较粗暴。而且我这里每次程序启动都会这样做一遍,其实我们可以利用数据库技术来存储这个列表,把这个操作改成手动的,这个就留给读者自己去完善了。)读取的同时,将它们用Song类型(存储了音乐名,作曲家,音乐时间长短和音乐存储位置)保存在songList内,通过songAdapter让它在songView这个控件上显示。几个layout就不贴出了,我已将源码上传至百度云盘,可供大家下载。

音乐播放部分:

首先是如何播放音乐,这个非常容易。我这里实现的功能是点击songView上的对应项就可以播放对应的音乐,这个只要在songView.setOnItemClickListener里调用一下playSong这个函数就可以了,playSong的函数里主要是通过点击的序号在songList里找到对应的对象,这样可以得到它的存储路径,通过mediaPlayer.setDataSource(song.getUrl());可以设置播放路径,然后播放即可。

最后我想说一下滚动条部分。这里我们必须要用到多线程来实时获得歌曲播放信息,但子线程是不支持UI修改的,所以我们通过handler.sendMessage,主线程通过handleMessage接收这个方法来对SeekBar的位置进行修改。具体大家可以参考我是怎么写的,更详细的可以看《第一行代码》第九章内容。

其他还实现了下一曲,循环播放,随机播放,单曲循环等功能,这些都不难,大家自己研究一下就可以了。


时间关系,就写到这里,附上源码:http://pan.baidu.com/s/1ge8Iv8f


时间关系,就写到这里,附上源码:http://pan.baidu.com/s/1ge8Iv8f