MediaPlayer类是Androd多媒体框架中的一个重要的组件,通过该类,我们可以获取并播放音视频。

对播放器的主要控制方法:
Android通过控制播放器的状态的方式来控制媒体文件的播放,其中:
prepare()和prepareAsync() 提供了同步和异步两种方式设置播放器进入prepare状态,需要注意的是,如果MediaPlayer实例是由create方法创建的,那么第一次启动播放前不需要再调用prepare()了,因为create方法里已经调用过了。
start()是真正启动文件播放的方法,
pause()和stop()比较简单,起到暂停和停止播放的作用,
seekTo()是定位方法,可以让播放器从指定的位置开始播放,需要注意的是该方法是个异步方法,也就是说该方法返回时并不意味着定位完成,尤其是播放的网络文件,真正定位完成时会触发OnSeekComplete.onSeekComplete(),如果需要是可以调用setOnSeekCompleteListener(OnSeekCompleteListener)设置监听器来处理的。
release()可以释放播放器占用的资源,一旦确定不再使用播放器时应当尽早调用它释放资源。
reset()可以使播放器从Error状态中恢复过来,重新会到Idle状态。

它支持三种不同的媒体来源:

本地资源
内部URI,比如你可以通过ContentResolver来获取
外部URL(流)

本地资源的获取则是将音频文件放在一个自己在res下面创建的raw文件中:

MediaPlayer mp = MediaPlayer.create(this, R.raw.test);

内部URI,

可以直接写上音频在sd卡的路径(前提是知道文件位置)
这里就直接写通过ContentResolver来获取SD卡中的所有歌曲文件了:

Cursor cursor=contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,null,null,null,null);
        while (cursor.moveToNext()){
//音乐id
Long  ID=cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID));
//音乐标题
String TITLE=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
//艺术家
String ARTIST=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));  
//专辑
String  ALBUM=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));  
//专辑id
Long    ALBUM_ID=cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID)); 
//时长
Long    DURATION=cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION)); 
//文件大小
Long    SIZE=cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE));  
//文件路径
String  DATA=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)); 
//是否为音乐
Long    IS_MUSIC=cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));  
        }

用以上这段代码来获取手机中的MP3歌曲的路径

MediaPlayer mediaPlayer=new MediaPlayer();
mediaPlayer.setDataSource(this, Uri.parse("file://"+DATA));
//播放前准备一下
 mediaPlayer.prepare();
//监听:准备完成的监听
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    mediaPlayer.start();
                }
            });

使用前要获取访问sd卡的权限
在AndroidManifest直接用以下的代码

//获取访问网络权限
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
//获取访问sd卡权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>

在SDK6.0会遇到一个这样的问题:requires Android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
原因:从6.0(api 23)开始, android采用了Runtime permission request, 即在运行时请求权限,而不是在编译的时候,即使在manifest.xml里面添加了权限也要在运行时请求。
但不是所有的permission都要Runtime request,涉及到资源文件请求时就会用到Runtime request,比如获取位置信息, content provider获取media的情况。
解决方法:

//运行时调用
 @SuppressLint("NewApi")
    private void requestReadExternalPermission() {
        if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {
            if (shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {
            } else {

                requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
            }
        } else {
        }
    }
//处理请求:
   @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 0: {
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                } else {
                }
                return;
            }
            default:
                break;

        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

外部URL(流):

MediaPlayer mediaPlayer=new MediaPlayer();
 //和内部uri唯一区别就是这一段,其他一样
mediaPlayer.setDataSource(this, Uri.parse("http://192.168.43.135/internet.mp3"));
//异步
 mediaPlayer.prepareAsync();