Android Open Source - muckebox-android Player Service






From Project

Back to project page muckebox-android.

License

The source code is released under:

Apache License

If you think the Android project muckebox-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*   
 * Copyright 2013 Karsten Patzwaldt/*from   w ww.  j a  v  a  2s  .  c o  m*/
 *
 * 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 org.muckebox.android.audio;

import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArraySet;

import org.muckebox.android.R;
import org.muckebox.android.db.MuckeboxContract.PlaylistEntry;
import org.muckebox.android.db.MuckeboxProvider;
import org.muckebox.android.db.PlaylistHelper;
import org.muckebox.android.net.DownloadService;
import org.muckebox.android.ui.activity.MuckeboxActivity;
import org.muckebox.android.utils.Preferences;
import org.muckebox.android.utils.RemoteControlReceiver;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.media.MediaMetadataRetriever;
import android.media.RemoteControlClient;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Parcelable;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;

public class PlayerService extends Service
    implements PlayerWrapper.Listener {
  private final static String LOG_TAG = "PlayerService";
  
  private final static int
      NOTIFICATION_ID = 23,
      PREFETCH_INTERVAL = 15;
  
  public final static String EXTRA_PLAYLIST_ITEM_ID = "playlist_item_id";
  
  public final static String
      ACTION_LOAD = "load",
      ACTION_PREVIOUS = "previous",
      ACTION_PAUSE = "pause",
      ACTION_RESUME = "resume",
      ACTION_NEXT = "next";
  
  private enum State {
    STOPPED, 
    PAUSED,
    BUFFERING,
    PLAYING
  };
  
  private final IBinder mBinder = new PlayerBinder();
  
  private State mState = State.STOPPED;
  private Set<PlayerListener> mListeners =
      new CopyOnWriteArraySet<PlayerListener>();

  private Handler mMainHandler;
  
  private HandlerThread mHelperThread;
  private Handler mHelperHandler;

    private ComponentName mRemoteEventReceiver = null;
    private RemoteControlClient mRemoteControlClient = null;
    private AudioManager mAudioManager = null;
    
    private boolean mReceiverRegistered = false;
    private boolean mHasAudioFocus = false;
    private boolean mResumeAfterFocusGain = false;
    
    private DownloadService mDownloadService;
    
    private PlayerWrapper mCurrentPlayer = null;
    private Timer mTimer = null;
    
    NotificationManager mNotificationManager = null;

    private OnAudioFocusChangeListener mAudioFocusChangeListener = new OnAudioFocusChangeListener() {
        @Override
        public void onAudioFocusChange(int focusChange) {
            Log.d(LOG_TAG, "onAudioFocusChange");
            
            if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
                onFocusLoss();
                
                if (mState == State.PLAYING || mState == State.BUFFERING) {
                    mResumeAfterFocusGain = true;
                    pause();
                }
            } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
                onFocusGained();
                
                if (mResumeAfterFocusGain) {
                    mResumeAfterFocusGain = false;
                    resume();
                }
            } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
                Log.d(LOG_TAG, "audio focus lost, stopping");
                onFocusLoss();
                stop();
            }
        }
    };
    
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service)
        {
            DownloadService.DownloadBinder binder =
                    (DownloadService.DownloadBinder) service;
            mDownloadService = binder.getService();

            Log.d(LOG_TAG, "Bound to download service");
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {
            mDownloadService = null;
            
            Log.d(LOG_TAG, "Unbound from download service");
        }
    };
    
    private class PrefetchTask extends TimerTask {
        public void run() {
            if (mCurrentPlayer != null) {
                mCurrentPlayer.prefetchNextTrack();
            }
        }
    }
    
    private void onFocusGained() {
        mHasAudioFocus = true;
        
        if (! mReceiverRegistered) {
            Log.d(LOG_TAG, "audio focus gained, registering remote");
            
            mAudioManager.registerMediaButtonEventReceiver(mRemoteEventReceiver);
            mAudioManager.registerRemoteControlClient(mRemoteControlClient);
            
            mReceiverRegistered = true;
        }
    }
    
    private void onFocusLoss() {
        Log.d(LOG_TAG, "audio focus lost transient, pausing");
        
        mHasAudioFocus = false;
        
        if (mReceiverRegistered) {
            mAudioManager.unregisterRemoteControlClient(mRemoteControlClient);
            mAudioManager.unregisterMediaButtonEventReceiver(mRemoteEventReceiver);
            
            mReceiverRegistered = false;
        }
    }
  
  @Override
  public void onCreate() {
    Log.d(LOG_TAG, "Service created.");
    
    bindService(new Intent(this, DownloadService.class),
            mConnection, Context.BIND_AUTO_CREATE);
        
        mMainHandler = new Handler(getMainLooper());
        
        mHelperThread = new HandlerThread("PlayerServiceHelper");
        mHelperThread.start();
        
        mHelperHandler = new Handler(mHelperThread.getLooper());
        
        String packageName = getPackageName();
        String className = RemoteControlReceiver.class.getName();
        
        Log.w(LOG_TAG, "package '" + packageName + "', class '" + className + "'");
        
        mRemoteEventReceiver = new ComponentName(packageName, className);
        mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
  }
  
  @Override
  public void onDestroy() {
      if (isPlaying()) {
          Log.e(LOG_TAG, "Player service still playing when destroyed");
          stop();
      }
      
      mHelperThread.quit();

      getBaseContext().unbindService(mConnection);

    Log.d(LOG_TAG, "Service destroyed.");
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      if (intent != null)
      {
          int playlistItem = intent.getIntExtra(EXTRA_PLAYLIST_ITEM_ID, 0);
          
          Log.d(LOG_TAG, "Got play intent for item " + playlistItem);
          
          playTrack(playlistItem);
      }
        
    return Service.START_STICKY;
  }
  
  public static void playPlaylistItem(Context context, int playlistItemId) {
        Intent intent = new Intent(context, PlayerService.class);
        
        intent.putExtra(PlayerService.EXTRA_PLAYLIST_ITEM_ID, playlistItemId);
        
        context.startService(intent);
  }
  
  private boolean getAudioFocus() {
      if (mHasAudioFocus)
          return mHasAudioFocus;
      
      Log.d(LOG_TAG, "Requesting audio focus");
      
      mHasAudioFocus = (mAudioManager.requestAudioFocus(mAudioFocusChangeListener,
            AudioManager.STREAM_MUSIC,
            AudioManager.AUDIOFOCUS_GAIN) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
      
      if (mHasAudioFocus) {
          onFocusGained();
      } else {
            Toast.makeText(this, getText(R.string.error_audiofocus),
                Toast.LENGTH_LONG).show();
      }
      
      return mHasAudioFocus;
  }
  
  private void dropAudioFocus() {
      if (mHasAudioFocus) {
          Log.d(LOG_TAG, "Abandoning audio focus");

          mAudioManager.abandonAudioFocus(mAudioFocusChangeListener);
          mHasAudioFocus = false;
            
            onFocusLoss();
      }
  }
  
  protected void playTrack(final int playlistEntryId) {
      if (mState != State.STOPPED)
          stop();
      
      ensureRemoteControl();
         
      if (getAudioFocus()) {
            mState = State.BUFFERING;
            
            for (PlayerListener l: mListeners) {
                if (l != null)
                    l.onStartBuffering();
            }
            
            mHelperHandler.post(new Runnable() {
                public void run() {
                    int trackId = PlaylistHelper.getTrackId(getApplicationContext(),
                        Uri.withAppendedPath(MuckeboxProvider.URI_PLAYLIST_ENTRY,
                            Integer.toString(playlistEntryId)));
    
                    mCurrentPlayer = new PlayerWrapper(getApplicationContext(),
                        mDownloadService, playlistEntryId, trackId);
                    mCurrentPlayer.setListener(PlayerService.this);
                    mCurrentPlayer.play();          
                }
            });
      }
  }

  private void ensureRemoteControl() {
      if (mRemoteControlClient == null) {
            Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
            mediaButtonIntent.setComponent(mRemoteEventReceiver);
            
            PendingIntent remotePendingIntent = PendingIntent.getBroadcast(
                getApplicationContext(), 0, mediaButtonIntent, 0);
            
            mRemoteControlClient = new RemoteControlClient(remotePendingIntent);
            mRemoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
      }
  }
  
  private void updateRemoteControl(PlayerWrapper.TrackInfo trackInfo)
  {
      if (mRemoteControlClient == null)
      {
          Log.e(LOG_TAG, "Remote control missing!");
          return;
      }
      
      mRemoteControlClient.setTransportControlFlags(
          (trackInfo.hasPrevious ? RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS : 0) +
          (trackInfo.hasNext ? RemoteControlClient.FLAG_KEY_MEDIA_NEXT : 0) +
          RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE +
          RemoteControlClient.FLAG_KEY_MEDIA_STOP);
          
      mRemoteControlClient.editMetadata(true).
          putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, trackInfo.artist).
          putString(MediaMetadataRetriever.METADATA_KEY_TITLE, trackInfo.title).
          putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, trackInfo.album).
          putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, trackInfo.duration * 1000).
          putLong(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER, trackInfo.trackNumber).
          apply();
  }
  
  private void setAsCurrent(final Uri playlistEntryUri) {
      mHelperHandler.post(new Runnable() {
          public void run() {
              Uri uri = (playlistEntryUri == null) ?
                  Uri.withAppendedPath(MuckeboxProvider.URI_PLAYLIST,
                      Integer.toString(Preferences.getCurrentPlaylistId())) :
                  playlistEntryUri;
              
              ContentValues values = new ContentValues();
              
              values.put(PlaylistEntry.SHORT_IS_CURRENT, (playlistEntryUri == null ? 0 : 1));
              
              getContentResolver().update(uri, values, null, null);
          }
      });
  }
  
  private void clearCurrent() {
      setAsCurrent(null);
  }
  
  private void updateNotification() {
      PlayerWrapper.TrackInfo trackInfo = null;
      
      if (mCurrentPlayer != null)
          trackInfo = mCurrentPlayer.getTrackInfo();
      
      if (trackInfo != null)
          mNotificationManager.notify(NOTIFICATION_ID, getNotification(trackInfo));
      else
          mNotificationManager.cancel(NOTIFICATION_ID);
  }
  
  private void startAndNotify(PlayerWrapper.TrackInfo trackInfo) {
        startForeground(NOTIFICATION_ID, getNotification(trackInfo));
  }
  
  private Notification getNotification(PlayerWrapper.TrackInfo trackInfo) {
      Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

      Notification.Builder builder =
          new Notification.Builder(this).
          setLargeIcon(bm).
          setOngoing(true).
          setContentTitle(trackInfo.shortTitle).
          setContentText(trackInfo.artist).
          setTicker(trackInfo.title);
      
      if (trackInfo.hasPrevious) {
          builder.addAction(R.drawable.av_previous_dark,
              getResources().getText(R.string.previous),
              getPendingIntent(KeyEvent.KEYCODE_MEDIA_PREVIOUS));
      }
      
      if (mState == State.PLAYING) {
          builder.setSmallIcon(R.drawable.av_play_dark);
          builder.addAction(R.drawable.av_pause_dark,
              getResources().getText(R.string.pause),
              getPendingIntent(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
      } else {
          builder.setSmallIcon(R.drawable.av_pause_dark);
          builder.addAction(R.drawable.av_play_dark,
              getResources().getText(R.string.resume),
              getPendingIntent(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
      }
          
      if (trackInfo.hasNext) {
          builder.addAction(R.drawable.av_next_dark,
              getResources().getText(R.string.next),
              getPendingIntent(KeyEvent.KEYCODE_MEDIA_NEXT));
      }
      
      Intent contentIntent = new Intent(this, MuckeboxActivity.class);
      contentIntent.setAction(MuckeboxActivity.ACTION_PLAYLIST);
      contentIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
      
      builder.setContentIntent(PendingIntent.getActivity(
          getApplicationContext(), 42, contentIntent, 0));
      
      return builder.build();
  }
  
  private PendingIntent getPendingIntent(int keyCode) {
        Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
        
        mediaButtonIntent.setComponent(mRemoteEventReceiver);
        mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT,
            (Parcelable) new KeyEvent(KeyEvent.ACTION_UP, keyCode));
        
        return PendingIntent.getBroadcast(
            getApplicationContext(), 23 + keyCode, mediaButtonIntent, 0);
  }

  public void stop() {
      stop(false);
  }
  
  public void stop(boolean keepFocus) {
      mState = State.STOPPED;

      if (mCurrentPlayer != null)
          mCurrentPlayer.destroy();
      
      mCurrentPlayer = null;

      clearCurrent();

      for (PlayerListener l: mListeners)
          if (l != null)
              l.onStopPlaying();

      if (! keepFocus)
          dropAudioFocus();
      
        stopForeground(true);
        stopPrefetchTimer();
        
      Log.d(LOG_TAG, "Stopped playing");
   }
  
  @Override
  public IBinder onBind(Intent intent) {
    return mBinder;
  }
  
  public class PlayerBinder extends Binder {
    public PlayerService getService() {
      return PlayerService.this;
    }
  }
  
  // public interface
  
  public void registerListener(PlayerListener listener)
  {
    mListeners.add(listener);
    
    listener.onConnected();
  }
  
  public void removeListener(PlayerListener listener) {
      mListeners.remove(listener);
  }

  public void resume() {
    if (mState == State.PAUSED)
    {
      mState = State.PLAYING;
      
      mCurrentPlayer.resume();

      for (PlayerListener l: mListeners)
        if (l != null) l.onPlayResumed();
      
      onResumed();
    }
  }
  
  public void pause() {
    if (mState == State.PLAYING)
    {
      mState = State.PAUSED;
      
      mCurrentPlayer.pause();
      
      for (PlayerListener l: mListeners)
        if (l != null) l.onPlayPaused();
      
      onPaused();
    }
  }
  
  private void onPaused() {
        if (mRemoteControlClient != null)
            mRemoteControlClient.setPlaybackState(
                RemoteControlClient.PLAYSTATE_PAUSED);
        
        updateNotification();
        stopPrefetchTimer();
        
        Log.d(LOG_TAG, "Paused");
  }
  
  private void onResumed() {
        if (mRemoteControlClient != null)
            mRemoteControlClient.setPlaybackState(
                RemoteControlClient.PLAYSTATE_PLAYING);
        
        updateNotification();
        startPrefetchTimer();
        
        Log.d(LOG_TAG, "Resuming");
  }
  
  public void previous() {
      prevNext(false);
  }
  
  public void next() {
      prevNext(true);
  }
  
  public void prevNext(final boolean isNext) {
      if (mState != State.STOPPED) {
          mHelperHandler.post(new Runnable() {
              public void run() {
                  Cursor c = getContentResolver().query(
                      Uri.withAppendedPath(
                          (isNext ? MuckeboxProvider.URI_PLAYLIST_AFTER : MuckeboxProvider.URI_PLAYLIST_BEFORE),
                          Long.toString(mCurrentPlayer.getPlaylistEntryId())),
                          null, null, null, null);

                  try {
                      if (isNext ? c.moveToFirst() : c.moveToLast()) {
                          final int nextPlaylistEntryId = c.getInt(c.getColumnIndex(PlaylistEntry.SHORT_ID));
                          
                          mMainHandler.post(new Runnable() {
                              public void run() {
                                  stop(true);
                                  playTrack(nextPlaylistEntryId);
                              }
                          });
                      }
                  } finally {
                      c.close();
                  }

              }
          });
      }

      Log.d(LOG_TAG, "Skip to " + (isNext ? "next" : "previous") + " track");
  }
  
  public void seek(int targetSeconds) {
      if (mState == State.PLAYING || mState == State.PAUSED) {
          mCurrentPlayer.seek(targetSeconds);
          startPrefetchTimer();
      }
  }

  public boolean isPlaying() {
    return mState == State.PLAYING;
  }
  
  public boolean isStopped() {
      return mState == State.STOPPED;
  }
  
  public boolean isPaused() {
      return mState == State.PAUSED;
  }
  
  public boolean isBuffering() {
      return mState == State.BUFFERING;
  }
  
  public Integer getCurrentTrackLength() {
      if (mCurrentPlayer != null)
          return mCurrentPlayer.getTrackLength();
      
      return 0;
  }
  
  public Integer getCurrentPlayPosition() {
      if (mState == State.PLAYING || mState == State.PAUSED)
          return mCurrentPlayer.getPlayPosition();
      
      return 0;
  }
  
  public Integer getCurrentTimeLeft() {
      Integer length = getCurrentTrackLength();
      Integer position = getCurrentPlayPosition();
      
      if (length == null || position == null)
          return 0;
      
      int ret = length - position;
      
      if (ret < 0) {
          Log.e(LOG_TAG, "Current time remaining < 0");
          ret = 0;
      }
      
      return ret;
  }
  
  public String getCurrentTrackTitle() {
      if (mCurrentPlayer != null)
          return mCurrentPlayer.getTrackTitle();
      
      return null;
  }
  
  public PlayerWrapper.TrackInfo getCurrentTrackInfo() {
      if (mCurrentPlayer != null)
          return mCurrentPlayer.getTrackInfo();
      
      return null;
  }
  
  private void startPrefetchTimer() {
      if (mCurrentPlayer != null) {
          Integer length = mCurrentPlayer.getTrackLength();
          Integer position = mCurrentPlayer.getPlayPosition();
          
          if (length != null && position != null) {
              long delay = length - position - PREFETCH_INTERVAL;
              
              delay *= 1000;
              
              if (delay > 0) {
                  stopPrefetchTimer();
                  
                    mTimer = new Timer();
                    mTimer.schedule(new PrefetchTask(), delay);
              }
          }
      }
  }
  
  private void stopPrefetchTimer() {
      if (mTimer != null) {
          mTimer.cancel();
          mTimer = null;
      }
  }

  @Override
  public void onStartPlaying(PlayerWrapper player) {
        for (PlayerListener l: mListeners)
            l.onStartPlaying();
        
        if (mRemoteControlClient != null)
            mRemoteControlClient.setPlaybackState(
                RemoteControlClient.PLAYSTATE_PLAYING);
        
        mState = State.PLAYING;
        
        updateNotification();
        startPrefetchTimer();
    }

    @Override
    public void onCompletion(PlayerWrapper player) {
        if (player.getTrackInfo().hasNext)
            next();
        else
            stop();
    }
    
    @Override
    public void onBufferingStarted(PlayerWrapper player) {
        for (PlayerListener l: mListeners) {
            if (l != null)
                l.onStartBuffering();
        }
        
        onPaused();
    }
    
    @Override
    public void onBufferingFinished(PlayerWrapper player) {
        for (PlayerListener l: mListeners) {
            if (l != null)
                l.onPlayResumed();
        }
        
        onResumed();
    }

    @Override
    public void onTrackInfo(PlayerWrapper wrapper, PlayerWrapper.TrackInfo trackInfo) {
        updateRemoteControl(trackInfo);
        
        for (PlayerListener l: mListeners)
        {
            if (l != null)
            {
                l.onNewTrack(trackInfo);
            }
        }
        
        PlayerService.this.startAndNotify(trackInfo);
        
        setAsCurrent(mCurrentPlayer.getPlaylistEntryUri());
    }
    
    @Override
    public void onStop(PlayerWrapper player) {
        stop();
    }
}




Java Source Code List

org.muckebox.android.Muckebox.java
org.muckebox.android.audio.PlayerListener.java
org.muckebox.android.audio.PlayerService.java
org.muckebox.android.audio.PlayerWrapper.java
org.muckebox.android.db.DownloadEntryCursor.java
org.muckebox.android.db.MuckeboxContract.java
org.muckebox.android.db.MuckeboxDbHelper.java
org.muckebox.android.db.MuckeboxProvider.java
org.muckebox.android.db.PlaylistHelper.java
org.muckebox.android.net.ApiHelper.java
org.muckebox.android.net.DownloadCatchupRunnable.java
org.muckebox.android.net.DownloadListener.java
org.muckebox.android.net.DownloadRunnable.java
org.muckebox.android.net.DownloadServer.java
org.muckebox.android.net.DownloadService.java
org.muckebox.android.net.MuckeboxHttpClient.java
org.muckebox.android.net.PreannounceTask.java
org.muckebox.android.net.RefreshAlbumsTask.java
org.muckebox.android.net.RefreshArtistsAlbumsTask.java
org.muckebox.android.net.RefreshArtistsTask.java
org.muckebox.android.net.RefreshHelper.java
org.muckebox.android.net.RefreshTask.java
org.muckebox.android.net.RefreshTracksTask.java
org.muckebox.android.ui.activity.MuckeboxActivity.java
org.muckebox.android.ui.activity.WizardActivity.java
org.muckebox.android.ui.fragment.AlbumListFragment.java
org.muckebox.android.ui.fragment.ArtistListFragment.java
org.muckebox.android.ui.fragment.DownloadListFragment.java
org.muckebox.android.ui.fragment.DrawerFragment.java
org.muckebox.android.ui.fragment.PlayerFragment.java
org.muckebox.android.ui.fragment.SettingsFragment.java
org.muckebox.android.ui.fragment.TrackListFragment.java
org.muckebox.android.ui.utils.ExpandableCursorAdapter.java
org.muckebox.android.ui.utils.HeightEvaluator.java
org.muckebox.android.ui.utils.ImageButtonHelper.java
org.muckebox.android.ui.utils.NavigationListener.java
org.muckebox.android.ui.utils.ScrollYAnimator.java
org.muckebox.android.ui.utils.TimeFormatter.java
org.muckebox.android.ui.widgets.ImageViewRotater.java
org.muckebox.android.ui.widgets.LiveSearchView.java
org.muckebox.android.ui.widgets.RefreshableListFragment.java
org.muckebox.android.ui.widgets.SearchableListFragment.java
org.muckebox.android.utils.BufferUtils.java
org.muckebox.android.utils.CacheCleaner.java
org.muckebox.android.utils.Preferences.java
org.muckebox.android.utils.RemoteControlReceiver.java