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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1432 - (show annotations) (download)
Tue May 3 12:35:34 2011 UTC (13 years ago) by torben
File size: 18266 byte(s)
don't crash if we couln't launch google maps (or other geo: uri handler)
1 package dk.thoerup.traininfo;
2
3 import static dk.thoerup.traininfo.R.string.departurelist_fetcharrivals;
4 import static dk.thoerup.traininfo.R.string.departurelist_fetchdepartures;
5 import static dk.thoerup.traininfo.R.string.generic_cancel;
6 import static dk.thoerup.traininfo.R.string.generic_retry;
7
8 import java.text.NumberFormat;
9
10 import android.app.AlertDialog;
11 import android.app.Dialog;
12 import android.app.ListActivity;
13 import android.app.ProgressDialog;
14 import android.content.DialogInterface;
15 import android.content.Intent;
16 import android.graphics.Typeface;
17 import android.net.Uri;
18 import android.os.AsyncTask;
19 import android.os.Bundle;
20 import android.util.Log;
21 import android.view.Menu;
22 import android.view.MenuItem;
23 import android.view.View;
24 import android.view.View.OnClickListener;
25 import android.widget.Button;
26 import android.widget.ListView;
27 import android.widget.TableLayout;
28 import android.widget.TableRow;
29 import android.widget.TextView;
30 import dk.thoerup.android.traininfo.common.DepartureBean;
31 import dk.thoerup.android.traininfo.common.DepartureEntry;
32 import dk.thoerup.android.traininfo.common.MetroBean;
33 import dk.thoerup.android.traininfo.common.MetroBean.MetroEntry;
34 import dk.thoerup.android.traininfo.common.StationEntry;
35 import dk.thoerup.traininfo.provider.DepartureProvider;
36 import dk.thoerup.traininfo.provider.MetroProvider;
37 import dk.thoerup.traininfo.provider.ProviderFactory;
38 import dk.thoerup.traininfo.util.MessageBox;
39
40 public class DepartureList extends ListActivity {
41
42 public static final int DLG_PROGRESS = 1;
43 static final int MENU_MAP = 100;
44 static final int MENU_NOTIFICATIONS = 101;
45 static final int MENU_METROMAP= 102;
46
47
48 DepartureListAdapter adapter;
49 DepartureProvider provider;
50 DepartureBean departures;
51
52 MetroBean metroBean;
53 MetroProvider metro;
54
55 int selectedItemId;
56 //DepartureBean currentDeparture;
57
58 ProgressDialog pgDialog;
59
60 DepartureFetcher fetcher;
61 MetroFetcher metroFetcher;
62
63 StationEntry station;
64
65 String trainType = "REGIONAL";
66
67 boolean arrival = false;
68
69 int commFailCounter = 0;
70
71 @Override
72 protected void onCreate(Bundle savedInstanceState) {
73 super.onCreate(savedInstanceState);
74 setContentView(R.layout.departurelist);
75
76 adapter = new DepartureListAdapter(this);
77 setListAdapter(adapter);
78
79 Intent launchedBy = getIntent();
80
81 station = (StationEntry) launchedBy.getSerializableExtra("stationbean");
82
83 ((TextView) findViewById(R.id.stationName)).setText( station.getName() );
84
85
86 ((TextView) findViewById(R.id.stationAddr)).setText( station.getAddress() );
87
88 final Button departureBtn = (Button) findViewById(R.id.departurebtn);
89 final Button arrivalBtn = (Button) findViewById(R.id.arrivalbtn);
90 final Button metroBtn = (Button) findViewById(R.id.metrobtn);
91 final Button regionalBtn = (Button) findViewById(R.id.regionalbtn);
92 final Button stogBtn = (Button) findViewById(R.id.stogbtn);
93
94 final View metroView = findViewById(R.id.metroonly);
95
96 departureBtn.setOnClickListener( new OnClickListener() {
97 @Override
98 public void onClick(View arg0) {
99 arrivalBtn.setBackgroundResource(R.drawable.custom_button);
100 departureBtn.setBackgroundResource(R.drawable.custom_button_hilight);
101 metroBtn.setBackgroundResource(R.drawable.custom_button);
102
103 getListView().setVisibility( View.VISIBLE );
104 metroView.setVisibility( View.GONE );
105 arrival = false;
106 startDepartureFetcher();
107 }
108 });
109 arrivalBtn.setOnClickListener( new OnClickListener() {
110 @Override
111 public void onClick(View arg0) {
112 arrivalBtn.setBackgroundResource(R.drawable.custom_button_hilight);
113 departureBtn.setBackgroundResource(R.drawable.custom_button);
114 metroBtn.setBackgroundResource(R.drawable.custom_button);
115
116 getListView().setVisibility( View.VISIBLE );
117 metroView.setVisibility( View.GONE );
118 arrival = true;
119 startDepartureFetcher();
120 }
121 });
122
123 regionalBtn.setOnClickListener( new OnClickListener() {
124 @Override
125 public void onClick(View arg0) {
126 regionalBtn.setBackgroundResource(R.drawable.custom_button_hilight);
127 stogBtn.setBackgroundResource(R.drawable.custom_button);
128 metroBtn.setBackgroundResource(R.drawable.custom_button);
129
130 departureBtn.setVisibility( View.VISIBLE );
131 arrivalBtn.setVisibility( View.VISIBLE );
132
133 getListView().setVisibility( View.VISIBLE );
134 metroView.setVisibility( View.GONE );
135 trainType = "REGIONAL";
136 startDepartureFetcher();
137 }
138 });
139 stogBtn.setOnClickListener( new OnClickListener() {
140 @Override
141 public void onClick(View arg0) {
142 regionalBtn.setBackgroundResource(R.drawable.custom_button);
143 stogBtn.setBackgroundResource(R.drawable.custom_button_hilight);
144 metroBtn.setBackgroundResource(R.drawable.custom_button);
145
146
147 departureBtn.setVisibility( View.VISIBLE );
148 arrivalBtn.setVisibility( View.VISIBLE );
149
150 getListView().setVisibility( View.VISIBLE );
151 metroView.setVisibility( View.GONE );
152 trainType = "STOG";
153 startDepartureFetcher();
154 }
155 });
156
157
158
159 metroBtn.setOnClickListener( new OnClickListener() {
160 @Override
161 public void onClick(View v) {
162 regionalBtn.setBackgroundResource(R.drawable.custom_button);
163 stogBtn.setBackgroundResource(R.drawable.custom_button);
164 metroBtn.setBackgroundResource(R.drawable.custom_button_hilight);
165
166 departureBtn.setVisibility( View.GONE );
167 arrivalBtn.setVisibility( View.GONE );
168
169 getListView().setVisibility( View.GONE );
170 metroView.setVisibility( View.VISIBLE );
171 startMetroFetcher();
172 }
173 });
174
175
176
177
178 // findViewById(R.id.header).setOnClickListener( mapLauncher );
179
180 int distance = station.getCalcdist();
181 if (distance != 0) {
182 NumberFormat format = NumberFormat.getNumberInstance();
183 format.setMaximumFractionDigits(1);
184 format.setMinimumFractionDigits(1);
185
186 ((TextView) findViewById(R.id.stationDistance)).setText( format.format((double)distance/1000.0) + " km." );
187 } else {
188 ((TextView) findViewById(R.id.stationDistance)).setVisibility(View.GONE);
189 }
190
191 ProviderFactory.purgeOldEntries(); //cleanup before fetching more data
192
193 Log.e("Station", station.toCSV() );
194
195 if (station.isMetro() == false) {
196 metroBtn.setVisibility( View.GONE );
197 }
198
199 metro = ProviderFactory.getMetroProvider();
200
201 if (station.isRegional() == false ) {
202 regionalBtn.setVisibility(View.GONE);
203 }
204
205 if (station.isStrain() == false ) {
206 stogBtn.setVisibility(View.GONE);
207 }
208
209 if (station.isRegional() == true && station.isStrain() == false ) {
210 if ( station.isMetro() == false )
211 regionalBtn.setVisibility(View.GONE);
212 trainType = "REGIONAL";
213 }
214
215 if (station.isRegional() == false && station.isStrain() == true) {
216 if (station.isMetro() == false)
217 stogBtn.setVisibility(View.GONE);
218
219 stogBtn.setBackgroundResource(R.drawable.custom_button_hilight);
220 trainType = "STOG";
221
222 }
223
224
225 if (station.isRegional() == false && station.isStrain() == false) {
226 getListView().setVisibility( View.GONE );
227 metroView.setVisibility( View.VISIBLE );
228
229 departureBtn.setVisibility( View.GONE );
230 arrivalBtn.setVisibility(View.GONE);
231 metroBtn.setVisibility( View.GONE );
232
233
234
235 if (savedInstanceState == null) {
236 startMetroFetcher();
237 } else {
238 metroBean = (MetroBean) savedInstanceState.getSerializable("metro");
239 loadMetroData();
240 }
241
242 } else {
243 provider = ProviderFactory.getDepartureProvider();
244
245 if (savedInstanceState == null) {
246 startDepartureFetcher();
247 } else {
248 departures = (DepartureBean) savedInstanceState.getSerializable("departures");
249
250 if ( (departures != null) && (departures.entries != null) ) {
251 adapter.setDepartures(departures.entries);
252 }
253 selectedItemId = savedInstanceState.getInt("selectedItemId");
254
255 if ( hasNotifications() ) {
256 findViewById(R.id.notifIcon).setVisibility(View.VISIBLE);
257 }
258
259 }
260 }
261 }
262
263 boolean hasNotifications() {
264 return (departures != null && departures.notifications.size() > 0);
265 }
266
267 @Override
268 public void onSaveInstanceState(Bundle outState)
269 {
270 if (pgDialog != null && pgDialog.isShowing())
271 dismissDialog(DLG_PROGRESS);
272
273 outState.putInt("selectedItemId", selectedItemId);
274
275 outState.putSerializable("departures", departures);
276 outState.putSerializable("metro", metroBean);
277 }
278
279
280
281 @Override
282 protected void onDestroy() {
283 super.onDestroy();
284
285 if (fetcher != null) {
286 fetcher.cancel(true);
287 }
288
289 if (metroFetcher != null) {
290 metroFetcher.cancel(true);
291 }
292 }
293
294 @Override
295 protected void onListItemClick(ListView l, View v, int position, long id) {
296 super.onListItemClick(l, v, position, id);
297
298 selectedItemId = position;
299
300 DepartureEntry dep = departures.entries.get(selectedItemId);
301
302 Intent intent = new Intent(this, TimetableList.class);
303 intent.putExtra("departure", dep);
304
305 startActivity(intent);
306
307 }
308
309
310 @Override
311 protected void onPrepareDialog(int id, Dialog dialog) {
312 super.onPrepareDialog(id, dialog);
313
314 switch (id) {
315 case DLG_PROGRESS:
316 pgDialog = (ProgressDialog) dialog;
317 int messageId = arrival == false ? departurelist_fetchdepartures : departurelist_fetcharrivals;
318 pgDialog.setMessage( getString(messageId) );
319 break;
320 }
321 }
322
323 @Override
324 protected Dialog onCreateDialog(int id) {
325 switch (id) {
326 case DLG_PROGRESS:
327
328 ProgressDialog dlg = new ProgressDialog(this);
329 dlg.setCancelable(true);
330 return dlg;
331 default:
332 return super.onCreateDialog(id);
333 }
334 }
335
336
337
338
339
340 @Override
341 public boolean onCreateOptionsMenu(Menu menu) {
342 MenuItem item;
343
344 item = menu.add(0, MENU_MAP, 0, getString(R.string.departurelist_showonmap) );
345 item.setIcon(android.R.drawable.ic_menu_mapmode);
346
347 item = menu.add(0, MENU_NOTIFICATIONS, 0, getString(R.string.departurelist_notifications) );
348 item.setIcon(android.R.drawable.ic_menu_info_details);
349
350 boolean notifEnabled = hasNotifications();
351 item.setEnabled(notifEnabled);
352
353 if (station.isMetro()) {
354 item = menu.add(0, MENU_METROMAP, 0, "Metro" ); //TODO:translate!?!
355 item.setIcon(android.R.drawable.ic_menu_mapmode);
356 }
357
358
359 return true;
360 }
361
362 @Override
363 public boolean onOptionsItemSelected(MenuItem item) {
364 boolean res;
365 switch(item.getItemId()) {
366 case MENU_MAP:
367 try {
368 Uri uri = Uri.parse("geo:" + station.getLatitude() + "," + station.getLongitude() + "?z=16");
369 startActivity( new Intent(Intent.ACTION_VIEW, uri));
370 } catch (ActivityNotFoundException anfe) {
371 Toast.makeText(this, "Could not launch google maps", Toast.LENGTH_LONG).show();
372 }
373 res = true;
374 break;
375 case MENU_NOTIFICATIONS:
376 Intent i = new Intent(this,dk.thoerup.traininfo.NotificationList.class);
377 i.putExtra(NotificationList.EXTRA_NOTIFICATIONS, departures.notifications);
378 startActivity(i);
379 res = true;
380 break;
381 case MENU_METROMAP:
382 Intent metroMap = new Intent(this,dk.thoerup.traininfo.MetroMap.class);
383 startActivity(metroMap);
384 res = true;
385 break;
386 default:
387 res = super.onOptionsItemSelected(item);
388 }
389 return res;
390 }
391
392 void startDepartureFetcher() {
393 showDialog(DLG_PROGRESS);
394 fetcher = new DepartureFetcher();
395 fetcher.execute(station.getId());
396 }
397
398 void startMetroFetcher() {
399 showDialog(DLG_PROGRESS);
400 metroFetcher = new MetroFetcher();
401 metroFetcher.execute(station.getId());
402 }
403
404 class DialogDismisser implements View.OnClickListener {
405
406 Dialog dlg;
407 public DialogDismisser(Dialog d) {
408 dlg = d;
409 }
410
411 @Override
412 public void onClick(View v) {
413 if (dlg.isShowing())
414 dlg.dismiss();
415 }
416 }
417
418 /*View.OnClickListener mapLauncher = new View.OnClickListener() {
419 @Override
420 public void onClick(View v) {
421 Uri uri = Uri.parse("geo:" + station.getLatitude() + "," + station.getLongitude());
422 startActivity( new Intent(Intent.ACTION_VIEW, uri));
423 }
424 };*/
425
426
427
428 class DepartureFetcher extends AsyncTask<Integer, Void, Void> {
429
430 @Override
431 protected void onPostExecute(Void result) {
432 super.onPostExecute(result);
433
434
435 pgDialog.dismiss();
436
437 if (departures != null && departures.errorCode == null) {
438 commFailCounter = 0;
439 DepartureList.this.getListView().setVisibility(View.GONE); //Experimental, inspired by http://osdir.com/ml/Android-Developers/2010-04/msg01198.html
440 adapter.setDepartures(departures.entries);
441 DepartureList.this.getListView().setVisibility(View.VISIBLE);
442
443
444 // handle notification icon.
445 if ( hasNotifications() ) {
446 View notifIcon = findViewById(R.id.notifIcon);
447 notifIcon.setVisibility(View.VISIBLE);
448 notifIcon.setClickable(true);
449 notifIcon.setOnClickListener( new View.OnClickListener() {
450 @Override
451 public void onClick(View v) {
452 Intent i = new Intent(DepartureList.this, dk.thoerup.traininfo.NotificationList.class);
453 i.putExtra(NotificationList.EXTRA_NOTIFICATIONS, departures.notifications);
454 startActivity(i);
455 }
456 });
457 }
458
459 if (departures.entries.size() == 0) {
460 int msgId = (arrival==false) ? R.string.departurelist_nodepartures : R.string.departurelist_noarrivals;
461 MessageBox.showMessage(DepartureList.this, getString(msgId), false);
462 }
463 } else { // communication or parse error
464 commFailCounter++;
465 AlertDialog.Builder builder = new AlertDialog.Builder(DepartureList.this);
466
467 if (departures != null && departures.errorCode != null ) { //got an error xml back
468 commFailCounter = 10;
469 builder.setMessage( getString(R.string.no_backend) );
470 } else {
471 builder.setMessage( getString(R.string.departurelist_fetcherror) );
472 }
473 builder.setCancelable(true);
474
475 if (commFailCounter < 3) {
476 builder.setPositiveButton(getString(generic_retry), new DialogInterface.OnClickListener() {
477 public void onClick(DialogInterface dialog, int id) {
478 dialog.dismiss();
479 startDepartureFetcher();
480
481 }
482 });
483 }
484 builder.setNegativeButton(getString(generic_cancel), new DialogInterface.OnClickListener() {
485 public void onClick(DialogInterface dialog, int id) {
486 dialog.dismiss();
487 DepartureList.this.finish();
488 }
489 });
490
491 try { //TODO: is this still necessary after the 0.9.4.1 fix ?
492 builder.show();
493 } catch (android.view.WindowManager.BadTokenException e) {
494 Log.i("DepartureList", "BadTokenException"); // this can happen if the user switched away from this activity, while doInBackground was running
495 }
496 }
497 }
498
499 @Override
500 protected Void doInBackground(Integer... params) {
501 departures = provider.lookupDepartures(params[0], DepartureList.this.arrival, trainType);
502 return null;
503 }
504
505 }
506
507 public void loadMetroData() {
508 ((TextView) findViewById(R.id.operations)).setText( metroBean.operationInfo );
509 ((TextView) findViewById(R.id.plan)).setText( metroBean.plan );
510
511
512 TableLayout table = (TableLayout) findViewById(R.id.metrotable);
513 table.removeAllViews();
514
515 TableRow head = new TableRow(this);
516
517 TextView h1 = new TextView(this);
518 h1.setText("Metro");
519 h1.setTextSize(16);
520 h1.setTypeface( Typeface.defaultFromStyle(Typeface.BOLD));
521
522
523 TableRow.LayoutParams params = new TableRow.LayoutParams();
524 params.span = 2;
525 head.addView(h1, params);
526
527
528
529 TextView h2 = new TextView(this);
530 h2.setTextSize(16);
531 h2.setTypeface( Typeface.defaultFromStyle(Typeface.BOLD));
532 h2.setText("Om minutter");
533
534 params = new TableRow.LayoutParams();
535 params.weight = 2;
536 head.addView(h2,params);
537
538
539
540 table.addView(head);
541
542 for (MetroEntry entry : metroBean.entries) {
543 TableRow row = new TableRow(this);
544
545 Log.e("Test", "" + entry.destination);
546
547 TextView v1 = new TextView(this);
548 v1.setTextSize(16);
549 v1.setText( entry.metro );
550 row.addView(v1);
551
552 TextView v2 = new TextView(this);
553 v2.setTextSize(16);
554 v2.setText( entry.destination );
555 row.addView(v2);
556
557 TextView v3 = new TextView(this);
558 v3.setTextSize(16);
559 v3.setText( entry.minutes );
560 row.addView(v3);
561
562 table.addView(row);
563
564 }
565 findViewById(R.id.rootView).requestLayout();
566 }
567
568 class MetroFetcher extends AsyncTask<Integer, Void, Void> {
569
570 @Override
571 protected void onPostExecute(Void result) {
572 super.onPostExecute(result);
573
574
575
576 pgDialog.dismiss();
577
578 if (metroBean != null) {
579 loadMetroData();
580 } else { // communication or parse error
581 commFailCounter++;
582 AlertDialog.Builder builder = new AlertDialog.Builder(DepartureList.this);
583 builder.setMessage("Error finding metro data");
584 builder.setCancelable(true);
585 if (commFailCounter < 3) {
586 builder.setPositiveButton(getString(generic_retry), new DialogInterface.OnClickListener() {
587 public void onClick(DialogInterface dialog, int id) {
588 dialog.dismiss();
589 startMetroFetcher();
590
591 }
592 });
593 }
594 builder.setNegativeButton(getString(generic_cancel), new DialogInterface.OnClickListener() {
595 public void onClick(DialogInterface dialog, int id) {
596 dialog.dismiss();
597 DepartureList.this.finish(); //TODO: should we really close the activity ??
598 }
599 });
600
601 try { //TODO: is this still necessary after the 0.9.4.1 fix ?
602 builder.show();
603 } catch (android.view.WindowManager.BadTokenException e) {
604 Log.i("DepartureList", "BadTokenException"); // this can happen if the user switched away from this activity, while doInBackground was running
605 }
606 }
607 }
608
609 @Override
610 protected Void doInBackground(Integer... params) {
611 metroBean = metro.lookupMetroInfo(params[0]);
612 return null;
613 }
614
615 }
616
617 }

  ViewVC Help
Powered by ViewVC 1.1.20