MediaPlayer初探一

1、打开音乐库

<span style="font-size:18px;">Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);     //打开音乐库
startActivityForResult(intent, 0);</span>
2、得到手机中音乐信息

<span style="font-size:14px;">private void get_list() {
        ContentResolver musicResolver = this.getContentResolver();
        Cursor musicCursor = musicResolver.query(
                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
                null);
        while (musicCursor.moveToNext()) {
            long id = musicCursor.getLong(musicCursor.getColumnIndex(MediaStore.Audio.AudioColumns._ID));
            String path = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.AudioColumns.DATA));//文件的路径
            String display_name = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.AudioColumns.DISPLAY_NAME));//文件的名字
            int size = musicCursor.getInt(musicCursor.getColumnIndex(MediaStore.Audio.AudioColumns.SIZE));//文件的长度
            String album = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.AudioColumns.ALBUM));//音乐的专辑
            String artist = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.AudioColumns.ARTIST));//歌手的名字
            String title = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.AudioColumns.TITLE));//歌曲的名字
            int duration = musicCursor.getInt(musicCursor.getColumnIndex(MediaStore.Audio.AudioColumns.DURATION));//歌曲的时长
            String mime_type = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.AudioColumns.MIME_TYPE));//歌曲的类型
            System.out.println("id:" + id + "\n path:" + path + "\n display_name:" + display_name + "\n size:" + size + "\n album:" + album + "\n artist:" + artist + "\n title:" + title + "\n duration:" + duration + "\n mimeType:" + mime_type);

        }
    }</span>

根据id来播放指定的音乐

long id = /* retrieve it from somewhere */;
Uri contentUri = ContentUris.withAppendedId(
        android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);

mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setDataSource(getApplicationContext(), contentUri);

// ...prepare and start...

3、MediaPlayer播放音频

创建MediaPlayer

     方式一

        // Load an audio resource from a package resource.
        MediaPlayer resourcePlayer =
                MediaPlayer.create(this, R.raw.my_audio);

        // Load an audio resource from a local file.
        MediaPlayer filePlayer = MediaPlayer.create(this,
                Uri.parse(“file:///sdcard/localfile.mp3”));

        // Load an audio resource from an online resource.
        MediaPlayer urlPlayer = MediaPlayer.create(this,
                Uri.parse(“http://site.com/audio/audio.mp3”));

        // Load an audio resource from a Content Provider.
        MediaPlayer contentPlayer = MediaPlayer.create(this,
                Settings.System.DEFAULT_RINGTONE_URI);

  方式二

 //加载raw的资源文件
        AssetFileDescriptor assetFileDescriptor = getResources().openRawResourceFd(R.raw.tfboys);
        mediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(),assetFileDescriptor.getStartOffset(),assetFileDescriptor.getLength());
        //加载asset的资源文件
        AssetFileDescriptor assetFileDescriptor = getAssets().openFd("tfboys.mp3");
        mediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(),assetFileDescriptor.getStartOffset(),assetFileDescriptor.getLength());
        //加载sd卡的文件
        mediaPlayer.setDataSource(path);
        //加载网络音频
        mediaPlayer.setDataSource(url);

*res/raw和assets的不同点:
1.res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即R.id.filename;assets文件夹下的文件不会被映射到R.java中,访问的时候需要AssetManager类。
2.res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹

播放音频

Uri myUri = ....; // initialize Uri here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();
*mediaPlayer.prepare()和MediaPlayer.prepareAnsy()的区别:

mediaPlayer.prepare()方法在UI线程中执行,MediaPlayer.prepareAnsy()是开启另一个线程用于MediaPlayer的准备工作

其它的操作:

   public void stop() {
        if (mediaPlayer != null){
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }

    public void replay() {
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.seekTo(0);
        } else {
            play();
        }
    }

    public void pause() {
        if (mediaPlayer != null)
            mediaPlayer.pause();
    }
MediaPlayer的准备监听:

mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                
            }
        });
MediaPlayer的错误监听:

mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                return false;
            }
        });

优化完善播放音频

根据电话状态来改变MediaPlayer的状态:

TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        telephonyManager.listen(new PhoneStateListener(){
            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                switch (state){
                    case TelephonyManager.CALL_STATE_RINGING://正在拨打电话
                        break;
                    case TelephonyManager.CALL_STATE_IDLE://挂断
                        break;
                }
            }
        },PhoneStateListener.LISTEN_CALL_STATE);

监听音频焦点的改变

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        audioManager.requestAudioFocus(new AudioManager.OnAudioFocusChangeListener() {
            @Override
            public void onAudioFocusChange(int focusChange) {
                switch (focusChange) {
                    case AudioManager.AUDIOFOCUS_GAIN:
                        System.out.println("得到焦点");
                        // 得到焦点
                        if (mediaPlayer == null) play();
                        else if (!mediaPlayer.isPlaying()) mediaPlayer.start();
                        mediaPlayer.setVolume(1.0f, 1.0f);
                        break;

                    case AudioManager.AUDIOFOCUS_LOSS:
                        System.out.println("将MediaPlayer进行释放");
                        // 失去焦点很长时间,应该将MediaPlayer进行释放
                        if (mediaPlayer.isPlaying()) mediaPlayer.stop();
                        mediaPlayer.release();
                        mediaPlayer = null;
                        break;

                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                        System.out.println("停止播放,不去释放MediaPlayer");
                        //失去焦点很短时间,但是我们不得不停止播放,我们不去释放MediaPlayer,因为还有可能被唤醒
                        if (mediaPlayer.isPlaying()) mediaPlayer.pause();
                        break;

                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                        System.out.println("失去焦点很短时间,但是一直保持播放");
                        // 失去焦点很短时间,但是他一直保持播放
                        if (mediaPlayer.isPlaying()) mediaPlayer.setVolume(0.1f, 0.1f);
                        break;
                }
            }
        },AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN);
有可能处理噪音,例如用户先用耳机听音乐然后将耳机拔下的情况:

<receiver android:name=".MusicIntentReceiver">
   <intent-filter>
      <action android:name="android.media.AUDIO_BECOMING_NOISY" />
   </intent-filter>
</receiver>
public class MusicIntentReceiver extends android.content.BroadcastReceiver {
   @Override
   public void onReceive(Context ctx, Intent intent) {
      if (intent.getAction().equals(
                    android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
          // signal your service to stop playback
          // (via an Intent, for instance)
      }
   }
}

同理播放视频也是一样的

视频是由图像和声音组成,图像则由SurfaceView来显示

sv = (SurfaceView) findViewById(R.id.sv);
        /* 下面设置Surface不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前 API11以下使用*/
        sv.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        sv.getHolder().addCallback(this);
为了避免SurfaceView销毁在创建图像变成黑屏,则实现SurfaceHolder.CallBack接口方法:

 @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if(position != 0){
            play();
            mediaPlayer.seekTo(position);
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        System.out.println("执行了surfaceChanged方法");
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if(mediaPlayer != null && mediaPlayer.isPlaying()){
            position = mediaPlayer.getCurrentPosition();
            mediaPlayer.stop();
        }
    }

图像和声音绑定

mediaPlayer.setDisplay(sv.getHolder());



你可能感兴趣的:(android)