public void onDestroy() {
   executorService.shutdown();
   serializeDownloadQueue();
   downloadService.clear(false);
   downloadService.unregisterReceiver(ejectEventReceiver);
   downloadService.unregisterReceiver(headsetEventReceiver);
   downloadService.unregisterReceiver(intentReceiver);
 }
  private void handleKeyEvent(KeyEvent event) {
    if (event.getAction() != KeyEvent.ACTION_DOWN || event.getRepeatCount() > 0) {
      return;
    }

    switch (event.getKeyCode()) {
      case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
      case KeyEvent.KEYCODE_HEADSETHOOK:
        downloadService.togglePlayPause();
        break;
      case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
        downloadService.previous();
        break;
      case KeyEvent.KEYCODE_MEDIA_NEXT:
        if (downloadService.getCurrentPlayingIndex() < downloadService.size() - 1) {
          downloadService.next();
        }
        break;
      case KeyEvent.KEYCODE_MEDIA_STOP:
        downloadService.reset();
        break;
      case KeyEvent.KEYCODE_MEDIA_PLAY:
        downloadService.play();
        break;
      case KeyEvent.KEYCODE_MEDIA_PAUSE:
        downloadService.pause();
        break;
      default:
        break;
    }
  }
  public void serializeDownloadQueue() {
    State state = new State();
    for (DownloadFile downloadFile : downloadService.getDownloads()) {
      state.songs.add(downloadFile.getSong());
    }
    state.currentPlayingIndex = downloadService.getCurrentPlayingIndex();
    state.currentPlayingPosition = downloadService.getPlayerPosition();

    Log.i(
        TAG,
        "Serialized currentPlayingIndex: "
            + state.currentPlayingIndex
            + ", currentPlayingPosition: "
            + state.currentPlayingPosition);
    FileUtil.serialize(downloadService, state, FILENAME_DOWNLOADS_SER);
  }
  private void deserializeDownloadQueue() {
    State state = FileUtil.deserialize(downloadService, FILENAME_DOWNLOADS_SER);
    if (state == null) {
      return;
    }
    Log.i(
        TAG,
        "Deserialized currentPlayingIndex: "
            + state.currentPlayingIndex
            + ", currentPlayingPosition: "
            + state.currentPlayingPosition);
    downloadService.restore(state.songs, state.currentPlayingIndex, state.currentPlayingPosition);

    // Work-around: Serialize again, as the restore() method creates a serialization without current
    // playing info.
    serializeDownloadQueue();
  }
 @Override
 public void onReceive(Context context, Intent intent) {
   String action = intent.getAction();
   Log.i(TAG, "intentReceiver.onReceive: " + action);
   if (DownloadServiceImpl.CMD_PLAY.equals(action)) {
     downloadService.play();
   } else if (DownloadServiceImpl.CMD_NEXT.equals(action)) {
     downloadService.next();
   } else if (DownloadServiceImpl.CMD_PREVIOUS.equals(action)) {
     downloadService.previous();
   } else if (DownloadServiceImpl.CMD_TOGGLEPAUSE.equals(action)) {
     downloadService.togglePlayPause();
   } else if (DownloadServiceImpl.CMD_PAUSE.equals(action)) {
     downloadService.pause();
   } else if (DownloadServiceImpl.CMD_STOP.equals(action)) {
     downloadService.pause();
     downloadService.seekTo(0);
   }
 }
  public void onCreate() {
    Runnable downloadChecker =
        new Runnable() {
          @Override
          public void run() {
            try {
              downloadService.checkDownloads();
            } catch (Throwable x) {
              Log.e(TAG, "checkDownloads() failed.", x);
            }
          }
        };

    executorService = Executors.newScheduledThreadPool(2);
    executorService.scheduleWithFixedDelay(downloadChecker, 5, 5, TimeUnit.SECONDS);

    // Pause when headset is unplugged.
    headsetEventReceiver =
        new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
            Log.i(TAG, "Headset event for: " + intent.getExtras().get("name"));
            if (intent.getExtras().getInt("state") == 0) {
              downloadService.pause();
            }
          }
        };
    downloadService.registerReceiver(
        headsetEventReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));

    // Stop when SD card is ejected.
    ejectEventReceiver =
        new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
            externalStorageAvailable = Intent.ACTION_MEDIA_MOUNTED.equals(intent.getAction());
            if (!externalStorageAvailable) {
              Log.i(TAG, "External media is ejecting. Stopping playback.");
              downloadService.reset();
            } else {
              Log.i(TAG, "External media is available.");
            }
          }
        };
    IntentFilter ejectFilter = new IntentFilter(Intent.ACTION_MEDIA_EJECT);
    ejectFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
    ejectFilter.addDataScheme("file");
    downloadService.registerReceiver(ejectEventReceiver, ejectFilter);

    // React to media buttons.
    Util.registerMediaButtonEventReceiver(downloadService);

    // Register the handler for outside intents.
    IntentFilter commandFilter = new IntentFilter();
    commandFilter.addAction(DownloadServiceImpl.CMD_PLAY);
    commandFilter.addAction(DownloadServiceImpl.CMD_TOGGLEPAUSE);
    commandFilter.addAction(DownloadServiceImpl.CMD_PAUSE);
    commandFilter.addAction(DownloadServiceImpl.CMD_STOP);
    commandFilter.addAction(DownloadServiceImpl.CMD_PREVIOUS);
    commandFilter.addAction(DownloadServiceImpl.CMD_NEXT);
    downloadService.registerReceiver(intentReceiver, commandFilter);

    deserializeDownloadQueue();

    new CacheCleaner(downloadService, downloadService).clean();
  }