频道栏目
首页 > 资讯 > Android > 正文

Android歌词秀设计思路(5)歌词播放服务

11-09-13        来源:[db:作者]  
收藏   我要投稿

接下来说明一下,提供歌词播放器服务的LyricPlayerService。这个类在整个播放过程中的作用是
1.负责管理LyricAdapter的生命周期。
2.控制音乐播放,歌词解析,并且协调音乐与歌词同步。
3.收集超类,LyricAdapter发来的通知并传递给登录的LyricAdapterListener
首先是看一下这个类在全体图中的位置。

 
从图中我们可以明显的看出这个类处于整个图中的节点位置,光从这一点就可以理解这个类的重要性。
代码不多,简单说明一下。
首先是定义用于从LyricPlayerService接收状态变化通知的接口并提供了指定具象接口的方法。
在歌曲播放过程中,继续应用退出LyricPlayerService还会继续执行。这时如果重新启动播放器应用程序,就有一个重新建立联系,也就是播放中的LyricPlayerService指定接口的场景。在LyricPlayerService的设计中,会重新调用LyricPlayerListener的onLyricLoad和onLyricChanged方法。这样应该可以简化应用侧的实现。
    //定义接受播放器状态变化的接口 
    public interface LyricPlayerListener{ 
        //播放位置发生变化 
        public void onPositionChanged(long position); 
        //播放器状态发生变化 
        public void onStateChanged(); 
        //当前歌词变化 
        public void onLyricChanged(int lyric_index); 
        //歌词文件解析完了 
        public void onLyricLoaded(); 
    } 
     
    private LyricPlayerListener mLyricPlayerListener = null; 
     
    void setLyricPlayerListener(LyricPlayerListener listener){ 
        mLyricPlayerListener = listener; 
        if(mLyricPlayerListener != null) 
        { 
            //新设定Listener直接调用onLyricLoad方法,给以个准备表是内容的机会。 
            mLyricPlayerListener.onLyricLoaded(); 
            int curLyric = mLyricAdapter.getCurrentLyric(); 
            if(curLyric >= 0 && curLyric < mLyricAdapter.getLyricCount()){ 
                //如果已经处于播放中状态,将现在歌词通知给Listener 
                mLyricPlayerListener.onLyricChanged(curLyric); 
            } 
        } 
    }
创建LyricAdapter的实例
private LyricAdapter mLyricAdapter = new LyricAdapter();
创建SafetyTimer的实例并制定动作。在OnTimer事件中,首先取得MediaPlayer的现在播放位置并将这个信息通知给LyricAdapter和登录的mLyricPlayerListener。内容很简单,但是这里是LyricPlayerService能够正常动作的最主要的部分。除了我们看不到的歌曲播放部分,这里差不多算是半个主程序了。
private SafetyTimer mLyricTimer = new SafetyTimer(500, new SafetyTimer.OnTimeListener(){ 
        public void OnTimer(){ 
            if(mMediaPlayer != null){ 
                int position = mMediaPlayer.getCurrentPosition(); 
                if(mLyricPlayerListener != null){ 
                    mLyricPlayerListener.onPositionChanged(position); 
                } 
                mLyricAdapter.notifyTime(position); 
            } 
        }    
    });
onCreate和onDestroy没有什么特别的。当然在onDestroy里面也可以调用mLyricAdapter.setListener(null); 没有什么区别。
@Override
    public void onCreate() { 
        super.onCreate(); 
        mLyricAdapter.setListener(this); 
    } 
 
    @Override
    public void onDestroy() { 
        super.onDestroy(); 
        mLyricAdapter = null; 
    }
接下来是播放控制关联方法。主要做以下几件事
1.调用超类的功能。
2.控制SafetyTimer的动作。
3.条用Listener的对应功能。
 
@Override
    public void start() { 
        if(isStop()){ 
            //停止状态开始,需要重新启动Timer 
            super.start(); 
            mLyricTimer.startTimer(); 
        }else{ 
            //暂停状态开始,不需要重启Timer 
            super.start(); 
        } 
        if(mLyricPlayerListener != null){ 
            mLyricPlayerListener.onStateChanged(); 
        } 
    }    
     
    @Override
    public void stop() { 
        mLyricTimer.stopTimer(); 
        super.stop(); 
        if(mLyricPlayerListener != null){ 
            mLyricPlayerListener.onStateChanged(); 
        } 
    }    
     
    @Override
    public void pause() { 
        super.pause(); 
        if(mLyricPlayerListener != null){ 
            mLyricPlayerListener.onStateChanged(); 
        } 
    }    
 
下面的两个方法覆盖了,超类的对应方法,把本来用来播放前后歌曲的功能改成播放同一首歌内的前后一句歌词。
@Override
   public void playNext(){ 
    seekToNextLyric(); 
   } 
    
   @Override
   public void playPrev(){ 
    seekToPrevLyric(); 
   }
以下是有关歌词的方法。基本上都是利用LyricAdapter和超类的位置控制功能。
public void loadLyric(){ 
        String url = getDataSource(); 
        //和歌曲在同一目录下,相同文件名,扩展名为lrc的文件 
        String strLyricFileUrl = url.substring(0, url.lastIndexOf(".") + 1) + "lrc"; 
        mLyricAdapter.LoadLyric(strLyricFileUrl); 
    } 
     
    public int getLyricCount(){ 
        return mLyricAdapter.getLyricCount(); 
    } 
     
    public String getLyric(int index){ 
        return mLyricAdapter.getLyric(index); 
    } 
     
    public long seekToLyric(int index){ 
        long position = mLyricAdapter.getLyricTime(index); 
        if(position != -1){ 
            return seek(position); 
        }else{ 
            return 0; 
        } 
    } 
     
    public void seekToPrevLyric(){ 
        int curLyric =  mLyricAdapter.getCurrentLyric(); 
        if(curLyric > 0){ 
            seekToLyric(curLyric - 1); 
        } 
    } 
     
    public void seekToNextLyric(){ 
        int curLyric =  mLyricAdapter.getCurrentLyric(); 
        if(curLyric < mLyricAdapter.getLyricCount() - 1){ 
            seekToLyric(curLyric + 1); 
        } 
    }
所剩不多了,重载onCompletion是想在这个时刻关闭Timer的同时,将这一变化通知个mLyricPlayerListener.
@Override
public void onCompletion(MediaPlayer mp) { 
    if(mLyricTimer.isRunging()){ 
        mLyricTimer.stopTimer(); 
    } 
    if(mLyricPlayerListener != null){ 
        mLyricPlayerListener.onStateChanged(); 
    } 
    super.onCompletion(mp); 
}  
最后是继承LyricAdapter.LyricListener需要的两个方法。将来自LyricAdapter的通知转送给已经登录的mLyricPlayerLister。之所以这样做是希望利用者在使用时可以简单一些。
@Override
    public void onLyricChanged(int lyric_index){ 
        if(mLyricPlayerListener != null){ 
            mLyricPlayerListener.onLyricChanged(lyric_index); 
        } 
    } 
     
    @Override
    public void onLyricLoaded(){ 
        if(mLyricPlayerListener != null){ 
            mLyricPlayerListener.onLyricLoaded(); 
            mLyricPlayerListener.onStateChanged(); 
        } 
    }
软件功能说明:原创:Android应用开发-Andorid歌词秀,含源码
工程,源码下载:Android歌词秀源码,工程文件2011/9/11版
作者“来自大连”

相关TAG标签
上一篇:Android歌词秀设计思路(4)通用的音乐播放服务(下)
下一篇: 关于设计模式的学习
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站