Android多媒体开发:MusicPlayer篇

来源:互联网 发布:淘宝视频怎么发布 编辑:程序博客网 时间:2024/06/06 09:09

今天被问到视频播放,录音的问题,又想起了曾经开发音视频播放,遇到的那些坑。其实多媒体的知识比较多,客户端开发难度也大,毕竟android应用层用java开发,对于音频开发,最好是有强大的C/C++功底才好研究底层,任重道远。
一起学习吧,先从音乐播放器开始。

一,先贴后台播放音乐的service部分代码

不一定要这样写,仅供参考。

/** * 可播放音视频的 MediaPlayerService duqian * 既可以activity绑定该service,也可以直接start,实现后台播放音乐 * 2016/01/08 */public class AudioPlayerService extends Service {    private static final String TAG = AudioPlayerService.class.getSimpleName();    private MyBinder myBinder;    private String music_name;    public AudioPlayerService() {        super();    }    private static VideoView mediaPlayer;    /**     * 初始化播放器控件     * @param videoView     */    private void initPlayer(VideoView videoView) {        mediaPlayer = videoView;    }    /**     * 播放音乐     */    public void play(){        if(mediaPlayer != null){            mediaPlayer.start();            notifyChange(MediaStaticVar.ACTION_PREPARED, MediaStaticVar.DATA_PREPARED);            //showNotification();        }    }    /**     * 暂停音乐     */    public void pause(){        if(mediaPlayer != null){            mediaPlayer.pause();        }        //stopNotification();    }    /**     * 跳到指定播放位置     * @param progress     */    private void seekTo(int progress) {        MediaStaticVar.progress = progress;        if(mediaPlayer != null){            mediaPlayer.seekTo(progress);        }    }    //是否正在播放    public boolean isPlaying(){        boolean playing =false;        if(mediaPlayer != null){            playing= mediaPlayer.isPlaying();        }        return playing;    }    //总时长    private long getDuration(){        long duration = 1000*60*6;        if (mediaPlayer!=null){            duration = mediaPlayer.getDuration();        }        return duration;    }    //当前时长    private long getCurrentPosition(){        long currentPosition = 0;        if (mediaPlayer!=null){            currentPosition = mediaPlayer.getCurrentPosition();        }        return currentPosition;    }    /**     * 创建播放器     * @param path     */    private void startPlay(String path,Context context) {        if (path == null||TextUtils.isEmpty(path)) {            return;        } else {            MediaStaticVar.path = path;            if (mediaPlayer==null){                LogUtils.debug(TAG, "mediaPlayer==null");                mediaPlayer = new VideoView(context);            }            mediaPlayer.setVideoPath(path);            mediaPlayer.seekTo(MediaStaticVar.progress);//上次播放的位置            mediaPlayer.requestFocus();            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {                @Override                public void onPrepared(MediaPlayer mediaPlayer) {                    mediaPlayer.setPlaybackSpeed(1.0f);                    play();                    //notifyChange(MediaStaticVar.ACTION_PREPARED, MediaStaticVar.DATA_PREPARED);                }            });            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {                @Override                public void onCompletion(MediaPlayer mp) {                    notifyChange(MediaStaticVar.ACTION_PREPARED,MediaStaticVar.DATA_COMPLETED);                }            });            mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {                @Override                public boolean onError(MediaPlayer mp, int what, int extra) {                    notifyChange(MediaStaticVar.ACTION_PREPARED,MediaStaticVar.DATA_ERROR);                    LogUtils.debug(what + "" + extra + "error");                    return true;                }            });        }    }    @Override    public IBinder onBind(Intent intent) {        LogUtils.debug(TAG,"onBind");        myBinder = new MyBinder();        return myBinder;//使用Binder对象,要返回    }    /**     * 定义一个类 继承 Binder,定义一个对象和调用者通信     */    private class MyBinder extends Binder implements IMusicPlayerService    {        @Override        public void callInitPlayer(VideoView videoView) {            initPlayer(videoView);        }        @Override        public void callPlayer(String path, Context mContext) {            startPlay(path,mContext);        }        @Override        public void callPause() {            pause();        }        @Override        public void callPlay() {            play();        }        @Override        public boolean callIsPlaying() {            return isPlaying();        }        @Override        public void callSeekTo(int progress) {            seekTo(progress);        }        @Override        public void callPrevious() {        }        @Override        public void callNext() {        }        @Override        public long callGetDuration() {            return getDuration();        }        @Override        public long callGetCurrentPosition() {            return getCurrentPosition();        }        @Override        public void callNotifyChange(String nofity, int action) {            notifyChange(nofity,action);        }        @Override        public void stopNotification() {            stopNotification();        }    }    @Override    public boolean onUnbind(Intent intent) {        LogUtils.debug(TAG,"on  unbind");        return super.onUnbind(intent);    }    @Override    public void onCreate() {        super.onCreate();    }    @Override    public void onDestroy() {        super.onDestroy();        if (mediaPlayer != null) {            try {                mediaPlayer.stopPlayback();                mediaPlayer = null;                LogUtils.debug(TAG,"mediaPlayer stop");            } catch (Exception e) {                e.printStackTrace();            }        }        stopNotification();        MediaStaticVar.progress = 0;        MediaStaticVar.path = "";    }    /**     * 发消息     * @param nofity     */    private void notifyChange(String nofity,int action){        Intent intent = new Intent();        if (nofity==null) {            intent.setAction(MediaStaticVar.ACTION_PREPARED);        }else{            intent.setAction(nofity);        }        intent.putExtra("data",action);        sendBroadcast(intent);//发广播    }}

二,IMusicPlayerService接口

如果activity绑定了该service,控制后台音乐的播放,暂停,下一曲,上一曲。那么可以写一个类似的接口, 定义一个类继承 Binder,实现IMusicPlayerService接口,以便service和调用者通信。

public interface IMusicPlayerService {    public void callInitPlayer(VideoView videoView);    public void callPlayer(String path,Context mContext);    public void callPause();    public void callPlay();    public boolean callIsPlaying();    public void callSeekTo(int progress);    public void callPrevious();    public void callNext();    public long callGetDuration();    public long callGetCurrentPosition();    public void callNotifyChange(String nofity,int action);    public void stopNotification();}

三,启动/绑定service

以下代码不全,仅供参考。

//开启服务    private IMusicPlayerService iservice; //服务    private MyConn conn;    private void startService(Class clazz) {        //1.开启服务,与本activity不绑定         Intent service = new Intent(context, clazz); service.setPackage(context.getPackageName());//这里你需要设置你应用的包名,5.0新要求        context.startService(service);//多次调用startService并不会启动多个service 而是会多次调用onStart    //2.开启服务与本activity绑定        Intent intent = new Intent(this,clazz);        conn = new MyConn();        bindService(intent,conn,Context.BIND_AUTO_CREATE);    }    private boolean isServiceConnected;    //定义绑定服务的接口    private class MyConn implements ServiceConnection{        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            //当绑定服务成功后,会回调此方法            isServiceConnected = true;            iservice = (IMusicPlayerService)service;           iservice.callPlayer(MediaStaticVar.path,context);//高清音乐,开始播放        }        @Override        public void onServiceDisconnected(ComponentName name) {            //当取消绑定服务成功后,会回调这个方法            iservice = null;        }    }

四,MediaPlayer相关介绍

对于背景音乐,将MediaPlayer封装在Service中即可实现。
MediaPlayer支持元数据、音频文件、音频流等形式的源数据的播放。
(1)播放元数据
所谓元数据即raw文件夹下的资源文件,调用方法如下:

mMediaPlayer=MediaPlayer.create(this, R.raw.test_cbr);mMediaPlayer.start();

(2)播放音频文件
对于本地文件,其数据源可以通过Uri来表示,在开始播放前需要设置播放类型并加载缓冲,示例如下:

Uri myUri="/path/to/localfile";MediaPlayer mediaPlayer=new MediaPlayer();mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer.setDataSource(getApplicationContext(), myUri);mediaPlayer.prepare();    //加载缓冲mediaPlayer.start();

(3)播放流
MediaPlayer支持基于网络的流播放,其支持的网络协议包括RSTP(RTP、SDP)、HTTP渐进流(HTTP Progressive Streaming)、HTTP生活流(HTTP Live Streaming Draft Protocol,仅Honeycomb版本中用到)等。Android4.0开始支持HTTPS协议,在网络播放和本地播放上略有不同,示例如下:

String url="http://duqian.net.cn/demo.mp3;MediaPlayer mediaPlayer=new MediaPlayer();mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);                                      mediaPlayer.setDataSource(url);mediaPlayer.prepare();    //加载缓冲mediaPlayer.start();

五,mediaPlayer设置监听

准备完成,播放完成,发生播放错误等,都可以监听。
不能在UI主线程中调用prepare方法。应通过prepareAsync方法将加载缓冲的工作放置在非UI主线程中进行,当准备工作完成时,MediaPlayer通过MediaPlayer.OnPreparedListener监听器可以监听到该事件。设置监听器的方法如下:

MediaPlayer.OnPreParedListener mPreparedListener=new MediaPlayer.OnPreparedListener(){    public void onPrepared(MediaPlayer mp){                                                                       mediaPlayer.start();                                                                }}

当播放结束时,通过MediaPlayer.OnCompletionListener可以监听到播放结束的消息,示例如下:

mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){public void onCompletion(MediaPlayer mediaPlayer){//stop  or next}});

MediaPlayer还存在一个出错的状态,即MEDIA_PLAYER_STATE_ERROR。监听出错的监听器为MediaPlayer.OnErrorListener。

mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {   @Override    public boolean onError(MediaPlayer mp, int what, int extra) {    LogUtils.debug(what + "" + extra + "error");    return true;    }});

六,个人的一点总结

其实android 系统API中的mediaPlayer使用起来还是挺方便的。当然也可以使用第三方多媒体框架,实现音视频的播放。
杜乾,Dusan,Q291902259;欢迎交流。

0 0
原创粉丝点击