PageRenderTime 313ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/app/src/main/java/com/music/player/haige/mvp/ui/music/service/MusicService.java

https://bitbucket.org/Naruto-S/haige-android
Java | 1549 lines | 1279 code | 233 blank | 37 comment | 187 complexity | 10ce4551acc6120887cfa8c25f903cb6 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (C) 2012 Andrew Neal
  3. * Copyright (C) 2014 The CyanogenMod Project
  4. * Copyright (C) 2015 Naman Dwivedi
  5. *
  6. * Licensed under the Apache License, Version 2.0
  7. * (the "License"); you may not use this file except in compliance with the
  8. * License. You may obtain a copy of the License at
  9. * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
  10. * or agreed to in writing, software distributed under the License is
  11. * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  12. * KIND, either express or implied. See the License for the specific language
  13. * governing permissions and limitations under the License.
  14. */
  15. package com.music.player.haige.mvp.ui.music.service;
  16. import android.Manifest;
  17. import android.annotation.SuppressLint;
  18. import android.app.AlarmManager;
  19. import android.app.PendingIntent;
  20. import android.app.Service;
  21. import android.content.BroadcastReceiver;
  22. import android.content.ComponentName;
  23. import android.content.Context;
  24. import android.content.Intent;
  25. import android.content.IntentFilter;
  26. import android.database.ContentObserver;
  27. import android.graphics.Bitmap;
  28. import android.graphics.BitmapFactory;
  29. import android.media.AudioManager;
  30. import android.media.AudioManager.OnAudioFocusChangeListener;
  31. import android.media.audiofx.AudioEffect;
  32. import android.os.Build;
  33. import android.os.Handler;
  34. import android.os.HandlerThread;
  35. import android.os.IBinder;
  36. import android.os.Looper;
  37. import android.os.PowerManager;
  38. import android.os.PowerManager.WakeLock;
  39. import android.os.SystemClock;
  40. import android.provider.MediaStore;
  41. import android.support.v4.content.PermissionChecker;
  42. import android.support.v4.media.MediaMetadataCompat;
  43. import android.support.v4.media.session.MediaSessionCompat;
  44. import android.support.v4.media.session.PlaybackStateCompat;
  45. import android.text.TextUtils;
  46. import com.bumptech.glide.load.engine.DiskCacheStrategy;
  47. import com.google.gson.Gson;
  48. import com.hc.core.http.imageloader.glide.GlideCore;
  49. import com.hc.core.utils.CoreUtils;
  50. import com.liulishuo.filedownloader.FileDownloader;
  51. import com.liulishuo.filedownloader.model.FileDownloadStatus;
  52. import com.liulishuo.filedownloader.util.FileDownloadUtils;
  53. import com.music.player.haige.R;
  54. import com.music.player.haige.app.Constants;
  55. import com.music.player.haige.app.GlobalConfiguration;
  56. import com.music.player.haige.app.HaigeApplication;
  57. import com.music.player.haige.di.component.DaggerMediaServiceComponent;
  58. import com.music.player.haige.mvp.model.entity.music.MusicPlaybackTrack;
  59. import com.music.player.haige.mvp.model.entity.music.Song;
  60. import com.music.player.haige.mvp.model.entity.music.SongDao;
  61. import com.music.player.haige.mvp.model.respository.provider.SongPlayCount;
  62. import com.music.player.haige.mvp.model.utils.CommonUtils;
  63. import com.music.player.haige.mvp.model.utils.HaigeUtil;
  64. import com.music.player.haige.mvp.model.utils.StringUtils;
  65. import com.music.player.haige.mvp.ui.music.receiver.MediaButtonIntentReceiver;
  66. import com.music.player.haige.mvp.ui.music.service.cache.HttpProxyCacheServer;
  67. import com.music.player.haige.mvp.ui.music.service.cache.MusicLog;
  68. import com.music.player.haige.mvp.ui.music.service.proxy.utils.MediaPlayerProxy;
  69. import com.music.player.haige.mvp.ui.music.utils.MusicUtils;
  70. import com.music.player.haige.mvp.ui.utils.DebugLogger;
  71. import com.music.player.haige.mvp.ui.utils.ResourceUtils;
  72. import com.music.player.haige.mvp.ui.utils.Utils;
  73. import com.tencent.bugly.crashreport.CrashReport;
  74. import java.io.File;
  75. import java.util.HashMap;
  76. import javax.inject.Inject;
  77. import timber.log.Timber;
  78. import static android.content.Intent.ACTION_SCREEN_OFF;
  79. import static com.music.player.haige.mvp.ui.music.service.proxy.utils.ProxyConstants.SD_REMAIN_SIZE;
  80. @SuppressLint("NewApi")
  81. public class MusicService extends Service {
  82. public static final String PLAYSTATE_CHANGED = "com.music.player.haige.playstatechanged";
  83. public static final String POSITION_CHANGED = "com.music.player.haige.positionchanged";
  84. public static final String META_CHANGED = "com.music.player.haige.metachanged";
  85. public static final String PLAYLIST_ITEM_MOVED = "com.music.player.haige.mmoved";
  86. public static final String QUEUE_CHANGED = "com.music.player.haige.queuechanged";
  87. public static final String PLAYLIST_CHANGED = "com.music.player.haige.playlistchanged";
  88. public static final String REPEATMODE_CHANGED = "com.music.player.haige.repeatmodechanged";
  89. public static final String SHUFFLEMODE_CHANGED = "com.music.player.haige.shufflemodechanged";
  90. public static final String TRACK_ERROR = "com.music.player.haige.trackerror";
  91. public static final String TIMBER_PACKAGE_NAME = "com.music.player.haige";
  92. public static final String MUSIC_PACKAGE_NAME = "com.android.music";
  93. public static final String SERVICECMD = "com.music.player.haige.musicservicecommand";
  94. public static final String TOGGLEPAUSE_ACTION = "com.music.player.haige.togglepause";
  95. public static final String PAUSE_ACTION = "com.music.player.haige.pause";
  96. public static final String STOP_ACTION = "com.music.player.haige.stop";
  97. public static final String PREVIOUS_ACTION = "com.music.player.haige.previous";
  98. public static final String PREVIOUS_FORCE_ACTION = "com.music.player.haige.previous.force";
  99. public static final String NEXT_ACTION = "com.music.player.haige.next";
  100. public static final String CLOSE_NOTITY_ACTION = "com.music.player.haige.close.notify";
  101. public static final String MUSIC_CHANGED = "com.music.player.haige.change_music";
  102. public static final String REPEAT_ACTION = "com.music.player.haige.repeat";
  103. public static final String SHUFFLE_ACTION = "com.music.player.haige.shuffle";
  104. public static final String FAVORITE_ACTION = "com.music.player.haige.favorite";
  105. public static final String FROM_MEDIA_BUTTON = "frommediabutton";
  106. public static final String REFRESH = "com.music.player.haige.refresh";
  107. public static final String LRC_UPDATED = "com.music.player.haige.updatelrc";
  108. public static final String UPDATE_LOCKSCREEN = "com.music.player.haige.updatelockscreen";
  109. public static final String CMDNAME = "command";
  110. public static final String CMDTOGGLEPAUSE = "togglepause";
  111. public static final String CMDSTOP = "stop";
  112. public static final String CMDPAUSE = "pause";
  113. public static final String CMDPLAY = "play";
  114. public static final String CMDPREVIOUS = "previous";
  115. public static final String CMDNEXT = "next";
  116. public static final String CMDNOTIF = "buttonId";
  117. public static final String TRACK_PREPARED = "com.music.player.haige.prepared";
  118. public static final String TRY_GET_TRACKINFO = "com.music.player.haige.gettrackinfo";
  119. public static final String BUFFER_UP = "com.music.player.haige.bufferup";
  120. public static final String LOCK_SCREEN = "com.music.player.haige.lock";
  121. public static final String SEND_PROGRESS = "com.music.player.haige.progress";
  122. public static final String MUSIC_LOADING = "com.music.player.haige.loading";
  123. public static final String SHUTDOWN = "com.music.player.haige.shutdown";
  124. public static final String SET_QUEUE = "com.music.player.haige.setqueue";
  125. // extra的key
  126. public static final String EXTRA_LOADING = "extra_loading"; // 是否是在加载状态
  127. public static final String CHANNEL_ID = "haige_channel_01";
  128. public static final int NEXT = 2;
  129. public static final int LAST = 3;
  130. private static final String TAG = MusicService.class.getName();
  131. public static final int LRC_DOWNLOADED = -10;
  132. private static final int IDLE_DELAY = 5 * 60 * 1000;
  133. private static final long REWIND_INSTEAD_PREVIOUS_THRESHOLD = 3000;
  134. private final IBinder mBinder = new ServiceStub(this);
  135. public MultiPlayer mPlayer;
  136. private String mFileToPlay;
  137. public WakeLock mWakeLock;
  138. private AlarmManager mAlarmManager;
  139. private PendingIntent mShutdownIntent;
  140. private boolean mShutdownScheduled;
  141. private AudioManager mAudioManager;
  142. private boolean mServiceInUse = false;
  143. private boolean mIsSupposedToBePlaying = false;
  144. private long mLastPlayedTime;
  145. public boolean mPausedByTransientLossOfFocus = false;
  146. private MediaSessionCompat mSession;
  147. private ComponentName mMediaButtonReceiverComponent;
  148. private int mShouldGotoNextCounter = 0;
  149. private int mOpenFailedCounter = 0;
  150. private int mMediaMountedCount = 0;
  151. private int mServiceStartId = -1;
  152. private MultiPlayerHandler mPlayerHandler;
  153. private HandlerThread mHandlerThread;
  154. private BroadcastReceiver mUnmountReceiver = null;
  155. private boolean mShowAlbumArtOnLockscreen;
  156. private SongPlayCount mSongPlayCount;
  157. private SongDao mRecentSongDao;
  158. private ContentObserver mMediaStoreObserver;
  159. private static Handler mUrlHandler;
  160. private MediaPlayerProxy mProxy;
  161. private RequestPlayUrl mRequestUrl;
  162. private boolean mIsSending = false;
  163. private boolean mIsLocked;
  164. private boolean mIsShort;
  165. private NNotificationManager mNNotificationManager;
  166. private MusicDataManager mMusicDataManager;
  167. private HttpProxyCacheServer httpProxyCacheServer;
  168. @Inject
  169. Gson mGson;
  170. private Thread mGetUrlThread = new Thread(new Runnable() {
  171. @Override
  172. public void run() {
  173. Looper.prepare();
  174. mUrlHandler = new Handler();
  175. Looper.loop();
  176. }
  177. });
  178. private final OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {
  179. @Override
  180. public void onAudioFocusChange(final int focusChange) {
  181. mPlayerHandler.obtainMessage(MultiPlayerHandler.FOCUSCHANGE, focusChange, 0).sendToTarget();
  182. }
  183. };
  184. private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
  185. @Override
  186. public void onReceive(final Context context, final Intent intent) {
  187. final String command = intent.getStringExtra(CMDNAME);
  188. Timber.d(TAG + " onreceive" + intent.toURI());
  189. handleCommandIntent(intent);
  190. }
  191. };
  192. @Override
  193. public IBinder onBind(final Intent intent) {
  194. Timber.d(TAG + " Service bound, intent = " + intent);
  195. cancelShutdown();
  196. mServiceInUse = true;
  197. return mBinder;
  198. }
  199. @Override
  200. public boolean onUnbind(final Intent intent) {
  201. Timber.d(TAG + " Service unbound");
  202. mServiceInUse = false;
  203. mMusicDataManager.saveQueue(true);
  204. if (mIsSupposedToBePlaying || mPausedByTransientLossOfFocus) {
  205. return true;
  206. } else if (mMusicDataManager.getPlaylist().size() > 0 || mPlayerHandler.hasMessages(MultiPlayerHandler.TRACK_ENDED)) {
  207. scheduleDelayedShutdown();
  208. return true;
  209. }
  210. stopSelf(mServiceStartId);
  211. return true;
  212. }
  213. @Override
  214. public void onRebind(final Intent intent) {
  215. cancelShutdown();
  216. mServiceInUse = true;
  217. }
  218. @Override
  219. public void onCreate() {
  220. Timber.d(TAG + " Creating service");
  221. super.onCreate();
  222. DaggerMediaServiceComponent
  223. .builder()
  224. .appComponent(CoreUtils.obtainAppComponentFromContext(HaigeApplication.getInstance()))
  225. .build()
  226. .inject(this);
  227. mNNotificationManager = new NNotificationManager(this);
  228. mNNotificationManager.createNotificationChannel(this);
  229. mMusicDataManager = new MusicDataManager(this, mGson);
  230. mGetUrlThread.start();
  231. //mLrcThread.start();
  232. mProxy = new MediaPlayerProxy(this);
  233. mProxy.init();
  234. mProxy.start();
  235. // gets a pointer to the playback state store
  236. mSongPlayCount = SongPlayCount.getInstance(this);
  237. mRecentSongDao = GlobalConfiguration.sRecentDaoSession.getSongDao();
  238. mHandlerThread = new HandlerThread("MultiPlayerHandler",
  239. android.os.Process.THREAD_PRIORITY_BACKGROUND);
  240. mHandlerThread.start();
  241. mPlayerHandler = new MultiPlayerHandler(this, mHandlerThread.getLooper());
  242. mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
  243. mMediaButtonReceiverComponent = new ComponentName(getPackageName(),
  244. MediaButtonIntentReceiver.class.getName());
  245. mAudioManager.registerMediaButtonEventReceiver(mMediaButtonReceiverComponent);
  246. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  247. setUpMediaSession();
  248. }
  249. mMusicDataManager.updateCardId();
  250. registerExternalStorageListener();
  251. mPlayer = new MultiPlayer(this);
  252. mPlayer.setHandler(mPlayerHandler);
  253. // Initialize the intent filter and each action
  254. final IntentFilter filter = new IntentFilter();
  255. filter.addAction(SERVICECMD);
  256. filter.addAction(TOGGLEPAUSE_ACTION);
  257. filter.addAction(PAUSE_ACTION);
  258. filter.addAction(STOP_ACTION);
  259. filter.addAction(NEXT_ACTION);
  260. filter.addAction(CLOSE_NOTITY_ACTION);
  261. filter.addAction(PREVIOUS_ACTION);
  262. filter.addAction(PREVIOUS_FORCE_ACTION);
  263. filter.addAction(REPEAT_ACTION);
  264. filter.addAction(SHUFFLE_ACTION);
  265. filter.addAction(TRY_GET_TRACKINFO);
  266. filter.addAction(ACTION_SCREEN_OFF);
  267. filter.addAction(LOCK_SCREEN);
  268. filter.addAction(SEND_PROGRESS);
  269. filter.addAction(SET_QUEUE);
  270. // Attach the broadcast listener
  271. registerReceiver(mIntentReceiver, filter);
  272. mMediaStoreObserver = new MediaStoreObserver(mPlayerHandler);
  273. getContentResolver().registerContentObserver(
  274. MediaStore.Audio.Media.INTERNAL_CONTENT_URI, true, mMediaStoreObserver);
  275. getContentResolver().registerContentObserver(
  276. MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, true, mMediaStoreObserver);
  277. // Initialize the wake lock
  278. final PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
  279. mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
  280. mWakeLock.setReferenceCounted(false);
  281. final Intent shutdownIntent = new Intent(this, MusicService.class);
  282. shutdownIntent.setAction(SHUTDOWN);
  283. mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
  284. mShutdownIntent = PendingIntent.getService(this, 0, shutdownIntent, 0);
  285. scheduleDelayedShutdown();
  286. reloadQueueAfterPermissionCheck();
  287. notifyChange(QUEUE_CHANGED);
  288. notifyChange(META_CHANGED);
  289. }
  290. private void setUpMediaSession() {
  291. mSession = new MediaSessionCompat(this, "haige");
  292. mSession.setCallback(new MediaSessionCompat.Callback() {
  293. @Override
  294. public void onPause() {
  295. pause();
  296. mPausedByTransientLossOfFocus = false;
  297. }
  298. @Override
  299. public void onPlay() {
  300. play();
  301. }
  302. @Override
  303. public void onSeekTo(long pos) {
  304. seek(pos);
  305. }
  306. @Override
  307. public void onSkipToNext() {
  308. gotoNext(true);
  309. }
  310. @Override
  311. public void onSkipToPrevious() {
  312. prev(false);
  313. }
  314. @Override
  315. public void onStop() {
  316. pause();
  317. mPausedByTransientLossOfFocus = false;
  318. seek(0);
  319. releaseServiceUiAndStop();
  320. }
  321. });
  322. mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
  323. }
  324. public MediaSessionCompat.Token getSessionToken() {
  325. return mSession.getSessionToken();
  326. }
  327. public void exit() {
  328. }
  329. @Override
  330. public void onDestroy() {
  331. Timber.d(TAG + " Destroying service");
  332. super.onDestroy();
  333. // Remove any sound effects
  334. final Intent audioEffectsIntent = new Intent(
  335. AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
  336. audioEffectsIntent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, getAudioSessionId());
  337. audioEffectsIntent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
  338. sendBroadcast(audioEffectsIntent);
  339. mNNotificationManager.cancelNotification(this);
  340. mAlarmManager.cancel(mShutdownIntent);
  341. mPlayerHandler.removeCallbacksAndMessages(null);
  342. if (CommonUtils.isJellyBeanMR2())
  343. mHandlerThread.quitSafely();
  344. else mHandlerThread.quit();
  345. mPlayer.release();
  346. mPlayer = null;
  347. mAudioManager.abandonAudioFocus(mAudioFocusListener);
  348. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
  349. mSession.release();
  350. getContentResolver().unregisterContentObserver(mMediaStoreObserver);
  351. mMusicDataManager.closeCursor();
  352. unregisterReceiver(mIntentReceiver);
  353. if (mUnmountReceiver != null) {
  354. unregisterReceiver(mUnmountReceiver);
  355. mUnmountReceiver = null;
  356. }
  357. mWakeLock.release();
  358. }
  359. @Override
  360. public int onStartCommand(final Intent intent, final int flags, final int startId) {
  361. Timber.d(TAG + " Got new intent " + intent + ", startId = " + startId);
  362. mServiceStartId = startId;
  363. if (intent != null) {
  364. final String action = intent.getAction();
  365. if (SHUTDOWN.equals(action)) {
  366. mShutdownScheduled = false;
  367. releaseServiceUiAndStop();
  368. return START_NOT_STICKY;
  369. }
  370. handleCommandIntent(intent);
  371. }
  372. scheduleDelayedShutdown();
  373. if (intent != null && intent.getBooleanExtra(FROM_MEDIA_BUTTON, false)) {
  374. MediaButtonIntentReceiver.completeWakefulIntent(intent);
  375. }
  376. return START_STICKY;
  377. }
  378. private void releaseServiceUiAndStop() {
  379. if (isPlaying()
  380. || mPausedByTransientLossOfFocus
  381. || mPlayerHandler.hasMessages(MultiPlayerHandler.TRACK_ENDED)) {
  382. return;
  383. }
  384. Timber.d(TAG + " Nothing is playing anymore, releasing app_layout_notification");
  385. mNNotificationManager.cancelNotification(this);
  386. mAudioManager.abandonAudioFocus(mAudioFocusListener);
  387. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
  388. mSession.setActive(false);
  389. if (!mServiceInUse) {
  390. mMusicDataManager.saveQueue(true);
  391. stopSelf(mServiceStartId);
  392. }
  393. }
  394. private void handleCommandIntent(Intent intent) {
  395. final String action = intent.getAction();
  396. final String command = SERVICECMD.equals(action) ? intent.getStringExtra(CMDNAME) : null;
  397. Timber.d(TAG + " handleCommandIntent: action = " + action + ", command = " + command);
  398. if (CMDNEXT.equals(command) || NEXT_ACTION.equals(action)) {
  399. gotoNext(true);
  400. } else if (CMDPREVIOUS.equals(command) || PREVIOUS_ACTION.equals(action)
  401. || PREVIOUS_FORCE_ACTION.equals(action)) {
  402. prev(PREVIOUS_FORCE_ACTION.equals(action));
  403. } else if (CMDTOGGLEPAUSE.equals(command) || TOGGLEPAUSE_ACTION.equals(action)) {
  404. if (isPlaying()) {
  405. pause();
  406. mPausedByTransientLossOfFocus = false;
  407. } else {
  408. play();
  409. }
  410. } else if (CMDPAUSE.equals(command) || PAUSE_ACTION.equals(action)) {
  411. pause();
  412. mPausedByTransientLossOfFocus = false;
  413. } else if (CMDPLAY.equals(command)) {
  414. play();
  415. } else if (CMDSTOP.equals(command) || STOP_ACTION.equals(action)) {
  416. pause();
  417. mPausedByTransientLossOfFocus = false;
  418. seek(0);
  419. releaseServiceUiAndStop();
  420. } else if (REPEAT_ACTION.equals(action)) {
  421. cycleRepeat();
  422. } else if (SHUFFLE_ACTION.equals(action)) {
  423. cycleShuffle();
  424. } else if (TRY_GET_TRACKINFO.equals(action)) {
  425. //getLrc(mMusicDataManager.getPlaylist().get(mMusicDataManager.getPlayPos()).mId);
  426. } else if (ACTION_SCREEN_OFF.equals(action)) {
  427. // if (isPlaying() && !mIsLocked) {
  428. // Intent lockscreen = new Intent(this, LockActivity.class);
  429. // lockscreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  430. // startActivity(lockscreen);
  431. // }
  432. } else if (LOCK_SCREEN.equals(action)) {
  433. mIsLocked = intent.getBooleanExtra("islock", true);
  434. Timber.d(TAG + " isloced = " + mIsLocked);
  435. } else if (SEND_PROGRESS.equals(action)) {
  436. if (isPlaying() && !mIsSending) {
  437. mPlayerHandler.post(sendDuration);
  438. mIsSending = true;
  439. } else if (!isPlaying()) {
  440. mPlayerHandler.removeCallbacks(sendDuration);
  441. mIsSending = false;
  442. }
  443. } else if (SET_QUEUE.equals(action)) {
  444. setQueuePosition(intent.getIntExtra("position", 0));
  445. } else if (CLOSE_NOTITY_ACTION.equals(action)) {
  446. mNNotificationManager.cancelNotification(this);
  447. }
  448. }
  449. private Runnable sendDuration = new Runnable() {
  450. @Override
  451. public void run() {
  452. notifyChange(SEND_PROGRESS);
  453. mPlayerHandler.postDelayed(sendDuration, 1000);
  454. }
  455. };
  456. public void updateNotification() {
  457. mNNotificationManager.updateNotification(this);
  458. }
  459. public void closeExternalStorageFiles(final String storagePath) {
  460. stop(true);
  461. notifyChange(QUEUE_CHANGED);
  462. notifyChange(META_CHANGED);
  463. }
  464. public void registerExternalStorageListener() {
  465. if (mUnmountReceiver == null) {
  466. mUnmountReceiver = new BroadcastReceiver() {
  467. @Override
  468. public void onReceive(final Context context, final Intent intent) {
  469. final String action = intent.getAction();
  470. if (Intent.ACTION_MEDIA_EJECT.equals(action)) {
  471. mMusicDataManager.saveQueue(true);
  472. mMusicDataManager.setQueueIsSaveable(false);
  473. closeExternalStorageFiles(intent.getData().getPath());
  474. } else if (Intent.ACTION_MEDIA_MOUNTED.equals(action)) {
  475. mMediaMountedCount++;
  476. mMusicDataManager.updateCardId();
  477. reloadQueueAfterPermissionCheck();
  478. mMusicDataManager.setQueueIsSaveable(true);
  479. notifyChange(QUEUE_CHANGED);
  480. notifyChange(META_CHANGED);
  481. }
  482. }
  483. };
  484. final IntentFilter filter = new IntentFilter();
  485. filter.addAction(Intent.ACTION_MEDIA_EJECT);
  486. filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
  487. filter.addDataScheme("file");
  488. registerReceiver(mUnmountReceiver, filter);
  489. }
  490. }
  491. private void scheduleDelayedShutdown() {
  492. Timber.d(TAG + " Scheduling shutdown in " + IDLE_DELAY + " ms");
  493. mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
  494. SystemClock.elapsedRealtime() + IDLE_DELAY, mShutdownIntent);
  495. mShutdownScheduled = true;
  496. }
  497. private void cancelShutdown() {
  498. Timber.d(TAG + " Cancelling delayed shutdown, scheduled = " + mShutdownScheduled);
  499. if (mShutdownScheduled) {
  500. mAlarmManager.cancel(mShutdownIntent);
  501. mShutdownScheduled = false;
  502. }
  503. }
  504. public void stop(final boolean goToIdle) {
  505. Timber.d(TAG + " Stopping playback, goToIdle = " + goToIdle);
  506. if (mPlayer.isInitialized()) {
  507. mPlayer.stop();
  508. }
  509. mFileToPlay = null;
  510. mMusicDataManager.closeCursor();
  511. if (goToIdle) {
  512. setIsSupposedToBePlaying(false, false);
  513. } else {
  514. if (CommonUtils.isLollipop()) {
  515. stopForeground(false);
  516. } else {
  517. stopForeground(true);
  518. }
  519. }
  520. }
  521. private void addToPlayList(final long[] list, int position) {
  522. mMusicDataManager.addToPlayList(list, position);
  523. }
  524. public void openCurrentAndNextPlay(boolean play) {
  525. openCurrentAndMaybeNext(play, true);
  526. }
  527. public void openCurrentAndNext() {
  528. openCurrentAndMaybeNext(false, true);
  529. }
  530. private void openCurrentAndMaybeNext(final boolean play, final boolean openNext) {
  531. synchronized (this) {
  532. Timber.d(TAG + " open current");
  533. mMusicDataManager.closeCursor();
  534. stop(false);
  535. boolean shutdown = false;
  536. if (mMusicDataManager.getPlaylist().size() == 0
  537. || mMusicDataManager.getPlaylistInfo().size() == 0 && mMusicDataManager.getPlayPos() >= mMusicDataManager.getPlaylist().size()) {
  538. mMusicDataManager.clearPlayInfo();
  539. return;
  540. }
  541. final long id = mMusicDataManager.getPlaylist().get(mMusicDataManager.getPlayPos()).mId;
  542. mMusicDataManager.updateCursor(id);
  543. if (mMusicDataManager.getPlaylistInfo().get(id) == null) {
  544. return;
  545. }
  546. if (!mMusicDataManager.getPlaylistInfo().get(id).isLocal) {
  547. if (mRequestUrl != null) {
  548. mRequestUrl.stop();
  549. mUrlHandler.removeCallbacks(mRequestUrl);
  550. }
  551. Song song = mMusicDataManager.getPlaylistInfo().get(id);
  552. mRequestUrl = new RequestPlayUrl(song, mIsShort, play);
  553. mUrlHandler.postDelayed(mRequestUrl, 70);
  554. } else {
  555. while (true) {
  556. if (mMusicDataManager.getCursor() != null
  557. && openFile(mMusicDataManager.getContentUriPath())) {
  558. break;
  559. }
  560. mMusicDataManager.closeCursor();
  561. if (mOpenFailedCounter++ < 10 && mMusicDataManager.getPlaylist().size() > 1) {
  562. final int pos = mMusicDataManager.getNextPosition(false);
  563. if (pos < 0) {
  564. shutdown = true;
  565. break;
  566. }
  567. mMusicDataManager.setPlayPos(pos);
  568. stop(false);
  569. mMusicDataManager.setPlayPos(pos);
  570. mMusicDataManager.updateCursor(mMusicDataManager.getPlaylist().get(mMusicDataManager.getPlayPos()).mId);
  571. } else {
  572. mOpenFailedCounter = 0;
  573. Timber.d(TAG + " Failed to open file for playback");
  574. shutdown = true;
  575. break;
  576. }
  577. }
  578. }
  579. if (shutdown) {
  580. scheduleDelayedShutdown();
  581. if (mIsSupposedToBePlaying) {
  582. mIsSupposedToBePlaying = false;
  583. notifyChange(PLAYSTATE_CHANGED);
  584. }
  585. } else if (openNext) {
  586. setNextTrack();
  587. }
  588. }
  589. }
  590. public void setOpenFailedCounter(int openFailedCounter) {
  591. this.mOpenFailedCounter = openFailedCounter;
  592. }
  593. class RequestPlayUrl implements Runnable {
  594. private Song song;
  595. private boolean isShort;
  596. private boolean play;
  597. private boolean stop;
  598. private RequestPlayUrl(Song song, boolean isShort, boolean play) {
  599. this.song = song;
  600. this.isShort = isShort;
  601. this.play = play;
  602. }
  603. public void stop() {
  604. stop = true;
  605. }
  606. @Override
  607. public void run() {
  608. try {
  609. String url;
  610. if (mIsShort && Utils.isNotEmptyString(song.shortUrl)) {
  611. url = song.shortUrl;
  612. DebugLogger.e(TAG, "short: true");
  613. } else {
  614. url = song.musicPath;
  615. DebugLogger.e(TAG, "short: false");
  616. }
  617. if (Utils.isNotEmptyString(url)) {
  618. Timber.e(TAG + " current url = " + url);
  619. } else {
  620. gotoNext(true);
  621. }
  622. if (!stop) {
  623. // 判断是否已经下载了这个文件
  624. String path = MusicUtils.getDownloadPath(song, mIsShort);
  625. int id = FileDownloadUtils.generateId(url, path);
  626. int status = FileDownloader.getImpl().getStatus(id, path);
  627. if (status == FileDownloadStatus.completed && new File(path).exists()) {
  628. mPlayer.setDataSource(path);
  629. } else {
  630. String proxyUrl = getProxyUrl(url, mIsShort);
  631. mPlayer.setDataSource(proxyUrl);
  632. }
  633. }
  634. if (play && !stop) {
  635. play();
  636. }
  637. } catch (Exception e) {
  638. e.printStackTrace();
  639. }
  640. }
  641. }
  642. private void initHttpProxyCacheServer() {
  643. httpProxyCacheServer = new HttpProxyCacheServer.Builder(HaigeApplication.getInstance())
  644. .maxCacheSize(SD_REMAIN_SIZE)
  645. .fileNameGenerator(new ProxyFileNameGenerator())
  646. .build();
  647. }
  648. public String getProxyUrl(String realUrl, boolean isShort) {
  649. if (Utils.isNull(httpProxyCacheServer)) {
  650. initHttpProxyCacheServer();
  651. }
  652. MusicLog.playerD("setUp url:" + realUrl);
  653. if (Utils.isNotNull(httpProxyCacheServer)) {
  654. httpProxyCacheServer.putIsShort(isShort);
  655. realUrl = httpProxyCacheServer.getProxyUrl(realUrl);
  656. }
  657. return realUrl;
  658. }
  659. public void sendErrorMessage(final String trackName) {
  660. final Intent i = new Intent(TRACK_ERROR);
  661. i.putExtra(TrackErrorExtra.TRACK_NAME, trackName);
  662. sendBroadcast(i);
  663. }
  664. public void setNextTrack() {
  665. mMusicDataManager.setNextTrack();
  666. }
  667. public void setNextDataSource(String path) {
  668. mPlayer.setNextDataSource(path);
  669. }
  670. public void sendUpdateBuffer(int progress) {
  671. Intent intent = new Intent(BUFFER_UP);
  672. intent.putExtra("progress", progress);
  673. sendBroadcast(intent);
  674. }
  675. public void notifyChange(final String what) {
  676. Timber.d(TAG + " notifyChange: what = " + what);
  677. if (SEND_PROGRESS.equals(what)) {
  678. final Intent intent = new Intent(SEND_PROGRESS);
  679. intent.putExtra("position", position());
  680. intent.putExtra("duration", duration());
  681. sendStickyBroadcast(intent);
  682. return;
  683. }
  684. // Update the lockscreen controls
  685. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  686. updateMediaSession(what);
  687. }
  688. if (what.equals(POSITION_CHANGED)) {
  689. return;
  690. }
  691. final Intent intent = new Intent(what);
  692. intent.putExtra(Song.KEY_MUSIC_ID, getAudioId());
  693. intent.putExtra(Song.KEY_ARTIST_NAME, getArtistName());
  694. intent.putExtra(Song.KEY_MUSIC_NAME, getTrackName());
  695. intent.putExtra(Song.KEY_MUSIC_URL, getPath());
  696. intent.putExtra(Song.KEY_ALBUM_NAME, getAlbumName());
  697. intent.putExtra(Song.KEY_ALBUM_DATA, getAlbumPath());
  698. intent.putExtra(Song.KEY_IS_PLAYING, isPlaying());
  699. intent.putExtra(Song.KEY_ALBUM_ID, getAlbumId());
  700. intent.putExtra(Song.KEY_IS_LOCAL, isTrackLocal());
  701. intent.putExtra(Song.KEY_MUSIC_COVER, getMusicCover());
  702. intent.putExtra(Song.KEY_LIKE, getMusicLikeCount());
  703. intent.putExtra(Song.KEY_SHARE, getMusicShareCount());
  704. intent.putExtra(Song.KEY_DOWNLOAD, getMusicDownloadCount());
  705. intent.putExtra(Song.KEY_MUSIC_URL, getMusicUrl());
  706. sendStickyBroadcast(intent);
  707. final Intent musicIntent = new Intent(intent);
  708. musicIntent.setAction(what.replace(TIMBER_PACKAGE_NAME, MUSIC_PACKAGE_NAME));
  709. sendStickyBroadcast(musicIntent);
  710. if (what.equals(META_CHANGED)) {
  711. try {
  712. Song song = getCurSong();
  713. if (song != null) {
  714. mRecentSongDao.insertOrReplace(getCurSong());
  715. }
  716. mSongPlayCount.bumpSongCount(getAudioId());
  717. } catch (Throwable t) {
  718. CrashReport.postCatchedException(t);
  719. }
  720. } else if (what.equals(QUEUE_CHANGED)) {
  721. Intent intent1 = new Intent(Constants.EMPTY_LIST);
  722. intent.putExtra("showorhide", "show");
  723. sendBroadcast(intent1);
  724. mMusicDataManager.saveQueue(true);
  725. if (isPlaying()) {
  726. mMusicDataManager.updateNextTrack();
  727. }
  728. } else {
  729. mMusicDataManager.saveQueue(false);
  730. }
  731. if (what.equals(PLAYSTATE_CHANGED)) {
  732. updateNotification();
  733. }
  734. }
  735. private void updateMediaSession(final String what) {
  736. int playState = mIsSupposedToBePlaying
  737. ? PlaybackStateCompat.STATE_PLAYING
  738. : PlaybackStateCompat.STATE_PAUSED;
  739. if (what.equals(PLAYSTATE_CHANGED) || what.equals(POSITION_CHANGED)) {
  740. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  741. mSession.setPlaybackState(new PlaybackStateCompat.Builder()
  742. .setState(playState, position(), 1.0f)
  743. .setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY_PAUSE |
  744. PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)
  745. .build());
  746. }
  747. } else if (what.equals(META_CHANGED) || what.equals(QUEUE_CHANGED)) {
  748. Bitmap albumArt = BitmapFactory.decodeResource(ResourceUtils.getResources(), R.drawable.app_ic_album_default);
  749. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  750. mSession.setMetadata(new MediaMetadataCompat.Builder()
  751. .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, getArtistName())
  752. .putString(MediaMetadataCompat.METADATA_KEY_ALBUM, getAlbumName())
  753. .putString(MediaMetadataCompat.METADATA_KEY_TITLE, getTrackName())
  754. .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, duration())
  755. .putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, getQueuePosition() + 1)
  756. .putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, getQueue().length)
  757. .putString(MediaMetadataCompat.METADATA_KEY_GENRE, getGenreName())
  758. .putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, mShowAlbumArtOnLockscreen ? albumArt : null)
  759. .build());
  760. mSession.setPlaybackState(new PlaybackStateCompat.Builder()
  761. .setState(playState, position(), 1.0f)
  762. .setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY_PAUSE |
  763. PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)
  764. .build());
  765. }
  766. }
  767. }
  768. private void reloadQueueAfterPermissionCheck() {
  769. if (CommonUtils.isMarshmallow()) {
  770. if (PermissionChecker.PERMISSION_GRANTED == PermissionChecker.checkSelfPermission(HaigeApplication.getInstance(), Manifest.permission.READ_EXTERNAL_STORAGE)) {
  771. mMusicDataManager.reloadQueue();
  772. }
  773. } else {
  774. mMusicDataManager.reloadQueue();
  775. }
  776. }
  777. public boolean removeTrackAtPosition(final long id, final int position) {
  778. return mMusicDataManager.removeTrackAtPosition(id, position);
  779. }
  780. public boolean openFile(final String path) {
  781. Timber.d(TAG + " openFile: path = " + path);
  782. synchronized (this) {
  783. if (path == null) {
  784. return false;
  785. }
  786. String mpUri = mMusicDataManager.openFile(path);
  787. if (!TextUtils.isEmpty(mpUri)) {
  788. return mMusicDataManager.notifyMetaChanged(mpUri);
  789. }
  790. mFileToPlay = path;
  791. mPlayer.setDataSource(mFileToPlay);
  792. if (mPlayer.isInitialized()) {
  793. mOpenFailedCounter = 0;
  794. return true;
  795. }
  796. String trackName = getTrackName();
  797. if (TextUtils.isEmpty(trackName)) {
  798. trackName = path;
  799. }
  800. sendErrorMessage(trackName);
  801. stop(true);
  802. return false;
  803. }
  804. }
  805. public void closeCursor() {
  806. synchronized (this) {
  807. mMusicDataManager.closeCursor();
  808. }
  809. }
  810. public void updateCursor() {
  811. synchronized (this) {
  812. mMusicDataManager.updateCursor(getAudioId());
  813. }
  814. }
  815. public int getAudioSessionId() {
  816. synchronized (this) {
  817. return mPlayer.getAudioSessionId();
  818. }
  819. }
  820. public int getMediaMountedCount() {
  821. return mMediaMountedCount;
  822. }
  823. public void setShuffleMode(int shuffleMode) {
  824. synchronized (this) {
  825. mMusicDataManager.setShuffleMode(shuffleMode);
  826. }
  827. }
  828. public int getShuffleMode() {
  829. return mMusicDataManager.getShuffleMode();
  830. }
  831. public int getRepeatMode() {
  832. return mMusicDataManager.getRepeatMode();
  833. }
  834. public void setRepeatMode(final int repeatMode) {
  835. synchronized (this) {
  836. mMusicDataManager.setRepeatMode(repeatMode);
  837. }
  838. }
  839. public int removeTrack(final long id) {
  840. return mMusicDataManager.removeTrack(id);
  841. }
  842. public int removeTracks(final int first, final int last) {
  843. return mMusicDataManager.removeTracks(first, last);
  844. }
  845. public int getQueuePosition() {
  846. return mMusicDataManager.getPlayPos();
  847. }
  848. public int getQueueHistorySize() {
  849. return mMusicDataManager.getHistory().size();
  850. }
  851. public int getQueueHistoryPosition(int position) {
  852. return mMusicDataManager.getQueueHistoryPosition(position);
  853. }
  854. public int[] getQueueHistoryList() {
  855. return mMusicDataManager.getQueueHistoryList();
  856. }
  857. public String getPath() {
  858. synchronized (this) {
  859. return mMusicDataManager.getPath();
  860. }
  861. }
  862. public String getAlbumName() {
  863. synchronized (this) {
  864. return mMusicDataManager.getAlbumName();
  865. }
  866. }
  867. public String getAlbumPath() {
  868. synchronized (this) {
  869. return mMusicDataManager.getAlbumPath();
  870. }
  871. }
  872. public String[] getAlbumPathAll() {
  873. synchronized (this) {
  874. return mMusicDataManager.getAlbumPathAll();
  875. }
  876. }
  877. public String getTrackName() {
  878. synchronized (this) {
  879. return mMusicDataManager.getTrackName();
  880. }
  881. }
  882. public boolean isTrackLocal() {
  883. synchronized (this) {
  884. return mMusicDataManager.isTrackLocal();
  885. }
  886. }
  887. public String getMusicName() {
  888. synchronized (this) {
  889. return mMusicDataManager.getMusicName();
  890. }
  891. }
  892. public String getMusicCover() {
  893. synchronized (this) {
  894. return mMusicDataManager.getMusicCover();
  895. }
  896. }
  897. public String getMusicUrl() {
  898. synchronized (this) {
  899. return mMusicDataManager.getMusicUrl();
  900. }
  901. }
  902. public int getMusicLikeCount() {
  903. synchronized (this) {
  904. return mMusicDataManager.getMusicLikeCount();
  905. }
  906. }
  907. public int getMusicShareCount() {
  908. synchronized (this) {
  909. return mMusicDataManager.getMusicShareCount();
  910. }
  911. }
  912. public int getMusicDownloadCount() {
  913. synchronized (this) {
  914. return mMusicDataManager.getMusicDownloadCount();
  915. }
  916. }
  917. public boolean isFavorite() {
  918. synchronized (this) {
  919. return mMusicDataManager.isFavorite();
  920. }
  921. }
  922. public String getAlbumPath(long id) {
  923. synchronized (this) {
  924. return mMusicDataManager.getAlbumPath(id);
  925. }
  926. }
  927. public String getGenreName() {
  928. synchronized (this) {
  929. return mMusicDataManager.getGenreName();
  930. }
  931. }
  932. public String getArtistName() {
  933. synchronized (this) {
  934. return mMusicDataManager.getArtistName();
  935. }
  936. }
  937. public long getAlbumId() {
  938. synchronized (this) {
  939. return mMusicDataManager.getAlbumId();
  940. }
  941. }
  942. public long getArtistId() {
  943. synchronized (this) {
  944. return mMusicDataManager.getArtistId();
  945. }
  946. }
  947. public long getAudioId() {
  948. return mMusicDataManager.getAudioId();
  949. }
  950. public MusicPlaybackTrack getCurrentTrack() {
  951. return mMusicDataManager.getCurrentTrack();
  952. }
  953. public synchronized MusicPlaybackTrack getTrack(int index) {
  954. return mMusicDataManager.getTrack(index);
  955. }
  956. public long getNextAudioId() {
  957. return mMusicDataManager.getNextAudioId();
  958. }
  959. public long getPreviousAudioId() {
  960. synchronized (this) {
  961. return mMusicDataManager.getPreviousAudioId();
  962. }
  963. }
  964. public long seek(long position) {
  965. if (Utils.isNotNull(mPlayer) && mPlayer.isInitialized()) {
  966. if (position < 0) {
  967. position = 0;
  968. } else if (position > mPlayer.duration()) {
  969. position = mPlayer.duration();
  970. }
  971. long result = mPlayer.seek(position);
  972. notifyChange(POSITION_CHANGED);
  973. return result;
  974. }
  975. return -1;
  976. }
  977. public void seekRelative(long deltaInMs) {
  978. synchronized (this) {
  979. if (Utils.isNotNull(mPlayer) && mPlayer.isInitialized()) {
  980. final long newPos = position() + deltaInMs;
  981. final long duration = duration();
  982. if (newPos < 0) {
  983. prev(true);
  984. // seek to the new duration + the leftover position
  985. seek(duration() + newPos);
  986. } else if (newPos >= duration) {
  987. gotoNext(true);
  988. // seek to the leftover duration
  989. seek(newPos - duration);
  990. } else {
  991. seek(newPos);
  992. }
  993. }
  994. }
  995. }
  996. public long position() {
  997. if (Utils.isNotNull(mPlayer) && mPlayer.isInitialized() && mPlayer.isTrackPrepared()) {
  998. try {
  999. return mPlayer.position();
  1000. } catch (Exception e) {
  1001. e.printStackTrace();
  1002. }
  1003. }
  1004. return -1;
  1005. }
  1006. public int getSecondPosition() {
  1007. if (Utils.isNotNull(mPlayer) && mPlayer.isInitialized()) {
  1008. return mPlayer.secondPosition();
  1009. }
  1010. return -1;
  1011. }
  1012. public long duration() {
  1013. if (mPlayer.isInitialized() && mPlayer.isTrackPrepared()) {
  1014. return mPlayer.duration();
  1015. }
  1016. return -1;
  1017. }
  1018. public HashMap<Long, Song> getPlayinfos() {
  1019. return mMusicDataManager.getPlaylistInfo();
  1020. }
  1021. public void putPlayinfos(final HashMap<Long, Song> songHashMap) {
  1022. synchronized (this) {
  1023. mMusicDataManager.putPlayinfos(songHashMap);
  1024. }
  1025. }
  1026. public Song getCurSong() {
  1027. return getPlayinfos().get(getAudioId());
  1028. }
  1029. public long[] getQueue() {
  1030. return mMusicDataManager.getQueue();
  1031. }
  1032. public long getQueueItemAtPosition(int position) {
  1033. return mMusicDataManager.getQueueItemAtPosition(position);
  1034. }
  1035. public int getQueueSize() {
  1036. return mMusicDataManager.getPlaylist().size();
  1037. }
  1038. public long getLastSeekPos() {
  1039. return mMusicDataManager.getLastSeekPos();
  1040. }
  1041. public int getNextPlayPos() {
  1042. return mMusicDataManager.getNextPosition();
  1043. }
  1044. public boolean isPlaying() {
  1045. return mIsSupposedToBePlaying;
  1046. }
  1047. private void setIsSupposedToBePlaying(boolean value, boolean notify) {
  1048. if (mIsSupposedToBePlaying != value) {
  1049. mIsSupposedToBePlaying = value;
  1050. if (!mIsSupposedToBePlaying) {
  1051. scheduleDelayedShutdown();
  1052. mLastPlayedTime = System.currentTimeMillis();
  1053. }
  1054. if (notify) {
  1055. notifyChange(PLAYSTATE_CHANGED);
  1056. }
  1057. }
  1058. }
  1059. public boolean recentlyPlayed() {
  1060. return isPlaying() || System.currentTimeMillis() - mLastPlayedTime < IDLE_DELAY;
  1061. }
  1062. public void open(final HashMap<Long, Song> songHashMap, final long[] list, final int position) {
  1063. synchronized (this) {
  1064. mMusicDataManager.open(songHashMap, list, position);
  1065. }
  1066. }
  1067. public void stop() {
  1068. stop(true);
  1069. }
  1070. public void play() {
  1071. play(true);
  1072. }
  1073. public void play(boolean createNewNextTrack) {
  1074. int status = mAudioManager.requestAudioFocus(mAudioFocusListener,
  1075. AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
  1076. Timber.e(TAG + " Starting playback: audio focus request status = " + status);
  1077. if (status != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
  1078. return;
  1079. }
  1080. final Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
  1081. intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, getAudioSessionId());
  1082. intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
  1083. sendBroadcast(intent);
  1084. mAudioManager.registerMediaButtonEventReceiver(new ComponentName(getPackageName(),
  1085. MediaButtonIntentReceiver.class.getName()));
  1086. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  1087. mSession.setActive(true);
  1088. }
  1089. if (createNewNextTrack) {
  1090. setNextTrack();
  1091. } else {
  1092. mMusicDataManager.setNextTrack(mMusicDataManager.getNextPosition());
  1093. }
  1094. if (shouldGotoNext()) {
  1095. // 添加"试错次数上限"加以限制
  1096. if (mShouldGotoNextCounter++ < 3) {
  1097. gotoNext(true);// 联系上下文,此行代码有待商榷,可能造成栈溢出(gotoNext()->play()->gotoNext())
  1098. return;
  1099. }
  1100. }
  1101. mShouldGotoNextCounter = 0;
  1102. mPlayer.start();
  1103. mPlayerHandler.removeMessages(MultiPlayerHandler.FADEDOWN);
  1104. mPlayerHandler.sendEmptyMessage(MultiPlayerHandler.FADEUP);
  1105. Timber.e("===>>> play setIsSupposedToBePlaying start ");
  1106. setIsSupposedToBePlaying(true, true);
  1107. Timber.e("===>>> play setIsSupposedToBePlaying end ");
  1108. Timber.e("===>>> play cancelShutdown start ");
  1109. cancelShutdown();
  1110. Timber.e("===>>> play cancelShutdown end ");
  1111. Timber.e("===>>> play updateNotification start ");
  1112. updateNotification();
  1113. Timber.e("===>>> play updateNotification end ");
  1114. Timber.e("===>>> play notifyChange start ");
  1115. notifyChange(META_CHANGED);
  1116. Timber.e("===>>> play notifyChange end ");
  1117. }
  1118. public void pause() {
  1119. Timber.d(TAG + " Pausing playback");
  1120. synchronized (this) {
  1121. mPlayerHandler.removeMessages(MultiPlayerHandler.FADEUP);
  1122. if (mIsSupposedToBePlaying) {
  1123. final Intent intent = new Intent(
  1124. AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
  1125. intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, getAudioSessionId());
  1126. intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
  1127. sendBroadcast(intent);
  1128. mPlayer.pause();
  1129. setIsSupposedToBePlaying(false, true);
  1130. notifyChange(META_CHANGED);
  1131. }
  1132. }
  1133. }
  1134. /**
  1135. * 是否应该进入到下一首
  1136. *
  1137. * @return
  1138. */
  1139. public boolean shouldGotoNext() {
  1140. if (mPlayer.isTrackPrepared()) {
  1141. final long duration = mPlayer.duration();
  1142. if (mMusicDataManager.getRepeatMode() != MusicDataManager.REPEAT_CURRENT
  1143. && duration > 2000
  1144. && mPlayer.position() > duration - 2000) {
  1145. return true;
  1146. }
  1147. }
  1148. return false;
  1149. }
  1150. public void gotoNext(final boolean force) {
  1151. Timber.d(TAG + " Going to next track");
  1152. synchronized (this) {
  1153. if (mMusicDataManager.getPlaylist().size() <= 0) {
  1154. Timber.d(TAG + " No play queue");
  1155. scheduleDelayedShutdown();
  1156. return;
  1157. }
  1158. int pos = mMusicDataManager.getNextPosition();
  1159. if (pos < 0) {
  1160. pos = mMusicDataManager.getNextPosition(force);
  1161. }
  1162. if (pos < 0) {
  1163. setIsSupposedToBePlaying(false, true);
  1164. return;
  1165. }
  1166. stop(false);
  1167. setAndRecordPlayPos(pos);
  1168. openCurrentAndNext();
  1169. play();
  1170. notifyChange(META_CHANGED);
  1171. notifyChange(MUSIC_CHANGED);
  1172. }
  1173. }
  1174. public void setAndRecordPlayPos(int nextPos) {
  1175. synchronized (this) {
  1176. mMusicDataManager.setAndRecordPlayPos(nextPos);
  1177. }
  1178. }
  1179. public void prev(boolean forcePrevious) {
  1180. synchronized (this) {
  1181. boolean goPrevious = getRepeatMode() != MusicDataManager.REPEAT_CURRENT &&
  1182. (position() < REWIND_INSTEAD_PREVIOUS_THRESHOLD || f

Large files files are truncated, but you can click here to view the full file