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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 480 - (hide annotations) (download)
Wed Oct 28 12:52:52 2009 UTC (14 years, 7 months ago) by torben
File size: 16430 byte(s)
Also save title
1 torben 237 package dk.thoerup.traininfo;
2    
3 torben 258 import java.util.ArrayList;
4     import java.util.List;
5 torben 294 import java.util.Locale;
6 torben 258
7 torben 336 import android.app.AlertDialog;
8 torben 237 import android.app.Dialog;
9     import android.app.ListActivity;
10     import android.app.ProgressDialog;
11 torben 336 import android.content.DialogInterface;
12 torben 237 import android.content.Intent;
13 torben 433 import android.content.SharedPreferences;
14 torben 435 import android.content.SharedPreferences.Editor;
15 torben 294 import android.location.Address;
16     import android.location.Geocoder;
17 torben 319 import android.location.Location;
18 torben 241 import android.os.AsyncTask;
19 torben 237 import android.os.Bundle;
20     import android.os.Handler;
21     import android.os.Message;
22 torben 294 import android.util.Log;
23 torben 433 import android.view.ContextMenu;
24 torben 381 import android.view.LayoutInflater;
25 torben 368 import android.view.Menu;
26     import android.view.MenuItem;
27 torben 237 import android.view.View;
28 torben 433 import android.view.ContextMenu.ContextMenuInfo;
29     import android.view.View.OnCreateContextMenuListener;
30     import android.widget.AdapterView;
31 torben 381 import android.widget.EditText;
32 torben 237 import android.widget.ListView;
33 torben 433 import android.widget.Toast;
34 torben 319 import dk.thoerup.traininfo.provider.ProviderFactory;
35     import dk.thoerup.traininfo.provider.StationProvider;
36 torben 368 import dk.thoerup.traininfo.stationmap.GeoPair;
37     import dk.thoerup.traininfo.stationmap.StationMapView;
38 torben 433 import dk.thoerup.traininfo.util.IntSet;
39 torben 245 import dk.thoerup.traininfo.util.MessageBox;
40 torben 237
41 torben 336 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 torben 368
47 torben 381 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 torben 433 public static final int OPTIONS_FAVORITES = 2005;
52    
53 torben 336
54 torben 237
55 torben 381 public static final int DLG_PROGRESS = 3001;
56     public static final int DLG_STATIONNAME = 3002;
57 torben 237
58 torben 440 static enum LookupMethod {
59     ByLocation,
60     ByName,
61     ByList,
62     MethodNone
63     }
64    
65    
66 torben 336 String dialogMessage = "";
67 torben 237 ProgressDialog dialog;
68 torben 319 LocationLookup locator = null;
69 torben 440 FindStationsTask findStationsTask;
70 torben 381 StationsFetchedHandler stationsFetched = new StationsFetchedHandler();
71 torben 237
72 torben 374 GeoPair location = new GeoPair();
73    
74 torben 258 boolean isRunning = false;
75     List<StationBean> stations = new ArrayList<StationBean>();
76    
77 torben 319 StationProvider stationProvider = ProviderFactory.getStationProvider();
78 torben 381
79     StationListAdapter adapter = null;
80 torben 258
81 torben 433 FavoritesMenu contextMenu = new FavoritesMenu();
82     IntSet favorites = new IntSet();
83    
84 torben 473 boolean showingFavorites = false;
85 torben 480 String dialogTitle;
86 torben 433 SharedPreferences prefs;
87    
88 torben 381 ///////////////////////////////////////////////////////////////////////////////////////////
89     //Activity call backs
90    
91 torben 258 @SuppressWarnings("unchecked")
92 torben 237 @Override
93     public void onCreate(Bundle savedInstanceState) {
94     super.onCreate(savedInstanceState);
95     setContentView(R.layout.main);
96    
97 torben 241
98 torben 237 adapter = new StationListAdapter(this);
99     setListAdapter(adapter);
100    
101 torben 433 ListView lv = getListView();
102     lv.setOnCreateContextMenuListener(contextMenu);
103    
104 torben 319 locator = new LocationLookup(this, stationsFetched);
105 torben 433
106    
107     prefs = getSharedPreferences("TrainStation", 0);
108     String favoriteString = prefs.getString("favorites", "");
109     if (! favoriteString.equals("") ) {
110     favorites.fromString(favoriteString);
111     }
112    
113 torben 258 if (savedInstanceState == null) {
114     startLookup();
115     } else {
116     stations = (ArrayList<StationBean>) savedInstanceState.getSerializable("stations");
117 torben 260 adapter.setStations(stations);
118 torben 374 location = (GeoPair) savedInstanceState.getSerializable("location");
119 torben 480 dialogTitle = savedInstanceState.getString("title");
120     setTitle(dialogTitle);
121 torben 258 }
122 torben 237 }
123 torben 371
124    
125 torben 243 @Override
126     public void onSaveInstanceState(Bundle outState)
127     {
128 torben 258 if (dialog != null && dialog.isShowing())
129 torben 243 dialog.dismiss();
130 torben 258 outState.putSerializable("stations", (ArrayList<StationBean>) stations);
131 torben 374 outState.putSerializable("location", location);
132 torben 480 outState.putString("title", dialogTitle);
133 torben 243 }
134 torben 237
135 torben 243
136 torben 237
137     @Override
138 torben 368 public boolean onCreateOptionsMenu(Menu menu) {
139 torben 419 MenuItem item;
140    
141 torben 439 item = menu.add(0, OPTIONS_RESCAN, 0, "Nearest stations");
142 torben 419 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 torben 433 item = menu.add(0, OPTIONS_FAVORITES, 0, "Favorites");
148     item.setIcon(android.R.drawable.ic_menu_agenda);
149    
150 torben 439 item = menu.add(0, OPTIONS_MAP, 0, "Station map");
151 torben 419 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 torben 368 return true;
156     }
157    
158     @Override
159     public boolean onOptionsItemSelected(MenuItem item) {
160 torben 381 boolean retval = true;
161    
162 torben 368
163     switch (item.getItemId()) {
164 torben 381 case OPTIONS_RESCAN:
165     startLookup();
166     break;
167     case OPTIONS_NAMESEARCH:
168     showDialog(DLG_STATIONNAME);
169     break;
170 torben 433 case OPTIONS_FAVORITES:
171     startFavoriteLookup();
172     break;
173 torben 368 case OPTIONS_MAP:
174    
175     Intent intent = new Intent(this,StationMapView.class);
176 torben 374 intent.putExtra("userlocation", location );
177 torben 368
178     ArrayList<GeoPair> stationPoints = new ArrayList<GeoPair>();
179     for (StationBean st : stations ) {
180 torben 369 stationPoints.add( new GeoPair(st.getLatitude(), st.getLongitude(), st.getName()) );
181 torben 368 }
182    
183     intent.putExtra("stations", stationPoints);
184    
185     startActivity(intent);
186     break;
187 torben 371 case OPTIONS_ABOUT:
188     String ver = this.getResources().getString(R.string.app_version);
189    
190 torben 401 Location loc = locator.getLocation();
191 torben 371 StringBuffer message = new StringBuffer();
192     message.append("TrainInfo DK v").append(ver).append("\n");
193     message.append("By Torben Nielsen\n");
194 torben 401 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 torben 371
199     MessageBox.showMessage(this, message.toString());
200     break;
201 torben 368 default:
202     retval = super.onOptionsItemSelected(item);
203     }
204    
205     return retval;
206     }
207 torben 433
208    
209 torben 368
210     @Override
211 torben 433 public boolean onContextItemSelected(MenuItem item) {
212     contextMenu.onContextItemSelected(item);
213     return true;
214    
215    
216     }
217    
218    
219    
220    
221     @Override
222 torben 237 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 torben 336 return dlg;
229 torben 381 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 torben 382 MessageBox.showMessage(StationList.this, "Two characters minimum" );
247 torben 381 }
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 torben 237 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 torben 336 if (!dialogMessage.equals("")) {
271     this.dialog.setMessage(dialogMessage);
272     dialogMessage = "";
273     }
274 torben 237 break;
275     }
276     }
277 torben 381
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 torben 237
284 torben 381 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 torben 237 public void startLookup() {
303     isRunning = true;
304 torben 381 dialogMessage = "Wait for location fix";
305 torben 237 showDialog(DLG_PROGRESS);
306    
307     locator.locateStations();
308 torben 336 stationsFetched.sendEmptyMessageDelayed(LOCATIONFIXTIMEOUT, 20000);
309 torben 237 }
310 torben 381
311     void startNameSearch(String name) {
312     dialogMessage = "Finding stations by name";
313     showDialog(DLG_PROGRESS);
314 torben 237
315 torben 440 findStationsTask = new FindStationsTask();
316     findStationsTask.searchByName(name, locator.getLocation());
317     findStationsTask.execute();
318 torben 381
319     }
320 torben 433
321     public void startFavoriteLookup() {
322    
323 torben 440 if (favorites.size() > 0) {
324 torben 433 dialogMessage = "Loading favorites";
325     showDialog(DLG_PROGRESS);
326 torben 237
327 torben 440 findStationsTask = new FindStationsTask();
328     findStationsTask.searchByIds(favorites.toString(), locator.getLocation());
329     findStationsTask.execute();
330 torben 433 } else {
331     MessageBox.showMessage(this, "Favorite list is empty");
332     }
333     }
334 torben 381
335 torben 433
336 torben 381
337     void startLocatorTask()
338     {
339     dialogMessage = "Finding nearby stations";
340     showDialog(DLG_PROGRESS);
341    
342 torben 440 findStationsTask = new FindStationsTask();
343     findStationsTask.searchByLocation( locator.getLocation() );
344     findStationsTask.execute();
345 torben 381 }
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 torben 237 @Override
380     public void handleMessage(Message msg) {
381 torben 336
382 torben 237 switch (msg.what) {
383     case GOTLOCATION:
384 torben 336 dismissDialog(DLG_PROGRESS);
385    
386     startLocatorTask();
387 torben 374 location = GeoPair.fromLocation( locator.getLocation() );
388 torben 336
389 torben 237 break;
390 torben 319
391 torben 237 case NOPROVIDER:
392 torben 336 dismissDialog(DLG_PROGRESS);
393     MessageBox.showMessage(StationList.this,"No location provider enabled. Plase enable gps.");
394 torben 237 break;
395 torben 336 case LOCATIONFIXTIMEOUT:
396 torben 237 if (isRunning) {
397 torben 336 locator.stopSearch();
398 torben 285 if (locator.hasLocation()) {
399 torben 336 stationsFetched.sendEmptyMessage( GOTLOCATION );
400     } else {
401     dismissDialog(DLG_PROGRESS);
402    
403     AlertDialog.Builder builder = new AlertDialog.Builder(StationList.this);
404 torben 420 builder.setMessage("Location fix timed out");
405 torben 336 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 torben 285 }
421 torben 237 }
422     break;
423     }
424     isRunning = false;
425     }
426     };
427 torben 381
428 torben 237
429 torben 440 class FindStationsTask extends AsyncTask<Void,Void,Void> {
430 torben 336
431 torben 381 LookupMethod method = LookupMethod.MethodNone;
432     boolean success;
433     String name;
434     Location loc;
435 torben 433 String ids;
436 torben 237
437 torben 381 public void searchByName(String n, Location l) {
438 torben 317
439 torben 381 method = LookupMethod.ByName;
440     loc = l;
441     name = n;
442 torben 317 }
443    
444 torben 381 public void searchByLocation(Location l) {
445     method = LookupMethod.ByLocation;
446     loc = l;
447     }
448    
449 torben 433 public void searchByIds(String id, Location l) {
450    
451     method = LookupMethod.ByList;
452     loc = l;
453     ids = id;
454     }
455    
456 torben 241 @Override
457     protected void onPreExecute() {
458 torben 258
459 torben 381 if (method.equals(LookupMethod.MethodNone))
460     throw new RuntimeException("Method not set");
461 torben 241 super.onPreExecute();
462     }
463    
464     @Override
465     protected Void doInBackground(Void... params) {
466 torben 473
467     switch (method) {
468     case ByLocation:
469 torben 381 success = stationProvider.lookupStations(loc);
470 torben 473 break;
471     case ByName:
472 torben 433 success = stationProvider.lookupStationsByName(name);
473 torben 473 break;
474     case ByList:
475 torben 433 success = stationProvider.lookupStationsByIds(ids);
476 torben 473 break;
477     default:
478     success = false; // not possible
479     }
480 torben 433
481 torben 473
482 torben 381 Location dummy = new Location("gps");
483 torben 319 List<StationBean> stations = stationProvider.getStations();
484 torben 381
485     for (StationBean station : stations) {
486 torben 317 String addr = lookupAddress(station.getLatitude(), station.getLongitude());
487     station.setAddress(addr);
488 torben 381
489 torben 478
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 torben 476 dummy.setLatitude(station.getLatitude());
493     dummy.setLongitude(station.getLongitude());
494     station.setDistance( (int)loc.distanceTo(dummy) );
495 torben 478 } else {
496     station.setDistance(0);
497 torben 476 }
498 torben 381 }
499 torben 478
500 torben 381 }
501 torben 317
502 torben 241 return null;
503     }
504    
505     @Override
506     protected void onPostExecute(Void result) {
507     super.onPostExecute(result);
508 torben 319 dialog.dismiss();
509    
510 torben 473 //set title
511     switch (method) {
512     case ByLocation:
513 torben 480 dialogTitle = "Traininfo DK - Nearby stations";
514 torben 473 break;
515     case ByName:
516 torben 480 dialogTitle = "Traininfo DK - Search";
517 torben 473 break;
518     case ByList:
519 torben 480 dialogTitle = "Traininfo DK - Favorites";
520 torben 473 break;
521     default:
522 torben 480 dialogTitle = "";//not possible
523 torben 473 }
524    
525 torben 480 StationList.this.setTitle(dialogTitle);
526 torben 473 //set title end
527    
528 torben 319 if (success) {
529     if (stationProvider.getStations().size() == 0)
530 torben 336 MessageBox.showMessage(StationList.this, "No stations found!"); // this should not be possible !?!
531 torben 319 stations = stationProvider.getStations();
532 torben 473 adapter.setStations( stations );
533 torben 319
534 torben 473 showingFavorites = method.equals(LookupMethod.ByList);
535    
536 torben 319 } else { //communication or parse errors
537 torben 336 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 torben 319 }
559 torben 241 }
560     }
561 torben 433
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 torben 441 if (!favorites.contains(stationID)) {
578 torben 433 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 torben 473
594 torben 433 favorites.remove(stationID);
595     Toast.makeText(StationList.this, "Station removed", Toast.LENGTH_SHORT).show();
596 torben 473
597     if (showingFavorites) {
598     stations.remove(selectedPosition);
599     adapter.notifyDataSetChanged();
600     }
601 torben 433 }
602 torben 435 Editor ed = prefs.edit();
603     ed.putString("favorites", favorites.toString());
604     ed.commit();
605 torben 433 }
606     }
607 torben 237 }

  ViewVC Help
Powered by ViewVC 1.1.20