PlayAudioImpl.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. package com.yc.music.impl;
  2. import android.content.Context;
  3. import android.content.Intent;
  4. import android.content.IntentFilter;
  5. import android.media.AudioManager;
  6. import android.media.MediaPlayer;
  7. import com.yc.music.config.MusicConstant;
  8. import com.yc.music.config.MusicPlayAction;
  9. import com.yc.music.config.PlayModeEnum;
  10. import com.yc.music.inter.InterPlayAudio;
  11. import com.yc.music.inter.OnPlayerEventListener;
  12. import com.yc.music.manager.AudioFocusManager;
  13. import com.yc.music.manager.MediaSessionManager;
  14. import com.yc.music.model.AudioBean;
  15. import com.yc.music.receiver.AudioBroadcastReceiver;
  16. import com.yc.music.receiver.AudioEarPhoneReceiver;
  17. import com.yc.music.service.PlayAudioService;
  18. import com.yc.music.tool.BaseAppHelper;
  19. import com.yc.music.tool.QuitTimerHelper;
  20. import com.yc.music.utils.MusicSpUtils;
  21. import com.yc.music.utils.NotificationHelper;
  22. import com.yc.videotool.VideoLogUtils;
  23. import java.io.IOException;
  24. import java.util.List;
  25. import java.util.Random;
  26. import static com.yc.music.service.PlayAudioService.UPDATE_PLAY_PROGRESS_SHOW;
  27. public class PlayAudioImpl implements InterPlayAudio {
  28. private Context context;
  29. private PlayAudioService service;
  30. /**
  31. * 播放进度监听器
  32. */
  33. private OnPlayerEventListener mListener;
  34. /**
  35. * 正在播放的歌曲的序号
  36. */
  37. private int mPlayingPosition = -1;
  38. /**
  39. * 正在播放的歌曲[本地|网络]
  40. */
  41. private AudioBean mPlayingMusic;
  42. /**
  43. * 音频list集合
  44. */
  45. private List<AudioBean> audioMusics;
  46. /**
  47. * 播放器
  48. */
  49. private MediaPlayer mPlayer;
  50. /**
  51. * 允许与媒体控制器、音量键、媒体按钮和传输控件交互
  52. */
  53. private MediaSessionManager mMediaSessionManager;
  54. /**
  55. * 捕获/丢弃音乐焦点处理
  56. */
  57. private AudioFocusManager mAudioFocusManager;
  58. /**
  59. * 来电/耳机拔出时暂停播放
  60. * 在播放时调用,在暂停时注销
  61. */
  62. private final AudioEarPhoneReceiver mNoisyReceiver = new AudioEarPhoneReceiver();
  63. private final IntentFilter mFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
  64. /**
  65. * 其他广播
  66. * 比如:屏幕灭了后再次亮了,会显示锁屏页面
  67. * 这个在onCreate中创建,在onDestroy中销毁
  68. */
  69. private final AudioBroadcastReceiver mAudioReceiver = new AudioBroadcastReceiver();
  70. /**
  71. * 广播接受者标识,避免多次注册广播
  72. */
  73. private boolean mReceiverTag = false;
  74. /**
  75. * 播放状态
  76. */
  77. private int mPlayState = MusicPlayAction.STATE_IDLE;
  78. @Override
  79. public void init(PlayAudioService service) {
  80. this.context = service;
  81. this.service = service;
  82. createMediaPlayer();
  83. initMediaSessionManager();
  84. initAudioFocusManager();
  85. initEarPhoneBroadcastReceiver();
  86. initAudioBroadcastReceiver();
  87. }
  88. @Override
  89. public void play(int position) {
  90. audioMusics = BaseAppHelper.get().getMusicList();
  91. if (audioMusics.isEmpty()) {
  92. return;
  93. }
  94. if (position < 0) {
  95. position = audioMusics.size() - 1;
  96. } else if (position >= audioMusics.size()) {
  97. //如果是最后一首音乐,则播放时直接播放第一首音乐
  98. position = 0;
  99. }
  100. mPlayingPosition = position;
  101. AudioBean music = audioMusics.get(mPlayingPosition);
  102. String id = music.getId();
  103. VideoLogUtils.e("PlayService"+"----id----"+ id);
  104. //保存当前播放的musicId,下次进来可以记录状态
  105. long musicId = Long.parseLong(id);
  106. MusicSpUtils.getInstance(MusicConstant.SP_NAME).put(MusicConstant.MUSIC_ID,musicId);
  107. play(music);
  108. }
  109. @Override
  110. public void play() {
  111. if (!isPreparing() && !isPausing()) {
  112. return;
  113. }
  114. if(mPlayingMusic==null){
  115. return;
  116. }
  117. if(mAudioFocusManager.requestAudioFocus()){
  118. if(mPlayer!=null){
  119. mPlayer.start();
  120. mPlayState = MusicPlayAction.STATE_PLAYING;
  121. //开始发送消息,执行进度条进度更新
  122. QuitTimerHelper.getInstance().getHandler().sendEmptyMessage(UPDATE_PLAY_PROGRESS_SHOW);
  123. if (mListener != null) {
  124. mListener.onPlayerStart();
  125. }
  126. //当点击播放按钮时(播放详情页面或者底部控制栏),同步通知栏中播放按钮状态
  127. NotificationHelper.get().showPlay(mPlayingMusic);
  128. //注册监听来电/耳机拔出时暂停播放广播
  129. if(!mReceiverTag){
  130. mReceiverTag = true;
  131. context.registerReceiver(mNoisyReceiver, mFilter);
  132. }
  133. mMediaSessionManager.updatePlaybackState();
  134. }
  135. }
  136. }
  137. @Override
  138. public void play(AudioBean music) {
  139. mPlayingMusic = music;
  140. createMediaPlayer();
  141. try {
  142. mPlayer.reset();
  143. //把音频路径传给播放器
  144. mPlayer.setDataSource(mPlayingMusic.getPath());
  145. //准备
  146. mPlayer.prepareAsync();
  147. //设置状态为准备中
  148. mPlayState = MusicPlayAction.STATE_PREPARING;
  149. //监听
  150. mPlayer.setOnPreparedListener(mOnPreparedListener);
  151. mPlayer.setOnBufferingUpdateListener(mOnBufferingUpdateListener);
  152. mPlayer.setOnCompletionListener(mOnCompletionListener);
  153. mPlayer.setOnSeekCompleteListener(mOnSeekCompleteListener);
  154. mPlayer.setOnErrorListener(mOnErrorListener);
  155. mPlayer.setOnInfoListener(mOnInfoListener);
  156. //当播放的时候,需要刷新界面信息
  157. if (mListener != null) {
  158. mListener.onChange(mPlayingMusic);
  159. }
  160. //更新通知栏
  161. NotificationHelper.get().showPlay(mPlayingMusic);
  162. //更新
  163. mMediaSessionManager.updateMetaData(mPlayingMusic);
  164. mMediaSessionManager.updatePlaybackState();
  165. } catch (IOException e) {
  166. e.printStackTrace();
  167. }
  168. }
  169. @Override
  170. public void stop() {
  171. if (isDefault()) {
  172. return;
  173. }
  174. pause();
  175. if(mPlayer!=null){
  176. mPlayer.reset();
  177. mPlayState = MusicPlayAction.STATE_IDLE;
  178. }
  179. }
  180. @Override
  181. public void playPause() {
  182. if (isPreparing()) {
  183. stop();
  184. } else if (isPlaying()) {
  185. pause();
  186. } else if (isPausing()) {
  187. play();
  188. } else {
  189. play(getPlayingPosition());
  190. }
  191. }
  192. @Override
  193. public void release() {
  194. //放弃音频焦点
  195. mAudioFocusManager.abandonAudioFocus();
  196. mMediaSessionManager.release();
  197. //注销广播接收者
  198. context.unregisterReceiver(mAudioReceiver);
  199. //销毁MediaPlayer
  200. mPlayer.reset();
  201. mPlayer.release();
  202. mPlayer = null;
  203. }
  204. @Override
  205. public void pause() {
  206. if(mPlayer!=null){
  207. //暂停
  208. mPlayer.pause();
  209. //切换状态
  210. mPlayState = MusicPlayAction.STATE_PAUSE;
  211. //移除,注意一定要移除,否则一直走更新方法
  212. QuitTimerHelper.getInstance().getHandler().removeMessages(UPDATE_PLAY_PROGRESS_SHOW);
  213. //监听
  214. if (mListener != null) {
  215. mListener.onPlayerPause();
  216. }
  217. //当点击暂停按钮时(播放详情页面或者底部控制栏),同步通知栏中暂停按钮状态
  218. NotificationHelper.get().showPause(mPlayingMusic);
  219. //注销监听来电/耳机拔出时暂停播放广播
  220. //判断广播是否注册
  221. if (mReceiverTag) {
  222. //Tag值 赋值为false 表示该广播已被注销
  223. mReceiverTag = false;
  224. context.unregisterReceiver(mNoisyReceiver);
  225. }
  226. mMediaSessionManager.updatePlaybackState();
  227. }
  228. }
  229. @Override
  230. public void seekTo(int progress) {
  231. //只有当播放或者暂停的时候才允许拖动bar
  232. if (isPlaying() || isPausing()) {
  233. mPlayer.seekTo(progress);
  234. if(mListener!=null){
  235. mListener.onUpdateProgress(progress);
  236. }
  237. mMediaSessionManager.updatePlaybackState();
  238. }
  239. }
  240. @Override
  241. public void next() {
  242. //建议都添加这个判断
  243. if (audioMusics.isEmpty()) {
  244. return;
  245. }
  246. int playMode = MusicSpUtils.getInstance(MusicConstant.SP_NAME).getInt(MusicConstant.PLAY_MODE, 0);
  247. int size = audioMusics.size();
  248. PlayModeEnum mode = PlayModeEnum.valueOf(playMode);
  249. switch (mode) {
  250. //随机
  251. case SHUFFLE:
  252. mPlayingPosition = new Random().nextInt(size);
  253. play(mPlayingPosition);
  254. break;
  255. //单曲
  256. case SINGLE:
  257. play(mPlayingPosition);
  258. break;
  259. //顺序播放并且循环
  260. case LOOP:
  261. default:
  262. if (mPlayingPosition != size - 1) {
  263. // 如果不是最后一首,则还有下一首
  264. mPlayingPosition++;
  265. } else {
  266. // 如果是最后一首,则切换回第一首
  267. mPlayingPosition = 0;
  268. }
  269. VideoLogUtils.e("PlayService"+"----mPlayingPosition----"+ mPlayingPosition);
  270. play(mPlayingPosition);
  271. break;
  272. }
  273. }
  274. @Override
  275. public void prev() {
  276. //建议都添加这个判断
  277. if (audioMusics.isEmpty()) {
  278. return;
  279. }
  280. int playMode = MusicSpUtils.getInstance(MusicConstant.SP_NAME).getInt(MusicConstant.PLAY_MODE, 0);
  281. int size = audioMusics.size();
  282. PlayModeEnum mode = PlayModeEnum.valueOf(playMode);
  283. switch (mode) {
  284. //随机
  285. case SHUFFLE:
  286. mPlayingPosition = new Random().nextInt(size);
  287. play(mPlayingPosition);
  288. break;
  289. //单曲
  290. case SINGLE:
  291. play(mPlayingPosition);
  292. break;
  293. //顺序播放并且循环
  294. case LOOP:
  295. default:
  296. if(mPlayingPosition != 0){
  297. // 如果不是第一首,则还有上一首
  298. mPlayingPosition--;
  299. } else {
  300. // 如果没有上一首,则切换到最后一首
  301. mPlayingPosition = size;
  302. }
  303. play(mPlayingPosition);
  304. break;
  305. }
  306. }
  307. @Override
  308. public void updatePlayProgress() {
  309. updatePlayProgressShow();
  310. }
  311. @Override
  312. public void setOnPlayEventListener(OnPlayerEventListener listener) {
  313. mListener = listener;
  314. }
  315. /**
  316. * 创建MediaPlayer对象
  317. */
  318. private void createMediaPlayer() {
  319. if(mPlayer==null){
  320. //MediaCodec codec = new MediaCodec();
  321. mPlayer = new MediaPlayer();
  322. }
  323. }
  324. /** 音频准备好的监听器 */
  325. private MediaPlayer.OnPreparedListener mOnPreparedListener = new MediaPlayer.OnPreparedListener() {
  326. /** 当音频准备好可以播放了,则这个方法会被调用 */
  327. @Override
  328. public void onPrepared(MediaPlayer mp) {
  329. if (isPreparing()) {
  330. play();
  331. }
  332. }
  333. };
  334. /** 当音频播放结束的时候的监听器 */
  335. private MediaPlayer.OnCompletionListener mOnCompletionListener = new MediaPlayer.OnCompletionListener() {
  336. /** 当音频播放结果的时候这个方法会被调用 */
  337. @Override
  338. public void onCompletion(MediaPlayer mp) {
  339. next();
  340. }
  341. };
  342. /** 当音频缓冲的监听器 */
  343. private MediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() {
  344. @Override
  345. public void onBufferingUpdate(MediaPlayer mp, int percent) {
  346. if (mListener != null) {
  347. // 缓冲百分比
  348. mListener.onBufferingUpdate(percent);
  349. }
  350. }
  351. };
  352. /** 跳转完成时的监听 */
  353. private MediaPlayer.OnSeekCompleteListener mOnSeekCompleteListener = new MediaPlayer.OnSeekCompleteListener() {
  354. @Override
  355. public void onSeekComplete(MediaPlayer mp) {
  356. }
  357. };
  358. /**
  359. * 播放错误的监听
  360. */
  361. private MediaPlayer.OnErrorListener mOnErrorListener = new MediaPlayer.OnErrorListener() {
  362. @Override
  363. public boolean onError(MediaPlayer mp, int what, int extra) {
  364. return false;
  365. }
  366. };
  367. /**
  368. * 设置音频信息监听器
  369. */
  370. private MediaPlayer.OnInfoListener mOnInfoListener = new MediaPlayer.OnInfoListener() {
  371. @Override
  372. public boolean onInfo(MediaPlayer mp, int what, int extra) {
  373. return false;
  374. }
  375. };
  376. /**
  377. * 是否正在播放
  378. * @return true表示正在播放
  379. */
  380. public boolean isPlaying() {
  381. return mPlayState == MusicPlayAction.STATE_PLAYING;
  382. }
  383. /**
  384. * 是否暂停
  385. * @return true表示暂停
  386. */
  387. public boolean isPausing() {
  388. return mPlayState == MusicPlayAction.STATE_PAUSE;
  389. }
  390. /**
  391. * 是否正在准备中
  392. * @return true表示正在准备中
  393. */
  394. public boolean isPreparing() {
  395. return mPlayState == MusicPlayAction.STATE_PREPARING;
  396. }
  397. /**
  398. * 是否正在准备中
  399. * @return true表示正在准备中
  400. */
  401. public boolean isDefault() {
  402. return mPlayState == MusicPlayAction.STATE_IDLE;
  403. }
  404. /**
  405. * 更新播放进度的显示,时间的显示
  406. */
  407. private void updatePlayProgressShow() {
  408. if (isPlaying() && mListener != null) {
  409. int currentPosition = mPlayer.getCurrentPosition();
  410. mListener.onUpdateProgress(currentPosition);
  411. }
  412. VideoLogUtils.e("updatePlayProgressShow");
  413. // 每30毫秒更新一下显示的内容,注意这里时间不要太短,因为这个是一个循环
  414. // 经过测试,60毫秒更新一次有点卡,30毫秒最为顺畅
  415. QuitTimerHelper.getInstance().getHandler().sendEmptyMessageDelayed(UPDATE_PLAY_PROGRESS_SHOW, 300);
  416. }
  417. /**
  418. * 获取正在播放的本地歌曲的序号
  419. */
  420. public int getPlayingPosition() {
  421. return mPlayingPosition;
  422. }
  423. /**
  424. * 获取正在播放的歌曲[本地|网络]
  425. */
  426. public AudioBean getPlayingMusic() {
  427. return mPlayingMusic;
  428. }
  429. /**
  430. * 获取播放的进度
  431. * @return long类型值
  432. */
  433. public long getCurrentPosition() {
  434. if (isPlaying() || isPausing()) {
  435. return mPlayer.getCurrentPosition();
  436. } else {
  437. return 0;
  438. }
  439. }
  440. /**
  441. * 判斷是否有上一首音頻
  442. * @return true表示有
  443. */
  444. public boolean isHavePre() {
  445. if(audioMusics !=null && audioMusics.size()>0){
  446. if(mPlayingPosition != 0){
  447. // 如果不是第一首,则还有上一首
  448. return true;
  449. } else {
  450. return false;
  451. }
  452. }else {
  453. return false;
  454. }
  455. }
  456. /**
  457. * 判斷是否有下一首音頻
  458. * @return true表示有
  459. */
  460. public boolean isHaveNext() {
  461. if(audioMusics !=null && audioMusics.size()>0){
  462. if (mPlayingPosition != audioMusics.size() - 1) {
  463. // 如果不是最后一首,则还有下一首
  464. return true;
  465. } else {
  466. // 如果是最后一首,则切换回第一首
  467. return false;
  468. }
  469. }else {
  470. return false;
  471. }
  472. }
  473. /**------------------------------------------------------------------------------------------*/
  474. /**
  475. * 允许与媒体控制器、音量键、媒体按钮和传输控件交互。
  476. * 播放器除了播放了音乐之外什么都没做,就可以分别在任务管理、锁屏、负一屏控制我的播放器
  477. */
  478. private void initMediaSessionManager() {
  479. mMediaSessionManager = new MediaSessionManager(service);
  480. }
  481. /**
  482. * 捕获/丢弃音乐焦点处理
  483. */
  484. private void initAudioFocusManager() {
  485. mAudioFocusManager = new AudioFocusManager(service);
  486. }
  487. /**
  488. * 初始化耳机插入和拔出监听
  489. */
  490. private void initEarPhoneBroadcastReceiver() {
  491. //这块直接在清单文件注册
  492. }
  493. /**
  494. * 初始化IntentFilter添加action意图
  495. * 主要是监听屏幕亮了与灭了
  496. */
  497. private void initAudioBroadcastReceiver() {
  498. final IntentFilter filter = new IntentFilter();
  499. //来电/耳机
  500. filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
  501. //锁屏
  502. filter.addAction(MusicConstant.LOCK_SCREEN_ACTION);
  503. //当屏幕灭了
  504. filter.addAction(Intent.ACTION_SCREEN_OFF);
  505. //当屏幕亮了
  506. filter.addAction(Intent.ACTION_SCREEN_ON);
  507. context.registerReceiver(mAudioReceiver, filter);
  508. }
  509. /**
  510. * 删除或下载歌曲后刷新正在播放的本地歌曲的序号
  511. */
  512. public void updatePlayingPosition() {
  513. int position = 0;
  514. long id = MusicSpUtils.getInstance(MusicConstant.SP_NAME).getLong(MusicConstant.MUSIC_ID,-1);
  515. if(audioMusics.isEmpty()){
  516. return;
  517. }
  518. for (int i = 0; i < audioMusics.size(); i++) {
  519. String musicId = audioMusics.get(i).getId();
  520. VideoLogUtils.e("PlayService"+"----musicId----"+ musicId);
  521. if (Long.parseLong(musicId) == id) {
  522. position = i;
  523. break;
  524. }
  525. }
  526. mPlayingPosition = position;
  527. long musicId = Long.parseLong(audioMusics.get(mPlayingPosition).getId());
  528. MusicSpUtils.getInstance(MusicConstant.SP_NAME).put(MusicConstant.MUSIC_ID,musicId);
  529. }
  530. }