接下来说明一下,提供歌词播放器服务的LyricPlayerService。这个类在整个播放过程中的作用是

1.负责管理LyricAdapter的生命周期。

2.控制音乐播放,歌词解析,并且协调音乐与歌词同步。

3.收集超类,LyricAdapter发来的通知并传递给登录的LyricAdapterListener

首先是看一下这个类在全体图中的位置。

从图中我们可以明显的看出这个类处于整个图中的节点位置,光从这一点就可以理解这个类的重要性。

代码不多,简单说明一下。

首先是定义用于从LyricPlayerService接收状态变化通知的接口并提供了指定具象接口的方法。

在歌曲播放过程中,继续应用退出LyricPlayerService还会继续执行。这时如果重新启动播放器应用程序,就有一个重新建立联系,也就是播放中的LyricPlayerService指定接口的场景。在LyricPlayerService的设计中,会重新调用LyricPlayerListener的onLyricLoad和onLyricChanged方法。这样应该可以简化应用侧的实现。

//定义接受播放器状态变化的接口

publicinterfaceLyricPlayerListener{

//播放位置发生变化

publicvoidonPositionChanged(longposition);

//播放器状态发生变化

publicvoidonStateChanged();

//当前歌词变化

publicvoidonLyricChanged(intlyric_index);

//歌词文件解析完了

publicvoidonLyricLoaded();

}

privateLyricPlayerListener mLyricPlayerListener =null;

voidsetLyricPlayerListener(LyricPlayerListener listener){

mLyricPlayerListener = listener;

if(mLyricPlayerListener !=null)

{

//新设定Listener直接调用onLyricLoad方法,给以个准备表是内容的机会。

mLyricPlayerListener.onLyricLoaded();

intcurLyric = mLyricAdapter.getCurrentLyric();

if(curLyric >=0&& curLyric < mLyricAdapter.getLyricCount()){

//如果已经处于播放中状态,将现在歌词通知给Listener

mLyricPlayerListener.onLyricChanged(curLyric);

}

}

}

创建LyricAdapter的实例

privateLyricAdapter mLyricAdapter =newLyricAdapter();

创建SafetyTimer的实例并制定动作。在OnTimer事件中,首先取得MediaPlayer的现在播放位置并将这个信息通知给LyricAdapter和登录的mLyricPlayerListener。内容很简单,但是这里是LyricPlayerService能够正常动作的最主要的部分。除了我们看不到的歌曲播放部分,这里差不多算是半个主程序了。

privateSafetyTimer mLyricTimer =newSafetyTimer(500,newSafetyTimer.OnTimeListener(){

publicvoidOnTimer(){

if(mMediaPlayer !=null){

intposition = mMediaPlayer.getCurrentPosition();

if(mLyricPlayerListener !=null){

mLyricPlayerListener.onPositionChanged(position);

}

mLyricAdapter.notifyTime(position);

}

}

});

onCreate和onDestroy没有什么特别的。当然在onDestroy里面也可以调用mLyricAdapter.setListener(null); 没有什么区别。

@Override

publicvoidonCreate() {

super.onCreate();

mLyricAdapter.setListener(this);

}

@Override

publicvoidonDestroy() {

super.onDestroy();

mLyricAdapter =null;

}

接下来是播放控制关联方法。主要做以下几件事

1.调用超类的功能。

2.控制SafetyTimer的动作。

3.条用Listener的对应功能。

@Override

publicvoidstart() {

if(isStop()){

//停止状态开始,需要重新启动Timer

super.start();

mLyricTimer.startTimer();

}else{

//暂停状态开始,不需要重启Timer

super.start();

}

if(mLyricPlayerListener !=null){

mLyricPlayerListener.onStateChanged();

}

}

@Override

publicvoidstop() {

mLyricTimer.stopTimer();

super.stop();

if(mLyricPlayerListener !=null){

mLyricPlayerListener.onStateChanged();

}

}

@Override

publicvoidpause() {

super.pause();

if(mLyricPlayerListener !=null){

mLyricPlayerListener.onStateChanged();

}

}

下面的两个方法覆盖了,超类的对应方法,把本来用来播放前后歌曲的功能改成播放同一首歌内的前后一句歌词。

@Override

publicvoidplayNext(){

seekToNextLyric();

}

@Override

publicvoidplayPrev(){

seekToPrevLyric();

}

以下是有关歌词的方法。基本上都是利用LyricAdapter和超类的位置控制功能。

publicvoidloadLyric(){

String url = getDataSource();

//和歌曲在同一目录下,相同文件名,扩展名为lrc的文件

String strLyricFileUrl = url.substring(0, url.lastIndexOf(".") +1) +"lrc";

mLyricAdapter.LoadLyric(strLyricFileUrl);

}

publicintgetLyricCount(){

returnmLyricAdapter.getLyricCount();

}

publicString getLyric(intindex){

returnmLyricAdapter.getLyric(index);

}

publiclongseekToLyric(intindex){

longposition = mLyricAdapter.getLyricTime(index);

if(position != -1){

returnseek(position);

}else{

return0;

}

}

publicvoidseekToPrevLyric(){

intcurLyric = mLyricAdapter.getCurrentLyric();

if(curLyric >0){

seekToLyric(curLyric -1);

}

}

publicvoidseekToNextLyric(){

intcurLyric = mLyricAdapter.getCurrentLyric();

if(curLyric < mLyricAdapter.getLyricCount() -1){

seekToLyric(curLyric +1);

}

}

所剩不多了,重载onCompletion是想在这个时刻关闭Timer的同时,将这一变化通知个mLyricPlayerListener.

@Override

publicvoidonCompletion(MediaPlayer mp) {

if(mLyricTimer.isRunging()){

mLyricTimer.stopTimer();

}

if(mLyricPlayerListener !=null){

mLyricPlayerListener.onStateChanged();

}

super.onCompletion(mp);

}

最后是继承LyricAdapter.LyricListener需要的两个方法。将来自LyricAdapter的通知转送给已经登录的mLyricPlayerLister。之所以这样做是希望利用者在使用时可以简单一些。

@Override

publicvoidonLyricChanged(intlyric_index){

if(mLyricPlayerListener !=null){

mLyricPlayerListener.onLyricChanged(lyric_index);

}

}

@Override

publicvoidonLyricLoaded(){

if(mLyricPlayerListener !=null){

mLyricPlayerListener.onLyricLoaded();

mLyricPlayerListener.onStateChanged();

}

}

android 歌词点击播放,Android歌词秀设计思路(5)歌词播放服务相关推荐

  1. Android歌词秀设计思路(7)水到渠成

    我们用了6篇文章的篇幅做了铺垫,终于到了真正的应用程序了.这部分还是一如既往的简单. 有关应用的类有两个,一个是LiryicMain,一个是SelectFileActivity.都是差不多最低限度的内 ...

  2. Android歌词秀设计思路(2)歌词处理

    这次的内容是歌词处理模块LyricAdapter类.这个类的主要功能有 1.歌词文件的解析 2.对外提供歌词访问服务(歌词数取得,歌词内容,时间的取得等) 3.根据播放位置检索对应的歌词. 4.在歌词 ...

  3. Android歌词秀设计思路(8)后记

    写下这篇博文的时候,访问量的总数刚好过2000次,先自己庆祝一下. 做程序已经十八九年,但是写文章介绍自己的程序还是第一次.是实话这件事的难度超出了我的预想. 一个是篇幅长,原先以为很简单的一个程序, ...

  4. android按钮点击变化,Android实现按钮点击效果(第一次点击变色,第二次恢复)...

    1.首先创建一个按钮 android:id="@+id/click" android:layout_width="fill_parent" android:la ...

  5. 解读Android 4.0 Camera原生应用程序的设计思路

    解读Android 4.0 Camera原生应用程序的设计思路 一篇很不错的文章: http://my.oschina.net/jerikc/blog/90791 1. 设置摄像头方向 2. 打开线程 ...

  6. android relativelayout 点击事件,Android Relativelayout点击背景行为

    所以我有一个RecyclerView,它是由我的自定义布局(代码如下)填充.我制作了一个可绘制的背景,并将其设置在我的自定义布局的根部,以便用户单击该项目时,背景颜色会发生变化.每个项目的布局上还有一 ...

  7. android view 点击变暗,Android应用开发Android ImageView点击变暗效果

    本文将带你了解Android应用开发Android ImageView点击变暗效果,希望本文对大家学Android有所帮助. < 自定义ImageView: 在ImageView中setPres ...

  8. android listview 点击获取焦点,android – ListView项目焦点行为

    我正在尝试创建一个EditText项目的ListView(使用自定义CursorAdapter),这样EditTexts最初看起来是不可编辑的,并且在长时间单击后变得可编辑.然后,用户将编辑EditT ...

  9. android ratingbar 点击事件,android – Capture RatingBar点击

    我似乎有一个问题,抓住我的评级栏点击.评分栏显示正常,并具有默认值.唯一的问题是我无法更改任何值,或者没有启用.我尝试了许多不同的东西(例如,在布局中启用,完全用 java构建).他们似乎都没有影响. ...

  10. Andorid歌词秀设计思路(1)SafetyTimer

    在Android中实现多媒体播放功能主要是通过MediaPlayer实现的.为了方便用户检测MediaPlayer的动作状态,Andorid为我们提供了一下接口 Nested Classes inte ...

最新文章

  1. 西部开源学习笔记BOOK2-《unit 4》
  2. 请人安装linux系统,我想安装linux操作系统,请指导一下
  3. 19.12 添加自定义监控项目 19.13/19.14 配置邮件告警 19.15 测试告警 19.16 不发邮件的问题处理...
  4. 阿里云上测试服务器的搭建
  5. Windows远程桌面(mstsc)不能复制粘贴的解决办法
  6. python 字符串 数组 判断,Python的字符串的数组指数
  7. 浅析Mysql InnoDB存储引擎事务原理
  8. 快速构建Windows 8风格应用33-构建锁屏提醒
  9. 使用 FieldMask 提高 C# gRpc 服务性能
  10. Http长连接的例子_亲测可用哦
  11. adfs服务器获取信息失败,在ADFS服务器上SAML LogOutRequest处理失败
  12. Tensorflow2.x代码实现计算Top-k Accuracy
  13. Lua4.0 实现#操作,获取table大小
  14. 使用Beautiful Soup 中遇到的小问题-----只能提取网页上第一页信息
  15. Flash 第二章 基本绘图工具-课堂笔记
  16. android 开源 视频播放器,安卓视频播放器——ijkPlayer(Bilibili开源)
  17. EXCEL制作行政区地图,小O地图EXCEL版发布新版本
  18. java Vector 在多线程使用中需要注意的问题
  19. 怎么彻底删除手机上的微信聊天记录?百看不如一试的删除方法!
  20. 基于C#的服装店进销存管理系统设计与实现

热门文章

  1. JavaWeb第七天
  2. 工业运动控制-电机选择、驱动器和控制器应用
  3. 什么是项目合同管理?
  4. C++不同的数据成员类型
  5. 积木题 (2017年秋季——某网站的面试笔试题)
  6. 如何准确找客户?有什么好的办法找客户吗?
  7. 在博客中自定义Google代理搜索
  8. 最近在看些远程办公的机会
  9. ERP与进销存、财务软件的区别
  10. SAP 人力资源工资配置项3---工资项配置