org.klnusbaum.udj.network.PlaylistSyncService.java Source code

Java tutorial

Introduction

Here is the source code for org.klnusbaum.udj.network.PlaylistSyncService.java

Source

/**
 * Copyright 2011 Kurtis L. Nusbaum
 * 
 * This file is part of UDJ.
 * 
 * UDJ is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 * 
 * UDJ is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with UDJ.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.klnusbaum.udj.network;

import android.content.Context;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.OperationCanceledException;
import android.accounts.AuthenticatorException;
import android.os.RemoteException;
import android.content.OperationApplicationException;
import android.util.Log;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Intent;
import android.app.Notification;
import android.app.NotificationManager;
import android.graphics.drawable.BitmapDrawable;

import java.io.IOException;

import org.json.JSONObject;
import org.json.JSONException;

import org.apache.http.auth.AuthenticationException;
import org.apache.http.ParseException;

import org.klnusbaum.udj.Constants;
import org.klnusbaum.udj.R;
import org.klnusbaum.udj.exceptions.NoLongerInPlayerException;
import org.klnusbaum.udj.exceptions.PlayerInactiveException;
import org.klnusbaum.udj.exceptions.KickedException;
import org.klnusbaum.udj.Utils;

/**
 * Adapter used to sync up with the UDJ server.
 */
public class PlaylistSyncService extends IntentService {

    private static final int SONG_ADD_EXCEPTION_ID = 1;
    private static final int SONG_REMOVE_EXCEPTION_ID = 2;
    private static final int SONG_SET_EXCEPTION_ID = 3;
    private static final int PLAYBACK_STATE_SET_EXCEPTION_ID = 4;
    private static final int PLAYER_VOLUME_SET_EXCEPTION_ID = 5;

    private static final String TAG = "PlaylistSyncService";

    public PlaylistSyncService() {
        super("PlaylistSyncService");
    }

    @Override
    public void onHandleIntent(Intent intent) {
        final Account account = (Account) intent.getParcelableExtra(Constants.ACCOUNT_EXTRA);
        String playerId = AccountManager.get(this).getUserData(account, Constants.LAST_PLAYER_ID_DATA);
        //TODO handle error if playerId is bad
        if (intent.getAction().equals(Intent.ACTION_INSERT)) {
            if (intent.getData().equals(Constants.PLAYLIST_URI)) {
                String libId = intent.getStringExtra(Constants.LIB_ID_EXTRA);
                addSongToPlaylist(account, playerId, libId, true, intent);
            } else if (intent.getData().equals(Constants.VOTES_URI)) {
                //TODO handle if lib id is bad
                String libId = intent.getStringExtra(Constants.LIB_ID_EXTRA);
                //TODO handle if votetype is bad
                int voteWeight = intent.getIntExtra(Constants.VOTE_WEIGHT_EXTRA, 0);
                voteOnSong(account, playerId, libId, voteWeight, true);
            }
            //updateActivePlaylist(account, playerId, true); 
        }
        /*else if(intent.getAction().equals(Intent.ACTION_VIEW)){
          updateActivePlaylist(account, playerId, true); 
        }*/
        else if (intent.getAction().equals(Intent.ACTION_DELETE)) {
            Log.d(TAG, "Handling delete");
            if (intent.getData().equals(Constants.PLAYLIST_URI)) {
                Log.d(TAG, "In plalist syncservice, about to insert song into remove requests");
                //TODO handle if Playlist id is bad.
                String libId = intent.getStringExtra(Constants.LIB_ID_EXTRA);
                removeSongFromPlaylist(account, playerId, libId, true, intent);
            }
            //updateActivePlaylist(account, playerId, true);
        } else if (intent.getAction().equals(Constants.ACTION_SET_CURRENT_SONG)) {
            Log.d(TAG, "Handling setting current song");
            String libId = intent.getStringExtra(Constants.LIB_ID_EXTRA);
            setCurrentSong(account, playerId, libId, true, intent);
            //updateActivePlaylist(account, playerId, true);
        } else if (intent.getAction().equals(Constants.ACTION_SET_PLAYBACK)) {
            setPlaybackState(intent, account, playerId, true);
            //updateActivePlaylist(account, playerId, true);
        } else if (intent.getAction().equals(Constants.ACTION_SET_VOLUME)) {
            setPlayerVolume(intent, account, playerId, true);
            //updateActivePlaylist(account, playerId, true);
        }
    }

    /*  private void updateActivePlaylist(
        Account account, String playerId, boolean attemptReauth)
      {
        Log.d(TAG, "updating active playlist");
        AccountManager am = AccountManager.get(this);
        String authToken = "";
        try{
          authToken = am.blockingGetAuthToken(account, "", true);
        }
        catch(IOException e){
          Log.e(TAG, "IO exception when retreiving playist");
        }
        catch(OperationCanceledException e){
          Log.e(TAG, "Op Canceled exception when retreiving playist");
        }
        catch(AuthenticatorException e){
          Log.e(TAG, "Authentication exception when retreiving playist");
        }
        
        
        try{
          JSONObject activePlaylist =
    ServerConnection.getActivePlaylist(playerId, authToken);
          RESTProcessor.setActivePlaylist(activePlaylist, am, account, this);
        }
        catch(JSONException e){
          Log.e(TAG, "JSON exception when retreiving playist");
          Log.e(TAG, e.getMessage());
        }
        catch(ParseException e){
          Log.e(TAG, "Parse exception when retreiving playist");
        }
        catch(IOException e){
          Log.e(TAG, "IO exception when retreiving playist");
        }
        catch(AuthenticationException e){
          if(attemptReauth){
    Log.e(TAG, "Soft Authentication exception when retreiving playist");
    am.invalidateAuthToken(Constants.ACCOUNT_TYPE, authToken); 
    updateActivePlaylist(account, playerId, false);
          }
          else{
    Log.e(TAG, "Hard Authentication exception when retreiving playist");
          } 
        }
        catch(RemoteException e){
          Log.e(TAG, "Remote exception when retreiving playist");
        }
        catch(OperationApplicationException e){
          Log.e(TAG, "Operation Application exception when retreiving playist");
        }
        catch(PlayerInactiveException e){
          Log.e(TAG, "Player Inactive exception when retreiving playlist");
          Utils.handleInactivePlayer(this, account);
        }
        catch (NoLongerInPlayerException e) {
          Utils.handleNoLongerInPlayer(this, account);
        }
        catch(KickedException e){
          Utils.handleKickedFromPlayer(this, account);
        }
        //TODO This point of the app seems very dangerous as there are so many
        // exceptions that could occuer. Need to pay special attention to this.
        
      }
      */

    private void setCurrentSong(Account account, String playerId, String libId, boolean attemptReauth,
            Intent originalIntent) {
        String authToken = "";
        AccountManager am = AccountManager.get(this);
        try {
            authToken = am.blockingGetAuthToken(account, "", true);
        } catch (AuthenticatorException e) {
            alertSetSongException(account, originalIntent);
            Log.e(TAG, "Authentication exception when setting song");
        } catch (OperationCanceledException e) {
            alertSetSongException(account, originalIntent);
            Log.e(TAG, "Op Canceled exception when setting song");
        } catch (IOException e) {
            alertSetSongException(account, originalIntent);
            Log.e(TAG, "IO exception when geting authtoken for setting song");
            Log.e(TAG, e.getMessage());
        }

        try {
            ServerConnection.setCurrentSong(playerId, libId, authToken);
            Intent setCurrentComplete = new Intent(Constants.BROADCAST_SET_CURRENT_COMPLETE);
            this.sendBroadcast(setCurrentComplete);
        } catch (IOException e) {
            alertSetSongException(account, originalIntent);
            Log.e(TAG, "IO exception when setting song");
            Log.e(TAG, e.getMessage());
        } catch (AuthenticationException e) {
            if (attemptReauth) {
                am.invalidateAuthToken(Constants.ACCOUNT_TYPE, authToken);
                addSongToPlaylist(account, playerId, libId, false, originalIntent);
                Log.e(TAG, "Soft Authentication exception when setting song");
            } else {
                alertSetSongException(account, originalIntent);
                Log.e(TAG, "Hard Authentication exception when setting song");
            }
        } catch (PlayerInactiveException e) {
            Log.e(TAG, "Event over exceptoin when setting song");
            Utils.handleInactivePlayer(this, account);
        } catch (NoLongerInPlayerException e) {
            Utils.handleNoLongerInPlayer(this, account);
        } catch (KickedException e) {
            Utils.handleKickedFromPlayer(this, account);
        }
    }

    private void addSongToPlaylist(Account account, String playerId, String libId, boolean attemptReauth,
            Intent originalIntent) {
        String authToken = "";
        AccountManager am = AccountManager.get(this);
        try {
            authToken = am.blockingGetAuthToken(account, "", true);
        } catch (AuthenticatorException e) {
            alertAddSongException(account, originalIntent);
            Log.e(TAG, "Authentication exception when adding to playist");
        } catch (OperationCanceledException e) {
            alertAddSongException(account, originalIntent);
            Log.e(TAG, "Op Canceled exception when adding to playist");
        } catch (IOException e) {
            alertAddSongException(account, originalIntent);
            Log.e(TAG, "IO exception when geting authtoken for adding to playist");
            Log.e(TAG, e.getMessage());
        }

        try {
            ServerConnection.addSongToActivePlaylist(playerId, libId, authToken);
        } catch (JSONException e) {
            alertAddSongException(account, originalIntent);
            Log.e(TAG, "JSON exception when adding to playist");
        } catch (ParseException e) {
            alertAddSongException(account, originalIntent);
            Log.e(TAG, "Parse exception when adding to playist");
        } catch (IOException e) {
            alertAddSongException(account, originalIntent);
            Log.e(TAG, "IO exception when adding to playist");
            Log.e(TAG, e.getMessage());
        } catch (AuthenticationException e) {
            if (attemptReauth) {
                am.invalidateAuthToken(Constants.ACCOUNT_TYPE, authToken);
                addSongToPlaylist(account, playerId, libId, false, originalIntent);
                Log.e(TAG, "Soft Authentication exception when adding to playist");
            } else {
                alertAddSongException(account, originalIntent);
                Log.e(TAG, "Hard Authentication exception when adding to playist");
            }
        } catch (PlayerInactiveException e) {
            Log.e(TAG, "Event over exceptoin when retreiving playlist");
            Utils.handleInactivePlayer(this, account);
        } catch (NoLongerInPlayerException e) {
            Utils.handleNoLongerInPlayer(this, account);
        } catch (KickedException e) {
            Utils.handleKickedFromPlayer(this, account);
        }

    }

    private void removeSongFromPlaylist(Account account, String playerId, String libId, boolean attemptReauth,
            Intent originalIntent) {
        String authToken = "";
        AccountManager am = AccountManager.get(this);
        try {
            authToken = am.blockingGetAuthToken(account, "", true);
        } catch (AuthenticatorException e) {
            alertRemoveSongException(account, originalIntent);
            Log.e(TAG, "Authentication exception when removing from playist");
        } catch (OperationCanceledException e) {
            alertRemoveSongException(account, originalIntent);
            Log.e(TAG, "Op Canceled exception when removing from playist");
        } catch (IOException e) {
            alertRemoveSongException(account, originalIntent);
            Log.e(TAG, "IO exception when removing from playist/getting authtoken");
            Log.e(TAG, e.getMessage());
        }

        try {
            Log.d(TAG, "Actually removing song");
            ServerConnection.removeSongFromActivePlaylist(playerId, libId, authToken);
            Intent removeSongComplete = new Intent(Constants.BROADCAST_REMOVE_SONG_COMPLETE);
            this.sendBroadcast(removeSongComplete);
        } catch (ParseException e) {
            alertRemoveSongException(account, originalIntent);
            Log.e(TAG, "Parse exception when removing from playist");
        } catch (IOException e) {
            alertRemoveSongException(account, originalIntent);
            Log.e(TAG, "IO exception when removing from playist");
            Log.e(TAG, e.getMessage());
        } catch (AuthenticationException e) {
            if (attemptReauth) {
                am.invalidateAuthToken(Constants.ACCOUNT_TYPE, authToken);
                removeSongFromPlaylist(account, playerId, libId, false, originalIntent);
                Log.e(TAG, "Soft Authentication exception when removing from playist");
            } else {
                alertRemoveSongException(account, originalIntent);
                Log.e(TAG, "Hard Authentication exception when removing from playist");
            }
        } catch (PlayerInactiveException e) {
            Log.e(TAG, "Event over exceptoin when removing from playlist");
            Utils.handleInactivePlayer(this, account);
        } catch (NoLongerInPlayerException e) {
            Utils.handleNoLongerInPlayer(this, account);
        } catch (KickedException e) {
            Utils.handleKickedFromPlayer(this, account);
        }
    }

    private void voteOnSong(Account account, String playerId, String libId, int voteWeight, boolean attemptReauth) {
        AccountManager am = AccountManager.get(this);
        String authToken = "";
        try {
            authToken = am.blockingGetAuthToken(account, "", true);
        } catch (IOException e) {
            Log.e(TAG, "IO exception when voting on playist");
        } catch (AuthenticatorException e) {
            Log.e(TAG, "Authentication exception when voting playist");
        } catch (OperationCanceledException e) {
            Log.e(TAG, "Op Canceled exception when voting playist");
        }

        try {
            ServerConnection.voteOnSong(playerId, libId, voteWeight, authToken);
            Intent voteCompleteBroadcast = new Intent(Constants.BROADCAST_VOTE_COMPLETED);
            this.sendBroadcast(voteCompleteBroadcast);
        } catch (ParseException e) {
            Log.e(TAG, "Parse exception when retreiving playist");
        } catch (IOException e) {
            Log.e(TAG, "IO exception when retreiving playist");
        } catch (AuthenticationException e) {
            if (attemptReauth) {
                Log.e(TAG, "Soft Authentication exception when retreiving playist");
                am.invalidateAuthToken(Constants.ACCOUNT_TYPE, authToken);
                voteOnSong(account, playerId, libId, voteWeight, false);
            } else {
                Log.e(TAG, "Hard Authentication exception when retreiving playist");
            }
        } catch (PlayerInactiveException e) {
            Log.e(TAG, "Event over exception when retreiving playlist");
            Utils.handleInactivePlayer(this, account);
        } catch (NoLongerInPlayerException e) {
            Utils.handleNoLongerInPlayer(this, account);
        } catch (KickedException e) {
            Utils.handleKickedFromPlayer(this, account);
        }
    }

    private void setPlayerVolume(Intent intent, Account account, String playerId, boolean attemptReauth) {
        AccountManager am = AccountManager.get(this);
        int desiredVolume = intent.getIntExtra(Constants.PLAYER_VOLUME_EXTRA, 0);
        Log.d(TAG, "proceeding to set volume of player to: " + String.valueOf(desiredVolume) + " on server");

        String authToken = "";
        try {
            authToken = am.blockingGetAuthToken(account, "", true);
        } catch (OperationCanceledException e) {
            //TODO do something here?
            Log.e(TAG, "Operation canceled exception in set playback");
            return;
        } catch (AuthenticatorException e) {
            //TODO do something here?
            Log.e(TAG, "Authenticator exception in set playback");
            return;
        } catch (IOException e) {
            //TODO do something here?
            Log.e(TAG, "IO exception in set playback");
            return;
        }

        try {
            ServerConnection.setPlayerVolume(playerId, desiredVolume, authToken);
        } catch (IOException e) {
            Log.e(TAG, "IO exception in set volume");
            alertSetVolumeException(account, intent);
            return;
        } catch (AuthenticationException e) {
            if (attemptReauth) {
                Log.d(TAG, "Soft Authentication exception when setting volume");
                am.invalidateAuthToken(Constants.ACCOUNT_TYPE, authToken);
                setPlayerVolume(intent, account, playerId, false);
            } else {
                Log.e(TAG, "Hard Authentication exception when setting volume");
                //TODO do something here?
            }
        } catch (PlayerInactiveException e) {
            Log.e(TAG, "Player inactive exception in set volume");
            Utils.handleInactivePlayer(this, account);
            return;
        } catch (NoLongerInPlayerException e) {
            Utils.handleNoLongerInPlayer(this, account);
            return;
        } catch (KickedException e) {
            Utils.handleKickedFromPlayer(this, account);
        }
    }

    private void setPlaybackState(Intent intent, Account account, String playerId, boolean attemptReauth) {
        AccountManager am = AccountManager.get(this);
        String authToken = "";
        try {
            authToken = am.blockingGetAuthToken(account, "", true);
        } catch (OperationCanceledException e) {
            //TODO do something here?
            Log.e(TAG, "Operation canceled exception in set playback");
            return;
        } catch (AuthenticatorException e) {
            //TODO do something here?
            Log.e(TAG, "Authenticator exception in set playback");
            return;
        } catch (IOException e) {
            //TODO do something here?
            Log.e(TAG, "IO exception in set playback");
            return;
        }

        int desiredPlaybackState = intent.getIntExtra(Constants.PLAYBACK_STATE_EXTRA, 0);
        try {
            ServerConnection.setPlaybackState(playerId, desiredPlaybackState, authToken);
        } catch (IOException e) {
            Log.e(TAG, "IO exception in set playback");
            alertSetPlaybackException(account, intent);
            return;
        } catch (AuthenticationException e) {
            if (attemptReauth) {
                Log.d(TAG, "Soft Authentication exception when setting playback state");
                am.invalidateAuthToken(Constants.ACCOUNT_TYPE, authToken);
                setPlaybackState(intent, account, playerId, false);
            } else {
                Log.e(TAG, "Hard Authentication exception when setting playback state");
                //TODO do something here?
            }
        } catch (PlayerInactiveException e) {
            Log.e(TAG, "Player inactive exception in set playback");
            Utils.handleInactivePlayer(this, account);
            return;
        } catch (NoLongerInPlayerException e) {
            Utils.handleNoLongerInPlayer(this, account);
            return;
        } catch (KickedException e) {
            Utils.handleKickedFromPlayer(this, account);
        }
    }

    private void alertSetVolumeException(Account account, Intent originalIntent) {
        alertException(account, originalIntent, R.string.set_volume_failed_title,
                R.string.set_volume_failed_content, PLAYBACK_STATE_SET_EXCEPTION_ID);
    }

    private void alertSetPlaybackException(Account account, Intent originalIntent) {
        alertException(account, originalIntent, R.string.set_playback_failed_title,
                R.string.set_playback_failed_content, PLAYBACK_STATE_SET_EXCEPTION_ID);
    }

    private void alertAddSongException(Account account, Intent originalIntent) {
        alertException(account, originalIntent, R.string.song_add_failed_title, R.string.song_add_failed_content,
                SONG_ADD_EXCEPTION_ID);
    }

    private void alertRemoveSongException(Account account, Intent originalIntent) {
        alertException(account, originalIntent, R.string.song_remove_failed_title,
                R.string.song_remove_failed_content, SONG_REMOVE_EXCEPTION_ID);
    }

    private void alertSetSongException(Account account, Intent originalIntent) {
        alertException(account, originalIntent, R.string.song_set_failed_title, R.string.song_set_failed_content,
                SONG_SET_EXCEPTION_ID);
    }

    private void alertException(Account account, Intent originalIntent, int titleRes, int contentRes,
            int notificationId) {

        PendingIntent pe = PendingIntent.getService(this, 0, originalIntent, 0);
        Notification notification = new Notification(R.drawable.udjlauncher, "", System.currentTimeMillis());
        notification.setLatestEventInfo(this, getString(titleRes), getString(contentRes), pe);
        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        nm.notify(notificationId, notification);
    }

}