最近在学习service相关的内容,在该部分的学习过程中,根据学习视频中的内容进行了总结归纳,以下是音乐播放器demo的开发思路,具体步骤及源码:

有关MVP框架的内容可看: link.

实现效果:

实现思路:

  1. 新建布局,初始化控件,设置点击事件
  2. 新建两个接口,一个用来定义相关操作(控制逻辑层),一个用来控制UI
  3. 创建service,注册service,(此处采用混合开启service的方式)(混合开启service: link.)开启service,绑定service
  4. 利用service绑定返回的binder对象来实现逻辑层的接口,UI接口
  5. 利用presenter实现逻辑操作,将该实例化对象给service
  6. 播放音频时的逻辑处理
  7. 将音频设置到模拟机上,manifest中设置读取权限
  8. 编写音频播放时、停止时的内部逻辑,修改button的显示内容
  9. 编写播放、暂停、停止时进度条的内部逻辑
  10. 实现进度条UI更新

——————————————————————————————
实现源码:
manifest中设置读写权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

音频文件存放路径:

IPlayerViewControl.java

public interface IPlayerViewControl {void onPlayStateChange(int state);  //播放状态改变的通知,state为当前状态void onSeekChange(int seek);        //播放进度改变
}

IPlayerControl.java

public interface IPlayControl {//播放状态public static final int PLAY_STATE_PLAY=1;    //播放public static final int PLAY_STATE_PAUSE=2;     //暂停public static final int PLAY_STATE_STOP=3;      //停止void regiestViewController(IPlayerViewControl viewController);  //把UI的控制接口设置给逻辑层void unRegiestViewController(); //取消接口通知的注册void playOrPause();    //播放或暂停音乐void stop();    //停止播放void seekTo(int seek);  //设置播放进度,seek表示播放进度
}

PlayerPresenter


import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Binder;
import android.util.Log;import com.example.serviceddemo.interfaces.IPlayControl;
import com.example.serviceddemo.interfaces.IPlayerViewControl;import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;public class PlayerPresenter extends Binder implements IPlayControl {private static final String TAG ="PlayerPresenter" ;private IPlayerViewControl mViewController;  //这个变量用来控制UIprivate int currentState=PLAY_STATE_STOP;   //默认状态为暂停private MediaPlayer mediaPlayer;private Timer timer;private SeekTimeTask seekTimeTask;@Overridepublic void regiestViewController(IPlayerViewControl viewController) {this.mViewController=viewController;}@Overridepublic void unRegiestViewController() {mViewController=null;}@Overridepublic void playOrPause() {Log.d(TAG,"playOrPause......");if(currentState == PLAY_STATE_STOP){//暂停状态,此时是没有播放器的,创建播放器initPlayer();//如果不为空的话就设置数据源if(mediaPlayer != null){try {mediaPlayer.setDataSource("/mnt/sdcard/song.mp3");mediaPlayer.prepare();mediaPlayer.start();currentState=PLAY_STATE_PLAY;startTimer();} catch (IOException e) {e.printStackTrace();}}}else if(currentState == PLAY_STATE_PLAY){      //如果当前的状态是播放的,那就去暂停if (mediaPlayer != null){mediaPlayer.pause();currentState=PLAY_STATE_PAUSE;stopTimer();}}else if (currentState == PLAY_STATE_PAUSE){    //如果当前的状态是暂停的,就继续播放音乐if (mediaPlayer != null) {mediaPlayer.start();currentState=PLAY_STATE_PLAY;startTimer();}}//通知UI界面修改if (mViewController != null){mViewController.onPlayStateChange(currentState);}}/*** 初始化播放器*/private void initPlayer() {if (mediaPlayer == null){mediaPlayer = new MediaPlayer();mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);  //利用MediaPlayer来播放MP3格式的音频}}@Overridepublic void stop() {        //停止时释放资源Log.d(TAG,"stop");if (mediaPlayer != null && mediaPlayer.isPlaying()) {mediaPlayer.stop();mediaPlayer.release();mediaPlayer=null;stopTimer();currentState=PLAY_STATE_STOP;if (mViewController != null){       //更新播放状态mViewController.onPlayStateChange(currentState);}}}@Overridepublic void seekTo(int seek) {Log.d(TAG,"seekTo"+seek);//播放的进度在0-100之间,需要做一个转换,但是实际的seek应该是一个播放进度的百分比if (mediaPlayer != null ){int tarSeek= (int) (seek * 1.0f / 100 * mediaPlayer.getDuration());mediaPlayer.seekTo(tarSeek);            //此时是人为主动控制进度条,改变播放内容}}/*** 播放的时候,开启timerTask*/private void startTimer(){if (timer == null){timer = new Timer();  //设置为成员变量}if (seekTimeTask == null){seekTimeTask=new SeekTimeTask();  //设置为成员变量}timer.schedule(seekTimeTask,0,500);     //每500ms更新一次}/*** 停止timerTask*/private void stopTimer(){if (timer != null){timer.cancel();  //不为空时,停止这个timerTasktimer=null;}if (seekTimeTask != null){seekTimeTask.cancel();seekTimeTask=null;}}private class SeekTimeTask extends TimerTask{@Overridepublic void run() {//获取当前的播放进度if(mediaPlayer != null && mViewController != null){int currentPosition = mediaPlayer.getCurrentPosition();int curPosition= (int) (currentPosition * 1.0f /mediaPlayer.getDuration() *100);mViewController.onSeekChange(curPosition);Log.d(TAG,"current play position is "+currentPosition);}}}
}

PlayerService.java

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;import androidx.annotation.Nullable;
import com.example.serviceddemo.presenter.PlayerPresenter;public class PlayerService extends Service {private static final String TAG ="PlayerService" ;private PlayerPresenter playerPresenter;@Overridepublic void onCreate() {Log.d(TAG,"oncreate...");if(playerPresenter == null){    //进行判空,防止重复创建playerPresenter = new PlayerPresenter();}super.onCreate();}@Nullable@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG,"onbind...");return playerPresenter;}@Overridepublic void onDestroy() {Log.d(TAG,"ondestroy...");super.onDestroy();playerPresenter=null;}
}

PlayActivity.java


import androidx.appcompat.app.AppCompatActivity;import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;import com.example.serviceddemo.interfaces.IPlayControl;
import com.example.serviceddemo.interfaces.IPlayerViewControl;
import com.example.serviceddemo.services.PlayerService;import static com.example.serviceddemo.interfaces.IPlayControl.PLAY_STATE_PAUSE;
import static com.example.serviceddemo.interfaces.IPlayControl.PLAY_STATE_PLAY;
import static com.example.serviceddemo.interfaces.IPlayControl.PLAY_STATE_STOP;public class PlayerActivity extends AppCompatActivity {private static final String TAG ="PlayerActivity" ;private SeekBar mseekBar;private Button mPlayOrPause,mClose;private PlayerConnection playerConnection;private IPlayControl iPlayControl;private boolean isUserTouchProgress=false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_player);initView();initEvent();         //设置相关事件initService();        //开启服务,混合开启服务的方式initBindService();   //绑定服务}/*** 初始化各种控件*/private void initView() {mseekBar=findViewById(R.id.seek_bar);mPlayOrPause=findViewById(R.id.play_or_pause_btn);mClose=findViewById(R.id.close_btn);}/*** 开启服务*/private void initService() {Log.d(TAG,"initService");Intent intent=new Intent(this,PlayerService.class);startService(intent);}/*** 绑定服务(选择混合开启服务的方式!)*/private void initBindService() {Log.d(TAG,"initBindService...");Intent intent=new Intent(this, PlayerService.class);if(playerConnection == null){playerConnection = new PlayerConnection();}bindService(intent,playerConnection,BIND_AUTO_CREATE);}private class  PlayerConnection implements ServiceConnection{@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.d(TAG,"onServiceConnected");iPlayControl = (IPlayControl) service;iPlayControl.regiestViewController(mIPlayerViewControl);}@Overridepublic void onServiceDisconnected(ComponentName name) {Log.d(TAG,"onServiceDisconnected");iPlayControl=null;}}/*** 初始化控件的各种事件*/private void initEvent() {mseekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {//进度条发生改变}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {//手已经触摸上去了isUserTouchProgress=true;}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {int touchProgress=seekBar.getProgress();Log.d(TAG,"touchProgress  is "+touchProgress);//停止拖动if (iPlayControl != null) {iPlayControl.seekTo(touchProgress);}isUserTouchProgress=false;}});mPlayOrPause.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//播放或者暂停if(iPlayControl != null){iPlayControl.playOrPause();}}});mClose.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//关闭的button被点击了if(iPlayControl != null){iPlayControl.stop();}}});}private IPlayerViewControl mIPlayerViewControl=new IPlayerViewControl() {@Overridepublic void onPlayStateChange(int state) {//播放状态改变时,要根据播放的状态来修改UI,就去定义播放状态switch (state) {case PLAY_STATE_PLAY://播放中的状态:将button显示内容改为“暂停”mPlayOrPause.setText("暂停");break;case PLAY_STATE_PAUSE://暂停中的状态:将button显示内容改为“播放”mPlayOrPause.setText("播放");break;case PLAY_STATE_STOP:mPlayOrPause.setText("播放");break;}}@Overridepublic void onSeekChange(final int seek) {runOnUiThread(new Runnable() {@Overridepublic void run() {if(! isUserTouchProgress){mseekBar.setProgress(seek);}}});}};/*** 解绑服务*/@Overrideprotected void onDestroy() {if(playerConnection != null){unbindService(playerConnection);iPlayControl.unRegiestViewController();Log.d(TAG,"onDestroy");}super.onDestroy();}}

activity_player.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><SeekBarandroid:id="@+id/seek_bar"android:layout_marginTop="10dp"android:layout_width="match_parent"android:max="100"android:layout_height="wrap_content"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:layout_marginTop="20dp"android:gravity="center"><Buttonandroid:id="@+id/play_or_pause_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="播放"/><Buttonandroid:id="@+id/close_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="停止"android:layout_marginLeft="50dp"/></LinearLayout>
</LinearLayout>

【Android-Service】基于MVP的音乐播放器demo实现思路(附源码)相关推荐

  1. jspm伊人静听音乐播放器系统毕业设计(附源码、运行环境)

    用户登录界面 歌曲排行榜界面  歌曲大全管理  歌曲排行榜管理  前台首页界面   免费赠送本源代码.数据库,请私信

  2. JAVA毕业设计Vue.js音乐播放器设计与实现计算机源码+lw文档+系统+调试部署+数据库

    JAVA毕业设计Vue.js音乐播放器设计与实现计算机源码+lw文档+系统+调试部署+数据库 JAVA毕业设计Vue.js音乐播放器设计与实现计算机源码+lw文档+系统+调试部署+数据库 本源码技术栈 ...

  3. Android Service的使用方法 音乐播放器实例

    Service翻译成中文是服务,熟悉Windows 系统的同学一定知道很熟悉了.Android里的Service跟Windows里的Service功能差不多,就是一个不可见的进程在后台执行,避免被用户 ...

  4. 基于JavaSwing开发MP3音乐播放器 课程设计 大作业源码 毕业设计

    基于JavaSwing开发MP3音乐播放器:   (大作业) 开发环境: Windows操作系统 开发工具: MyEclipse+Jdk 运行效果图:  基于JavaSwing开发MP3音乐播放器:  ...

  5. android音乐播放器上一首,安卓源码(音乐播放器,有播放和下一首,和进度条等功能)...

    [实例简介] 安卓音乐播放器,可以完美播放音乐,放下使用,在安卓eclipse下使用. [实例截图] [核心代码] Player └── Player ├── AndroidManifest.xml ...

  6. Java音乐播放器,窗体程序 完整源码

    今天为大家分享一个音乐播放器的开发与制作,目前系统已经完成了初步功能,后续会进一步完善.整个系统界面漂亮,有完整得源码,希望大家可以喜欢.喜欢的帮忙点赞和关注.一起编程.一起进步 开发环境 开发语言为 ...

  7. 一起用python做个炫酷音乐播放器【V3.0含源码及打包exe】

    前言 熟悉的小伙伴都知道,前段时间写了一篇关于音乐播放器的文章–Python自制一款炫酷音乐播放器.不少小伙伴私信我,对播放器提了一些改进建议,对播放器的一些逻辑bug优化完善.今天音乐播放器3.0版 ...

  8. 一个基于Android开发的简单的音乐播放器

    一个基于Android开发的简单的音乐播放器 记得当时老师让我们写因为播放器时,脑子一头雾水,网上杂七杂八的资料也很少有用,因此索性就自己写一篇,希望对有缘人有用. 因为有好多人问我要源码,所以附上g ...

  9. Android应用--简、美音乐播放器原型放送(作者:小巫)

    Android应用--简.美音乐播放器原型放送 2013年7月5日简.美音乐播放器开发 前言:小巫的简.美音乐播放器从5月7号开始开发,之前以为时间很充足,也没有估量整个软件的需求,如果简单实现基本的 ...

最新文章

  1. COOKIE和SESSION关系和区别
  2. python教程实例-python教程实例
  3. DDR3和eMMC区别
  4. 在Apworks数据服务中使用基于Entity Framework Core的仓储(Repository)实现
  5. 开发指南专题三:JEECG微云快速开发平台项目编码规范
  6. Flutter Duration详细概述
  7. kubenetes 1.4 安装后8080端口无法访问
  8. 使用python写机器学习算法遇到的问题
  9. linux查询电信端口,linux下获取电信,网通,铁通IP地址
  10. 格力空调通讯协议_格力空调485-格力风管机空调内外机单片机RS485通讯协议格式是怎样的-电气资讯 - 电工屋...
  11. linux下maxwell安装教程,Ubuntu下若干软件的安装方法
  12. 【win10操作系统基础】我的电脑 控制面板 win10桌面图标有个箭头如何不显示 去掉win10桌面图标箭头的方法
  13. python实现输入一个正整数_Python中实现输入一个整数的案例
  14. 5V开关电路应用设计
  15. CUDA编译(一)---使用nvcc编译cuda
  16. SHEN ZHEN归来!
  17. 论文复刻:排污权机制是否提高了企业全要素生产率(附代码、数据、原文献)
  18. 《权力的游戏》电脑高清壁纸 无水印
  19. 中国商用割草机市场趋势报告、技术动态创新及市场预测
  20. android 录像工具,Android 屏幕录制(Surface\ Texture 录制)工具库

热门文章

  1. 奶牛跟蜗牛,哪种动物智商更高?——T检验帮你找到答案
  2. 【教程】LATTICE DIAMOND 工程新建介绍
  3. Camera MetaData 介绍
  4. CASS10.1.6免狗安装包下载教程
  5. android 自定义圆形pop,自定义通过PopupWindow实现通用菜单
  6. 线性代数让我想想:什么是秩?
  7. qt中调用matlab生成的动态库
  8. 计算机应用基础教学内容,计算机应用基础教学大纲
  9. 【亲测可用】revit2022安装教程
  10. oracle 备份命令