Android Open Source - shareplay Selection Activity






From Project

Back to project page shareplay.

License

The source code is released under:

Copyright (c) 2014, Benjamin Damer All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: ...

If you think the Android project shareplay 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

package com.afqa123.shareplay;
// w  w  w .  jav  a2 s.c  o m
import java.io.FileNotFoundException;
import java.net.ConnectException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URLConnection;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.app.TabActivity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.database.Cursor;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.InputType;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager.BadTokenException;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.EditText;
import android.widget.FilterQueryProvider;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SimpleCursorAdapter;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TextView;

import com.afqa123.log.Logger;
import com.afqa123.log.LoggerFactory;
import com.afqa123.shareplay.common.Constants;
import com.afqa123.shareplay.common.CustomFeedback;
import com.afqa123.shareplay.common.DBHelper;
import com.afqa123.shareplay.common.ListWrapper;
import com.afqa123.shareplay.impl.Client;
import com.afqa123.shareplay.impl.Client.OnAuthorizationListener;
import com.afqa123.shareplay.impl.Client.OnCatalogUpdateListener;
import com.afqa123.shareplay.impl.Client.OnConnectedListener;
import com.afqa123.shareplay.impl.Client.OnDownloadListener;
import com.afqa123.shareplay.impl.Client.OnErrorListener;
import com.afqa123.shareplay.impl.Server;
import com.afqa123.shareplay.impl.ServerProvider;
import com.afqa123.shareplay.interfaces.IClient;
import com.afqa123.shareplay.interfaces.IServerProvider;
import com.afqa123.shareplay.interfaces.MediaPlayerInterface;

public class SelectionActivity extends TabActivity {
  
  public static final String PARAM_SERVER_ID = "server_id";
  private static final String PARAM_ARTIST_ID = "artist_id";
  private static final String PARAM_ALBUM_ID = "album_id";
  private static final String PARAM_PLAYLIST_ID = "playlist_id";
  private static final String PARAM_IDX_ARTIST = "idx_artist";
  private static final String PARAM_IDX_ALBUM = "idx_album";
  private static final String PARAM_IDX_PLAYLIST = "idx_playlist";
  private static final String PARAM_IDX_SONG = "idx_song";  
  private static final String PARAM_POS_ARTIST = "pos_artist";
  private static final String PARAM_POS_ALBUM = "pos_album";
  private static final String PARAM_POS_PLAYLIST = "pos_playlist";
  private static final String PARAM_POS_SONG = "pos_song";
  private static final String PARAM_FILTER_ARTIST = "filter_artist";
  private static final String PARAM_FILTER_ALBUM = "filter_album";
  private static final String PARAM_FILTER_PLAYLIST = "filter_playlist";
  private static final String PARAM_FILTER_SONG = "filter_song";
  private static final Logger logger = LoggerFactory.getLogger(SelectionActivity.class);
  
  private Long serverId;
  private Long artistId;
  private Long albumId;
  private Long songId;
  private Long playlistId;
  private ListWrapper artistList;
  private ListWrapper albumList;
  private ListWrapper playlistList;
  private ListWrapper songList;
  private IClient client;
  private TabHost tabHost;
  private ImageView imagePause;
  private ImageView imagePlay;
  private TextView textArtist;
  private TextView textSong;
  private MediaPlayerInterface player;
  private IServerProvider provider;
  private DBHelper db;
  private boolean restoreState;
  private CustomFeedback feedback;
  
  private final ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
      try {
        player = MediaPlayerInterface.Stub.asInterface(service);
        if (player == null) {
          throw new Exception("Error getting MediaPlayerInterface.");
        }
        player.setServer(serverId, client.getPlaybackURL());
        player.update();
      } catch (Exception ex) {
        logger.warn("Error setting playback URL.", ex);
        showDialogSafe(DialogFactory.DIALOG_ERROR);
      }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
      player = null;
    }
  };

  private final BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent i) {
      String song = null;
      String artist = null;
      Bundle extras = i.getExtras();
      final String msg = extras.getString(MediaPlayerService.PARAM_MSG);
      if (MediaPlayerService.MSG_PLAY.equals(msg)) {
        song = extras.getString(MediaPlayerService.PARAM_SONG);
        artist = extras.getString(MediaPlayerService.PARAM_ARTIST);
        imagePause.setVisibility(ImageView.VISIBLE);
        imagePlay.setVisibility(ImageView.GONE);
      } else if (MediaPlayerService.MSG_PAUSE.equals(msg)) {
        imagePlay.setVisibility(ImageView.VISIBLE);
        imagePause.setVisibility(ImageView.GONE);
      }
      textSong.setText(song);
      textArtist.setText(artist);
    }
  };
  
  private final OnTabChangeListener onTabChange = new OnTabChangeListener() {
    @Override
    public void onTabChanged(String tabId) {
      if (getString(R.string.tab_artists).equals(tabId)) {
        artistId = null;
        albumId = null;          
        playlistId = null;
      } else if (getString(R.string.tab_albums).equals(tabId)) {
        albumList.clearFilters();
        albumId = null;    
        playlistId = null;
      } else if (getString(R.string.tab_playlists).equals(tabId)) {
        playlistList.clearFilters();
        playlistId = null;
      } else if (getString(R.string.tab_songs).equals(tabId)) {
        songList.clearFilters();
      }      
      refreshList();
    }
    };
  
    private final OnItemClickListener onListArtistsClick = new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapter, View view, int pos, long id) {
      artistId = id;
      albumList.setStale(true);
      tabHost.setCurrentTab(1);
    }
  };
    
  private final OnItemClickListener onListAlbumsClick = new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapter, View view, int pos, long id) {
      albumId = id;
      songList.setStale(true);
      tabHost.setCurrentTab(3);
    }
  };
  
  private final OnItemClickListener onListPlaylistsClick = new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapter, View view, int pos, long id) {
      artistId = null;
      albumId = null;
      artistList.clearFilters();
      albumList.clearFilters();
      songList.clearFilters();
      // first entry is always "all songs", so skip playlist in
      // that case
      if (pos == 0) {
        playlistId = null;
      } else {
        playlistId = id;
      }
      songList.setStale(true);
      tabHost.setCurrentTab(3);              
    }
  };

  private final OnItemClickListener _onListSongsClick = new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapter, View view, int pos, long id) {
      try {    
        final String constraint = DBHelper.prepareFilter(songList.getFilter());
        player.load(client.getCatalog().getSongItems(artistId, albumId, playlistId, constraint));
        player.select(id);
      } catch (RemoteException ex) {
        logger.warn("Error playing starting playback.", ex);
      }
    }
  };

  private final OnItemLongClickListener _onListSongsLongClick = new OnItemLongClickListener() {
    @Override
    public boolean onItemLongClick(AdapterView<?> adapter, View view, int pos, long id) {
      songId = id;
      showDialog(DialogFactory.DIALOG_ITEM_ACTIONS);
      return true;
    }
  };

  private final OnClickListener _onImagePauseClick = new OnClickListener() {
    @Override
    public void onClick(View v) {
      if (player == null)
        return;
      try {
        player.pause();
        imagePlay.setVisibility(ImageView.VISIBLE);
        imagePause.setVisibility(ImageView.GONE);
      } catch (RemoteException e) {

      }
    }
  };
  
  private final OnClickListener _onImagePlayClick = new OnClickListener() {
    @Override
    public void onClick(View v) {
      if (player == null)
        return;
      try {
        player.play();
        imagePause.setVisibility(ImageView.VISIBLE);
        imagePlay.setVisibility(ImageView.GONE);          
      } catch (RemoteException e) {

      }
    }
  };
    
  private void createTab(int tabId, int contentId) {
    String tabText = getString(tabId);
    View view = LayoutInflater.from(this).inflate(R.layout.tab_indicator, null);
    TextView tv = (TextView)view.findViewById(R.id.tab_text);
    tv.setText(tabId);
      tabHost.addTab(tabHost.newTabSpec(tabText)
          .setIndicator(view)
          .setContent(contentId));
  }
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    logger.info("Creating activity.");
    setContentView(R.layout.activity_selection);
    
    tabHost = getTabHost();
      createTab(R.string.tab_artists, R.id.tab_artists);
    createTab(R.string.tab_albums, R.id.tab_albums);
    createTab(R.string.tab_playlists, R.id.tab_playlists);
    createTab(R.string.tab_songs, R.id.tab_songs);
      tabHost.setOnTabChangedListener(onTabChange);    
      
      artistList = new ListWrapper(findViewById(R.id.list_artists), onListArtistsClick, null);
      albumList = new ListWrapper(findViewById(R.id.list_albums), onListAlbumsClick, null);
      playlistList = new ListWrapper(findViewById(R.id.list_playlists), onListPlaylistsClick, null);
      songList = new ListWrapper(findViewById(R.id.list_songs), _onListSongsClick, _onListSongsLongClick);

        textSong = (TextView)findViewById(R.id.text_song);
    textArtist = (TextView)findViewById(R.id.text_artist);

    imagePause = (ImageView)findViewById(R.id.image_pause);
    imagePause.setOnClickListener(_onImagePauseClick);
    imagePlay = (ImageView)findViewById(R.id.image_play);
    imagePlay.setOnClickListener(_onImagePlayClick);

    ImageView imagePrevious = (ImageView)findViewById(R.id.image_previous);
    imagePrevious.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View v) {
        if (player == null)
          return;
        try {
          player.rewind();
        } catch (RemoteException e) {
        }
      }
    });
    ImageView imageNext = (ImageView)findViewById(R.id.image_next);
    imageNext.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View v) {
        if (player == null)
          return;
        try {
          player.forward();
        } catch (RemoteException e) {
        }
      }
    });
    ImageButton imageSearch = (ImageButton)findViewById(R.id.image_search);
    imageSearch.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View v) {
        onSearchRequested();
      }      
    });
    
         db = new DBHelper(this);
        provider = new ServerProvider(this, db, null);

        // set client to null, so it isn't used until we reconnect to the server
        client = null;
        
       final Bundle extras = getIntent().getExtras();
    serverId = extras.getLong(PARAM_SERVER_ID);
    
       if (savedInstanceState != null) {
        if (savedInstanceState.containsKey(PARAM_ARTIST_ID)) {
          artistId = savedInstanceState.getLong(PARAM_ARTIST_ID);
        }
        if (savedInstanceState.containsKey(PARAM_ALBUM_ID)) {
          albumId = savedInstanceState.getLong(PARAM_ALBUM_ID);
        }
        if (savedInstanceState.containsKey(PARAM_PLAYLIST_ID)) {
          playlistId = savedInstanceState.getLong(PARAM_PLAYLIST_ID);
        }
        // update list position after orientation change
        restoreState = true;
          artistList.setFilter(savedInstanceState.containsKey(PARAM_FILTER_ARTIST) ? savedInstanceState.getString(PARAM_FILTER_ARTIST) : null);
          albumList.setFilter(savedInstanceState.containsKey(PARAM_FILTER_ALBUM) ? savedInstanceState.getString(PARAM_FILTER_ALBUM) : null);
          playlistList.setFilter(savedInstanceState.containsKey(PARAM_FILTER_PLAYLIST) ? savedInstanceState.getString(PARAM_FILTER_PLAYLIST) : null);
          songList.setFilter(savedInstanceState.containsKey(PARAM_FILTER_SONG) ? savedInstanceState.getString(PARAM_FILTER_SONG) : null);
          artistList.setPosition(savedInstanceState.getInt(PARAM_IDX_ARTIST), savedInstanceState.getInt(PARAM_POS_ARTIST));
          albumList.setPosition(savedInstanceState.getInt(PARAM_IDX_ALBUM), savedInstanceState.getInt(PARAM_POS_ALBUM));
          playlistList.setPosition(savedInstanceState.getInt(PARAM_IDX_PLAYLIST), savedInstanceState.getInt(PARAM_IDX_PLAYLIST));
          songList.setPosition(savedInstanceState.getInt(PARAM_IDX_SONG), savedInstanceState.getInt(PARAM_POS_SONG));
    }     
  }
  
  @Override
  protected void onStart() {
    super.onStart();
    logger.info("Starting activity.");

    if (client != null) {
      return;
    }
    
    final ProgressDialog connectDialog = 
      ProgressDialog.show(this, null, getString(R.string.dialog_connecting), true, true, new OnCancelListener() {
        @Override
        public void onCancel(DialogInterface arg0) {
          // if the user cancels out of the connection dialog,
          // end activity
          finish();
        }
      });
    
    Client c = new Client();
    c.setOnAuthorizationListener(new OnAuthorizationListener() {
      @Override
      public void onAuthorizationRequired() {
        hideDialogSafe(connectDialog);
        showDialogSafe(DialogFactory.DIALOG_PASSWORD);
      }
    });
    c.setOnConnectedListener(new OnConnectedListener() {
      @Override
      public void onConnected() {
        hideDialogSafe(connectDialog);
        
                // make sure there are any artists at all
                if (client.getCatalog().getArtistCount() == 0) {
                  client.updateCatalog(true);
                } else {
                  refreshList();          
                } 

                // always start service, in case it was killed
                 startService(new Intent(SelectionActivity.this, MediaPlayerService.class));

          // Bind to service
          bindService(new Intent(SelectionActivity.this, MediaPlayerService.class),
              connection, Context.BIND_AUTO_CREATE);
      
          // Register update receiver
              registerReceiver(receiver, new IntentFilter(MediaPlayerService.STATUS_UPDATE));  
      }
    });
    c.setOnErrorListener(new OnErrorListener() {
      @Override
      public void onError(Exception ex) {
        logger.error("Error starting activity.", ex);
        hideDialogSafe(connectDialog);
        showErrorDialog("SelectionActivity.onStart.Client.OnErrorListener", ex);
      }
    });    
    c.setOnCatalogUpdateListener(new OnCatalogUpdateListener() {

      private int _requestedOrientation;

      private ProgressDialog _pd;
      
      @Override
      public void onCatalogEmpty() {
        _requestedOrientation = SelectionActivity.this.getRequestedOrientation();
        SelectionActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        
        _pd = new ProgressDialog(SelectionActivity.this);
          _pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
          _pd.setTitle(getString(R.string.dialog_catalog_update));
          _pd.setIndeterminate(false);
          _pd.setCancelable(true);
          _pd.setMessage(getString(R.string.label_requesting_data));
          _pd.setProgress(0);
          _pd.setMax(1);
          _pd.setOnCancelListener(new OnCancelListener() {
          @Override
          public void onCancel(DialogInterface arg0) {
            client.cancelUpdate();
          }
          });
          
          if (!isFinishing())
            _pd.show();
      }

      @Override
      public void onCatalogUpdated(int count, int total) {
        _pd.setProgress(count);
        if (count == 0) {
            _pd.setMax(total);
            _pd.setMessage(getString(R.string.label_adding_songs));          
        }
      }
      
      @Override
      public void onPlaylistUpdated(int count, int total, String name) {
        if (count == 0) {
          _pd.setMax(total);
        }
        
        _pd.setProgress(count + 1);
        _pd.setMessage(getString(R.string.label_adding_playlist) + name);
      }

      @Override
      public void onCatalogComplete() {
        // get rid of cursor, so it'll be refreshed after
        // the catalog update
        artistList.releaseCursor();
        
        int count = client.getCatalog().getArtistCount();
        if (count > 0) {
          if (tabHost.getCurrentTab() != 0) {
            tabHost.setCurrentTab(0);
          } else {
            refreshList();
          }
          
          SelectionActivity.this.setRequestedOrientation(_requestedOrientation);
          hideDialogSafe(_pd);
        } else {
          tabHost.setCurrentTab(0);
          SelectionActivity.this.setRequestedOrientation(_requestedOrientation);
          hideDialogSafe(_pd);
          showDialogSafe(DialogFactory.DIALOG_ERROR);
        }
      }
      
      @Override
      public void onCatalogError(Exception ex) {
        tabHost.setCurrentTab(0);
        SelectionActivity.this.setRequestedOrientation(_requestedOrientation);
        hideDialogSafe(_pd);
        showErrorDialog("SelectionActivity.onStart.Client.onCatalogError", ex);
      }
    });
    c.setOnDowloadListener(new OnDownloadListener() {

      private int _requestedOrientation;

      private ProgressDialog _pd;

      @Override
      public void onDownloadStart() {
        _requestedOrientation = SelectionActivity.this.getRequestedOrientation();
        SelectionActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        
        _pd = new ProgressDialog(SelectionActivity.this);
          _pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
          _pd.setIndeterminate(true);
          _pd.setCancelable(true);
          _pd.setMessage(getString(R.string.label_download_song));
          _pd.setOnCancelListener(new OnCancelListener() {
          @Override
          public void onCancel(DialogInterface arg0) {
            client.cancelDownload();
          }
          });
          
          if (!isFinishing())
            _pd.show();
      }

      @Override
      public void onDownloadComplete() {
        SelectionActivity.this.setRequestedOrientation(_requestedOrientation);
        hideDialogSafe(_pd);
      }

      @Override
      public void onDownloadError(Exception ex) {
        SelectionActivity.this.setRequestedOrientation(_requestedOrientation);
        hideDialogSafe(_pd);
        showErrorDialog("SelectionActivity.onStart.Client.OnDownloadListener", ex);
      }
    });
    
      tabHost.setCurrentTab(0);

    client = c;

    // Added as a potential fix for issue #8
    Server server = provider.getServer(serverId);
    if (server == null) {
      String payload = ((ServerProvider)provider).getServerListDebug();
      showErrorDialog("SelectionActivity.onStart", 
          new Exception("No server found for id: " + (serverId == null ? "null" : serverId.toString()) + "\n" + payload));
    } else {
         client.connect(db, server);
    }    
  }
  
  @Override
  protected void onDestroy() {
    logger.info("Destroying activity.");
    try {
      // Unregister update receiver
      unregisterReceiver(receiver);
      // Unbind service
      unbindService(connection);
    } catch (Exception ex) {
      logger.warn("Error stopping activity.", ex);
    }
    // make sure we cancel the update thread, in case it is still
    // running
    if (client.isConnected()) {
      client.cancelUpdate();
    }
    artistList.releaseCursor();
    albumList.releaseCursor();
    playlistList.releaseCursor();
    songList.releaseCursor();
    db.close();
    super.onDestroy();
  }

  private Cursor refreshListCursor(CharSequence textFilter) throws Exception {
    String constraint = DBHelper.prepareFilter(textFilter);
    switch (tabHost.getCurrentTab()) {
    case 0:
      return client.getCatalog().getArtists(constraint);
    case 1:
      return client.getCatalog().getAlbums(artistId, constraint);
    case 2:
      return client.getCatalog().getPlaylists(constraint);
    case 3:
      return client.getCatalog().getSongs(artistId, albumId, playlistId, constraint);
    default:
      throw new Exception("Invalid tab selection.");
    }  
  }
  
  private void refreshList() {
    if (client == null || !client.isConnected())
      return;
    
    try {
      ListWrapper lw;      
      switch (tabHost.getCurrentTab()) {
      case 0:
        lw = artistList;
        break;
      case 1:
        lw = albumList;
        break;
      case 2:
        lw = playlistList;
        break;
      case 3:
        lw = songList;
        break;
      default:
        throw new Exception("Invalid tab.");
      }
      
      if (lw.isStale()) {
        lw.setCursor(refreshListCursor(lw.getFilter()));
        SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
                R.layout.row_simple, lw.getCursor(),
                new String[] { "name" },
                new int[] { R.id.text1 });
  
        // Filter by NAME
        adapter.setStringConversionColumn(0);
        adapter.setFilterQueryProvider(new FilterQueryProvider() {
          @Override
          public Cursor runQuery(CharSequence constraint) {
            Cursor c;
            try {
              c = refreshListCursor(constraint);
            } catch (Exception ex) {
              logger.error("Error running list query.", ex);
              c = null;
            }
            return c;
          }
        });
                  
        lw.getView().setAdapter(adapter);
        lw.setStale(false);        
        if (restoreState) {
          lw.restoreState();
          restoreState = false;
        }
      }      
    } catch (Exception ex) {
      logger.error("Error refreshing list.", ex);
    }    
  }
  
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
      MenuInflater inflater = getMenuInflater();
      inflater.inflate(R.menu.selection, menu);
      final MenuItem shuffleItem = menu.getItem(0);
      final MenuItem repeatItem = menu.getItem(1);      
      try {
        boolean shuffleMode = player.isShuffleMode();
        shuffleItem.setChecked(shuffleMode);
        if (shuffleMode) {
          shuffleItem.setIcon(R.drawable.icon48_shuffle_on);
        } else {
          shuffleItem.setIcon(R.drawable.icon48_shuffle_off);          
        }
        boolean repeatMode = player.isRepeatMode();
        repeatItem.setChecked(repeatMode);
        if (repeatMode) {
          repeatItem.setIcon(R.drawable.icon48_repeat_on);
        } else {
          repeatItem.setIcon(R.drawable.icon48_repeat_off);          
        }
      } catch (Exception ex) {
        logger.warn("Error creating options menu.", ex);
      }      
      return true;
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    try {
      switch (item.getItemId()) {
        case R.id.item_refresh:
          artistList.clearFilters();
          client.updateCatalog(true);
          return true;
          
        case R.id.item_clear_filters:
          artistId = null;
          albumId = null;
          artistList.clearFilters();
          albumList.clearFilters();
          playlistList.clearFilters();
          songList.clearFilters();
          tabHost.setCurrentTab(0);
          return true;
          
        case R.id.item_shuffle:
        {
          boolean checked = !item.isChecked(); 
          player.setShuffleMode(checked);
          item.setChecked(checked);
            if (checked) {
              item.setIcon(R.drawable.icon48_shuffle_on);
            } else {
              item.setIcon(R.drawable.icon48_shuffle_off);          
            }
        }
        return true;
          
        case R.id.item_repeat:
        {
          boolean checked = !item.isChecked(); 
          player.setRepeatMode(checked);
          item.setChecked(checked);
            if (checked) {
              item.setIcon(R.drawable.icon48_repeat_on);
            } else {
              item.setIcon(R.drawable.icon48_repeat_off);          
            }
          }
        return true;
        
        case R.id.item_info:
          showDialog(DialogFactory.DIALOG_INFO);
          return true;          
        default:
          return super.onOptionsItemSelected(item);
      }
      
    } catch (Exception ex) {
      logger.error("Error selecting options item.", ex);
      return super.onOptionsItemSelected(item);
    }
  }

  @Override
  public void onBackPressed() {
    switch (tabHost.getCurrentTab()) {
    case 0:
      // this leaves the app, so end music
      try {
        player.quit();
      } catch (Exception ex) {
        logger.warn("Error pausing player.", ex);
      }
      super.onBackPressed();
      break;      
    case 1:
      tabHost.setCurrentTab(0);
      break;
    case 2:
      tabHost.setCurrentTab(0);
      break;
    case 3:
      if (playlistId != null) {
        tabHost.setCurrentTab(2);        
      } else if (albumId != null) {
        tabHost.setCurrentTab(1);
      } else {
        tabHost.setCurrentTab(0);
      }
      break;      
    }
  }
  
  /**
   * Show soft keyboard to filter current list view.
   */
  @Override
  public boolean onSearchRequested() {
    switch (tabHost.getCurrentTab()) {
    case 0:
      artistList.focus();
      break;
    case 1:
      albumList.focus();
      break;
    case 2:
      playlistList.focus();
      break;
    case 3:
      songList.focus();
      break;
    }        
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,InputMethodManager.HIDE_IMPLICIT_ONLY);
    return false;
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    if (artistId != null)
      outState.putLong(PARAM_ARTIST_ID, artistId);    
    if (albumId != null)
      outState.putLong(PARAM_ALBUM_ID, albumId);
    if (playlistId != null)
      outState.putLong(PARAM_PLAYLIST_ID, playlistId);
    
    int index = artistList.getView().getFirstVisiblePosition();
    View child = artistList.getView().getChildAt(index);
    outState.putInt(PARAM_IDX_ARTIST, index);
    outState.putInt(PARAM_POS_ARTIST, child == null ? 0 : child.getTop());

    index = albumList.getView().getFirstVisiblePosition();
    child = albumList.getView().getChildAt(index);
    outState.putInt(PARAM_IDX_ALBUM, index);
    outState.putInt(PARAM_POS_ALBUM, child == null ? 0 : child.getTop());

    index = playlistList.getView().getFirstVisiblePosition();
    child = playlistList.getView().getChildAt(index);
    outState.putInt(PARAM_IDX_PLAYLIST, index);
    outState.putInt(PARAM_POS_PLAYLIST, child == null ? 0 : child.getTop());

    index = songList.getView().getFirstVisiblePosition();
    child = songList.getView().getChildAt(index);
    outState.putInt(PARAM_IDX_SONG, index);
    outState.putInt(PARAM_POS_SONG, child == null ? 0 : child.getTop());

    String tf = artistList.getFilter();
    if (tf != null && tf.length() > 0) {
      outState.putString(PARAM_FILTER_ARTIST, tf.toString());
    }

    tf = albumList.getFilter();
    if (tf != null && tf.length() > 0) {
      outState.putString(PARAM_FILTER_ALBUM, tf.toString());
    }
    
    tf = playlistList.getFilter();
    if (tf != null && tf.length() > 0) {
      outState.putString(PARAM_FILTER_PLAYLIST, tf.toString());
    }
    
    tf = songList.getFilter();
    if (tf != null && tf.length() > 0) {
      outState.putString(PARAM_FILTER_SONG, tf.toString());
    }
  }

  @Override
  protected Dialog onCreateDialog(int id) {
    Dialog result;
    AlertDialog.Builder ab = new AlertDialog.Builder(this);
       
    switch (id) {
    case DialogFactory.DIALOG_ERROR:
         result = 
           ab.setTitle(R.string.dialog_error)
           .setMessage(R.string.message_connect_server)
           .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
            finish();
          }
           })
           .create();
         break;
         
    case DialogFactory.DIALOG_ERROR_ITUNES:
      result = 
        ab.setTitle(R.string.dialog_error)
          .setMessage(R.string.message_connect_itunes)
          .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
            
            @Override
            public void onClick(DialogInterface dialog, int which) {
              finish();
            }
          })
          .create();
      break;
      
    case DialogFactory.DIALOG_ERROR_CONNECTION:
      result = 
        ab.setTitle(R.string.dialog_error)
          .setMessage(R.string.message_error_connection)
          .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {            
            @Override
            public void onClick(DialogInterface dialog, int which) {
              finish();
            }
          })
          .create();
      break;
         
    case DialogFactory.DIALOG_ERROR_FEEDBACK:
      result = 
        ab.setTitle(R.string.dialog_error)
        .setMessage(R.string.message_connect_server_fb)
        .setPositiveButton(R.string.button_yes, new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
            if (feedback == null) {
              feedback = new CustomFeedback(SelectionActivity.this, "unknown!", null);
            }
            
            feedback.setClient(client);
            feedback.setServer(client.getServer());
            feedback.submit();

            finish();
          }
           })
        .setNeutralButton(R.string.button_no, new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
            // nothing to do
            finish();
          }
           })
        .setNegativeButton(R.string.button_dont_ask_again, new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
            SharedPreferences prefs = getSharedPreferences(Constants.PREFERENCES, Activity.MODE_PRIVATE);
            SharedPreferences.Editor editor = prefs.edit();
            editor.putBoolean(Constants.PREFERENCE_FEEDBACK, false);
            editor.commit();
            finish();
          }
           })
        .create();
      break;
      
    case DialogFactory.DIALOG_PASSWORD:
      final EditText input = new EditText(this);
      input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);

      result = 
        ab.setTitle(R.string.dialog_enter_password)
        .setMessage(R.string.label_enter_password)
        .setView(input)
        .setOnCancelListener(new DialogInterface.OnCancelListener() {
          @Override
          public void onCancel(DialogInterface dialog) {
            input.setText("");
          }
        })
        .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
            Server server = provider.getServer(serverId);
            server.setPassword(input.getText().toString());
            provider.updateServer(server);
            onStart();
          }
        })
        .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
            input.setText("");
            finish();
          }
        })
        .create();
      break;
      
    case DialogFactory.DIALOG_INFO:
      ab.setTitle(R.string.dialog_info)
        .setMessage(R.string.message_help)
           .setCancelable(true)
           .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                 dialog.dismiss();
               }
           });
      result = ab.create();
      break;
      
    case DialogFactory.DIALOG_ITEM_ACTIONS:
      final String options[] = { getString(R.string.label_download) };
      
      ab.setTitle(R.string.dialog_actions);
      ab.setItems(options, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
          switch (which) {
          case 0:
            dialog.dismiss();
            // if we ever move to 2.3, we can use DownloadManager for this
            client.downloadSong(songId);
            break;
                        
          default:
            break;
          }
        }
      });
      result = ab.create();
      break;
            
    default:
      result = super.onCreateDialog(id);
      break;
    }
      
    return result;
  }

  private void showDialogSafe(int id) {
    try {
      if (!isFinishing()) {
        showDialog(id);
      }
    } catch (BadTokenException ex) {
      logger.warn("Error showing dialog.", ex);
    }
  }
  
  /**
   * We have seen errors in market that were caused by being
   * unable to properly dismiss the progress dialog. 
   * 
   * These are likely caused by the app being destroyed.
   */
  private void hideDialogSafe(final ProgressDialog pd) {
    try {
      if (pd != null)
        pd.dismiss();
    } catch (IllegalArgumentException ex) {
      logger.warn("Error dismissing progress dialog.", ex);
    }
  }
  
  private void showErrorDialog(final String src, final Exception ex) {
    // check if user is trying to connect to iTunes, if so, show specific error
    if (ex instanceof FileNotFoundException && client != null) {
      URLConnection uc = ((Client)client).getConnection();
      
      if (uc != null) {
        String server = uc.getHeaderField("daap-server");
        if (server != null && server.startsWith("iTunes")) {
          showDialogSafe(DialogFactory.DIALOG_ERROR_ITUNES);
          return; // we are done
        }
      }
    // Generic network errors
    } else if (ex instanceof ConnectException || 
        ex instanceof SocketException ||
        ex instanceof SocketTimeoutException) {
      showDialogSafe(DialogFactory.DIALOG_ERROR_CONNECTION);
      return; // we are done
    } 
      
    // handle all other errors
    SharedPreferences prefs = getSharedPreferences(Constants.PREFERENCES, Activity.MODE_PRIVATE);
    if (prefs.getBoolean(Constants.PREFERENCE_FEEDBACK, true)) {
      feedback = new CustomFeedback(this, src, ex);
      showDialogSafe(DialogFactory.DIALOG_ERROR_FEEDBACK);
    } else {
      showDialogSafe(DialogFactory.DIALOG_ERROR);      
    }
  }
}




Java Source Code List

com.afqa123.log.DefaultLogger.java
com.afqa123.log.FileLogger.java
com.afqa123.log.LoggerFactory.java
com.afqa123.log.Logger.java
com.afqa123.log.NullLogger.java
com.afqa123.shareplay.DialogFactory.java
com.afqa123.shareplay.MediaPlayerService.java
com.afqa123.shareplay.SelectionActivity.java
com.afqa123.shareplay.SharePlayActivity.java
com.afqa123.shareplay.common.AuthorizationException.java
com.afqa123.shareplay.common.Base64.java
com.afqa123.shareplay.common.Constants.java
com.afqa123.shareplay.common.CustomFeedback.java
com.afqa123.shareplay.common.DAAPException.java
com.afqa123.shareplay.common.DBHelper.java
com.afqa123.shareplay.common.Feedback.java
com.afqa123.shareplay.common.Filename.java
com.afqa123.shareplay.common.ListWrapper.java
com.afqa123.shareplay.common.StoppableThread.java
com.afqa123.shareplay.common.StreamProxy.java
com.afqa123.shareplay.data.ContentCode.java
com.afqa123.shareplay.data.Item.java
com.afqa123.shareplay.data.Playlist.java
com.afqa123.shareplay.impl.Client.java
com.afqa123.shareplay.impl.DatabaseCatalog.java
com.afqa123.shareplay.impl.ServerProvider.java
com.afqa123.shareplay.impl.Server.java
com.afqa123.shareplay.interfaces.Catalog.java
com.afqa123.shareplay.interfaces.IClient.java
com.afqa123.shareplay.interfaces.IServerProvider.java