Android Open Source - grtransit Times 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 av  a 2s  . c o m
 *
 * 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.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.format.Time;
import android.util.Log;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

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.ListArrayAdapter;
import net.kw.shrdlu.grtgtfs.LayoutAdapters.TimesArrayAdapter;
import net.kw.shrdlu.grtgtfs.NotificationCallback;
import net.kw.shrdlu.grtgtfs.R;
import net.kw.shrdlu.grtgtfs.ServiceCalendar;

import java.util.ArrayList;

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

  private String mRouteid = null, mHeadsign, mStopid, mStopname;
  private ArrayList<String[]> mListDetails = null;
  private boolean PrefChanged = true; // force redraw

  private static boolean mCalendarChecked = false, mCalendarOK;

  @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 String pkgstr = mContext.getApplicationContext().getPackageName();
    final Intent intent = getIntent();
    mRouteid = intent.getStringExtra(pkgstr + ".route_id");
    mHeadsign = intent.getStringExtra(pkgstr + ".headsign");
    mStopid = intent.getStringExtra(pkgstr + ".stop_id");
        mStopname = intent.getStringExtra(pkgstr + ".stop_name");
  }

  @Override
  protected void onResume() {
    super.onResume();

    // See if we need to recalculate and redraw the screen.
    // This happens if the user brings up the preferences screen.
    if (PrefChanged) {
      new ProcessBusTimes().execute();
      PrefChanged = false;
    }
  }

  /* Do the processing to load the ArrayAdapter for display. */
  private class ProcessBusTimes extends AsyncTask<Void, Integer, Integer> implements NotificationCallback {
    static final String TAG = "";

    // TODO -- should set a listener that will call this callback.

    // A callback from CalendarService, for updating our progress bar
    @Override
    public void notificationCallback(Integer progress) {
      publishProgress(progress);
    }

    @Override
    protected void onPreExecute() {
      // Log.v(TAG, "onPreExecute()");
            setProgressBarVisibility(true);
    }

    // Update the progress bar.
    @Override
    protected void onProgressUpdate(Integer... parms) {
      setProgress(parms[0]);
    }

    @Override
    protected Integer doInBackground(Void... foo) {
      // Log.v(TAG, "doInBackground()");

      // Will find where to position the list of bus departure times
      final Time t = new Time();
      t.setToNow();
      final String timenow = String.format("%02d:%02d:%02d", t.hour, t.minute, t.second);
      final String datenow = String.format("%04d%02d%02d", t.year, t.month + 1, t.monthDay);

      // Make sure we actually have some valid data, since schedules change often.
      if (!mCalendarChecked) {
        mCalendarOK = CheckCalendar(datenow);
      }
      if (!mCalendarOK) {
        return null;
      }

      if (mRouteid == null) {
        // showing all routes
        mListDetails = ServiceCalendar.getRouteDepartureTimes(mStopid, datenow,
                        !GRTApplication.mPreferences.showAllBusses(), this);
      } else {

        // TODO Setting a listener means not passing `this'

        // showing just one route
        mListDetails = ServiceCalendar.getRouteDepartureTimes(mStopid, mRouteid, mHeadsign, datenow,
            !GRTApplication.mPreferences.showAllBusses(), this);
      }

      // Find when the next bus leaves
      int savedpos = -1;
      for (int i = 0; i < mListDetails.size(); i++) {
        final String departure_time = mListDetails.get(i)[0];
        if (departure_time.compareTo(timenow) >= 0) {
          savedpos = i;
          break;
        }
      }

      return savedpos;
    }

    @Override
    protected void onPostExecute(Integer savedpos) {
      // Log.v(TAG, "onPostExecute()");

      if (!mCalendarOK) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setIcon(R.drawable.grticon);
        builder.setTitle(R.string.app_name);
        builder.setMessage(R.string.calendar_expired);
        builder.create();
        builder.show();
        return;
      }

            setProgress(10000); // max -- makes it slide away

      TextView tv = null;
      final ListView lv = getListView();
      if (lv.getFooterViewsCount() == 0) {
        tv = new TextView(mContext);
        lv.addFooterView(tv);
      }
      lv.setOnTouchListener(mGestureListener);

            getActionBar().setTitle("Stop " + mStopid + " " + mStopname);
      if (mRouteid == null) { // showing all routes
                getActionBar().setSubtitle("All routes");
        if (tv != null) {
          tv.setText(R.string.tap_time_for_route);
        }
        final TimesArrayAdapter adapter = new TimesArrayAdapter(mContext, R.layout.row2layout, mListDetails);
        mContext.setListAdapter(adapter);
      } else {
                getActionBar().setSubtitle("Route " + mHeadsign);
        if (tv != null) {
          tv.setText(R.string.tap_time_for_trip);
        }
        final ListArrayAdapter adapter = new ListArrayAdapter(mContext, R.layout.rowlayout, mListDetails);
        mContext.setListAdapter(adapter);
      }

      // Calculate the time difference
      Toast msg;
      if (savedpos >= 0) {
        final Time t = new Time();
        t.setToNow();

        final String nextdeparture = mListDetails.get(savedpos)[0];
        int hourdiff = Integer.parseInt(nextdeparture.substring(0, 2));
        hourdiff -= t.hour;
        hourdiff *= 60;
        int mindiff = Integer.parseInt(nextdeparture.substring(3, 5));
        mindiff -= t.minute;
        hourdiff += mindiff;

        if (hourdiff >= 60) {
          msg = Toast.makeText(mContext, "Next bus leaves at " + ServiceCalendar.formattedTime(nextdeparture),
              Toast.LENGTH_LONG);
        } else {
          final String plural = hourdiff > 1 ? "s" : "";
          msg = Toast.makeText(mContext, "Next bus leaves in " + hourdiff + " minute" + plural, Toast.LENGTH_LONG);
        }

        getListView().setSelectionFromTop(savedpos, 50); // position next bus just below top

      } else {
        setSelection(mListDetails.size()); // position the list at the last bus
        msg = Toast.makeText(mContext, R.string.no_more_busses, Toast.LENGTH_LONG);
      }

      msg.setGravity(Gravity.TOP, 0, 0);
      msg.show();
    }
  }

  /* Make sure the calendar is current. Updates mCalendarChecked if we get a result of some sort. */
  private boolean CheckCalendar(String datenow) {
    boolean retval = true; // report OK even if failure, so we just continue
    final String[] selectargs = { datenow, datenow };
    Cursor csr = null;

    try {
      csr = DatabaseHelper.ReadableDB().rawQuery(
          "select count(*) from calendar where " + "start_date <= ? and end_date >= ?", selectargs);
    } catch (final SQLException e) {
      Log.e(TAG, "DB query failed checking calendar expiry: " + e.getMessage());
    }

    if (csr != null) {
      if (csr.getCount() == 0 || !csr.moveToFirst() || csr.getInt(0) <= 0) {
        retval = false;
      }

      mCalendarChecked = true;
      csr.close();
    }

    return retval;
  }

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

    final String[] items = (String[]) l.getAdapter().getItem(position);
    if (items == null) {
      return;
    }

    // Allow narrowing to one route, if we're showing many.
    if (mRouteid == null) { // showing all routes
      final String route_id = items[2];
      final String headsign = items[3];

      final Intent bustimes = new Intent(mContext, TimesActivity.class);
      final String pkgstr = mContext.getApplicationContext().getPackageName();
      bustimes.putExtra(pkgstr + ".route_id", route_id);
      bustimes.putExtra(pkgstr + ".headsign", headsign);
      bustimes.putExtra(pkgstr + ".stop_id", mStopid);
            bustimes.putExtra(pkgstr + ".stop_name", mStopname);
      mContext.startActivity(bustimes);

    } else { // 1 route
      final String trip_id = items[2];

      final Intent tripstops = new Intent(mContext, TripStopsActivity.class);
      final String pkgstr = mContext.getApplicationContext().getPackageName();
      tripstops.putExtra(pkgstr + ".trip_id", trip_id);
      tripstops.putExtra(pkgstr + ".stop_id", mStopid);
            tripstops.putExtra(pkgstr + ".stop_name", mStopname);
      tripstops.putExtra(pkgstr + ".route_id", mRouteid);
      tripstops.putExtra(pkgstr + ".headsign", mHeadsign);
      mContext.startActivity(tripstops);

    }
  }

    // Catch the user selecting the map option from the navigation drawer,
    // and show the map with this stop centered.
  @Override
  public boolean onNavOptionSelected(int itemid) {
    switch (itemid) {
            case R.id.menu_showmap: {
            GRTApplication.tracker.send(new HitBuilders.EventBuilder()
                    .setCategory(mContext.getLocalClassName())
                    .setAction("Menu show route")
                    .setLabel(mRouteid == null ? "All" : mRouteid + " - " + mHeadsign)
                    .build());

      // Perform action on click
      final String pkgstr = mContext.getApplicationContext().getPackageName();
      final Intent busroutes = new Intent(mContext, RouteActivity.class);
      busroutes.putExtra(pkgstr + ".route_id", mRouteid);
      busroutes.putExtra(pkgstr + ".headsign", mHeadsign);
      busroutes.putExtra(pkgstr + ".stop_id", mStopid);
            busroutes.putExtra(pkgstr + ".stop_name", mStopname);
      startActivity(busroutes);
      return true;
    }
    default: {
      return false;
    }
    }
  }

  private final View.OnTouchListener mGestureListener = new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return mGestureDetector.onTouchEvent(event);
    }
  };

  // Catch flings, to show all busses coming to this stop.
  // This must be called on the GIU thread.
  private final GestureDetector mGestureDetector = new GestureDetector(mContext,
      new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
          // Log.d(TAG, "fling X " + velocityX + ", Y " + velocityY);
          // Catch a fling sort of from left to right
          if (velocityX > 100 && Math.abs(velocityX) > Math.abs(velocityY)) {
            // Log.d(TAG, "fling detected");
                        GRTApplication.tracker.send(new HitBuilders.EventBuilder(mContext.getLocalClassName(), "fling left").build());
            finish();
            return true;
          }
          return false;
        }
      });
}




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