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

  ViewVC Help
Powered by ViewVC 1.1.20