package com.geoloqi.ui; import java.util.ArrayList; import java.util.List; import android.app.ListActivity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageButton; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import com.geoloqi.mapattack.R; import com.geoloqi.data.Game; import com.geoloqi.interfaces.RPCException; import com.geoloqi.rpc.MapAttackClient; import com.geoloqi.services.GeoloqiPositioning; import com.geoloqi.widget.GameListArrayAdapter; public class GameListActivity extends ListActivity implements OnClickListener { public static final String TAG = "GameListActivity"; public static final String PARAM_GAME_LIST = "game_list"; public static final String PARAM_NEAREST_INTERSECTION = "nearest_intersection"; public static final String PARAM_SYNC_ON_START = "sync_on_start"; private boolean mSyncOnStart = true; private Intent mPositioningIntent; private ArrayList<Game> mGameList = null; private String mNearestIntersection = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.game_list_activity); // Find our views final Button refreshButton = (Button) findViewById(R.id.refresh_button); final ImageButton geoloqiButton = (ImageButton) findViewById(R.id.geoloqi); // Set our on click listeners refreshButton.setOnClickListener(this); geoloqiButton.setOnClickListener(this); // Reference our positioning service Intent mPositioningIntent = new Intent(this, GeoloqiPositioning.class); if (savedInstanceState != null) { // Restore our saved instance state mSyncOnStart = savedInstanceState.getBoolean(PARAM_SYNC_ON_START, true); mNearestIntersection = savedInstanceState.getString(PARAM_NEAREST_INTERSECTION); mGameList = savedInstanceState.getParcelableArrayList(PARAM_GAME_LIST); setNearestIntersection(mNearestIntersection); populateGameList(mGameList); } if (mSyncOnStart || mGameList.isEmpty()) { // Start our positioning service stopService(mPositioningIntent); startService(mPositioningIntent); // Search for nearby games setLoading(true); new RequestGamesListTask(this, getLastKnownLocation(), false).execute(); } } @Override public void onDestroy() { super.onDestroy(); stopService(mPositioningIntent); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(PARAM_SYNC_ON_START, false); outState.putString(PARAM_NEAREST_INTERSECTION, mNearestIntersection); outState.putParcelableArrayList(PARAM_GAME_LIST, (ArrayList<? extends Parcelable>) mGameList); } /** * Populate the ListView with a new GameListArrayAdapter * from the provided List of Game objects. * * @param games */ private void populateGameList(final ArrayList<Game> games) { setLoading(false); if (games != null) { mGameList = games; setListAdapter(new GameListArrayAdapter(this, R.layout.game_list_element, mGameList.toArray(new Game[mGameList.size()]))); } } /** * Set the game list label with the nearest intersection. * * @param intersection */ private void setNearestIntersection(final String intersection) { if (!TextUtils.isEmpty(intersection)) { mNearestIntersection = intersection; TextView textView = (TextView) findViewById(R.id.game_list_label); if (textView != null) { textView.setText(String.format("Games near %s", intersection)); } } } /** Get the last known location from the device. */ private Location getLastKnownLocation() { LocationManager lm = ((LocationManager) getSystemService(LOCATION_SERVICE)); List<String> providers = lm.getAllProviders(); for (String provider : providers) { Location last = lm.getLastKnownLocation(provider); if (last != null) { return last; } } return null; } @Override public void onListItemClick(ListView l, View v, int position, long id) { final Game selection = (Game) l.getItemAtPosition(position); // Start the MapAttackActivity for the indicated game Intent intent = new Intent(this, MapAttackActivity.class); intent.putExtra(MapAttackActivity.PARAM_GAME_ID, selection.id); startActivity(intent); } @Override public void onClick(View view) { switch(view.getId()) { case R.id.refresh_button: new RequestGamesListTask(this, getLastKnownLocation()).execute(); break; case R.id.geoloqi: final Intent geoloqiIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://geoloqi.com/")); geoloqiIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); geoloqiIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(geoloqiIntent); break; } } /** Show or hide the loading indicator. */ private void setLoading(boolean loading) { ProgressBar spinner = (ProgressBar) findViewById(R.id.loading); ListView listView = getListView(); View emptyView = listView.getEmptyView(); if (loading) { spinner.setVisibility(View.VISIBLE); listView.setVisibility(View.GONE); emptyView.setVisibility(View.GONE); } else { spinner.setVisibility(View.GONE); listView.setVisibility(View.VISIBLE); emptyView.setVisibility(View.GONE); } } /** * A simple AsyncTask to request the game list from the server. * @TODO: Move this to an external class file. * */ private static class RequestGamesListTask extends AsyncTask<Void, Void, ArrayList<Game>> { private final Context mContext; private final Location mLocation; private String mIntersection = null; private ProgressDialog mProgressDialog = null; public RequestGamesListTask(final Context context, final Location location) { this(context, location, true); } public RequestGamesListTask(final Context context, final Location location, final boolean displayDialog) { mContext = context; mLocation = location; // Build a progress dialog if (displayDialog) { mProgressDialog = new ProgressDialog(context); mProgressDialog.setTitle(null); mProgressDialog.setMessage(context.getString(R.string.game_list_loading_text)); } } @Override protected void onPreExecute() { // Show our progress dialog if (mProgressDialog != null) { mProgressDialog.show(); } } @Override protected ArrayList<Game> doInBackground(Void... params) { if (mLocation != null) { try { // Get the MapAttackClient final MapAttackClient client = MapAttackClient.getApplicationClient(mContext); // Get the nearest intersection mIntersection = client.getNearestIntersection(mLocation.getLatitude(), mLocation.getLongitude()); // Get the game list return client.getGames(mLocation.getLatitude(), mLocation.getLongitude()); } catch (RPCException e) { Log.e(TAG, "Got an RPCException when looking for nearby games.", e); } } return new ArrayList<Game>(); } @Override protected void onPostExecute(ArrayList<Game> games) { try { final GameListActivity activity = (GameListActivity) mContext; activity.setNearestIntersection(mIntersection); activity.populateGameList(games); } catch (ClassCastException e) { Log.w(TAG, "Got a ClassCastException when trying to update the game list!", e); } // Dismiss our progress dialog if (mProgressDialog != null) { mProgressDialog.dismiss(); } } } }