/app/src/main/java/com/music/player/haige/mvp/ui/music/service/MusicService.java
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
- /*
- * Copyright (C) 2012 Andrew Neal
- * Copyright (C) 2014 The CyanogenMod Project
- * Copyright (C) 2015 Naman Dwivedi
- *
- * Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
- * or agreed to in writing, software distributed under the License is
- * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- */
- package com.music.player.haige.mvp.ui.music.service;
- import android.Manifest;
- import android.annotation.SuppressLint;
- import android.app.AlarmManager;
- import android.app.PendingIntent;
- import android.app.Service;
- import android.content.BroadcastReceiver;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.database.ContentObserver;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.media.AudioManager;
- import android.media.AudioManager.OnAudioFocusChangeListener;
- import android.media.audiofx.AudioEffect;
- import android.os.Build;
- import android.os.Handler;
- import android.os.HandlerThread;
- import android.os.IBinder;
- import android.os.Looper;
- import android.os.PowerManager;
- import android.os.PowerManager.WakeLock;
- import android.os.SystemClock;
- import android.provider.MediaStore;
- import android.support.v4.content.PermissionChecker;
- import android.support.v4.media.MediaMetadataCompat;
- import android.support.v4.media.session.MediaSessionCompat;
- import android.support.v4.media.session.PlaybackStateCompat;
- import android.text.TextUtils;
- import com.bumptech.glide.load.engine.DiskCacheStrategy;
- import com.google.gson.Gson;
- import com.hc.core.http.imageloader.glide.GlideCore;
- import com.hc.core.utils.CoreUtils;
- import com.liulishuo.filedownloader.FileDownloader;
- import com.liulishuo.filedownloader.model.FileDownloadStatus;
- import com.liulishuo.filedownloader.util.FileDownloadUtils;
- import com.music.player.haige.R;
- import com.music.player.haige.app.Constants;
- import com.music.player.haige.app.GlobalConfiguration;
- import com.music.player.haige.app.HaigeApplication;
- import com.music.player.haige.di.component.DaggerMediaServiceComponent;
- import com.music.player.haige.mvp.model.entity.music.MusicPlaybackTrack;
- import com.music.player.haige.mvp.model.entity.music.Song;
- import com.music.player.haige.mvp.model.entity.music.SongDao;
- import com.music.player.haige.mvp.model.respository.provider.SongPlayCount;
- import com.music.player.haige.mvp.model.utils.CommonUtils;
- import com.music.player.haige.mvp.model.utils.HaigeUtil;
- import com.music.player.haige.mvp.model.utils.StringUtils;
- import com.music.player.haige.mvp.ui.music.receiver.MediaButtonIntentReceiver;
- import com.music.player.haige.mvp.ui.music.service.cache.HttpProxyCacheServer;
- import com.music.player.haige.mvp.ui.music.service.cache.MusicLog;
- import com.music.player.haige.mvp.ui.music.service.proxy.utils.MediaPlayerProxy;
- import com.music.player.haige.mvp.ui.music.utils.MusicUtils;
- import com.music.player.haige.mvp.ui.utils.DebugLogger;
- import com.music.player.haige.mvp.ui.utils.ResourceUtils;
- import com.music.player.haige.mvp.ui.utils.Utils;
- import com.tencent.bugly.crashreport.CrashReport;
- import java.io.File;
- import java.util.HashMap;
- import javax.inject.Inject;
- import timber.log.Timber;
- import static android.content.Intent.ACTION_SCREEN_OFF;
- import static com.music.player.haige.mvp.ui.music.service.proxy.utils.ProxyConstants.SD_REMAIN_SIZE;
- @SuppressLint("NewApi")
- public class MusicService extends Service {
- public static final String PLAYSTATE_CHANGED = "com.music.player.haige.playstatechanged";
- public static final String POSITION_CHANGED = "com.music.player.haige.positionchanged";
- public static final String META_CHANGED = "com.music.player.haige.metachanged";
- public static final String PLAYLIST_ITEM_MOVED = "com.music.player.haige.mmoved";
- public static final String QUEUE_CHANGED = "com.music.player.haige.queuechanged";
- public static final String PLAYLIST_CHANGED = "com.music.player.haige.playlistchanged";
- public static final String REPEATMODE_CHANGED = "com.music.player.haige.repeatmodechanged";
- public static final String SHUFFLEMODE_CHANGED = "com.music.player.haige.shufflemodechanged";
- public static final String TRACK_ERROR = "com.music.player.haige.trackerror";
- public static final String TIMBER_PACKAGE_NAME = "com.music.player.haige";
- public static final String MUSIC_PACKAGE_NAME = "com.android.music";
- public static final String SERVICECMD = "com.music.player.haige.musicservicecommand";
- public static final String TOGGLEPAUSE_ACTION = "com.music.player.haige.togglepause";
- public static final String PAUSE_ACTION = "com.music.player.haige.pause";
- public static final String STOP_ACTION = "com.music.player.haige.stop";
- public static final String PREVIOUS_ACTION = "com.music.player.haige.previous";
- public static final String PREVIOUS_FORCE_ACTION = "com.music.player.haige.previous.force";
- public static final String NEXT_ACTION = "com.music.player.haige.next";
- public static final String CLOSE_NOTITY_ACTION = "com.music.player.haige.close.notify";
- public static final String MUSIC_CHANGED = "com.music.player.haige.change_music";
- public static final String REPEAT_ACTION = "com.music.player.haige.repeat";
- public static final String SHUFFLE_ACTION = "com.music.player.haige.shuffle";
- public static final String FAVORITE_ACTION = "com.music.player.haige.favorite";
- public static final String FROM_MEDIA_BUTTON = "frommediabutton";
- public static final String REFRESH = "com.music.player.haige.refresh";
- public static final String LRC_UPDATED = "com.music.player.haige.updatelrc";
- public static final String UPDATE_LOCKSCREEN = "com.music.player.haige.updatelockscreen";
- public static final String CMDNAME = "command";
- public static final String CMDTOGGLEPAUSE = "togglepause";
- public static final String CMDSTOP = "stop";
- public static final String CMDPAUSE = "pause";
- public static final String CMDPLAY = "play";
- public static final String CMDPREVIOUS = "previous";
- public static final String CMDNEXT = "next";
- public static final String CMDNOTIF = "buttonId";
- public static final String TRACK_PREPARED = "com.music.player.haige.prepared";
- public static final String TRY_GET_TRACKINFO = "com.music.player.haige.gettrackinfo";
- public static final String BUFFER_UP = "com.music.player.haige.bufferup";
- public static final String LOCK_SCREEN = "com.music.player.haige.lock";
- public static final String SEND_PROGRESS = "com.music.player.haige.progress";
- public static final String MUSIC_LOADING = "com.music.player.haige.loading";
- public static final String SHUTDOWN = "com.music.player.haige.shutdown";
- public static final String SET_QUEUE = "com.music.player.haige.setqueue";
- // extra的key
- public static final String EXTRA_LOADING = "extra_loading"; // 是否是在加载状态
- public static final String CHANNEL_ID = "haige_channel_01";
- public static final int NEXT = 2;
- public static final int LAST = 3;
- private static final String TAG = MusicService.class.getName();
- public static final int LRC_DOWNLOADED = -10;
- private static final int IDLE_DELAY = 5 * 60 * 1000;
- private static final long REWIND_INSTEAD_PREVIOUS_THRESHOLD = 3000;
- private final IBinder mBinder = new ServiceStub(this);
- public MultiPlayer mPlayer;
- private String mFileToPlay;
- public WakeLock mWakeLock;
- private AlarmManager mAlarmManager;
- private PendingIntent mShutdownIntent;
- private boolean mShutdownScheduled;
- private AudioManager mAudioManager;
- private boolean mServiceInUse = false;
- private boolean mIsSupposedToBePlaying = false;
- private long mLastPlayedTime;
- public boolean mPausedByTransientLossOfFocus = false;
- private MediaSessionCompat mSession;
- private ComponentName mMediaButtonReceiverComponent;
- private int mShouldGotoNextCounter = 0;
- private int mOpenFailedCounter = 0;
- private int mMediaMountedCount = 0;
- private int mServiceStartId = -1;
- private MultiPlayerHandler mPlayerHandler;
- private HandlerThread mHandlerThread;
- private BroadcastReceiver mUnmountReceiver = null;
- private boolean mShowAlbumArtOnLockscreen;
- private SongPlayCount mSongPlayCount;
- private SongDao mRecentSongDao;
- private ContentObserver mMediaStoreObserver;
- private static Handler mUrlHandler;
- private MediaPlayerProxy mProxy;
- private RequestPlayUrl mRequestUrl;
- private boolean mIsSending = false;
- private boolean mIsLocked;
- private boolean mIsShort;
- private NNotificationManager mNNotificationManager;
- private MusicDataManager mMusicDataManager;
- private HttpProxyCacheServer httpProxyCacheServer;
- @Inject
- Gson mGson;
- private Thread mGetUrlThread = new Thread(new Runnable() {
- @Override
- public void run() {
- Looper.prepare();
- mUrlHandler = new Handler();
- Looper.loop();
- }
- });
- private final OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {
- @Override
- public void onAudioFocusChange(final int focusChange) {
- mPlayerHandler.obtainMessage(MultiPlayerHandler.FOCUSCHANGE, focusChange, 0).sendToTarget();
- }
- };
- private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(final Context context, final Intent intent) {
- final String command = intent.getStringExtra(CMDNAME);
- Timber.d(TAG + " onreceive" + intent.toURI());
- handleCommandIntent(intent);
- }
- };
- @Override
- public IBinder onBind(final Intent intent) {
- Timber.d(TAG + " Service bound, intent = " + intent);
- cancelShutdown();
- mServiceInUse = true;
- return mBinder;
- }
- @Override
- public boolean onUnbind(final Intent intent) {
- Timber.d(TAG + " Service unbound");
- mServiceInUse = false;
- mMusicDataManager.saveQueue(true);
- if (mIsSupposedToBePlaying || mPausedByTransientLossOfFocus) {
- return true;
- } else if (mMusicDataManager.getPlaylist().size() > 0 || mPlayerHandler.hasMessages(MultiPlayerHandler.TRACK_ENDED)) {
- scheduleDelayedShutdown();
- return true;
- }
- stopSelf(mServiceStartId);
- return true;
- }
- @Override
- public void onRebind(final Intent intent) {
- cancelShutdown();
- mServiceInUse = true;
- }
- @Override
- public void onCreate() {
- Timber.d(TAG + " Creating service");
- super.onCreate();
- DaggerMediaServiceComponent
- .builder()
- .appComponent(CoreUtils.obtainAppComponentFromContext(HaigeApplication.getInstance()))
- .build()
- .inject(this);
- mNNotificationManager = new NNotificationManager(this);
- mNNotificationManager.createNotificationChannel(this);
- mMusicDataManager = new MusicDataManager(this, mGson);
- mGetUrlThread.start();
- //mLrcThread.start();
- mProxy = new MediaPlayerProxy(this);
- mProxy.init();
- mProxy.start();
- // gets a pointer to the playback state store
- mSongPlayCount = SongPlayCount.getInstance(this);
- mRecentSongDao = GlobalConfiguration.sRecentDaoSession.getSongDao();
- mHandlerThread = new HandlerThread("MultiPlayerHandler",
- android.os.Process.THREAD_PRIORITY_BACKGROUND);
- mHandlerThread.start();
- mPlayerHandler = new MultiPlayerHandler(this, mHandlerThread.getLooper());
- mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- mMediaButtonReceiverComponent = new ComponentName(getPackageName(),
- MediaButtonIntentReceiver.class.getName());
- mAudioManager.registerMediaButtonEventReceiver(mMediaButtonReceiverComponent);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- setUpMediaSession();
- }
- mMusicDataManager.updateCardId();
- registerExternalStorageListener();
- mPlayer = new MultiPlayer(this);
- mPlayer.setHandler(mPlayerHandler);
- // Initialize the intent filter and each action
- final IntentFilter filter = new IntentFilter();
- filter.addAction(SERVICECMD);
- filter.addAction(TOGGLEPAUSE_ACTION);
- filter.addAction(PAUSE_ACTION);
- filter.addAction(STOP_ACTION);
- filter.addAction(NEXT_ACTION);
- filter.addAction(CLOSE_NOTITY_ACTION);
- filter.addAction(PREVIOUS_ACTION);
- filter.addAction(PREVIOUS_FORCE_ACTION);
- filter.addAction(REPEAT_ACTION);
- filter.addAction(SHUFFLE_ACTION);
- filter.addAction(TRY_GET_TRACKINFO);
- filter.addAction(ACTION_SCREEN_OFF);
- filter.addAction(LOCK_SCREEN);
- filter.addAction(SEND_PROGRESS);
- filter.addAction(SET_QUEUE);
- // Attach the broadcast listener
- registerReceiver(mIntentReceiver, filter);
- mMediaStoreObserver = new MediaStoreObserver(mPlayerHandler);
- getContentResolver().registerContentObserver(
- MediaStore.Audio.Media.INTERNAL_CONTENT_URI, true, mMediaStoreObserver);
- getContentResolver().registerContentObserver(
- MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, true, mMediaStoreObserver);
- // Initialize the wake lock
- final PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
- mWakeLock.setReferenceCounted(false);
- final Intent shutdownIntent = new Intent(this, MusicService.class);
- shutdownIntent.setAction(SHUTDOWN);
- mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
- mShutdownIntent = PendingIntent.getService(this, 0, shutdownIntent, 0);
- scheduleDelayedShutdown();
- reloadQueueAfterPermissionCheck();
- notifyChange(QUEUE_CHANGED);
- notifyChange(META_CHANGED);
- }
- private void setUpMediaSession() {
- mSession = new MediaSessionCompat(this, "haige");
- mSession.setCallback(new MediaSessionCompat.Callback() {
- @Override
- public void onPause() {
- pause();
- mPausedByTransientLossOfFocus = false;
- }
- @Override
- public void onPlay() {
- play();
- }
- @Override
- public void onSeekTo(long pos) {
- seek(pos);
- }
- @Override
- public void onSkipToNext() {
- gotoNext(true);
- }
- @Override
- public void onSkipToPrevious() {
- prev(false);
- }
- @Override
- public void onStop() {
- pause();
- mPausedByTransientLossOfFocus = false;
- seek(0);
- releaseServiceUiAndStop();
- }
- });
- mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
- }
- public MediaSessionCompat.Token getSessionToken() {
- return mSession.getSessionToken();
- }
- public void exit() {
- }
- @Override
- public void onDestroy() {
- Timber.d(TAG + " Destroying service");
- super.onDestroy();
- // Remove any sound effects
- final Intent audioEffectsIntent = new Intent(
- AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
- audioEffectsIntent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, getAudioSessionId());
- audioEffectsIntent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
- sendBroadcast(audioEffectsIntent);
- mNNotificationManager.cancelNotification(this);
- mAlarmManager.cancel(mShutdownIntent);
- mPlayerHandler.removeCallbacksAndMessages(null);
- if (CommonUtils.isJellyBeanMR2())
- mHandlerThread.quitSafely();
- else mHandlerThread.quit();
- mPlayer.release();
- mPlayer = null;
- mAudioManager.abandonAudioFocus(mAudioFocusListener);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
- mSession.release();
- getContentResolver().unregisterContentObserver(mMediaStoreObserver);
- mMusicDataManager.closeCursor();
- unregisterReceiver(mIntentReceiver);
- if (mUnmountReceiver != null) {
- unregisterReceiver(mUnmountReceiver);
- mUnmountReceiver = null;
- }
- mWakeLock.release();
- }
- @Override
- public int onStartCommand(final Intent intent, final int flags, final int startId) {
- Timber.d(TAG + " Got new intent " + intent + ", startId = " + startId);
- mServiceStartId = startId;
- if (intent != null) {
- final String action = intent.getAction();
- if (SHUTDOWN.equals(action)) {
- mShutdownScheduled = false;
- releaseServiceUiAndStop();
- return START_NOT_STICKY;
- }
- handleCommandIntent(intent);
- }
- scheduleDelayedShutdown();
- if (intent != null && intent.getBooleanExtra(FROM_MEDIA_BUTTON, false)) {
- MediaButtonIntentReceiver.completeWakefulIntent(intent);
- }
- return START_STICKY;
- }
- private void releaseServiceUiAndStop() {
- if (isPlaying()
- || mPausedByTransientLossOfFocus
- || mPlayerHandler.hasMessages(MultiPlayerHandler.TRACK_ENDED)) {
- return;
- }
- Timber.d(TAG + " Nothing is playing anymore, releasing app_layout_notification");
- mNNotificationManager.cancelNotification(this);
- mAudioManager.abandonAudioFocus(mAudioFocusListener);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
- mSession.setActive(false);
- if (!mServiceInUse) {
- mMusicDataManager.saveQueue(true);
- stopSelf(mServiceStartId);
- }
- }
- private void handleCommandIntent(Intent intent) {
- final String action = intent.getAction();
- final String command = SERVICECMD.equals(action) ? intent.getStringExtra(CMDNAME) : null;
- Timber.d(TAG + " handleCommandIntent: action = " + action + ", command = " + command);
- if (CMDNEXT.equals(command) || NEXT_ACTION.equals(action)) {
- gotoNext(true);
- } else if (CMDPREVIOUS.equals(command) || PREVIOUS_ACTION.equals(action)
- || PREVIOUS_FORCE_ACTION.equals(action)) {
- prev(PREVIOUS_FORCE_ACTION.equals(action));
- } else if (CMDTOGGLEPAUSE.equals(command) || TOGGLEPAUSE_ACTION.equals(action)) {
- if (isPlaying()) {
- pause();
- mPausedByTransientLossOfFocus = false;
- } else {
- play();
- }
- } else if (CMDPAUSE.equals(command) || PAUSE_ACTION.equals(action)) {
- pause();
- mPausedByTransientLossOfFocus = false;
- } else if (CMDPLAY.equals(command)) {
- play();
- } else if (CMDSTOP.equals(command) || STOP_ACTION.equals(action)) {
- pause();
- mPausedByTransientLossOfFocus = false;
- seek(0);
- releaseServiceUiAndStop();
- } else if (REPEAT_ACTION.equals(action)) {
- cycleRepeat();
- } else if (SHUFFLE_ACTION.equals(action)) {
- cycleShuffle();
- } else if (TRY_GET_TRACKINFO.equals(action)) {
- //getLrc(mMusicDataManager.getPlaylist().get(mMusicDataManager.getPlayPos()).mId);
- } else if (ACTION_SCREEN_OFF.equals(action)) {
- // if (isPlaying() && !mIsLocked) {
- // Intent lockscreen = new Intent(this, LockActivity.class);
- // lockscreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- // startActivity(lockscreen);
- // }
- } else if (LOCK_SCREEN.equals(action)) {
- mIsLocked = intent.getBooleanExtra("islock", true);
- Timber.d(TAG + " isloced = " + mIsLocked);
- } else if (SEND_PROGRESS.equals(action)) {
- if (isPlaying() && !mIsSending) {
- mPlayerHandler.post(sendDuration);
- mIsSending = true;
- } else if (!isPlaying()) {
- mPlayerHandler.removeCallbacks(sendDuration);
- mIsSending = false;
- }
- } else if (SET_QUEUE.equals(action)) {
- setQueuePosition(intent.getIntExtra("position", 0));
- } else if (CLOSE_NOTITY_ACTION.equals(action)) {
- mNNotificationManager.cancelNotification(this);
- }
- }
- private Runnable sendDuration = new Runnable() {
- @Override
- public void run() {
- notifyChange(SEND_PROGRESS);
- mPlayerHandler.postDelayed(sendDuration, 1000);
- }
- };
- public void updateNotification() {
- mNNotificationManager.updateNotification(this);
- }
- public void closeExternalStorageFiles(final String storagePath) {
- stop(true);
- notifyChange(QUEUE_CHANGED);
- notifyChange(META_CHANGED);
- }
- public void registerExternalStorageListener() {
- if (mUnmountReceiver == null) {
- mUnmountReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(final Context context, final Intent intent) {
- final String action = intent.getAction();
- if (Intent.ACTION_MEDIA_EJECT.equals(action)) {
- mMusicDataManager.saveQueue(true);
- mMusicDataManager.setQueueIsSaveable(false);
- closeExternalStorageFiles(intent.getData().getPath());
- } else if (Intent.ACTION_MEDIA_MOUNTED.equals(action)) {
- mMediaMountedCount++;
- mMusicDataManager.updateCardId();
- reloadQueueAfterPermissionCheck();
- mMusicDataManager.setQueueIsSaveable(true);
- notifyChange(QUEUE_CHANGED);
- notifyChange(META_CHANGED);
- }
- }
- };
- final IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_MEDIA_EJECT);
- filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
- filter.addDataScheme("file");
- registerReceiver(mUnmountReceiver, filter);
- }
- }
- private void scheduleDelayedShutdown() {
- Timber.d(TAG + " Scheduling shutdown in " + IDLE_DELAY + " ms");
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + IDLE_DELAY, mShutdownIntent);
- mShutdownScheduled = true;
- }
- private void cancelShutdown() {
- Timber.d(TAG + " Cancelling delayed shutdown, scheduled = " + mShutdownScheduled);
- if (mShutdownScheduled) {
- mAlarmManager.cancel(mShutdownIntent);
- mShutdownScheduled = false;
- }
- }
- public void stop(final boolean goToIdle) {
- Timber.d(TAG + " Stopping playback, goToIdle = " + goToIdle);
- if (mPlayer.isInitialized()) {
- mPlayer.stop();
- }
- mFileToPlay = null;
- mMusicDataManager.closeCursor();
- if (goToIdle) {
- setIsSupposedToBePlaying(false, false);
- } else {
- if (CommonUtils.isLollipop()) {
- stopForeground(false);
- } else {
- stopForeground(true);
- }
- }
- }
- private void addToPlayList(final long[] list, int position) {
- mMusicDataManager.addToPlayList(list, position);
- }
- public void openCurrentAndNextPlay(boolean play) {
- openCurrentAndMaybeNext(play, true);
- }
- public void openCurrentAndNext() {
- openCurrentAndMaybeNext(false, true);
- }
- private void openCurrentAndMaybeNext(final boolean play, final boolean openNext) {
- synchronized (this) {
- Timber.d(TAG + " open current");
- mMusicDataManager.closeCursor();
- stop(false);
- boolean shutdown = false;
- if (mMusicDataManager.getPlaylist().size() == 0
- || mMusicDataManager.getPlaylistInfo().size() == 0 && mMusicDataManager.getPlayPos() >= mMusicDataManager.getPlaylist().size()) {
- mMusicDataManager.clearPlayInfo();
- return;
- }
- final long id = mMusicDataManager.getPlaylist().get(mMusicDataManager.getPlayPos()).mId;
- mMusicDataManager.updateCursor(id);
- if (mMusicDataManager.getPlaylistInfo().get(id) == null) {
- return;
- }
- if (!mMusicDataManager.getPlaylistInfo().get(id).isLocal) {
- if (mRequestUrl != null) {
- mRequestUrl.stop();
- mUrlHandler.removeCallbacks(mRequestUrl);
- }
- Song song = mMusicDataManager.getPlaylistInfo().get(id);
- mRequestUrl = new RequestPlayUrl(song, mIsShort, play);
- mUrlHandler.postDelayed(mRequestUrl, 70);
- } else {
- while (true) {
- if (mMusicDataManager.getCursor() != null
- && openFile(mMusicDataManager.getContentUriPath())) {
- break;
- }
- mMusicDataManager.closeCursor();
- if (mOpenFailedCounter++ < 10 && mMusicDataManager.getPlaylist().size() > 1) {
- final int pos = mMusicDataManager.getNextPosition(false);
- if (pos < 0) {
- shutdown = true;
- break;
- }
- mMusicDataManager.setPlayPos(pos);
- stop(false);
- mMusicDataManager.setPlayPos(pos);
- mMusicDataManager.updateCursor(mMusicDataManager.getPlaylist().get(mMusicDataManager.getPlayPos()).mId);
- } else {
- mOpenFailedCounter = 0;
- Timber.d(TAG + " Failed to open file for playback");
- shutdown = true;
- break;
- }
- }
- }
- if (shutdown) {
- scheduleDelayedShutdown();
- if (mIsSupposedToBePlaying) {
- mIsSupposedToBePlaying = false;
- notifyChange(PLAYSTATE_CHANGED);
- }
- } else if (openNext) {
- setNextTrack();
- }
- }
- }
- public void setOpenFailedCounter(int openFailedCounter) {
- this.mOpenFailedCounter = openFailedCounter;
- }
- class RequestPlayUrl implements Runnable {
- private Song song;
- private boolean isShort;
- private boolean play;
- private boolean stop;
- private RequestPlayUrl(Song song, boolean isShort, boolean play) {
- this.song = song;
- this.isShort = isShort;
- this.play = play;
- }
- public void stop() {
- stop = true;
- }
- @Override
- public void run() {
- try {
- String url;
- if (mIsShort && Utils.isNotEmptyString(song.shortUrl)) {
- url = song.shortUrl;
- DebugLogger.e(TAG, "short: true");
- } else {
- url = song.musicPath;
- DebugLogger.e(TAG, "short: false");
- }
- if (Utils.isNotEmptyString(url)) {
- Timber.e(TAG + " current url = " + url);
- } else {
- gotoNext(true);
- }
- if (!stop) {
- // 判断是否已经下载了这个文件
- String path = MusicUtils.getDownloadPath(song, mIsShort);
- int id = FileDownloadUtils.generateId(url, path);
- int status = FileDownloader.getImpl().getStatus(id, path);
- if (status == FileDownloadStatus.completed && new File(path).exists()) {
- mPlayer.setDataSource(path);
- } else {
- String proxyUrl = getProxyUrl(url, mIsShort);
- mPlayer.setDataSource(proxyUrl);
- }
- }
- if (play && !stop) {
- play();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- private void initHttpProxyCacheServer() {
- httpProxyCacheServer = new HttpProxyCacheServer.Builder(HaigeApplication.getInstance())
- .maxCacheSize(SD_REMAIN_SIZE)
- .fileNameGenerator(new ProxyFileNameGenerator())
- .build();
- }
- public String getProxyUrl(String realUrl, boolean isShort) {
- if (Utils.isNull(httpProxyCacheServer)) {
- initHttpProxyCacheServer();
- }
- MusicLog.playerD("setUp url:" + realUrl);
- if (Utils.isNotNull(httpProxyCacheServer)) {
- httpProxyCacheServer.putIsShort(isShort);
- realUrl = httpProxyCacheServer.getProxyUrl(realUrl);
- }
- return realUrl;
- }
- public void sendErrorMessage(final String trackName) {
- final Intent i = new Intent(TRACK_ERROR);
- i.putExtra(TrackErrorExtra.TRACK_NAME, trackName);
- sendBroadcast(i);
- }
- public void setNextTrack() {
- mMusicDataManager.setNextTrack();
- }
- public void setNextDataSource(String path) {
- mPlayer.setNextDataSource(path);
- }
- public void sendUpdateBuffer(int progress) {
- Intent intent = new Intent(BUFFER_UP);
- intent.putExtra("progress", progress);
- sendBroadcast(intent);
- }
- public void notifyChange(final String what) {
- Timber.d(TAG + " notifyChange: what = " + what);
- if (SEND_PROGRESS.equals(what)) {
- final Intent intent = new Intent(SEND_PROGRESS);
- intent.putExtra("position", position());
- intent.putExtra("duration", duration());
- sendStickyBroadcast(intent);
- return;
- }
- // Update the lockscreen controls
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- updateMediaSession(what);
- }
- if (what.equals(POSITION_CHANGED)) {
- return;
- }
- final Intent intent = new Intent(what);
- intent.putExtra(Song.KEY_MUSIC_ID, getAudioId());
- intent.putExtra(Song.KEY_ARTIST_NAME, getArtistName());
- intent.putExtra(Song.KEY_MUSIC_NAME, getTrackName());
- intent.putExtra(Song.KEY_MUSIC_URL, getPath());
- intent.putExtra(Song.KEY_ALBUM_NAME, getAlbumName());
- intent.putExtra(Song.KEY_ALBUM_DATA, getAlbumPath());
- intent.putExtra(Song.KEY_IS_PLAYING, isPlaying());
- intent.putExtra(Song.KEY_ALBUM_ID, getAlbumId());
- intent.putExtra(Song.KEY_IS_LOCAL, isTrackLocal());
- intent.putExtra(Song.KEY_MUSIC_COVER, getMusicCover());
- intent.putExtra(Song.KEY_LIKE, getMusicLikeCount());
- intent.putExtra(Song.KEY_SHARE, getMusicShareCount());
- intent.putExtra(Song.KEY_DOWNLOAD, getMusicDownloadCount());
- intent.putExtra(Song.KEY_MUSIC_URL, getMusicUrl());
- sendStickyBroadcast(intent);
- final Intent musicIntent = new Intent(intent);
- musicIntent.setAction(what.replace(TIMBER_PACKAGE_NAME, MUSIC_PACKAGE_NAME));
- sendStickyBroadcast(musicIntent);
- if (what.equals(META_CHANGED)) {
- try {
- Song song = getCurSong();
- if (song != null) {
- mRecentSongDao.insertOrReplace(getCurSong());
- }
- mSongPlayCount.bumpSongCount(getAudioId());
- } catch (Throwable t) {
- CrashReport.postCatchedException(t);
- }
- } else if (what.equals(QUEUE_CHANGED)) {
- Intent intent1 = new Intent(Constants.EMPTY_LIST);
- intent.putExtra("showorhide", "show");
- sendBroadcast(intent1);
- mMusicDataManager.saveQueue(true);
- if (isPlaying()) {
- mMusicDataManager.updateNextTrack();
- }
- } else {
- mMusicDataManager.saveQueue(false);
- }
- if (what.equals(PLAYSTATE_CHANGED)) {
- updateNotification();
- }
- }
- private void updateMediaSession(final String what) {
- int playState = mIsSupposedToBePlaying
- ? PlaybackStateCompat.STATE_PLAYING
- : PlaybackStateCompat.STATE_PAUSED;
- if (what.equals(PLAYSTATE_CHANGED) || what.equals(POSITION_CHANGED)) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- mSession.setPlaybackState(new PlaybackStateCompat.Builder()
- .setState(playState, position(), 1.0f)
- .setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY_PAUSE |
- PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)
- .build());
- }
- } else if (what.equals(META_CHANGED) || what.equals(QUEUE_CHANGED)) {
- Bitmap albumArt = BitmapFactory.decodeResource(ResourceUtils.getResources(), R.drawable.app_ic_album_default);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- mSession.setMetadata(new MediaMetadataCompat.Builder()
- .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, getArtistName())
- .putString(MediaMetadataCompat.METADATA_KEY_ALBUM, getAlbumName())
- .putString(MediaMetadataCompat.METADATA_KEY_TITLE, getTrackName())
- .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, duration())
- .putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, getQueuePosition() + 1)
- .putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, getQueue().length)
- .putString(MediaMetadataCompat.METADATA_KEY_GENRE, getGenreName())
- .putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, mShowAlbumArtOnLockscreen ? albumArt : null)
- .build());
- mSession.setPlaybackState(new PlaybackStateCompat.Builder()
- .setState(playState, position(), 1.0f)
- .setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY_PAUSE |
- PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)
- .build());
- }
- }
- }
- private void reloadQueueAfterPermissionCheck() {
- if (CommonUtils.isMarshmallow()) {
- if (PermissionChecker.PERMISSION_GRANTED == PermissionChecker.checkSelfPermission(HaigeApplication.getInstance(), Manifest.permission.READ_EXTERNAL_STORAGE)) {
- mMusicDataManager.reloadQueue();
- }
- } else {
- mMusicDataManager.reloadQueue();
- }
- }
- public boolean removeTrackAtPosition(final long id, final int position) {
- return mMusicDataManager.removeTrackAtPosition(id, position);
- }
- public boolean openFile(final String path) {
- Timber.d(TAG + " openFile: path = " + path);
- synchronized (this) {
- if (path == null) {
- return false;
- }
- String mpUri = mMusicDataManager.openFile(path);
- if (!TextUtils.isEmpty(mpUri)) {
- return mMusicDataManager.notifyMetaChanged(mpUri);
- }
- mFileToPlay = path;
- mPlayer.setDataSource(mFileToPlay);
- if (mPlayer.isInitialized()) {
- mOpenFailedCounter = 0;
- return true;
- }
- String trackName = getTrackName();
- if (TextUtils.isEmpty(trackName)) {
- trackName = path;
- }
- sendErrorMessage(trackName);
- stop(true);
- return false;
- }
- }
- public void closeCursor() {
- synchronized (this) {
- mMusicDataManager.closeCursor();
- }
- }
- public void updateCursor() {
- synchronized (this) {
- mMusicDataManager.updateCursor(getAudioId());
- }
- }
- public int getAudioSessionId() {
- synchronized (this) {
- return mPlayer.getAudioSessionId();
- }
- }
- public int getMediaMountedCount() {
- return mMediaMountedCount;
- }
- public void setShuffleMode(int shuffleMode) {
- synchronized (this) {
- mMusicDataManager.setShuffleMode(shuffleMode);
- }
- }
- public int getShuffleMode() {
- return mMusicDataManager.getShuffleMode();
- }
- public int getRepeatMode() {
- return mMusicDataManager.getRepeatMode();
- }
- public void setRepeatMode(final int repeatMode) {
- synchronized (this) {
- mMusicDataManager.setRepeatMode(repeatMode);
- }
- }
- public int removeTrack(final long id) {
- return mMusicDataManager.removeTrack(id);
- }
- public int removeTracks(final int first, final int last) {
- return mMusicDataManager.removeTracks(first, last);
- }
- public int getQueuePosition() {
- return mMusicDataManager.getPlayPos();
- }
- public int getQueueHistorySize() {
- return mMusicDataManager.getHistory().size();
- }
- public int getQueueHistoryPosition(int position) {
- return mMusicDataManager.getQueueHistoryPosition(position);
- }
- public int[] getQueueHistoryList() {
- return mMusicDataManager.getQueueHistoryList();
- }
- public String getPath() {
- synchronized (this) {
- return mMusicDataManager.getPath();
- }
- }
- public String getAlbumName() {
- synchronized (this) {
- return mMusicDataManager.getAlbumName();
- }
- }
- public String getAlbumPath() {
- synchronized (this) {
- return mMusicDataManager.getAlbumPath();
- }
- }
- public String[] getAlbumPathAll() {
- synchronized (this) {
- return mMusicDataManager.getAlbumPathAll();
- }
- }
- public String getTrackName() {
- synchronized (this) {
- return mMusicDataManager.getTrackName();
- }
- }
- public boolean isTrackLocal() {
- synchronized (this) {
- return mMusicDataManager.isTrackLocal();
- }
- }
- public String getMusicName() {
- synchronized (this) {
- return mMusicDataManager.getMusicName();
- }
- }
- public String getMusicCover() {
- synchronized (this) {
- return mMusicDataManager.getMusicCover();
- }
- }
- public String getMusicUrl() {
- synchronized (this) {
- return mMusicDataManager.getMusicUrl();
- }
- }
- public int getMusicLikeCount() {
- synchronized (this) {
- return mMusicDataManager.getMusicLikeCount();
- }
- }
- public int getMusicShareCount() {
- synchronized (this) {
- return mMusicDataManager.getMusicShareCount();
- }
- }
- public int getMusicDownloadCount() {
- synchronized (this) {
- return mMusicDataManager.getMusicDownloadCount();
- }
- }
- public boolean isFavorite() {
- synchronized (this) {
- return mMusicDataManager.isFavorite();
- }
- }
- public String getAlbumPath(long id) {
- synchronized (this) {
- return mMusicDataManager.getAlbumPath(id);
- }
- }
- public String getGenreName() {
- synchronized (this) {
- return mMusicDataManager.getGenreName();
- }
- }
- public String getArtistName() {
- synchronized (this) {
- return mMusicDataManager.getArtistName();
- }
- }
- public long getAlbumId() {
- synchronized (this) {
- return mMusicDataManager.getAlbumId();
- }
- }
- public long getArtistId() {
- synchronized (this) {
- return mMusicDataManager.getArtistId();
- }
- }
- public long getAudioId() {
- return mMusicDataManager.getAudioId();
- }
- public MusicPlaybackTrack getCurrentTrack() {
- return mMusicDataManager.getCurrentTrack();
- }
- public synchronized MusicPlaybackTrack getTrack(int index) {
- return mMusicDataManager.getTrack(index);
- }
- public long getNextAudioId() {
- return mMusicDataManager.getNextAudioId();
- }
- public long getPreviousAudioId() {
- synchronized (this) {
- return mMusicDataManager.getPreviousAudioId();
- }
- }
- public long seek(long position) {
- if (Utils.isNotNull(mPlayer) && mPlayer.isInitialized()) {
- if (position < 0) {
- position = 0;
- } else if (position > mPlayer.duration()) {
- position = mPlayer.duration();
- }
- long result = mPlayer.seek(position);
- notifyChange(POSITION_CHANGED);
- return result;
- }
- return -1;
- }
- public void seekRelative(long deltaInMs) {
- synchronized (this) {
- if (Utils.isNotNull(mPlayer) && mPlayer.isInitialized()) {
- final long newPos = position() + deltaInMs;
- final long duration = duration();
- if (newPos < 0) {
- prev(true);
- // seek to the new duration + the leftover position
- seek(duration() + newPos);
- } else if (newPos >= duration) {
- gotoNext(true);
- // seek to the leftover duration
- seek(newPos - duration);
- } else {
- seek(newPos);
- }
- }
- }
- }
- public long position() {
- if (Utils.isNotNull(mPlayer) && mPlayer.isInitialized() && mPlayer.isTrackPrepared()) {
- try {
- return mPlayer.position();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return -1;
- }
- public int getSecondPosition() {
- if (Utils.isNotNull(mPlayer) && mPlayer.isInitialized()) {
- return mPlayer.secondPosition();
- }
- return -1;
- }
- public long duration() {
- if (mPlayer.isInitialized() && mPlayer.isTrackPrepared()) {
- return mPlayer.duration();
- }
- return -1;
- }
- public HashMap<Long, Song> getPlayinfos() {
- return mMusicDataManager.getPlaylistInfo();
- }
- public void putPlayinfos(final HashMap<Long, Song> songHashMap) {
- synchronized (this) {
- mMusicDataManager.putPlayinfos(songHashMap);
- }
- }
- public Song getCurSong() {
- return getPlayinfos().get(getAudioId());
- }
- public long[] getQueue() {
- return mMusicDataManager.getQueue();
- }
- public long getQueueItemAtPosition(int position) {
- return mMusicDataManager.getQueueItemAtPosition(position);
- }
- public int getQueueSize() {
- return mMusicDataManager.getPlaylist().size();
- }
- public long getLastSeekPos() {
- return mMusicDataManager.getLastSeekPos();
- }
- public int getNextPlayPos() {
- return mMusicDataManager.getNextPosition();
- }
- public boolean isPlaying() {
- return mIsSupposedToBePlaying;
- }
- private void setIsSupposedToBePlaying(boolean value, boolean notify) {
- if (mIsSupposedToBePlaying != value) {
- mIsSupposedToBePlaying = value;
- if (!mIsSupposedToBePlaying) {
- scheduleDelayedShutdown();
- mLastPlayedTime = System.currentTimeMillis();
- }
- if (notify) {
- notifyChange(PLAYSTATE_CHANGED);
- }
- }
- }
- public boolean recentlyPlayed() {
- return isPlaying() || System.currentTimeMillis() - mLastPlayedTime < IDLE_DELAY;
- }
- public void open(final HashMap<Long, Song> songHashMap, final long[] list, final int position) {
- synchronized (this) {
- mMusicDataManager.open(songHashMap, list, position);
- }
- }
- public void stop() {
- stop(true);
- }
- public void play() {
- play(true);
- }
- public void play(boolean createNewNextTrack) {
- int status = mAudioManager.requestAudioFocus(mAudioFocusListener,
- AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
- Timber.e(TAG + " Starting playback: audio focus request status = " + status);
- if (status != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
- return;
- }
- final Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
- intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, getAudioSessionId());
- intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
- sendBroadcast(intent);
- mAudioManager.registerMediaButtonEventReceiver(new ComponentName(getPackageName(),
- MediaButtonIntentReceiver.class.getName()));
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- mSession.setActive(true);
- }
- if (createNewNextTrack) {
- setNextTrack();
- } else {
- mMusicDataManager.setNextTrack(mMusicDataManager.getNextPosition());
- }
- if (shouldGotoNext()) {
- // 添加"试错次数上限"加以限制
- if (mShouldGotoNextCounter++ < 3) {
- gotoNext(true);// 联系上下文,此行代码有待商榷,可能造成栈溢出(gotoNext()->play()->gotoNext())
- return;
- }
- }
- mShouldGotoNextCounter = 0;
- mPlayer.start();
- mPlayerHandler.removeMessages(MultiPlayerHandler.FADEDOWN);
- mPlayerHandler.sendEmptyMessage(MultiPlayerHandler.FADEUP);
- Timber.e("===>>> play setIsSupposedToBePlaying start ");
- setIsSupposedToBePlaying(true, true);
- Timber.e("===>>> play setIsSupposedToBePlaying end ");
- Timber.e("===>>> play cancelShutdown start ");
- cancelShutdown();
- Timber.e("===>>> play cancelShutdown end ");
- Timber.e("===>>> play updateNotification start ");
- updateNotification();
- Timber.e("===>>> play updateNotification end ");
- Timber.e("===>>> play notifyChange start ");
- notifyChange(META_CHANGED);
- Timber.e("===>>> play notifyChange end ");
- }
- public void pause() {
- Timber.d(TAG + " Pausing playback");
- synchronized (this) {
- mPlayerHandler.removeMessages(MultiPlayerHandler.FADEUP);
- if (mIsSupposedToBePlaying) {
- final Intent intent = new Intent(
- AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
- intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, getAudioSessionId());
- intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
- sendBroadcast(intent);
- mPlayer.pause();
- setIsSupposedToBePlaying(false, true);
- notifyChange(META_CHANGED);
- }
- }
- }
- /**
- * 是否应该进入到下一首
- *
- * @return
- */
- public boolean shouldGotoNext() {
- if (mPlayer.isTrackPrepared()) {
- final long duration = mPlayer.duration();
- if (mMusicDataManager.getRepeatMode() != MusicDataManager.REPEAT_CURRENT
- && duration > 2000
- && mPlayer.position() > duration - 2000) {
- return true;
- }
- }
- return false;
- }
- public void gotoNext(final boolean force) {
- Timber.d(TAG + " Going to next track");
- synchronized (this) {
- if (mMusicDataManager.getPlaylist().size() <= 0) {
- Timber.d(TAG + " No play queue");
- scheduleDelayedShutdown();
- return;
- }
- int pos = mMusicDataManager.getNextPosition();
- if (pos < 0) {
- pos = mMusicDataManager.getNextPosition(force);
- }
- if (pos < 0) {
- setIsSupposedToBePlaying(false, true);
- return;
- }
- stop(false);
- setAndRecordPlayPos(pos);
- openCurrentAndNext();
- play();
- notifyChange(META_CHANGED);
- notifyChange(MUSIC_CHANGED);
- }
- }
- public void setAndRecordPlayPos(int nextPos) {
- synchronized (this) {
- mMusicDataManager.setAndRecordPlayPos(nextPos);
- }
- }
- public void prev(boolean forcePrevious) {
- synchronized (this) {
- boolean goPrevious = getRepeatMode() != MusicDataManager.REPEAT_CURRENT &&
- (position() < REWIND_INSTEAD_PREVIOUS_THRESHOLD || f…
Large files files are truncated, but you can click here to view the full file