音频的播放、简单音乐播放器

音频的播放

在Android中播放音频文件一般都是使用MediaPlayer类来实现的,它对多种格式的音频文件提供了非常全面的控制方法,从而使得播放音乐的工作变得非常简单。

MediaPlayer的生命周期


从上图可以清楚的看出MediaPlayer的工作流程。
首先创建一个MediaPlayer对象,然后调用setDataSource()方法来设置音频播放的路径,再调用prepare()方法使MediaPlayer进行准备状态,接下来调用start()方法就可以开始播放音频,调用pause()方法就可以暂停播放,调用reset()方法就会停止播放。

下面我们写一个简单的音乐播放器,实现一些简单的功能,来深入理解MediaPlayer的用法。

简单的音乐播放器

注意:在我们向模拟器中导入歌曲的时候,不能有中午的歌曲名,否则导入失败!
首先搭建我们的主界面:

<LinearLayout 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:orientation="vertical" tools:context=".MainActivity">
    <ListView  android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"></ListView>
    <LinearLayout  android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:orientation="horizontal">
        <TextView  android:id="@+id/currenttime" android:layout_width="wrap_content" android:layout_height="wrap_content" />
        <SeekBar  android:id="@+id/seekbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1"/>
        <TextView  android:id="@+id/totalttime" android:layout_width="wrap_content" android:layout_height="wrap_content" />
    </LinearLayout>
    <LinearLayout  android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FFFFFF" android:orientation="horizontal" android:gravity="center">
        <ImageButton  android:id="@+id/last" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@mipmap/before"/>
        <ImageButton  android:id="@+id/play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/play"/>
        <ImageButton  android:id="@+id/next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@mipmap/next"/>
    </LinearLayout>
</LinearLayout>

接下来是Drawable文件夹的内容,我们为播放,暂停按钮设置两种不同的转换!
play.xml

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

pause.xml

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

接下来,为我们的ListView设置布局,展示专辑图片,歌名和歌手名

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal">
    <ImageView  android:id="@+id/imageview" android:layout_width="50dp" android:layout_height="50dp" android:layout_margin="10dp"/>
    <LinearLayout  android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:orientation="vertical">
        <TextView  android:id="@+id/textview_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="name"/>
        <TextView  android:id="@+id/textview_artist" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="name"/>
    </LinearLayout>
</LinearLayout>

然后为我们的歌曲列表写一个适配器MusicAdapter

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaMetadataRetriever;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.File;

/** * Created by Administrator on 2015/9/10. */
public class MusicAdapter extends BaseAdapter{
    private LayoutInflater inflater;
    private File[] musics;

    public MusicAdapter(File[] musics, LayoutInflater inflater) {
        this.musics = musics;
        this.inflater = inflater;
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        ViewHolder viewHolder;
        if(convertView==null){
            view=inflater.inflate(R.layout.musiclist,null);
            viewHolder=new ViewHolder();
            viewHolder.imageView= (ImageView) view.findViewById(R.id.imageview);
            viewHolder.textView_name= (TextView) view.findViewById(R.id.textview_name);
            viewHolder.textView_artist= (TextView) view.findViewById(R.id.textview_artist);
            view.setTag(viewHolder);
        }else{
            view=convertView;
            viewHolder= (ViewHolder) view.getTag();
        }
        MediaMetadataRetriever mediaMetadataRetriever=new MediaMetadataRetriever();
        mediaMetadataRetriever.setDataSource(musics[position].getAbsolutePath());
        byte[] image=mediaMetadataRetriever.getEmbeddedPicture();//得到歌曲的专辑图片
        if (image!=null){
            Bitmap bitmap= BitmapFactory.decodeByteArray(image,0,image.length);
            viewHolder.imageView.setImageBitmap(bitmap);
        }else {
            viewHolder.imageView.setImageResource(R.mipmap.ic_launcher);
        }
        String artist=mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);//得到歌曲的歌手名
        if (artist!=null){
        viewHolder.textView_artist.setText(artist);}
        else {
            viewHolder.textView_artist.setText("<未知>");
        }
        viewHolder.textView_name.setText(musics[position].getName());//设置歌曲名
        return view;
    }

    class ViewHolder{
        ImageView imageView;
        TextView textView_name;
        TextView textView_artist;
    }
}

然后定义一个我们自己的常量类Config

/** * Created by Administrator on 2015/9/10. */
public class Config {
    public static final int TOTAL_TIME=0;
    public static final int CURRENT_TIME=1;
    public static final int START_MUSIC=0;
    public static final int PAUSE_MUSIC=1;
    public static final int SEEK_TO=2;
    public static final String BROADCAST_TAG="com.music.play";
    public static final String TYPE="type";
    public static final String TIME="time";
    public static final String PATH="musicpath";
    public static final String PROGRESS="progress";
}

接着写一个播放音乐的服务类,所有关于音乐播放的内容都放在这个服务中

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.support.annotation.Nullable;
import java.io.IOException;

/** * Created by Administrator on 2015/9/10. */
public class MusicService extends Service{
    private MediaPlayer mediaPlayer;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int type=intent.getIntExtra(Config.TYPE, 0);
        switch (type){
            case Config.START_MUSIC://播放音乐
                String musicPath=intent.getStringExtra(Config.PATH);
                if (mediaPlayer==null){
                    mediaPlayer=new MediaPlayer();
                }
                mediaPlayer.reset();
                try {
                    mediaPlayer.setDataSource(musicPath);
                    mediaPlayer.prepare();
                    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                        @Override
                        public void onPrepared(MediaPlayer mp) {
                            mp.start();
                            int totalTime=mp.getDuration();//得到总时间
                            Intent intent=new Intent(Config.BROADCAST_TAG);
                            intent.putExtra(Config.TYPE,Config.TOTAL_TIME);
                            intent.putExtra(Config.TIME,totalTime);//将歌曲总时间传回去
                            sendBroadcast(intent);
                            new MusicplayerThread().start();
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case Config.PAUSE_MUSIC://暂停歌曲
                if(mediaPlayer.isPlaying()){
                    mediaPlayer.pause();
                }else {
                    mediaPlayer.start();
                    new MusicplayerThread().start();
                }
                break;
            case Config.SEEK_TO://拖动SeekBar,设置播放进度
                int progress=intent.getIntExtra(Config.PROGRESS,0);//得到拖动位置
                mediaPlayer.seekTo(progress);
                break;
            default:
                break;
        }
        return super.onStartCommand(intent, flags, startId);
    }
    class MusicplayerThread extends Thread{
        @Override
        public void run() {
            while (mediaPlayer.isPlaying()){
                int currentTime=mediaPlayer.getCurrentPosition();//得到当前播放时间
                Intent intent=new Intent(Config.BROADCAST_TAG);
                intent.putExtra(Config.TYPE,Config.CURRENT_TIME);
                intent.putExtra(Config.TIME,currentTime);//将当前播放时间传回去
                sendBroadcast(intent);
                try {
                    Thread.sleep(1000);//休眠,不让消息发送太频繁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if(mediaPlayer!=null){
            mediaPlayer.stop();
            mediaPlayer.release();//释放相关资源
        }
    }
}

然后不要忘了在applica标签下注册我们的服务

<service android:name=".MusicService"></service>

最后就是我们主活动中的代码:

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.text.SimpleDateFormat;

public class MainActivity extends Activity {
    private MyMusicBroadcastReceicer myMusicBroadcastReceicer;
    private SeekBar seekBar;
    private TextView textView_totaltime;
    private TextView textView_currenttime;
    private boolean isPlay;
    private boolean isPause;
    private boolean isFirstClick = true;
    private ImageButton button_play;
    private int listposition;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //File musicFile= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
        File file = Environment.getExternalStorageDirectory();
        File musicFile = new File(file, "/Music");
        final File[] files = musicFile.listFiles();//得到Music文件夹下所有文件
        MusicAdapter adapter = new MusicAdapter(files, getLayoutInflater());
        final ListView listView = (ListView) findViewById(R.id.listview);
        seekBar = (SeekBar) findViewById(R.id.seekbar);
        textView_totaltime = (TextView) findViewById(R.id.totalttime);
        textView_currenttime = (TextView) findViewById(R.id.currenttime);
        listView.setAdapter(adapter);
        myMusicBroadcastReceicer = new MyMusicBroadcastReceicer();
        IntentFilter intentFilter = new IntentFilter(Config.BROADCAST_TAG);
        registerReceiver(myMusicBroadcastReceicer, intentFilter);//动态注册广播
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {//点击ListView播放当前选中歌曲
                button_play.setBackgroundResource(R.drawable.pause);
                isFirstClick=false;
                isPlay=true;
                isPause=false;
                listposition=position;//得到当前选中位置
                Intent intent = new Intent(getApplicationContext(), MusicService.class);
                intent.putExtra(Config.TYPE, Config.START_MUSIC);
                intent.putExtra(Config.PATH, files[position].getAbsolutePath());
                startService(intent);
            }
        });
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                Intent intent = new Intent(getApplicationContext(), MusicService.class);
                intent.putExtra(Config.TYPE, Config.SEEK_TO);
                intent.putExtra(Config.PROGRESS, seekBar.getProgress());//传回拖动位置
                startService(intent);
            }
        });
        ImageButton button_last = (ImageButton) findViewById(R.id.last);
        button_last.setOnClickListener(new View.OnClickListener() {//播放上一首歌
            @Override
            public void onClick(View v) {
                listposition=listposition-1;
                button_play.setBackgroundResource(R.drawable.pause);
                isFirstClick=false;
                isPlay = true;
                isPause = false;
                if(listposition>=0){
                    Intent intent = new Intent(getApplicationContext(), MusicService.class);
                    intent.putExtra(Config.TYPE, Config.START_MUSIC);
                    intent.putExtra(Config.PATH, files[listposition].getAbsolutePath());
                    startService(intent);
                }else {
                    Toast.makeText(getApplicationContext(), "对不起,已经是第一首歌了!", Toast.LENGTH_SHORT).show();
                    listposition=0;
                }
            }
        });
        button_play = (ImageButton) findViewById(R.id.play);

        button_play.setOnClickListener(new View.OnClickListener() {//播放歌曲
            @Override
            public void onClick(View v) {
                if (isFirstClick) {//第一次点击播放,默认播放第一首歌
                    button_play.setBackgroundResource(R.drawable.pause);
                    Intent intent = new Intent(getApplicationContext(), MusicService.class);
                    intent.putExtra(Config.TYPE, Config.START_MUSIC);
                    intent.putExtra(Config.PATH, files[0].getAbsolutePath());
                    startService(intent);
                    isFirstClick = false;
                    isPlay = true;
                    isPause = false;
                } else {
                    if (isPlay) {
                        button_play.setBackgroundResource(R.drawable.play);
                        Intent intent = new Intent(getApplicationContext(), MusicService.class);
                        intent.putExtra(Config.TYPE, Config.PAUSE_MUSIC);
                        startService(intent);
                        isPlay = false;
                        isPause = true;
                    } else if (isPause) {
                        button_play.setBackgroundResource(R.drawable.pause);
                        Intent intent = new Intent(getApplicationContext(), MusicService.class);
                        intent.putExtra(Config.TYPE, Config.PAUSE_MUSIC);
                        startService(intent);
                        isPlay = true;
                        isPause = false;
                    }
                }
            }
        });
        ImageButton button_next = (ImageButton) findViewById(R.id.next);
        button_next.setOnClickListener(new View.OnClickListener() {//播放下一首歌
            @Override
            public void onClick(View v) {
                button_play.setBackgroundResource(R.drawable.pause);
                isFirstClick=false;
                isPlay = true;
                isPause = false;
                listposition=listposition+1;
                if(listposition<=files.length-1){
                    Intent intent = new Intent(getApplicationContext(), MusicService.class);
                    intent.putExtra(Config.TYPE, Config.START_MUSIC);
                    intent.putExtra(Config.PATH, files[listposition].getAbsolutePath());
                    startService(intent);
                }else{
                    Toast.makeText(getApplicationContext(), "对不起,已经是最后一首歌了!", Toast.LENGTH_SHORT).show();
                    listposition=files.length-1;
                }
            }
        });

    }

    class MyMusicBroadcastReceicer extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            int type = intent.getIntExtra(Config.TYPE, 0);
            SimpleDateFormat format = new SimpleDateFormat("mm:ss");//设置歌曲显示时间格式
            switch (type) {
                case Config.TOTAL_TIME:
                    int totalTime = intent.getIntExtra(Config.TIME, 0);
                    seekBar.setMax(totalTime);
                    textView_totaltime.setText(format.format(totalTime));
                    break;
                case Config.CURRENT_TIME:
                    int currentTime = intent.getIntExtra(Config.TIME, 0);
                    seekBar.setProgress(currentTime);
                    textView_currenttime.setText(format.format(currentTime));
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(myMusicBroadcastReceicer);//将广播解除注册
    }
}

大功告成!来看一下效果!
音频的播放、简单音乐播放器_第1张图片
这样就实现了播放器的基本功能!

你可能感兴趣的:(mediaplayer,简单的音乐播放器)