/[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 1027 - (show annotations) (download)
Wed Sep 8 06:03:45 2010 UTC (13 years, 8 months ago) by torben
File size: 16449 byte(s)
Clean up the cache to avoid OutOfMemoryError exceptions
1 package dk.thoerup.traininfo;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6
7 import android.app.Activity;
8 import android.app.AlertDialog;
9 import android.app.Dialog;
10 import android.app.ListActivity;
11 import android.app.ProgressDialog;
12 import android.content.DialogInterface;
13 import android.content.Intent;
14 import android.content.SharedPreferences;
15 import android.content.SharedPreferences.Editor;
16 import android.location.Location;
17 import android.os.AsyncTask;
18 import android.os.Bundle;
19 import android.os.Handler;
20 import android.os.Message;
21
22 import android.view.ContextMenu;
23 import android.view.LayoutInflater;
24 import android.view.Menu;
25 import android.view.MenuItem;
26 import android.view.View;
27 import android.view.ContextMenu.ContextMenuInfo;
28 import android.view.View.OnCreateContextMenuListener;
29 import android.widget.AdapterView;
30 import android.widget.EditText;
31 import android.widget.ListView;
32 import android.widget.Toast;
33 import dk.thoerup.traininfo.provider.ProviderFactory;
34 import dk.thoerup.traininfo.provider.StationProvider;
35 import dk.thoerup.traininfo.stationmap.GeoPair;
36 import dk.thoerup.traininfo.stationmap.StationMapView;
37 import dk.thoerup.traininfo.util.IntSet;
38 import dk.thoerup.traininfo.util.MessageBox;
39
40 import static dk.thoerup.traininfo.R.string.*;
41
42 public class StationList extends ListActivity {
43 public static final int GOTLOCATION = 1001;
44 public static final int GOTSTATIONLIST = 1002;
45 public static final int NOPROVIDER = 1003;
46 public static final int LOCATIONFIXTIMEOUT = 1004;
47
48 public static final int OPTIONS_MAP = 2003;
49 public static final int OPTIONS_GPSINFO = 2004;
50
51 public static final int DLG_PROGRESS = 3001;
52 public static final int DLG_STATIONNAME = 3002;
53
54
55 public static final int GPS_TIMEOUT_MS = 15000; //how long are we willing to wait for gps fix -in milliseconds
56
57
58 static enum LookupMethod {
59 ByLocation,
60 ByName,
61 ByList,
62 MethodNone
63 }
64
65
66 String dialogMessage = "";
67 ProgressDialog dialog;
68 LocationLookup locationLookup = null;
69 FindStationsTask findStationsTask;
70 StationsFetchedHandler stationsFetched = new StationsFetchedHandler();
71
72 GeoPair location = new GeoPair();
73
74 boolean isLaunchedforShortcut;
75 boolean isRunning = false;
76 List<StationBean> stations = new ArrayList<StationBean>();
77
78 StationProvider stationProvider = ProviderFactory.getStationProvider();
79
80 StationListAdapter adapter = null;
81
82 FavoritesMenu contextMenu = new FavoritesMenu();
83 IntSet favorites = new IntSet();
84
85 WelcomeScreen.ListType listType;
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.stationlist);
96
97
98 adapter = new StationListAdapter(this);
99 setListAdapter(adapter);
100
101 ListView lv = getListView();
102 lv.setOnCreateContextMenuListener(contextMenu);
103
104 locationLookup = 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 listType = (WelcomeScreen.ListType) getIntent().getSerializableExtra("type");
114 setTitle();
115
116 isLaunchedforShortcut = getIntent().getBooleanExtra("shortcut", false);
117
118 if (savedInstanceState == null) {
119
120
121 switch (listType) {
122 case ListNearest:
123 startLookup();
124 break;
125 case ListSearch:
126 showDialog(DLG_STATIONNAME);
127 break;
128 case ListFavorites:
129 startFavoriteLookup();
130 break;
131 default:
132 // Not possible !?!
133 }
134
135 } else {
136 stations = (ArrayList<StationBean>) savedInstanceState.getSerializable("stations");
137 adapter.setStations(stations);
138 location = (GeoPair) savedInstanceState.getSerializable("location");
139 }
140
141 }
142
143
144
145
146 @Override
147 protected void onStart() {
148 super.onStart();
149 ProviderFactory.purgeOldEntries();
150 }
151
152
153
154
155 @Override
156 protected void onDestroy() {
157 super.onDestroy();
158
159 isRunning = false;
160
161 if (locationLookup != null) {
162 locationLookup.stopSearch();
163 }
164 if (findStationsTask != null) {
165 findStationsTask.cancel(true);
166 }
167 }
168
169
170 protected void setTitle() {
171 String dialogTitle = getResources().getString(app_name);
172 switch (listType) {
173 case ListNearest:
174 dialogTitle += " - " + getString(stationlist_nearbystations);
175 break;
176 case ListSearch:
177 dialogTitle += " - " + getString(stationlist_search);
178 break;
179 case ListFavorites:
180 dialogTitle += " - " + getString(stationlist_favorites);
181 break;
182 default:
183 dialogTitle = "";//not possible
184 }
185
186 setTitle(dialogTitle);
187
188 }
189
190
191
192 @Override
193 public void onSaveInstanceState(Bundle outState)
194 {
195 if (dialog != null && dialog.isShowing())
196 dialog.dismiss();
197 outState.putSerializable("stations", (ArrayList<StationBean>) stations);
198 outState.putSerializable("location", location);
199
200 }
201
202
203
204 @Override
205 public boolean onCreateOptionsMenu(Menu menu) {
206 MenuItem item;
207
208 item = menu.add(0, OPTIONS_MAP, 0, getString(stationlist_stationmap));
209 item.setIcon(android.R.drawable.ic_menu_mapmode);
210
211 item = menu.add(0, OPTIONS_GPSINFO, 0, getString(stationlist_gpsinfo));
212 item.setIcon(android.R.drawable.ic_menu_mapmode);
213
214 return true;
215 }
216
217 @Override
218 public boolean onOptionsItemSelected(MenuItem item) {
219 boolean retval = true;
220
221 //TODO: Cleanup
222 switch (item.getItemId()) {
223 case OPTIONS_MAP:
224
225 Intent intent = new Intent(this,StationMapView.class);
226
227 ArrayList<GeoPair> stationPoints = new ArrayList<GeoPair>();
228 for (StationBean st : stations ) {
229 stationPoints.add( new GeoPair(st.getLatitude(), st.getLongitude(), st.getName()) );
230 }
231
232 intent.putExtra("stations", stationPoints);
233
234 startActivity(intent);
235 break;
236 case OPTIONS_GPSINFO:
237 Location loc = locationLookup.getLocation();
238 StringBuffer message = new StringBuffer();
239 message.append( getString(stationlist_locationinfo) ).append(":\n");
240 if (loc != null) {
241 message.append( getString(stationlist_obtainedby) ).append( loc.getProvider() ).append("\n");
242 message.append( getString(stationlist_accuracy) ).append( (int)loc.getAccuracy()).append("m\n");
243 message.append( getString(stationlist_latitude) ).append( (float)loc.getLatitude()).append("\n");
244 message.append( getString(stationlist_longitude) ).append( (float)loc.getLongitude() ).append("\n");
245 } else {
246 message.append( getString(stationlist_nolocation) );
247 }
248
249 MessageBox.showMessage(this, message.toString(), false);
250 break;
251 default:
252 retval = super.onOptionsItemSelected(item);
253 }
254
255 return retval;
256 }
257
258
259
260 @Override
261 public boolean onContextItemSelected(MenuItem item) {
262 contextMenu.onContextItemSelected(item);
263 return true;
264
265
266 }
267
268 public void showMessageAndClose(String message) {
269 AlertDialog.Builder builder = new AlertDialog.Builder(this);
270 builder.setMessage(message)
271 .setCancelable(false)
272 .setPositiveButton("OK", new DialogInterface.OnClickListener() {
273 public void onClick(DialogInterface dialog, int id) {
274 dialog.dismiss();
275 StationList.this.finish();
276 }
277 })
278 .show();
279 }
280
281
282
283
284 @Override
285 protected Dialog onCreateDialog(int id) {
286 switch (id) {
287 case DLG_PROGRESS:
288 ProgressDialog dlg = new ProgressDialog(this);
289 dlg.setMessage( getString(stationlist_waitforlocation) );
290 dlg.setCancelable(false);
291 return dlg;
292 case DLG_STATIONNAME:
293 LayoutInflater factory = LayoutInflater.from(this);
294 final View rootView = factory.inflate(R.layout.textinput, null);
295
296
297 AlertDialog.Builder builder = new AlertDialog.Builder(this);
298
299 builder.setTitle( getString(stationlist_stationsearch) );
300 builder.setView(rootView);
301 builder.setCancelable(true);
302 builder.setPositiveButton( getString(generic_search), new DialogInterface.OnClickListener() {
303 public void onClick(DialogInterface dialog, int which) {
304 EditText et = (EditText) rootView.findViewById(R.id.EditText);
305 dialog.dismiss();
306 String search = et.getText().toString().trim();
307 if (search.length() >= 2) {
308 startNameSearch(search);
309 } else {
310 showMessageAndClose( getString(stationlist_twocharmin) );
311 }
312 }
313 });
314 builder.setNegativeButton(getString(generic_cancel), new DialogInterface.OnClickListener() {
315 public void onClick(DialogInterface dialog, int which) {
316 dialog.dismiss();
317 StationList.this.finish(); // Close this Activity
318 }
319 });
320 return builder.create();
321
322 default:
323 return super.onCreateDialog(id);
324 }
325
326 }
327
328
329 @Override
330 protected void onPrepareDialog(int id, Dialog dialog) {
331 super.onPrepareDialog(id, dialog);
332 switch (id) {
333 case DLG_PROGRESS:
334 this.dialog = (ProgressDialog) dialog;
335 if (!dialogMessage.equals("")) {
336 this.dialog.setMessage(dialogMessage);
337 dialogMessage = "";
338 }
339 break;
340 }
341 }
342
343 @Override
344 protected void onListItemClick(ListView l, View v, int position, long id) {
345 super.onListItemClick(l, v, position, id);
346
347 StationBean station = stations.get(position);
348
349 if (isLaunchedforShortcut == true) {
350 Intent i = new Intent();
351 i.putExtra("station", station);
352 setResult(Activity.RESULT_OK, i);
353 finish();
354 } else {
355 Intent intent = new Intent(this, DepartureList.class);
356 intent.putExtra("stationbean", station);
357 startActivity(intent);
358 }
359 }
360
361 /////////////////////////////////////////////////////////////
362 //
363
364 public void startLookup() {
365 isRunning = true;
366 dialogMessage = getString( stationlist_waitforlocation );
367 showDialog(DLG_PROGRESS);
368
369 locationLookup.locateStations();
370 stationsFetched.sendEmptyMessageDelayed(LOCATIONFIXTIMEOUT, GPS_TIMEOUT_MS);
371 }
372
373 void startNameSearch(String name) {
374 dialogMessage = getString( stationlist_findbyname );
375 showDialog(DLG_PROGRESS);
376
377 findStationsTask = new FindStationsTask();
378 findStationsTask.searchByName(name);
379 findStationsTask.execute();
380
381 }
382
383 public void startFavoriteLookup() {
384
385 if (favorites.size() > 0) {
386 dialogMessage = getString( stationlist_loadfavorites );
387 showDialog(DLG_PROGRESS);
388
389 findStationsTask = new FindStationsTask();
390 findStationsTask.searchByIds( favorites.toString() );
391 findStationsTask.execute();
392 } else {
393 showMessageAndClose( getString( stationlist_nofavorites ) );
394 }
395 }
396
397
398
399 void startLocatorTask()
400 {
401 dialogMessage = getString( stationlist_findingnearby );
402 showDialog(DLG_PROGRESS);
403
404 findStationsTask = new FindStationsTask();
405 findStationsTask.searchByLocation( locationLookup.getLocation() );
406 findStationsTask.execute();
407 }
408
409
410 ////////////////////////////////////////////////////////////////////////////
411 // Inner classes
412
413 class StationsFetchedHandler extends Handler {
414 @Override
415 public void handleMessage(Message msg) {
416
417 switch (msg.what) {
418 case GOTLOCATION:
419 dismissDialog(DLG_PROGRESS);
420
421 startLocatorTask();
422 location = GeoPair.fromLocation( locationLookup.getLocation() );
423
424 break;
425
426 case NOPROVIDER:
427 dismissDialog(DLG_PROGRESS);
428 MessageBox.showMessage(StationList.this, getString(stationlist_nolocationprovider), true );
429 //StationList.this.finish();
430 break;
431 case LOCATIONFIXTIMEOUT:
432 if (isRunning) {
433 locationLookup.stopSearch();
434 if (locationLookup.hasLocation()) {
435 stationsFetched.sendEmptyMessage( GOTLOCATION );
436 } else {
437 dismissDialog(DLG_PROGRESS);
438
439 AlertDialog.Builder builder = new AlertDialog.Builder(StationList.this);
440 builder.setMessage( getString( stationlist_gpstimeout) );
441 builder.setCancelable(true);
442 builder.setPositiveButton(getString(generic_retry), new DialogInterface.OnClickListener() {
443 public void onClick(DialogInterface dialog, int id) {
444 dialog.dismiss();
445 startLookup();
446
447 }
448 });
449 builder.setNegativeButton( getString(generic_cancel), new DialogInterface.OnClickListener() {
450 public void onClick(DialogInterface dialog, int id) {
451 dialog.dismiss();
452 }
453 });
454 builder.show();
455
456 }
457 }
458 break;
459 }
460 isRunning = false;
461 }
462 };
463
464
465 class FindStationsTask extends AsyncTask<Void,Void,Void> {
466
467 LookupMethod method = LookupMethod.MethodNone;
468 String name;
469 Location loc;
470 String ids;
471
472 public void searchByName(String n) {
473
474 method = LookupMethod.ByName;
475 name = n;
476 }
477
478 public void searchByLocation(Location l) {
479 method = LookupMethod.ByLocation;
480 loc = l;
481 }
482
483 public void searchByIds(String id) {
484
485 method = LookupMethod.ByList;
486 ids = id;
487 }
488
489 @Override
490 protected void onPreExecute() {
491
492 if (method.equals(LookupMethod.MethodNone))
493 throw new RuntimeException("Method not set");
494 super.onPreExecute();
495 }
496
497 @Override
498 protected Void doInBackground(Void... params) {
499
500 switch (method) {
501 case ByLocation:
502 stations = stationProvider.lookupStations(loc);
503 break;
504 case ByName:
505 stations = stationProvider.lookupStationsByName(name);
506 break;
507 case ByList:
508 stations = stationProvider.lookupStationsByIds(ids);
509 break;
510 default:
511 stations = null; // not possible
512 }
513
514
515 return null;
516 }
517
518 @Override
519 protected void onPostExecute(Void result) {
520 super.onPostExecute(result);
521 dialog.dismiss();
522
523
524 if (stations != null) {
525 if (stations.size() == 0) {
526 showMessageAndClose(getString(stationlist_nostations));
527 }
528
529 StationList.this.getListView().invalidateViews();
530 adapter.setStations( stations );
531
532
533 } else { //communication or parse errors
534 AlertDialog.Builder builder = new AlertDialog.Builder(StationList.this);
535 builder.setMessage(getString(stationlist_fetcherror));
536 builder.setCancelable(true);
537 builder.setPositiveButton(getString(generic_retry), new DialogInterface.OnClickListener() {
538 public void onClick(DialogInterface dialog, int id) {
539 dialog.dismiss();
540
541 Runnable runner = null;
542 switch (method) {
543 case ByLocation:
544 runner = new Runnable() {
545 @Override
546 public void run() {
547 startLocatorTask();
548 }
549 };
550 break;
551 case ByName:
552 runner = new Runnable() {
553 @Override
554 public void run() {
555 startNameSearch( FindStationsTask.this.name );
556 }
557 };
558 break;
559 case ByList:
560 runner = new Runnable() {
561 @Override
562 public void run() {
563 startFavoriteLookup();
564 }
565 };
566 break;
567 }
568
569 stationsFetched.post( runner );
570 }
571 });
572 builder.setNegativeButton(getString(generic_cancel), new DialogInterface.OnClickListener() {
573 public void onClick(DialogInterface dialog, int id) {
574 dialog.dismiss();
575 StationList.this.finish();
576 }
577 });
578
579 builder.show();
580 }
581 }
582 }
583
584
585 class FavoritesMenu implements OnCreateContextMenuListener {
586 private final static int FAVORITES_ADD = 9001;
587 private final static int FAVORITES_REMOVE = 9002;
588
589 private int selectedPosition;
590
591
592 @Override
593 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
594
595 AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
596 selectedPosition = info.position;
597 int stationID = stations.get(selectedPosition).getId();
598
599 if (!favorites.contains(stationID)) {
600 menu.add(0, FAVORITES_ADD, 0, getString(stationlist_addfavorite) );
601 } else {
602 menu.add(0, FAVORITES_REMOVE, 0, getString(stationlist_removefavorite) );
603 }
604
605 }
606
607 public void onContextItemSelected(MenuItem item) {
608 StationBean sb = stations.get(selectedPosition);
609
610 int stationID = sb.getId();
611 if (item.getItemId() == FAVORITES_ADD) {
612 favorites.add(stationID);
613 Toast.makeText(StationList.this, getString(stationlist_stationadded), Toast.LENGTH_SHORT).show();
614 } else {
615
616 favorites.remove(stationID);
617 Toast.makeText(StationList.this, getString(stationlist_stationremoved), Toast.LENGTH_SHORT).show();
618
619
620 if (listType.equals( WelcomeScreen.ListType.ListFavorites) ) {
621 stations.remove(selectedPosition);
622 adapter.notifyDataSetChanged();
623 }
624 }
625 Editor ed = prefs.edit();
626 ed.putString("favorites", favorites.toString());
627 ed.commit();
628 }
629 }
630 }

  ViewVC Help
Powered by ViewVC 1.1.20