/[projects]/android/TrainInfo/src/dk/thoerup/traininfo/StationList.java
ViewVC logotype

Contents of /android/TrainInfo/src/dk/thoerup/traininfo/StationList.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 480 - (show annotations) (download)
Wed Oct 28 12:52:52 2009 UTC (14 years, 6 months ago) by torben
File size: 16430 byte(s)
Also save title
1 package dk.thoerup.traininfo;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.Locale;
6
7 import android.app.AlertDialog;
8 import android.app.Dialog;
9 import android.app.ListActivity;
10 import android.app.ProgressDialog;
11 import android.content.DialogInterface;
12 import android.content.Intent;
13 import android.content.SharedPreferences;
14 import android.content.SharedPreferences.Editor;
15 import android.location.Address;
16 import android.location.Geocoder;
17 import android.location.Location;
18 import android.os.AsyncTask;
19 import android.os.Bundle;
20 import android.os.Handler;
21 import android.os.Message;
22 import android.util.Log;
23 import android.view.ContextMenu;
24 import android.view.LayoutInflater;
25 import android.view.Menu;
26 import android.view.MenuItem;
27 import android.view.View;
28 import android.view.ContextMenu.ContextMenuInfo;
29 import android.view.View.OnCreateContextMenuListener;
30 import android.widget.AdapterView;
31 import android.widget.EditText;
32 import android.widget.ListView;
33 import android.widget.Toast;
34 import dk.thoerup.traininfo.provider.ProviderFactory;
35 import dk.thoerup.traininfo.provider.StationProvider;
36 import dk.thoerup.traininfo.stationmap.GeoPair;
37 import dk.thoerup.traininfo.stationmap.StationMapView;
38 import dk.thoerup.traininfo.util.IntSet;
39 import dk.thoerup.traininfo.util.MessageBox;
40
41 public class StationList extends ListActivity {
42 public static final int GOTLOCATION = 1001;
43 public static final int GOTSTATIONLIST = 1002;
44 public static final int NOPROVIDER = 1003;
45 public static final int LOCATIONFIXTIMEOUT = 1004;
46
47 public static final int OPTIONS_RESCAN = 2001;
48 public static final int OPTIONS_NAMESEARCH = 2002;
49 public static final int OPTIONS_MAP = 2003;
50 public static final int OPTIONS_ABOUT = 2004;
51 public static final int OPTIONS_FAVORITES = 2005;
52
53
54
55 public static final int DLG_PROGRESS = 3001;
56 public static final int DLG_STATIONNAME = 3002;
57
58 static enum LookupMethod {
59 ByLocation,
60 ByName,
61 ByList,
62 MethodNone
63 }
64
65
66 String dialogMessage = "";
67 ProgressDialog dialog;
68 LocationLookup locator = null;
69 FindStationsTask findStationsTask;
70 StationsFetchedHandler stationsFetched = new StationsFetchedHandler();
71
72 GeoPair location = new GeoPair();
73
74 boolean isRunning = false;
75 List<StationBean> stations = new ArrayList<StationBean>();
76
77 StationProvider stationProvider = ProviderFactory.getStationProvider();
78
79 StationListAdapter adapter = null;
80
81 FavoritesMenu contextMenu = new FavoritesMenu();
82 IntSet favorites = new IntSet();
83
84 boolean showingFavorites = false;
85 String dialogTitle;
86 SharedPreferences prefs;
87
88 ///////////////////////////////////////////////////////////////////////////////////////////
89 //Activity call backs
90
91 @SuppressWarnings("unchecked")
92 @Override
93 public void onCreate(Bundle savedInstanceState) {
94 super.onCreate(savedInstanceState);
95 setContentView(R.layout.main);
96
97
98 adapter = new StationListAdapter(this);
99 setListAdapter(adapter);
100
101 ListView lv = getListView();
102 lv.setOnCreateContextMenuListener(contextMenu);
103
104 locator = new LocationLookup(this, stationsFetched);
105
106
107 prefs = getSharedPreferences("TrainStation", 0);
108 String favoriteString = prefs.getString("favorites", "");
109 if (! favoriteString.equals("") ) {
110 favorites.fromString(favoriteString);
111 }
112
113 if (savedInstanceState == null) {
114 startLookup();
115 } else {
116 stations = (ArrayList<StationBean>) savedInstanceState.getSerializable("stations");
117 adapter.setStations(stations);
118 location = (GeoPair) savedInstanceState.getSerializable("location");
119 dialogTitle = savedInstanceState.getString("title");
120 setTitle(dialogTitle);
121 }
122 }
123
124
125 @Override
126 public void onSaveInstanceState(Bundle outState)
127 {
128 if (dialog != null && dialog.isShowing())
129 dialog.dismiss();
130 outState.putSerializable("stations", (ArrayList<StationBean>) stations);
131 outState.putSerializable("location", location);
132 outState.putString("title", dialogTitle);
133 }
134
135
136
137 @Override
138 public boolean onCreateOptionsMenu(Menu menu) {
139 MenuItem item;
140
141 item = menu.add(0, OPTIONS_RESCAN, 0, "Nearest stations");
142 item.setIcon(android.R.drawable.ic_menu_mylocation);
143
144 item = menu.add(0, OPTIONS_NAMESEARCH, 0, "Search for station");
145 item.setIcon(android.R.drawable.ic_menu_search);
146
147 item = menu.add(0, OPTIONS_FAVORITES, 0, "Favorites");
148 item.setIcon(android.R.drawable.ic_menu_agenda);
149
150 item = menu.add(0, OPTIONS_MAP, 0, "Station map");
151 item.setIcon(android.R.drawable.ic_menu_mapmode);
152
153 item = menu.add(0, OPTIONS_ABOUT, 0, "About");
154 item.setIcon(android.R.drawable.ic_menu_info_details);
155 return true;
156 }
157
158 @Override
159 public boolean onOptionsItemSelected(MenuItem item) {
160 boolean retval = true;
161
162
163 switch (item.getItemId()) {
164 case OPTIONS_RESCAN:
165 startLookup();
166 break;
167 case OPTIONS_NAMESEARCH:
168 showDialog(DLG_STATIONNAME);
169 break;
170 case OPTIONS_FAVORITES:
171 startFavoriteLookup();
172 break;
173 case OPTIONS_MAP:
174
175 Intent intent = new Intent(this,StationMapView.class);
176 intent.putExtra("userlocation", location );
177
178 ArrayList<GeoPair> stationPoints = new ArrayList<GeoPair>();
179 for (StationBean st : stations ) {
180 stationPoints.add( new GeoPair(st.getLatitude(), st.getLongitude(), st.getName()) );
181 }
182
183 intent.putExtra("stations", stationPoints);
184
185 startActivity(intent);
186 break;
187 case OPTIONS_ABOUT:
188 String ver = this.getResources().getString(R.string.app_version);
189
190 Location loc = locator.getLocation();
191 StringBuffer message = new StringBuffer();
192 message.append("TrainInfo DK v").append(ver).append("\n");
193 message.append("By Torben Nielsen\n");
194 message.append("\n");
195 message.append("Location info:\n");
196 message.append("-Obtained by: ").append(loc != null ? loc.getProvider() : "-").append("\n");
197 message.append("-Accuracy: ").append(loc != null ? (int)loc.getAccuracy() : "-").append("m\n");
198
199 MessageBox.showMessage(this, message.toString());
200 break;
201 default:
202 retval = super.onOptionsItemSelected(item);
203 }
204
205 return retval;
206 }
207
208
209
210 @Override
211 public boolean onContextItemSelected(MenuItem item) {
212 contextMenu.onContextItemSelected(item);
213 return true;
214
215
216 }
217
218
219
220
221 @Override
222 protected Dialog onCreateDialog(int id) {
223 switch (id) {
224 case DLG_PROGRESS:
225 ProgressDialog dlg = new ProgressDialog(this);
226 dlg.setMessage("Wait for location fix");
227 dlg.setCancelable(false);
228 return dlg;
229 case DLG_STATIONNAME:
230 LayoutInflater factory = LayoutInflater.from(this);
231 final View rootView = factory.inflate(R.layout.textinput, null);
232
233
234 AlertDialog.Builder builder = new AlertDialog.Builder(this);
235
236 builder.setTitle("Station search");
237 builder.setView(rootView);
238 builder.setCancelable(true);
239 builder.setPositiveButton("Search", new DialogInterface.OnClickListener() {
240 public void onClick(DialogInterface dialog, int which) {
241 EditText et = (EditText) rootView.findViewById(R.id.EditText);
242 dialog.dismiss();
243 if (et.getText().toString().length() >= 2) {
244 startNameSearch(et.getText().toString());
245 } else {
246 MessageBox.showMessage(StationList.this, "Two characters minimum" );
247 }
248 }
249 });
250 builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
251 public void onClick(DialogInterface dialog, int which) {
252 dialog.dismiss();
253 }
254 });
255 return builder.create();
256
257 default:
258 return super.onCreateDialog(id);
259 }
260
261 }
262
263
264 @Override
265 protected void onPrepareDialog(int id, Dialog dialog) {
266 super.onPrepareDialog(id, dialog);
267 switch (id) {
268 case DLG_PROGRESS:
269 this.dialog = (ProgressDialog) dialog;
270 if (!dialogMessage.equals("")) {
271 this.dialog.setMessage(dialogMessage);
272 dialogMessage = "";
273 }
274 break;
275 }
276 }
277
278 @Override
279 protected void onListItemClick(ListView l, View v, int position, long id) {
280 super.onListItemClick(l, v, position, id);
281
282 StationBean station = stations.get(position);
283
284 double latitude = station.getLatitude();
285 double longitude = station.getLongitude();
286
287
288
289 Intent intent = new Intent(this, DepartureList.class);
290 intent.putExtra("name", station.getName());
291 intent.putExtra("distance", station.getDistance());
292 intent.putExtra("latitude", latitude);
293 intent.putExtra("longitude", longitude);
294 intent.putExtra("stationid", station.getId());
295 intent.putExtra("address", station.getAddress());
296 startActivity(intent);
297 }
298
299 /////////////////////////////////////////////////////////////
300 //
301
302 public void startLookup() {
303 isRunning = true;
304 dialogMessage = "Wait for location fix";
305 showDialog(DLG_PROGRESS);
306
307 locator.locateStations();
308 stationsFetched.sendEmptyMessageDelayed(LOCATIONFIXTIMEOUT, 20000);
309 }
310
311 void startNameSearch(String name) {
312 dialogMessage = "Finding stations by name";
313 showDialog(DLG_PROGRESS);
314
315 findStationsTask = new FindStationsTask();
316 findStationsTask.searchByName(name, locator.getLocation());
317 findStationsTask.execute();
318
319 }
320
321 public void startFavoriteLookup() {
322
323 if (favorites.size() > 0) {
324 dialogMessage = "Loading favorites";
325 showDialog(DLG_PROGRESS);
326
327 findStationsTask = new FindStationsTask();
328 findStationsTask.searchByIds(favorites.toString(), locator.getLocation());
329 findStationsTask.execute();
330 } else {
331 MessageBox.showMessage(this, "Favorite list is empty");
332 }
333 }
334
335
336
337 void startLocatorTask()
338 {
339 dialogMessage = "Finding nearby stations";
340 showDialog(DLG_PROGRESS);
341
342 findStationsTask = new FindStationsTask();
343 findStationsTask.searchByLocation( locator.getLocation() );
344 findStationsTask.execute();
345 }
346
347
348 String lookupAddress(double latitude, double longitude) {
349
350 Geocoder coder = new Geocoder(this, new Locale("da"));
351 StringBuilder sb = new StringBuilder();
352 Log.i("lookupaddr", "" + latitude + "/" + longitude);
353 try {
354 List<Address> addressList = coder.getFromLocation(latitude, longitude, 1);
355 Address addr = addressList.get(0);
356
357
358 int max = addr.getMaxAddressLineIndex();
359 for (int i=0; i<max; i++) {
360 if (i>0)
361 sb.append(", ");
362
363 sb.append(addr.getAddressLine(i));
364 }
365
366
367 } catch (Exception e) {
368 Log.e("DepartureList", "geocoder failed", e);
369 }
370
371 return sb.toString();
372 }
373
374
375 ////////////////////////////////////////////////////////////////////////////
376 // Inner classes
377
378 class StationsFetchedHandler extends Handler {
379 @Override
380 public void handleMessage(Message msg) {
381
382 switch (msg.what) {
383 case GOTLOCATION:
384 dismissDialog(DLG_PROGRESS);
385
386 startLocatorTask();
387 location = GeoPair.fromLocation( locator.getLocation() );
388
389 break;
390
391 case NOPROVIDER:
392 dismissDialog(DLG_PROGRESS);
393 MessageBox.showMessage(StationList.this,"No location provider enabled. Plase enable gps.");
394 break;
395 case LOCATIONFIXTIMEOUT:
396 if (isRunning) {
397 locator.stopSearch();
398 if (locator.hasLocation()) {
399 stationsFetched.sendEmptyMessage( GOTLOCATION );
400 } else {
401 dismissDialog(DLG_PROGRESS);
402
403 AlertDialog.Builder builder = new AlertDialog.Builder(StationList.this);
404 builder.setMessage("Location fix timed out");
405 builder.setCancelable(true);
406 builder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
407 public void onClick(DialogInterface dialog, int id) {
408 dialog.dismiss();
409 startLookup();
410
411 }
412 });
413 builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
414 public void onClick(DialogInterface dialog, int id) {
415 dialog.dismiss();
416 }
417 });
418 builder.show();
419
420 }
421 }
422 break;
423 }
424 isRunning = false;
425 }
426 };
427
428
429 class FindStationsTask extends AsyncTask<Void,Void,Void> {
430
431 LookupMethod method = LookupMethod.MethodNone;
432 boolean success;
433 String name;
434 Location loc;
435 String ids;
436
437 public void searchByName(String n, Location l) {
438
439 method = LookupMethod.ByName;
440 loc = l;
441 name = n;
442 }
443
444 public void searchByLocation(Location l) {
445 method = LookupMethod.ByLocation;
446 loc = l;
447 }
448
449 public void searchByIds(String id, Location l) {
450
451 method = LookupMethod.ByList;
452 loc = l;
453 ids = id;
454 }
455
456 @Override
457 protected void onPreExecute() {
458
459 if (method.equals(LookupMethod.MethodNone))
460 throw new RuntimeException("Method not set");
461 super.onPreExecute();
462 }
463
464 @Override
465 protected Void doInBackground(Void... params) {
466
467 switch (method) {
468 case ByLocation:
469 success = stationProvider.lookupStations(loc);
470 break;
471 case ByName:
472 success = stationProvider.lookupStationsByName(name);
473 break;
474 case ByList:
475 success = stationProvider.lookupStationsByIds(ids);
476 break;
477 default:
478 success = false; // not possible
479 }
480
481
482 Location dummy = new Location("gps");
483 List<StationBean> stations = stationProvider.getStations();
484
485 for (StationBean station : stations) {
486 String addr = lookupAddress(station.getLatitude(), station.getLongitude());
487 station.setAddress(addr);
488
489
490 if (method.equals(LookupMethod.ByName) || method.equals(LookupMethod.ByList)) {
491 if (loc != null) { //only do the distance calc if we have a location
492 dummy.setLatitude(station.getLatitude());
493 dummy.setLongitude(station.getLongitude());
494 station.setDistance( (int)loc.distanceTo(dummy) );
495 } else {
496 station.setDistance(0);
497 }
498 }
499
500 }
501
502 return null;
503 }
504
505 @Override
506 protected void onPostExecute(Void result) {
507 super.onPostExecute(result);
508 dialog.dismiss();
509
510 //set title
511 switch (method) {
512 case ByLocation:
513 dialogTitle = "Traininfo DK - Nearby stations";
514 break;
515 case ByName:
516 dialogTitle = "Traininfo DK - Search";
517 break;
518 case ByList:
519 dialogTitle = "Traininfo DK - Favorites";
520 break;
521 default:
522 dialogTitle = "";//not possible
523 }
524
525 StationList.this.setTitle(dialogTitle);
526 //set title end
527
528 if (success) {
529 if (stationProvider.getStations().size() == 0)
530 MessageBox.showMessage(StationList.this, "No stations found!"); // this should not be possible !?!
531 stations = stationProvider.getStations();
532 adapter.setStations( stations );
533
534 showingFavorites = method.equals(LookupMethod.ByList);
535
536 } else { //communication or parse errors
537 AlertDialog.Builder builder = new AlertDialog.Builder(StationList.this);
538 builder.setMessage("Error on finding nearby stations");
539 builder.setCancelable(true);
540 builder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
541 public void onClick(DialogInterface dialog, int id) {
542 dialog.dismiss();
543
544 stationsFetched.post( new Runnable() {
545 @Override
546 public void run() {
547 startLocatorTask();
548 }
549 });
550 }
551 });
552 builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
553 public void onClick(DialogInterface dialog, int id) {
554 dialog.dismiss();
555 }
556 });
557 builder.show();
558 }
559 }
560 }
561
562
563 class FavoritesMenu implements OnCreateContextMenuListener {
564 private final static int FAVORITES_ADD = 9001;
565 private final static int FAVORITES_REMOVE = 9002;
566
567 private int selectedPosition;
568
569
570 @Override
571 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
572
573 AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
574 selectedPosition = info.position;
575 int stationID = stations.get(selectedPosition).getId();
576
577 if (!favorites.contains(stationID)) {
578 menu.add(0, FAVORITES_ADD, 0, "Add to favorites");
579 } else {
580 menu.add(0, FAVORITES_REMOVE, 0, "Remove from favorites");
581 }
582
583 }
584
585 public void onContextItemSelected(MenuItem item) {
586 StationBean sb = stations.get(selectedPosition);
587
588 int stationID = sb.getId();
589 if (item.getItemId() == FAVORITES_ADD) {
590 favorites.add(stationID);
591 Toast.makeText(StationList.this, "Station added", Toast.LENGTH_SHORT).show();
592 } else {
593
594 favorites.remove(stationID);
595 Toast.makeText(StationList.this, "Station removed", Toast.LENGTH_SHORT).show();
596
597 if (showingFavorites) {
598 stations.remove(selectedPosition);
599 adapter.notifyDataSetChanged();
600 }
601 }
602 Editor ed = prefs.edit();
603 ed.putString("favorites", favorites.toString());
604 ed.commit();
605 }
606 }
607 }

  ViewVC Help
Powered by ViewVC 1.1.20