Advertisement
RisingUp

MusicPlayBackService

Jul 20th, 2015
547
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 20.38 KB | None | 0 0
  1. public class MusicPlaybackService extends Service {
  2.  
  3.     /**
  4.      * DEBUG
  5.      */
  6.     private static final String LOG_TAG = "MusicPlaybackService";
  7.  
  8.     /**
  9.      * Notification ID
  10.      */
  11.     private static final int NOTIFICATION_ID = 12427;
  12.  
  13.     /**
  14.      * {@link android.media.MediaPlayer} instance
  15.      */
  16.     private MusicPlayer mMediaPlayer;
  17.  
  18.     /**
  19.      * {@link aj.jair.music.MusicPlaybackService.ServiceBinder}
  20.      * for binding {@link android.app.Activity} or {@link android.support.v4.app.FragmentActivity}
  21.      * with {@link aj.jair.music.MusicPlaybackService}
  22.      */
  23.     private final IBinder mBinder = new ServiceBinder();
  24.  
  25.     /**
  26.      * Song Data
  27.      */
  28.     public static int mSongNumber = -1;
  29.     public int mPreviousSongNumber = -1;
  30.     private Song mSong;
  31.  
  32.     /**
  33.      * List containing all the songs or Queue
  34.      */
  35.     private ArrayList<Song> mSongs;
  36.  
  37.     private AudioManager mAudioManager;
  38.  
  39.     /**
  40.      * Called to go toggle between pausing and playing the music
  41.      */
  42.     public static final String PLAY_PAUSE_ACTION = "aj.jair.music.toggle.playback";
  43.  
  44.     /**
  45.      * Called to pause the playback
  46.      */
  47.     public static final String PAUSE_ACTION = "aj.jair.music.pause";
  48.  
  49.     /**
  50.      * Called to go to pause the playback
  51.      */
  52.     public static final String PLAY_ACTION = "aj.jair.music.play";
  53.  
  54.     /**
  55.      * Called to go to reset the playback
  56.      */
  57.     public static final String STOP_ACTION = "aj.jair.music.stop";
  58.  
  59.     /**
  60.      * Called to go to the previous track
  61.      */
  62.     public static final String PREVIOUS_ACTION = "aj.jair.music.previous";
  63.  
  64.     /**
  65.      * Called to go to the next track
  66.      */
  67.     public static final String NEXT_ACTION = "aj.jair.music.next";
  68.  
  69.     /**
  70.      * Called to start/reset shuffle
  71.      */
  72.     public static final String SHUFFLE_ACTION = "aj.jair.music.shuffle";
  73.  
  74.     /**
  75.      * Called to start/reset shuffle
  76.      */
  77.     public static final String REPEAT_ACTION = "aj.jair.music.repeat";
  78.  
  79.     /**
  80.      * Indicates the meta data has changed in some way, like a track change
  81.      */
  82.     public static final String META_CHANGED = "aj.jair.music.metachanged";
  83.  
  84.     /**
  85.      * Indicates that the music has paused or resumed
  86.      */
  87.     public static final String PLAY_STATE_CHANGED = "aj.jair.music.playstatechanged";
  88.  
  89.     private MediaSessionCompat mMediaSessionCompat;
  90.  
  91.     /**
  92.      * For headset keystrokes
  93.      */
  94.     // For double press recognition
  95.     private static final int DOUBLE_CLICK = 400;
  96.     private long mLastClickTime = 0;
  97.  
  98.     public class ServiceBinder extends Binder {
  99.         public MusicPlaybackService getService() {
  100.             return MusicPlaybackService.this;
  101.         }
  102.     }
  103.  
  104.     @Override
  105.     public IBinder onBind(Intent intent) {
  106.         return mBinder;
  107.     }
  108.  
  109.     @Override
  110.     public int onStartCommand(Intent intent, int flags, int startId) {
  111.         //setupMediaSession();
  112.         // Initialize the wake lock
  113.         if (intent != null) {
  114.             final String action = intent.getAction();
  115.             /**
  116.              * Handles calls from Notification, Widget & UI
  117.              */
  118.             if (PLAY_PAUSE_ACTION.equals(action)) {
  119.                 /*if (isMediaPlayerActive()) {
  120.                     if (!isNotification()) startNotification();
  121.                     if (isPlaying()) pause();
  122.                     else resume();
  123.                 } else setupFromWidget(action);*/
  124.                 if (isMediaPlayerActive()) {
  125.                     if (isPlaying()) mTransportController.pause();
  126.                     else mTransportController.play();
  127.                 }
  128.                 else setupFromWidget(action);
  129.             } else if (NEXT_ACTION.equals(action)) {
  130.                 /*if (isMediaPlayerActive()) {
  131.                     if (!isNotification()) startNotification();
  132.                     playNext(mSongNumber);
  133.                 }
  134.                 else setupFromWidget(action);*/
  135.                 if (isMediaPlayerActive()) mTransportController.skipToNext();
  136.                 else setupFromWidget(action);
  137.             } else if (PREVIOUS_ACTION.equals(action)) {
  138.                 /*if (isMediaPlayerActive()) {
  139.                     if (!isNotification()) startNotification();
  140.                     playPrevious(mSongNumber);
  141.                 }
  142.                 else setupFromWidget(action);*/
  143.                 if (isMediaPlayerActive()) mTransportController.skipToPrevious();
  144.                 else setupFromWidget(action);
  145.             } else if (STOP_ACTION.equals(action)) {
  146.                 /*if (isMediaPlayerActive()) {
  147.                     Log.d(LOG_TAG, "Stopping Self");
  148.                     pause();
  149.                     commitMusicData();
  150.                     stopSelf();
  151.                     //releaseAudioManager();
  152.                 }
  153.                 stopNotification();*/
  154.                 //stopSelf();
  155.                 if (isMediaPlayerActive()) mTransportController.stop();
  156.             }
  157.         }
  158.         return START_STICKY;
  159.     }
  160.  
  161.     /**
  162.      * Initializes the remote control client
  163.      */
  164.     private void setupMediaSession() {
  165.         /* Activate Audio Manager */
  166.         mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
  167.         mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
  168.                 AudioManager.AUDIOFOCUS_GAIN);
  169.  
  170.         ComponentName mRemoteControlResponder = new ComponentName(getPackageName(),
  171.                 MediaButtonReceiver.class.getName());
  172.         //final Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
  173.         //mediaButtonIntent.setComponent(mRemoteControlResponder);
  174.         boolean useLockscreen = PrefUtils.getBoolean(getBaseContext(), "useLockscreen", true);
  175.         mMediaSessionCompat = new MediaSessionCompat(this, "JairSession", mRemoteControlResponder, null);
  176.         //mMediaSessionCompat.setFlags(useLockscreen ? MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS : MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);
  177.          mMediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
  178.         mMediaSessionCompat.setCallback(mMediaSessionCallback);
  179.         //mMediaSessionCompat.setRatingType(RatingCompat.RATING_HEART);
  180.         //mMediaSessionCompat.setSessionActivity(retrievePlaybackActions(5));
  181.          mMediaSessionCompat.setPlaybackState(new PlaybackStateCompat.Builder()
  182.                 .setState(PlaybackStateCompat.STATE_PAUSED, 0, 0)
  183.                 .setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_SKIP_TO_NEXT|PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)
  184.                 .build());
  185.         //updateMediaSessionMetaData();
  186.         mMediaSessionCompat.setActive(true);
  187.         //mTransportController = mMediaSessionCompat.getController().getTransportControls();
  188.  
  189.         //Log.d(LOG_TAG, "isActive = " + mMediaSessionCompat.isActive());
  190.         //Log.d(LOG_TAG, "Remote = " + mMediaSessionCompat.getRemoteControlClient());
  191.     }
  192.  
  193.     /**
  194.      * Play the next song
  195.      * @param songNumber current song number
  196.      */
  197.     public void playNext(int songNumber) {
  198.         if (isShuffle) {
  199.             Log.d(LOG_TAG, "Shuffling song");
  200.             mPreviousSongNumber = mSongNumber;
  201.             mSongNumber = mShuffler.nextInt(mSongs.size());
  202.             if (mSongNumber < mSongs.size()) {
  203.                 Log.d(LOG_TAG, "Playing shuffled");
  204.                 play(mSongNumber);
  205.             }
  206.         } else {
  207.             songNumber = songNumber + 1;
  208.             if (songNumber < mSongs.size()) {
  209.                 Log.d(LOG_TAG, "Playing next song");
  210.                 mSongNumber = songNumber;
  211.                 mSong = mSongs.get(mSongNumber);
  212.                 //checkAndStartNotification();
  213.                 play(getSongPath());
  214.             } else {
  215.                 Log.d(LOG_TAG, "Playing first song");
  216.                 mSongNumber = 0;
  217.                 mSong = mSongs.get(mSongNumber);
  218.                 //checkAndStartNotification();
  219.                 play(getSongPath());
  220.             }
  221.         }
  222.     }
  223.  
  224.     /**
  225.      * Play the previous song
  226.      *
  227.      * @param songNumber of current song
  228.      */
  229.     public void playPrevious(int songNumber) {
  230.         if (mPreviousSongNumber != -1 && isShuffle) {
  231.             if (mPreviousSongNumber < mSongs.size()) {
  232.                 Log.d(LOG_TAG, "Playing shuffled");
  233.                 play(mPreviousSongNumber);
  234.                 mPreviousSongNumber = -1;
  235.             }
  236.         } else {
  237.             songNumber = songNumber - 1;
  238.             if (songNumber >= 0 && songNumber < mSongs.size()) {
  239.                 Log.d(LOG_TAG, "Playing previous song");
  240.                 mSongNumber = songNumber;
  241.                 mSong = mSongs.get(mSongNumber);
  242.                 play(getSongPath());
  243.             } else {
  244.                 Log.d(LOG_TAG, "Playing last song");
  245.                 mSongNumber = mSongs.size() - 1;
  246.                 mSong = mSongs.get(mSongNumber);
  247.                 play(getSongPath());
  248.             }
  249.         }
  250.     }
  251.  
  252.     /**
  253.      * Initiating the basic elements
  254.      *
  255.      * @param mSongs     List of songs
  256.      * @param songNumber of current song
  257.      */
  258.     public void init(ArrayList<Song> mSongs, int songNumber) {
  259.         Log.d(LOG_TAG, "init()");
  260.         setupMediaSession();
  261.     }
  262.  
  263.     @Override
  264.     public void onDestroy() {
  265.         super.onDestroy();
  266.         Log.d(LOG_TAG, "Destroying music service");
  267.         releaseMediaSession();
  268.         releaseAudioManager();
  269.     }
  270.  
  271.     /**
  272.      * Releasing the {@link android.media.AudioManager}
  273.      */
  274.     public void releaseAudioManager() {
  275.         if (mAudioManager != null) {
  276.             Log.d(LOG_TAG, "Un-registering Audio focus listener");
  277.             mAudioManager.abandonAudioFocus(mAudioFocusListener);
  278.             //Log.d(LOG_TAG, "Un-registering Remote controller");
  279.             //mAudioManager.unregisterRemoteControlClient(mRemoteControlClient);
  280.         }
  281.     }
  282.  
  283.     private void releaseMediaSession() {
  284.         if (mMediaSessionCompat != null && mMediaSessionCompat.isActive()) {
  285.             Log.d(LOG_TAG, "Un-registering Media Session");
  286.             mMediaSessionCompat.release();
  287.         }
  288.     }
  289.  
  290.     /**
  291.      * Pause the media player playback
  292.      */
  293.     public void pause() {
  294.         Log.d(LOG_TAG, "Music playback paused");
  295.         mMediaPlayer.pause();    
  296.         // Update the lockscreen controls
  297.         mMediaSessionCompat.setPlaybackState(
  298.                 new PlaybackStateCompat.Builder()
  299.                         .setState(PlaybackStateCompat.STATE_PAUSED, getCurrentPosition(), 1.0f)
  300.          //               .setActions(
  301.           //                      PlaybackStateCompat.ACTION_SEEK_TO |
  302.          //                               PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
  303.           //                              PlaybackStateCompat.ACTION_SKIP_TO_NEXT |
  304.            //                             PlaybackStateCompat.ACTION_PLAY_PAUSE |
  305.            //                             PlaybackStateCompat.ACTION_PLAY |
  306.           //                              PlaybackStateCompat.ACTION_PAUSE |
  307.           //                              PlaybackStateCompat.ACTION_STOP
  308.           //              )
  309.                         .build());
  310.     }
  311.  
  312.     /**
  313.      * Start playing the song from song path
  314.      *
  315.      * @param path for song
  316.      */
  317.     public void play(String path) {
  318.         Log.d(LOG_TAG, "Starting song playback");
  319.         mMediaPlayer.reset();
  320.         mMediaPlayer.setDataSource(path);
  321.         mMediaPlayer.start();
  322.          mMediaSessionCompat.setActive(true);
  323.         updateMediaSessionMetaData();
  324.     }
  325.  
  326.  
  327.     /**
  328.      * Resuming the paused song
  329.      */
  330.     public void resume() {
  331.         Log.d(LOG_TAG, "Resuming song");
  332.         mMediaPlayer.start();
  333.     }
  334.  
  335.     /**
  336.      * Play the song located at song number
  337.      *
  338.      * @param songNumber of current song
  339.      */
  340.     public void play(int songNumber) {
  341.         if (songNumber < mSongs.size()) {
  342.             Log.d(LOG_TAG, "Playing song");
  343.             mSongNumber = songNumber;
  344.             mSong = mSongs.get(songNumber);
  345.             play(getSongPath());
  346.         }
  347.     }
  348.  
  349.     /**
  350.      * Playing songs after completion of previous song
  351.      * Intelligent algorithm which knows to shuffle
  352.      * or repeat or reset song or end the queue
  353.      */
  354.     private void onSongCompletion() {
  355.         Log.d(LOG_TAG, "Song playback completed");
  356.         // Marks Step 1
  357.         if (isShuffle) {
  358.             // Shuffle->ON : Play a random song
  359.             Log.d(LOG_TAG, "Shuffling song");
  360.             mSongNumber = mShuffler.nextInt(mSongs.size());
  361.             if (mSongNumber < mSongs.size()) {
  362.                 Log.d(LOG_TAG, "Playing shuffled");
  363.                 play(mSongNumber);
  364.             }
  365.         } else {
  366.             // Marks Step 2
  367.             if (isRepeatCurrent) {
  368.                 Log.d(LOG_TAG, "Repeating current song");
  369.                 seekTo(0);
  370.                 resume();
  371.             } else {
  372.                 if (mSongNumber < mSongs.size() - 1) // 2nd last song
  373.                     playNext(mSongNumber);
  374.                 else {
  375.                     // Last song
  376.                     if (isRepeatAll) {
  377.                         Log.d(LOG_TAG, "Repeating the queue");
  378.                         play(0);
  379.                     } else {
  380.                         Log.d(LOG_TAG, "End of list");
  381.                         pause();
  382.                     }
  383.                 }
  384.             }
  385.         }
  386.     }
  387.  
  388.    
  389.     /**
  390.      * @param which Which {@link android.app.PendingIntent} to return
  391.      * @return A {@link android.app.PendingIntent} ready to control playback
  392.      */
  393.     private PendingIntent retrievePlaybackActions(final int which) {
  394.         Intent action;
  395.         PendingIntent pendingIntent;
  396.         final ComponentName serviceName = new ComponentName(getBaseContext(), MusicPlaybackService.class);
  397.         switch (which) {
  398.             case 1:
  399.                 // Play and pause
  400.                 action = new Intent(MusicPlaybackService.PLAY_PAUSE_ACTION);
  401.                 action.setComponent(serviceName);
  402.                 pendingIntent = PendingIntent.getService(getBaseContext(), 1, action, 0);
  403.                 return pendingIntent;
  404.             case 2:
  405.                 // Skip tracks
  406.                 action = new Intent(MusicPlaybackService.NEXT_ACTION);
  407.                 action.setComponent(serviceName);
  408.                 pendingIntent = PendingIntent.getService(getBaseContext(), 2, action, 0);
  409.                 return pendingIntent;
  410.             case 3:
  411.                 // Previous tracks
  412.                 action = new Intent(MusicPlaybackService.PREVIOUS_ACTION);
  413.                 action.setComponent(serviceName);
  414.                 pendingIntent = PendingIntent.getService(getBaseContext(), 3, action, 0);
  415.                 return pendingIntent;
  416.             case 4:
  417.                 // Stop and collapse the notification
  418.                 action = new Intent(MusicPlaybackService.STOP_ACTION);
  419.                 action.setComponent(serviceName);
  420.                 pendingIntent = PendingIntent.getService(getBaseContext(), 4, action, 0);
  421.                 return pendingIntent;
  422.             case 5:
  423.                 Intent player = new Intent(getBaseContext(), Main.class);
  424.                 player.putExtra(NOW_PLAYING, true);
  425.                 pendingIntent = PendingIntent.getActivity(getBaseContext(), 0, player, PendingIntent.FLAG_UPDATE_CURRENT);
  426.                 return pendingIntent;
  427.             default:
  428.                 break;
  429.         }
  430.  
  431.         return null;
  432.     }
  433.  
  434.     /**
  435.      * Audio focus listener for Jair lockscreen key press listening
  436.      */
  437.     private final OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {
  438.  
  439.         @Override
  440.         public void onAudioFocusChange(final int focusChange) {
  441.             // TODO: Add fading to loss & gain
  442.             if (isMediaPlayerActive()) {
  443.                 Log.d(LOG_TAG, "F = " + focusChange);
  444.                 switch (focusChange) {
  445.                     case AudioManager.AUDIOFOCUS_LOSS:
  446.                         if (isPlaying())
  447.                             mPausedByTransientLossOfFocus = false;
  448.                         pause();
  449.                         break;
  450.                     case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
  451.                         if (isPlaying()) {
  452.                             mPausedByTransientLossOfFocus = true;
  453.                             pause();
  454.                         }
  455.                         break;
  456.                     case AudioManager.AUDIOFOCUS_GAIN:
  457.                         if (!isPlaying() && mPausedByTransientLossOfFocus) {
  458.                             mPausedByTransientLossOfFocus = false;
  459.                             //mCurrentVolume = 0f;
  460.                             //mMediaPlayer.setVolume(0f);
  461.                             resume();
  462.                         }
  463.                         break;
  464.                /* case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
  465.                     // Lost focus for a short time, but it's ok to keep playing
  466.                     // at an attenuated level
  467.                     if (mMediaPlayer.isPlaying()) mMediaPlayer.setVolume(0.1f);
  468.                     break;*/
  469.                     default:
  470.                 }
  471.             }
  472.         }
  473.     };
  474.  
  475.     /**
  476.      * Updates the lockscreen controls, if enabled.
  477.      */
  478.     private void updateMediaSessionMetaData() {
  479.             //boolean useLockscreen = PrefUtils.getBoolean(getBaseContext(), "useLockscreen", true);
  480.             //if (useLockscreen/* && mSong != null*/) {
  481.                 mMediaSessionCompat.setPlaybackState(new PlaybackStateCompat.Builder()
  482.                         .setActions(
  483.                                         PlaybackStateCompat.ACTION_PLAY_PAUSE |
  484.                                         PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
  485.                                         PlaybackStateCompat.ACTION_SKIP_TO_NEXT |
  486.                                          
  487.                                         )
  488.                         .setState(
  489.                                 isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
  490.                                 getCurrentPosition(),
  491.                                 1.0f)
  492.                         .build());
  493.                 mMediaSessionCompat.setMetadata(new MediaMetadataCompat.Builder()
  494.                         .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, getArtistName())
  495.                         .putString(MediaMetadataCompat.METADATA_KEY_ALBUM, getAlbumName())
  496.                         .putString(MediaMetadataCompat.METADATA_KEY_TITLE, getTrackName())
  497.                         .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, getDuration())
  498.                         .putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, mSongNumber)
  499.                         .putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, mSongs.size())
  500.                         .putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, MusicUtils.getArtwork(this, getAlbumID(), true))
  501.                         .build());
  502.                 mMediaSessionCompat.setActive(true);
  503.             //}
  504.     }  
  505.  
  506.    
  507.  
  508.     private final MediaSessionCompat.Callback mMediaSessionCallback = new MediaSessionCompat.Callback() {
  509.  
  510.         @Override
  511.         public void onPlay() {
  512.             super.onPlay();
  513.             //Log.d(LOG_TAG, "Play()");
  514.             resume();
  515.         }
  516.  
  517.         @Override
  518.         public void onPause() {
  519.             super.onPause();
  520.             //Log.d(LOG_TAG, "onPause()");
  521.             pause();
  522.         }
  523.  
  524.         @Override
  525.         public void onSkipToNext() {
  526.             super.onSkipToNext();
  527.             //Log.d(LOG_TAG, "onSkipToNext()");
  528.             playNext(mSongNumber);
  529.         }
  530.  
  531.         @Override
  532.         public void onSkipToPrevious() {
  533.             super.onSkipToPrevious();
  534.             //Log.d(LOG_TAG, "onSkipToPrevious()");
  535.             playPrevious(mSongNumber);
  536.         }
  537.  
  538.         @Override
  539.         public void onSeekTo(long pos) {
  540.             super.onSeekTo(pos);
  541.             //Log.d(LOG_TAG, "onSeekTo()");
  542.             seekTo(pos);
  543.         }
  544.  
  545.         @Override
  546.         public void onStop() {
  547.             super.onStop();
  548.             //Log.d(LOG_TAG, "onStop()");
  549.             pause();
  550.             commitMusicData();
  551.             updatePlayingUI(STOP_ACTION);
  552.             stopSelf();
  553.         }
  554.     };
  555.  
  556. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement