Android Open Source - grtransit Favstops Activity






From Project

Back to project page grtransit.

License

The source code is released under:

GNU General Public License

If you think the Android project grtransit 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 2011 Giles Malet./*from   w w  w  .  j a v a  2  s .com*/
 *
 * This file is part of GRTransit.
 * 
 * GRTransit 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 3 of the License, or
 * (at your option) any later version.
 * 
 * GRTransit 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 GRTransit.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.kw.shrdlu.grtgtfs.Activities;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.format.Time;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;

import com.google.android.gms.analytics.HitBuilders;

import net.kw.shrdlu.grtgtfs.DatabaseHelper;
import net.kw.shrdlu.grtgtfs.GRTApplication;
import net.kw.shrdlu.grtgtfs.LayoutAdapters.FavstopsArrayAdapter;
import net.kw.shrdlu.grtgtfs.R;
import net.kw.shrdlu.grtgtfs.ServiceCalendar;

import java.util.ArrayList;

public class FavstopsActivity extends MenuListActivity {
  private static final String TAG = "FavstopsActivity";

  private ArrayList<String[]> mDetails;
  private String mStopid;
  private FavstopsArrayAdapter mAdapter;
  private final SQLiteDatabase DB = DatabaseHelper.ReadableDB();

  @Override
  public void onCreate(Bundle savedInstanceState) {
    mContext = this;

        // Will use the action bar progress bar
        requestWindowFeature(Window.FEATURE_PROGRESS);

        setContentView(R.layout.timeslayout);
    super.onCreate(savedInstanceState);

    final ListView lv = getListView();
    final TextView tv = new TextView(mContext);
    tv.setText(R.string.longpress_removes_stop);
    lv.addFooterView(tv);

    /* Make sure we can access a database */
    if (DB == null) {
      final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int id) {
          mContext.finish();
                }
      };
      final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
      builder.setTitle(R.string.db_is_awol)
      .setMessage(R.string.db_not_avail)
      .setNegativeButton(R.string.exit, listener)
      .create()
      .show();
    }

    // ProcessStops(); // will be done in onResume()
  }

  /* Separate the processing of stops, so we can re-do it when we need to refresh the screen on a new intent. */
  private static boolean mShownalert = false;

  void ProcessStops() {

    mDetails = new ArrayList<>();
    final ArrayList<String[]> favstops = GRTApplication.mPreferences.GetBusstopFavourites();
    // Convert from stop/description to required 4-entry layout.
    synchronized (mDetails) {
      for (final String[] stop : favstops) {
        // Just do what we can for now
        mDetails.add(new String[] { stop[0], stop[1], "", getString(R.string.loading_times), "?" });
      }
    }
    mAdapter = new FavstopsArrayAdapter(this, R.layout.favouritesrow, mDetails);
    setListAdapter(mAdapter);

        // TODO synchronising on non-final var... and accessing that var outside the lock, above & below.
        // See http://stackoverflow.com/questions/21458625/when-a-lock-holds-a-non-final-object-can-the-objects-reference-still-be-change/21460055#21460055

        // Must do all this without doing a database read, which allows database upgrade
    // to happen in the background on a service thread, without us blocking, until
    // we really have to.
    if (!mDetails.isEmpty()) {

      // register to get long clicks on bus stop list
      getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
          // Log.i(TAG, "onItemLongClickClick position " + position);
          onListItemLongClick(parent, view, position, id);
          return true; // to say we consumed the click
        }
      });

      // Load times of next bus for each stop.
      new LoadTimes().execute();

    } else if (!mShownalert) {
      mShownalert = true;

      TextView textView;
      final View messageView = mContext.getLayoutInflater().inflate(R.layout.about, null, false);

      textView = (TextView) messageView.findViewById(R.id.about_header);
      textView.setVisibility(TextView.GONE);
      textView = (TextView) messageView.findViewById(R.id.about_credits);
      textView.setText(R.string.no_favourites);
      textView.setHorizontallyScrolling(false); // make text wrap.

      final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
      // builder.setIcon(R.drawable.grticon);
      builder.setTitle(R.string.title_favourites).setView(messageView).create().show();
    }
  }

  // If we're popping back down the stack, the favourites list could have been added to
  // since we were last here, so make sure it is reloaded before display.
  @Override
  protected void onResume() {
    super.onResume();

    /* Give up if there's no database */
    if (DB == null) {
      return;
    }

    mListDetail.invalidate();
    ProcessStops();
  }

  // Called from the listener above for a long click
    void onListItemLongClick(AdapterView<?> parent, View v, int position, long id) {
    // Log.v(TAG, "long clicked position " + position);

    final String[] strs = (String[]) parent.getItemAtPosition(position);
    if (strs == null) {
      return;
    }
    mStopid = strs[0];
    final String stop_name = strs[1];
    final int aryposn = position; // so we can access it in the listener class.

    final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int id) {
        switch (id) {
        case DialogInterface.BUTTON_POSITIVE:
          GRTApplication.mPreferences.RemoveBusstopFavourite(mStopid);
          synchronized (mDetails) {
            mDetails.remove(aryposn);
          }
          // activities in the stack may contain out of date lists, so flush and start again.
          mContext.startActivity(new Intent(mContext, FavstopsActivity.class));
          break;
          // case DialogInterface.BUTTON_NEGATIVE:
          // // nothing
          // break;
        }
        dialog.cancel();
      }
    };

    final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
    builder.setTitle("Stop " + mStopid + ", " + stop_name);
    builder.setMessage(R.string.favs_remove_from_list).setPositiveButton(R.string.yes, listener)
    .setNegativeButton(R.string.no, listener);
    builder.create();
    builder.show();
  }

  @Override
  protected void onListItemClick(ListView l, View v, int position, long id) {
    // Log.v(TAG, "clicked position " + position);

    final String[] strs = (String[]) l.getItemAtPosition(position);
    if (strs == null) {
      return;
    }
    mStopid = strs[0];
    final String stop_name = strs[1];

        GRTApplication.tracker.send(new HitBuilders.EventBuilder()
                .setCategory(mContext.getLocalClassName())
                .setAction("Select stop")
                .setLabel(mStopid)
                .build());

    final Intent newintent = new Intent(mContext, TimesActivity.class);
    final String pkgstr = mContext.getApplicationContext().getPackageName();
    newintent.putExtra(pkgstr + ".stop_id", mStopid);
    newintent.putExtra(pkgstr + ".stop_name", stop_name);
    mContext.startActivity(newintent);
  }

  /* Do the processing to load the ArrayAdapter for display. */
  private class LoadTimes extends AsyncTask<Void, Integer, Void> {

    @Override
    protected void onPreExecute() {
            setProgressBarVisibility(true);
    }

    @Override
    protected void onProgressUpdate(Integer... parms) {
      mAdapter.notifyDataSetChanged();
            setProgress(parms[0]);
    }

    @Override
    protected Void doInBackground(Void... foo) {

      // Find time of next bus for each stop.
      final Time t = new Time(); // TODO - this duplicates BusTimes?
      t.setToNow();
      final String datenow = String.format("%04d%02d%02d", t.year, t.month + 1, t.monthDay);

      Integer progresscount = 0;
      synchronized (mDetails) {
        for (final String[] pref : mDetails) {
          final String stopid = pref[0];
          // final String stopdescr = pref[1];

          // Log.d(TAG, "Searching for busses for stop " + stopid + " " + stopdescr);
          final String[] nextbus = ServiceCalendar.getNextDepartureTime(stopid, datenow);
          if (nextbus != null) {
            // Log.d(TAG, "Next bus for stop " + stopid + ": " + nextbus[0] + " " + nextbus[1] + " - " +
            // nextbus[2]);
            pref[2] = nextbus[0]; // time
            pref[3] = nextbus[2]; // route headsign
            pref[4] = nextbus[1]; // route number
          } else {
            // Log.d(TAG, "Next bus for stop " + stopid + ": --none--");
            pref[2] = " -- -- --"; // time
            pref[3] = getString(R.string.no_more_busses); // route details
            pref[4] = "-";
          }
          publishProgress(++progresscount * 10000 / mDetails.size());
        }
      }
      return null;
    }

    @Override
    protected void onPostExecute(Void foo) {
            getActionBar().setTitle(R.string.title_favourites);
            getActionBar().setSubtitle(null);
            setProgress(10000); // max -- makes it slide away
    }
  }
}




Java Source Code List

net.kw.shrdlu.grtgtfs.DatabaseHelper.java
net.kw.shrdlu.grtgtfs.GRTApplication.java
net.kw.shrdlu.grtgtfs.NavOptions.java
net.kw.shrdlu.grtgtfs.NotificationCallback.java
net.kw.shrdlu.grtgtfs.Preferences.java
net.kw.shrdlu.grtgtfs.RouteOverlay.java
net.kw.shrdlu.grtgtfs.ServiceCalendar.java
net.kw.shrdlu.grtgtfs.StopsOverlay.java
net.kw.shrdlu.grtgtfs.Activities.ClosestStopsActivity.java
net.kw.shrdlu.grtgtfs.Activities.FavstopsActivity.java
net.kw.shrdlu.grtgtfs.Activities.MenuListActivity.java
net.kw.shrdlu.grtgtfs.Activities.MenuMapActivity.java
net.kw.shrdlu.grtgtfs.Activities.PrefsActivity.java
net.kw.shrdlu.grtgtfs.Activities.RiderAlertsActivity.java
net.kw.shrdlu.grtgtfs.Activities.RouteActivity.java
net.kw.shrdlu.grtgtfs.Activities.RouteselectActivity.java
net.kw.shrdlu.grtgtfs.Activities.SearchActivity.java
net.kw.shrdlu.grtgtfs.Activities.StartupActivity.java
net.kw.shrdlu.grtgtfs.Activities.StopsActivity.java
net.kw.shrdlu.grtgtfs.Activities.TimesActivity.java
net.kw.shrdlu.grtgtfs.Activities.TripStopsActivity.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.FavstopsArrayAdapter.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.ListArrayAdapter.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.ListCursorAdapter.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.NavDrawerItem.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.NavDrawerListAdapter.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.TimeStopdescArrayAdapter.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.TimesArrayAdapter.java