Added quick route functionality

This commit is contained in:
dkeen@dkeen-laptop 2012-07-16 08:06:31 -07:00
parent e79dc2ba46
commit bb63de996e
12 changed files with 253 additions and 102 deletions

View File

@ -53,6 +53,18 @@
<data android:mimeType="vnd.android.cursor.dir/com.dougkeen.bart.favorite" /> <data android:mimeType="vnd.android.cursor.dir/com.dougkeen.bart.favorite" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name="QuickRouteActivity"
android:label="@string/quick_departure_lookup"
android:theme="@android:style/Theme.Dialog" >
<intent-filter>
<action android:name="android.intent.action.PICK" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.dir/com.dougkeen.bart.arbitraryroute" />
</intent-filter>
</activity>
<activity <activity
android:name="ViewDeparturesActivity" android:name="ViewDeparturesActivity"
android:label="@string/departures" > android:label="@string/departures" >
@ -62,6 +74,7 @@
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/com.dougkeen.bart.favorite" /> <data android:mimeType="vnd.android.cursor.item/com.dougkeen.bart.favorite" />
<data android:mimeType="vnd.android.cursor.item/com.dougkeen.bart.arbitraryroute" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:paddingLeft="5dp" android:paddingRight="5dp">
<TextView android:id="@+id/origin_label" android:text="@string/origin"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textSize="15dp" android:layout_below="@+id/form_header"
android:layout_alignLeft="@+id/form_header"></TextView>
<Spinner android:id="@+id/origin_spinner" android:layout_below="@id/origin_label"
android:layout_height="wrap_content" android:layout_width="fill_parent" />
<TextView android:id="@+id/destination_label" android:text="@string/destination"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textSize="15dp" android:layout_below="@+id/origin_spinner"
android:layout_alignLeft="@+id/origin_spinner"></TextView>
<Spinner android:id="@+id/destination_spinner"
android:layout_below="@id/destination_label" android:layout_height="wrap_content"
android:layout_width="fill_parent" />
<CheckBox android:id="@+id/return_checkbox"
android:layout_below="@id/destination_spinner" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:text="@string/also_add_return_route" />
<LinearLayout android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_below="@id/return_checkbox"
style="@style/ButtonBar" android:id="@+id/buttonBar"
android:orientation="horizontal">
<Button android:text="@string/save" android:layout_weight="1"
android:layout_height="wrap_content" android:id="@+id/saveButton"
android:layout_width="fill_parent"></Button>
<Button android:text="@string/cancel" android:layout_weight="1"
android:layout_height="wrap_content" android:id="@+id/cancelButton"
android:layout_width="fill_parent"></Button>
</LinearLayout>
</RelativeLayout>

View File

@ -15,4 +15,19 @@
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" /> android:layout_weight="1" />
<FrameLayout
style="ButtonBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" >
<Button
android:id="@+id/quickLookupButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/quick_departure_lookup" />
</FrameLayout>
</LinearLayout> </LinearLayout>

72
res/layout/route_form.xml Normal file
View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="5dp"
android:paddingRight="5dp" >
<TextView
android:id="@+id/origin_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="@string/origin"
android:textSize="15dp" >
</TextView>
<Spinner
android:id="@+id/origin_spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/origin_label" />
<TextView
android:id="@+id/destination_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/origin_spinner"
android:layout_below="@+id/origin_spinner"
android:text="@string/destination"
android:textSize="15dp" >
</TextView>
<Spinner
android:id="@+id/destination_spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/destination_label" />
<CheckBox
android:id="@+id/return_checkbox"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/destination_spinner"
android:text="@string/also_add_return_route"
android:visibility="gone" />
<LinearLayout
android:id="@+id/buttonBar"
style="@style/ButtonBar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/return_checkbox"
android:orientation="horizontal" >
<Button
android:id="@+id/okButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/ok" >
</Button>
<Button
android:id="@+id/cancelButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/cancel" >
</Button>
</LinearLayout>
</RelativeLayout>

View File

@ -30,4 +30,6 @@
<string name="view_system_map">View system map</string> <string name="view_system_map">View system map</string>
<string name="system_map">System map</string> <string name="system_map">System map</string>
<string name="departures">Departures</string> <string name="departures">Departures</string>
<string name="ok">OK</string>
<string name="quick_departure_lookup">Quick departure lookup</string>
</resources> </resources>

View File

@ -126,4 +126,8 @@
<item name="android:layout_marginBottom">5dp</item> <item name="android:layout_marginBottom">5dp</item>
</style> </style>
<style name="bottomButton">
<item name="android:background">#222</item>
</style>
</resources> </resources>

View File

@ -0,0 +1,78 @@
package com.dougkeen.bart;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.Toast;
import com.dougkeen.bart.model.Station;
public abstract class AbstractRouteSelectionActivity extends Activity {
public AbstractRouteSelectionActivity() {
super();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.route_form);
SpinnerAdapter originSpinnerAdapter = new ArrayAdapter<Station>(this,
R.layout.simple_spinner_item, Station.getStationList());
((Spinner) findViewById(R.id.origin_spinner))
.setAdapter(originSpinnerAdapter);
SpinnerAdapter destinationSpinnerAdapter = new ArrayAdapter<Station>(
this, R.layout.simple_spinner_item, Station.getStationList());
((Spinner) findViewById(R.id.destination_spinner))
.setAdapter(destinationSpinnerAdapter);
Button okButton = (Button) findViewById(R.id.okButton);
okButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Station origin = (Station) ((Spinner) findViewById(R.id.origin_spinner))
.getSelectedItem();
Station destination = (Station) ((Spinner) findViewById(R.id.destination_spinner))
.getSelectedItem();
if (origin == null) {
Toast.makeText(v.getContext(),
com.dougkeen.bart.R.string.error_null_origin,
Toast.LENGTH_LONG);
return;
}
if (destination == null) {
Toast.makeText(v.getContext(),
com.dougkeen.bart.R.string.error_null_destination,
Toast.LENGTH_LONG);
return;
}
if (origin.equals(destination)) {
Toast.makeText(
v.getContext(),
com.dougkeen.bart.R.string.error_matching_origin_and_destination,
Toast.LENGTH_LONG);
return;
}
onOkButtonClick(origin, destination);
}
});
Button cancelButton = (Button) findViewById(R.id.cancelButton);
cancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
setResult(RESULT_CANCELED);
finish();
}
});
}
abstract protected void onOkButtonClick(Station origin, Station destination);
}

View File

@ -1,83 +1,25 @@
package com.dougkeen.bart; package com.dougkeen.bart;
import com.dougkeen.bart.data.RoutesColumns;
import com.dougkeen.bart.model.Constants;
import com.dougkeen.bart.model.Station;
import android.app.Activity;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.Toast;
public class AddRouteActivity extends Activity { import com.dougkeen.bart.data.RoutesColumns;
import com.dougkeen.bart.model.Constants;
import com.dougkeen.bart.model.Station;
public class AddRouteActivity extends AbstractRouteSelectionActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
findViewById(R.id.return_checkbox).setVisibility(View.VISIBLE);
setContentView(R.layout.add_favorite);
SpinnerAdapter originSpinnerAdapter = new ArrayAdapter<Station>(this,
R.layout.simple_spinner_item, Station.getStationList());
((Spinner) findViewById(R.id.origin_spinner))
.setAdapter(originSpinnerAdapter);
SpinnerAdapter destinationSpinnerAdapter = new ArrayAdapter<Station>(
this, R.layout.simple_spinner_item, Station.getStationList());
((Spinner) findViewById(R.id.destination_spinner))
.setAdapter(destinationSpinnerAdapter);
Button saveButton = (Button) findViewById(R.id.saveButton);
saveButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
onSaveButtonClick();
}
});
Button cancelButton = (Button) findViewById(R.id.cancelButton);
cancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
setResult(RESULT_CANCELED);
finish();
}
});
} }
protected void onSaveButtonClick() { @Override
Station origin = (Station) ((Spinner) findViewById(R.id.origin_spinner)) protected void onOkButtonClick(Station origin, Station destination) {
.getSelectedItem();
Station destination = (Station) ((Spinner) findViewById(R.id.destination_spinner))
.getSelectedItem();
if (origin == null) {
Toast.makeText(this, com.dougkeen.bart.R.string.error_null_origin,
Toast.LENGTH_LONG);
return;
}
if (destination == null) {
Toast.makeText(this,
com.dougkeen.bart.R.string.error_null_destination,
Toast.LENGTH_LONG);
return;
}
if (origin.equals(destination)) {
Toast.makeText(
this,
com.dougkeen.bart.R.string.error_matching_origin_and_destination,
Toast.LENGTH_LONG);
return;
}
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(RoutesColumns.FROM_STATION.string, origin.abbreviation); values.put(RoutesColumns.FROM_STATION.string, origin.abbreviation);
values.put(RoutesColumns.TO_STATION.string, destination.abbreviation); values.put(RoutesColumns.TO_STATION.string, destination.abbreviation);
@ -97,5 +39,4 @@ public class AddRouteActivity extends Activity {
setResult(RESULT_OK, (new Intent()).setAction(newUri.toString())); setResult(RESULT_OK, (new Intent()).setAction(newUri.toString()));
finish(); finish();
} }
} }

View File

@ -0,0 +1,17 @@
package com.dougkeen.bart;
import android.content.Intent;
import com.dougkeen.bart.model.Constants;
import com.dougkeen.bart.model.Station;
public class QuickRouteActivity extends AbstractRouteSelectionActivity {
@Override
protected void onOkButtonClick(Station origin, Station destination) {
startActivity(new Intent(Intent.ACTION_VIEW,
Constants.ARBITRARY_ROUTE_CONTENT_URI_ROOT.buildUpon()
.appendPath(origin.abbreviation)
.appendPath(destination.abbreviation).build()));
}
}

View File

@ -21,6 +21,7 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.Button;
import android.widget.ListView; import android.widget.ListView;
import android.widget.SimpleCursorAdapter; import android.widget.SimpleCursorAdapter;
import android.widget.SimpleCursorAdapter.ViewBinder; import android.widget.SimpleCursorAdapter.ViewBinder;
@ -88,6 +89,15 @@ public class RoutesListActivity extends ActionBarListActivity {
setListAdapter(adapter); setListAdapter(adapter);
registerForContextMenu(getListView()); registerForContextMenu(getListView());
((Button) findViewById(R.id.quickLookupButton))
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(Intent.ACTION_PICK,
Constants.ARBITRARY_ROUTE_CONTENT_URI_ROOT));
}
});
} }
private void refreshFares() { private void refreshFares() {

View File

@ -9,6 +9,8 @@ import android.content.ContentUris;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.UriMatcher; import android.content.UriMatcher;
import android.database.Cursor; import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;
import android.database.SQLException; import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder; import android.database.sqlite.SQLiteQueryBuilder;
@ -22,6 +24,8 @@ public class BartContentProvider extends ContentProvider {
private static final int FAVORITES = 1; private static final int FAVORITES = 1;
private static final int FAVORITE_ID = 2; private static final int FAVORITE_ID = 2;
private static final int ARBITRARY_ROUTE = 3;
private static final int ARBITRARY_ROUTE_UNDEFINED = 4;
/** /**
* The default sort order for events * The default sort order for events
@ -33,6 +37,9 @@ public class BartContentProvider extends ContentProvider {
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(Constants.AUTHORITY, "favorites", FAVORITES); sUriMatcher.addURI(Constants.AUTHORITY, "favorites", FAVORITES);
sUriMatcher.addURI(Constants.AUTHORITY, "favorites/#", FAVORITE_ID); sUriMatcher.addURI(Constants.AUTHORITY, "favorites/#", FAVORITE_ID);
sUriMatcher.addURI(Constants.AUTHORITY, "route/*/*", ARBITRARY_ROUTE);
sUriMatcher.addURI(Constants.AUTHORITY, "route",
ARBITRARY_ROUTE_UNDEFINED);
sFavoritesProjectionMap = new HashMap<String, String>(); sFavoritesProjectionMap = new HashMap<String, String>();
sFavoritesProjectionMap.put(RoutesColumns._ID.string, sFavoritesProjectionMap.put(RoutesColumns._ID.string,
@ -45,7 +52,8 @@ public class BartContentProvider extends ContentProvider {
RoutesColumns.FARE.string); RoutesColumns.FARE.string);
sFavoritesProjectionMap.put(RoutesColumns.FARE_LAST_UPDATED.string, sFavoritesProjectionMap.put(RoutesColumns.FARE_LAST_UPDATED.string,
RoutesColumns.FARE_LAST_UPDATED.string); RoutesColumns.FARE_LAST_UPDATED.string);
sFavoritesProjectionMap.put(RoutesColumns.AVERAGE_TRIP_SAMPLE_COUNT.string, sFavoritesProjectionMap.put(
RoutesColumns.AVERAGE_TRIP_SAMPLE_COUNT.string,
RoutesColumns.AVERAGE_TRIP_SAMPLE_COUNT.string); RoutesColumns.AVERAGE_TRIP_SAMPLE_COUNT.string);
sFavoritesProjectionMap.put(RoutesColumns.AVERAGE_TRIP_LENGTH.string, sFavoritesProjectionMap.put(RoutesColumns.AVERAGE_TRIP_LENGTH.string,
RoutesColumns.AVERAGE_TRIP_LENGTH.string); RoutesColumns.AVERAGE_TRIP_LENGTH.string);
@ -66,6 +74,10 @@ public class BartContentProvider extends ContentProvider {
return Constants.FAVORITE_CONTENT_TYPE; return Constants.FAVORITE_CONTENT_TYPE;
} else if (match == FAVORITE_ID) { } else if (match == FAVORITE_ID) {
return Constants.FAVORITE_CONTENT_ITEM_TYPE; return Constants.FAVORITE_CONTENT_ITEM_TYPE;
} else if (match == ARBITRARY_ROUTE) {
return Constants.ARBITRARY_ROUTE_TYPE;
} else if (match == ARBITRARY_ROUTE_UNDEFINED) {
return Constants.ARBITRARY_ROUTE_UNDEFINED_TYPE;
} else { } else {
throw new IllegalArgumentException("Unknown URI " + uri); throw new IllegalArgumentException("Unknown URI " + uri);
} }
@ -82,14 +94,29 @@ public class BartContentProvider extends ContentProvider {
int match = sUriMatcher.match(uri); int match = sUriMatcher.match(uri);
if (match == FAVORITES) { if (match == ARBITRARY_ROUTE) {
qb.setTables(DatabaseHelper.FAVORITES_TABLE_NAME); MatrixCursor returnCursor = new MatrixCursor(projection);
qb.setProjectionMap(sFavoritesProjectionMap); RowBuilder newRow = returnCursor.newRow();
for (String column : projection) {
if (column.equals(RoutesColumns.FROM_STATION.string)) {
newRow.add(uri.getPathSegments().get(1));
} else if (column.equals(RoutesColumns.TO_STATION.string)) {
newRow.add(uri.getPathSegments().get(2));
} else {
newRow.add(null);
}
}
return returnCursor;
} else if (match == FAVORITE_ID) { } else if (match == FAVORITE_ID) {
qb.setTables(DatabaseHelper.FAVORITES_TABLE_NAME); qb.setTables(DatabaseHelper.FAVORITES_TABLE_NAME);
qb.setProjectionMap(sFavoritesProjectionMap); qb.setProjectionMap(sFavoritesProjectionMap);
qb.appendWhere(RoutesColumns._ID + " = " qb.appendWhere(RoutesColumns._ID + " = "
+ uri.getPathSegments().get(1)); + uri.getPathSegments().get(1));
} else if (match == FAVORITES) {
qb.setTables(DatabaseHelper.FAVORITES_TABLE_NAME);
qb.setProjectionMap(sFavoritesProjectionMap);
} else { } else {
throw new IllegalArgumentException("Unknown URI " + uri); throw new IllegalArgumentException("Unknown URI " + uri);
} }

View File

@ -5,9 +5,13 @@ import android.net.Uri;
public class Constants { public class Constants {
public static final String AUTHORITY = "com.dougkeen.bart.dataprovider"; public static final String AUTHORITY = "com.dougkeen.bart.dataprovider";
public static final String FAVORITE_CONTENT_TYPE = "vnd.android.cursor.dir/com.dougkeen.bart.favorite"; public static final String FAVORITE_CONTENT_TYPE = "vnd.android.cursor.dir/com.dougkeen.bart.favorite";
public static final String ARBITRARY_ROUTE_UNDEFINED_TYPE = "vnd.android.cursor.dir/com.dougkeen.bart.arbitraryroute";
public static final String ARBITRARY_ROUTE_TYPE = "vnd.android.cursor.item/com.dougkeen.bart.arbitraryroute";
public static final String FAVORITE_CONTENT_ITEM_TYPE = "vnd.android.cursor.item/com.dougkeen.bart.favorite"; public static final String FAVORITE_CONTENT_ITEM_TYPE = "vnd.android.cursor.item/com.dougkeen.bart.favorite";
public static final Uri FAVORITE_CONTENT_URI = Uri.parse("content://" public static final Uri FAVORITE_CONTENT_URI = Uri.parse("content://"
+ AUTHORITY + "/favorites"); + AUTHORITY + "/favorites");
public static final Uri ARBITRARY_ROUTE_CONTENT_URI_ROOT = Uri
.parse("content://" + AUTHORITY + "/route");
public static final String MAP_URL = "http://m.bart.gov/images/global/system-map29.gif"; public static final String MAP_URL = "http://m.bart.gov/images/global/system-map29.gif";
public static final String TAG = "BartRunner"; public static final String TAG = "BartRunner";