OSDN Git Service

#19468
[tokyorunners/tokyorunners.git] / src / net / kazhik / android / tokyorunners / TokyoRunners.java
1 package net.kazhik.android.tokyorunners;
2
3 import java.io.InputStream;
4 import java.text.SimpleDateFormat;
5 import java.util.Date;
6 import java.util.Iterator;
7
8 import org.xmlpull.v1.XmlPullParser;
9 import org.xmlpull.v1.XmlPullParserFactory;
10
11 import android.app.AlertDialog;
12 import android.app.Dialog;
13 import android.app.TabActivity;
14 import android.content.Context;
15 import android.content.DialogInterface;
16 import android.content.Intent;
17 import android.content.SharedPreferences;
18 import android.database.Cursor;
19 import android.location.Location;
20 import android.location.LocationListener;
21 import android.location.LocationManager;
22 import android.location.LocationProvider;
23 import android.media.AudioManager;
24 import android.media.ToneGenerator;
25 import android.os.Bundle;
26 import android.os.Debug;
27 import android.os.Handler;
28 import android.os.SystemClock;
29 import android.preference.PreferenceManager;
30 import android.text.format.DateUtils;
31 import android.util.Log;
32 import android.view.KeyEvent;
33 import android.view.Menu;
34 import android.view.MenuItem;
35 import android.view.View;
36 import android.view.WindowManager;
37 import android.view.View.OnClickListener;
38 import android.widget.ArrayAdapter;
39 import android.widget.Button;
40 import android.widget.Chronometer;
41 import android.widget.ListView;
42 import android.widget.TabHost;
43 import android.widget.TextView;
44 import android.widget.Toast;
45
46 // TODO: Auto-generated Javadoc
47 /**
48  * The Class TokyoRunners.
49  */
50 public class TokyoRunners extends TabActivity implements LocationListener {
51
52         /** The m_prefs. */
53         private SharedPreferences m_prefs;
54         
55         /** The m_loc mgr. */
56         private LocationManager m_locMgr = null;
57         
58         /** The m_elapsed time. */
59         private Chronometer m_elapsedTime;
60         
61         /** The m_lap time. */
62         private Chronometer m_lapTime;
63         
64         /** The m_running. */
65         private boolean m_running = false;
66
67         /** The m_use gps. */
68         private boolean m_useGPS = false;
69         
70         /** The m_autosplit. */
71         private boolean m_autosplit = false;
72
73     /** The m_handler. */
74     private Handler m_handler = new Handler();
75     
76         /** The m_running record. */
77         private static RunningRecord m_runningRecord;
78
79         /** The Constant m_minAccuracy. */
80         private static final int m_minAccuracy = 200;
81
82         /**
83          * The Class StartStopButton.
84          */
85         class StartStopButton implements OnClickListener {
86                 
87                 /* (non-Javadoc)
88                  * @see android.view.View.OnClickListener#onClick(android.view.View)
89                  */
90                 public void onClick(View v) {
91                         if (m_running == true) {
92                                 stop();
93                         } else {
94                                 start();
95                         }
96                 }
97         };
98
99         /**
100          * The Class ResetLapButton.
101          */
102         class ResetLapButton implements OnClickListener {
103                 
104                 /* (non-Javadoc)
105                  * @see android.view.View.OnClickListener#onClick(android.view.View)
106                  */
107                 public void onClick(View v) {
108                         if (m_running == true) {
109                                 lap();
110                         } else {
111                                 reset();
112                         }
113                 }
114         };
115
116         /**
117          * Called when the activity is first created.
118          * 
119          * @param savedInstanceState the saved instance state
120          */
121         @Override
122         public void onCreate(Bundle savedInstanceState) {
123                 super.onCreate(savedInstanceState);
124
125 //              Debug.startMethodTracing("tokyorunners");
126
127                 setContentView(R.layout.stopwatch);
128
129                 // タブの設定
130                 TabHost tabHost = getTabHost();
131
132                 TabHost.TabSpec stopwatchTab = tabHost.newTabSpec("stopwatch");
133                 stopwatchTab.setIndicator(getString(R.string.title_stopwatch));
134                 stopwatchTab.setContent(R.id.stopwatchmode);
135                 tabHost.addTab(stopwatchTab);
136
137                 TabHost.TabSpec mapTab = tabHost.newTabSpec("map");
138                 mapTab.setIndicator(getString(R.string.title_map));
139                 mapTab.setContent(new Intent(this, MapMode.class));
140                 tabHost.addTab(mapTab);
141
142                 tabHost.setCurrentTab(0);
143
144                 tabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
145                         @Override
146                         public void onTabChanged(String tag) {
147                                 if (tag.equals("stopwatch")) {
148                                 } else if (tag.equals("map")) {
149                                 }
150
151                         }
152                 });
153
154                 m_runningRecord = new RunningRecord(getContentResolver());
155
156                 m_prefs = PreferenceManager.getDefaultSharedPreferences(this);
157
158                 // GPS設定
159                 m_useGPS = m_prefs.getBoolean("use_gps", true);
160                 if (m_useGPS) {
161                         initGps();
162                 }
163
164                 // タイム表示
165                 m_elapsedTime = (Chronometer) findViewById(R.id.elapsed_time);
166                 m_lapTime = (Chronometer) findViewById(R.id.lap_time);
167
168                 // ボタン
169                 Button btnStartStop = (Button) findViewById(R.id.button_start_stop);
170                 btnStartStop.setOnClickListener(new StartStopButton());
171
172                 Button btnResetLap = (Button) findViewById(R.id.button_reset_lap);
173                 btnResetLap.setOnClickListener(new ResetLapButton());
174
175                 // スプリットタイム/ラップタイム履歴
176                 ListView lvLaptime = (ListView) findViewById(R.id.lap_history);
177                 ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,
178                                 R.layout.laptime);
179                 lvLaptime.setAdapter(arrayAdapter);
180
181                 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
182
183         }
184
185         /**
186          * Inits the gps.
187          */
188         private void initGps() {
189                 m_locMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
190
191                 String strGpsFreq = m_prefs.getString("gps_frequency", "0");
192                 int gps_freq = Integer.parseInt(strGpsFreq);
193                 m_locMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
194                                 gps_freq * 1000, 5, this);
195
196                 m_autosplit = m_prefs.getBoolean("auto_split", false);
197                 if (m_autosplit) {
198                         int interval = Integer.parseInt(m_prefs.getString("split_interval",
199                                         "5"));
200                         m_runningRecord.setSplitInterval(interval);
201                 }
202
203         }
204
205         /* (non-Javadoc)
206          * @see android.app.Activity#onActivityResult(int, int, android.content.Intent)
207          */
208         @Override
209         protected void onActivityResult(int requestCode, int resultCode, Intent data) {
210                 super.onActivityResult(requestCode, resultCode, data);
211
212                 switch (requestCode) {
213                 case Constants.REQUEST_CODE_SETTINGS:
214                         m_useGPS = m_prefs.getBoolean("use_gps", true);
215                         if (m_useGPS) {
216                                 initGps();
217                         } else {
218                                 if (m_locMgr != null) {
219                                         m_locMgr.removeUpdates(this);
220                                 }
221                         }
222                         break;
223                 case Constants.REQUEST_CODE_HISTORY:
224                         if (data != null) {
225                                 long selectedStartTime = data.getLongExtra("startTime", 0);
226                                 readHistory(selectedStartTime);
227                         }
228                         break;
229                 }
230         }
231
232     /**
233      * Read gpx file.
234      * 
235      * @param filename the filename
236      */
237     private void readGpxFile(String filename) {
238
239         XmlPullParserFactory pullMaker;
240         try {
241             pullMaker = XmlPullParserFactory.newInstance();
242
243             XmlPullParser parser = pullMaker.newPullParser();
244             InputStream fis = getAssets().open(filename);
245
246             parser.setInput(fis, null);
247
248             // state flags
249             boolean inTrackPoint = false;
250             boolean inElevation = false;
251             boolean inName = false;
252             boolean inTime = false;
253             Location loc = null;
254             long currentTime = 0;
255             String pointName = null;
256             SimpleDateFormat timeFormatter = new SimpleDateFormat("y'-'M'-'d'T'H':'m':'s'Z'");
257
258             int eventType = parser.getEventType();
259             while (eventType != XmlPullParser.END_DOCUMENT) {
260                 switch (eventType) {
261                 case XmlPullParser.START_DOCUMENT:
262                     break;
263                 case XmlPullParser.START_TAG:
264                     if (parser.getName().compareTo("trkpt") == 0) {
265
266                         // now get the lat and lon
267                         String lat = parser.getAttributeValue(null, "lat");
268                         String lon = parser.getAttributeValue(null, "lon");
269
270                         loc = new Location(LocationManager.GPS_PROVIDER);
271                                 loc.setLatitude(Double.parseDouble(lat));
272                                 loc.setLongitude(Double.parseDouble(lon));
273
274                         inTrackPoint = true;
275                     } else if (parser.getName().compareTo("ele") == 0) {
276                         if (inTrackPoint) {
277                             inElevation = true;
278                         }
279                     } else if (parser.getName().compareTo("name") == 0) {
280                         if (inTrackPoint) {
281                             inName = true;
282                         }
283                     } else if (parser.getName().compareTo("time") == 0) {
284                         if (inTrackPoint) {
285                             inTime = true;
286                         }
287                     }
288                     break;
289                 case XmlPullParser.END_TAG:
290                     if (parser.getName().equals("trkpt")) {
291                         inTrackPoint = false;
292                                 m_runningRecord.addRecord(currentTime, loc, pointName, false);
293
294                         loc = null;
295
296                     } else if (parser.getName().equals("ele")) {
297                         inElevation = false;
298                     } else if (parser.getName().equals("name")) {
299                         inName = false;
300                     } else if (parser.getName().equals("time")) {
301                         inTime = false;
302                     }
303                     break;
304                 case XmlPullParser.TEXT:
305                     if (inTrackPoint) {
306                         if (inElevation) {
307                         } else if (inName) {
308                                 pointName = parser.getText();
309                         } else if (inTime) {
310                                 String timeStr = parser.getText();
311                             currentTime = timeFormatter.parse(timeStr).getTime();
312                         }
313                     }
314                     break;
315
316                 }
317                 eventType = parser.next();
318             }
319
320         } catch (Exception e) {
321             Log.e("xml_perf", "Pull parser failed", e);
322         }
323         m_handler.post(new Runnable() {
324             public void run() {
325                 Toast.makeText(getApplicationContext(), "Finished XmlPull parsing", Toast.LENGTH_SHORT).show();
326             }
327         });
328     }
329         
330         /**
331          * Read history.
332          * 
333          * @param startTime the start time
334          */
335         private void readHistory(long startTime) {
336
337                 String[] columns = { RunningRecordProvider.CURRENT_TIME,
338                                 RunningRecordProvider.LATITUDE,
339                                 RunningRecordProvider.LONGITUDE,
340                                 RunningRecordProvider.POINT_NAME };
341                 String selection = RunningRecordProvider.START_TIME + " = ?";
342                 String[] selectionArgs = { Long.toString(startTime) };
343                 String sortOrder = RunningRecordProvider.CURRENT_TIME + " asc";
344                 Cursor cursor = managedQuery(RunningRecordProvider.REC_URI, columns,
345                                 selection, selectionArgs, sortOrder);
346                 if (cursor == null) {
347                         return;
348                 }
349
350                 Log.d(this.getClass().getName(), "row count:" + cursor.getCount());
351
352                 reset();
353
354                 ArrayAdapter<String> lapHistory = getLapHistoryAdapter();
355
356                 long currentTime = 0;
357                 int latitude = 0;
358                 int longitude = 0;
359                 String pointName = "";
360                 long prevTime = startTime;
361
362                 TextView elapsedTimeView = (TextView) findViewById(R.id.elapsed_time);
363                 TextView lapTimeView = (TextView) findViewById(R.id.lap_time);
364                 TextView distanceView = (TextView) findViewById(R.id.distance);
365
366                 int idxCurrentTime = cursor
367                                 .getColumnIndex(RunningRecordProvider.CURRENT_TIME);
368                 int idxLatitude = cursor.getColumnIndex(RunningRecordProvider.LATITUDE);
369                 int idxLongitude = cursor
370                                 .getColumnIndex(RunningRecordProvider.LONGITUDE);
371                 int idxPointName = cursor
372                                 .getColumnIndex(RunningRecordProvider.POINT_NAME);
373
374                 while (cursor.moveToNext()) {
375                         currentTime = cursor.getLong(idxCurrentTime);
376                         latitude = cursor.getInt(idxLatitude);
377                         longitude = cursor.getInt(idxLongitude);
378                         pointName = cursor.getString(idxPointName);
379
380 //                      Log.d(this.getClass().getName(), currentTime + ";" + pointName);
381                         // Laptime History
382                         Location loc = null;
383
384                         if (latitude != 0 && longitude != 0) {
385                                 loc = new Location(LocationManager.GPS_PROVIDER);
386
387                                 loc.setLatitude((double) (latitude / 1E6));
388                                 loc.setLongitude((double) (longitude / 1E6));
389                         }
390                         m_runningRecord.addRecord(currentTime, loc, pointName, false);
391
392                         if (pointName.length() == 0) {
393                         } else if (currentTime != startTime) {
394                                 StringBuffer strBuff = new StringBuffer();
395                                 strBuff.append(pointName);
396                                 strBuff.append(": ");
397                                 strBuff.append(DateUtils
398                                                 .formatElapsedTime((currentTime - startTime) / 1000));
399                                 strBuff.append("/");
400                                 strBuff.append(DateUtils
401                                                 .formatElapsedTime((currentTime - prevTime) / 1000));
402                                 lapHistory.insert(strBuff.toString(), 0);
403                                 prevTime = currentTime;
404                         }
405
406                 }
407                 // Elapsed Time
408                 elapsedTimeView.setText(DateUtils
409                                 .formatElapsedTime((currentTime - startTime) / 1000));
410                 // Latest Laptime
411                 lapTimeView.setText(DateUtils
412                                 .formatElapsedTime((currentTime - prevTime) / 1000));
413                 // Distance
414                 distanceView.setText(m_runningRecord.getDistanceString());
415
416         }
417
418         /* (non-Javadoc)
419          * @see android.app.ActivityGroup#onDestroy()
420          */
421         @Override
422         public void onDestroy() {
423                 Log.d(this.getClass().getName(), "onDestroy():");
424                 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
425
426                 m_runningRecord = null;
427
428                 if (m_useGPS) {
429                         m_locMgr.removeUpdates(this);
430                 }
431
432                 super.onDestroy();
433
434         }
435
436         /* (non-Javadoc)
437          * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
438          */
439         @Override
440         public boolean onCreateOptionsMenu(Menu menu) {
441                 menu.add(Menu.NONE, Constants.MENU_HISTORY, Menu.NONE,
442                                 R.string.menu_history).setIcon(R.drawable.history2);
443                 menu.add(Menu.NONE, Constants.MENU_SETTING, Menu.NONE,
444                                 R.string.menu_setting).setIcon(
445                                 android.R.drawable.ic_menu_preferences);
446                 return super.onCreateOptionsMenu(menu);
447         }
448
449         /* (non-Javadoc)
450          * @see android.app.Activity#onPrepareOptionsMenu(android.view.Menu)
451          */
452         @Override
453         public boolean onPrepareOptionsMenu(Menu menu) {
454                 boolean enabled;
455                 if (getTabHost().getCurrentTabTag().equals("stopwatch")) {
456                         enabled = !m_running;
457                 } else {
458                         enabled = false;
459                 }
460                 menu.findItem(Constants.MENU_HISTORY).setEnabled(enabled);
461                 
462                 MenuItem item = menu.findItem(Constants.MENU_HERE);
463                 if (item != null) {
464                         item.setEnabled(!m_running);
465                 }
466
467                 return super.onPrepareOptionsMenu(menu);
468         }
469
470         /* (non-Javadoc)
471          * @see android.app.Activity#onCreateDialog(int)
472          */
473         @Override
474         public Dialog onCreateDialog(int id) {
475
476                 AlertDialog.Builder builder = new AlertDialog.Builder(this);
477                 switch (id) {
478                 case Constants.DIALOG_EXIT_ID:
479                         builder.setTitle(R.string.dialog_exit_title);
480                         builder.setMessage(R.string.dialog_exit_message);
481                         builder.setPositiveButton(R.string.dialog_yes,
482                                         new DialogInterface.OnClickListener() {
483                                                 @Override
484                                                 public void onClick(DialogInterface dialog, int which) {
485 //                                                      Debug.stopMethodTracing();
486                                                         finish();
487
488                                                 }
489                                         });
490                         builder.setNegativeButton(R.string.dialog_no,
491                                         new DialogInterface.OnClickListener() {
492                                                 @Override
493                                                 public void onClick(DialogInterface dialog, int which) {
494                                                         dialog.cancel();
495
496                                                 }
497                                         });
498
499                         break;
500                 default:
501                         break;
502                 }
503
504                 AlertDialog alertDialog = builder.create();
505                 return alertDialog;
506         }
507
508         /* (non-Javadoc)
509          * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
510          */
511         @Override
512         public boolean onOptionsItemSelected(MenuItem item) {
513                 Intent intent;
514                 switch (item.getItemId()) {
515                 case Constants.MENU_HISTORY:
516                         intent = new Intent(this, RunningHistory.class);
517                         intent.setAction(Intent.ACTION_VIEW);
518                         startActivityForResult(intent, Constants.REQUEST_CODE_HISTORY);
519                         break;
520                 case Constants.MENU_SETTING:
521                         intent = new Intent(this, Config.class);
522                         intent.setAction(Intent.ACTION_VIEW);
523                         startActivityForResult(intent, Constants.REQUEST_CODE_SETTINGS);
524                         break;
525                 default:
526                         break;
527                 }
528                 return false;
529         }
530
531         /* (non-Javadoc)
532          * @see android.location.LocationListener#onLocationChanged(android.location.Location)
533          */
534         public void onLocationChanged(Location location) {
535                 ExLog.put(location.toString());
536
537                 // 走行中でない場合は何もしない
538                 if (m_running == false) {
539                         return;
540                 }
541
542                 // 音声出力でスタートを知らせる
543                 Location prevLocation = m_runningRecord.getPrevLocation();
544                 if (prevLocation == null) {
545                         ToneGenerator toneGenerator = new ToneGenerator(
546                                         AudioManager.STREAM_SYSTEM, ToneGenerator.MAX_VOLUME);
547                         toneGenerator.startTone(ToneGenerator.TONE_PROP_BEEP);
548                         toneGenerator.stopTone();
549                 }
550
551                 // 精度が低いデータは無視
552                 // 移動距離が精度より小さい場合も無視
553                 if (location.hasAccuracy()) {
554                         if (location.getAccuracy() > m_minAccuracy) {
555                                 ExLog.put("Accuracy low: " + location.getAccuracy() + ";"
556                                                 + m_minAccuracy);
557                                 return;
558                         }
559                         if (prevLocation != null
560                                         && prevLocation.distanceTo(location) < location
561                                                         .getAccuracy()) {
562                                 ExLog.put("Move not enough: " + location.getAccuracy() + ";"
563                                                 + prevLocation.distanceTo(location));
564                                 return;
565                         }
566
567                 }
568
569                 String pointName = m_runningRecord.addRecord(location.getTime(),
570                                 location, "");
571
572                 // ラップタイム履歴
573                 if (pointName.length() > 0) {
574                         String laptimeStr = calculateSplitAndLap();
575
576                         ArrayAdapter<String> lapHistory = getLapHistoryAdapter();
577
578                         String strLaptime = pointName + ": " + laptimeStr;
579
580                         lapHistory.insert(strLaptime, 0);
581                 }
582
583                 // 距離
584                 TextView distanceView = (TextView) findViewById(R.id.distance);
585                 distanceView.setText(m_runningRecord.getDistanceString());
586
587                 // MapModeに通知
588                 Intent intent = new Intent("NewRunningRecord");
589                 intent.putExtra("RunningRecord", location.getTime());
590                 sendBroadcast(intent);
591
592         }
593
594         /* (non-Javadoc)
595          * @see android.location.LocationListener#onProviderDisabled(java.lang.String)
596          */
597         public void onProviderDisabled(String provider) {
598                 Log.d(this.getClass().getName(), "onProviderDisabled()");
599                 m_locMgr.removeUpdates(this);
600
601         }
602
603         /* (non-Javadoc)
604          * @see android.location.LocationListener#onProviderEnabled(java.lang.String)
605          */
606         public void onProviderEnabled(String provider) {
607                 Log.d(this.getClass().getName(), "onProviderEnabled()");
608         }
609
610         /* (non-Javadoc)
611          * @see android.location.LocationListener#onStatusChanged(java.lang.String, int, android.os.Bundle)
612          */
613         public void onStatusChanged(String provider, int status, Bundle extras) {
614                 String statusStr = "";
615                 switch (status) {
616                 case LocationProvider.AVAILABLE:
617                         statusStr = "Available";
618                         break;
619                 case LocationProvider.OUT_OF_SERVICE:
620                         statusStr = "Out of service";
621                         break;
622                 case LocationProvider.TEMPORARILY_UNAVAILABLE:
623                         statusStr = "Temporarily unavailable";
624                         break;
625                 default:
626                         statusStr = "Unknown status";
627                         break;
628                 }
629                 Log.d(this.getClass().getName(), "onStatusChanged(): " + statusStr);
630
631         }
632
633         /**
634          * Start.
635          */
636         private void start() {
637                 reset();
638                 m_elapsedTime.start();
639                 m_lapTime.start();
640
641                 long currentTime = System.currentTimeMillis();
642                 Location startPoint = null;
643                 if (m_useGPS) {
644                         startPoint = m_locMgr
645                                         .getLastKnownLocation(LocationManager.GPS_PROVIDER);
646
647                         if (Math.abs(currentTime - startPoint.getTime()) > 3 * 1000) {
648                                 Log.d(this.getClass().getName(), "GPS data isn't accurate.");
649                                 startPoint = null;
650                         } else {
651                                 currentTime = startPoint.getTime();
652                         }
653                 }
654                 m_runningRecord.addRecord(currentTime, startPoint,
655                                 getString(R.string.point_start));
656                 m_running = true;
657
658                 Button startStopButton = (Button) findViewById(R.id.button_start_stop);
659                 Button resetLapButton = (Button) findViewById(R.id.button_reset_lap);
660                 startStopButton.setText(R.string.button_stop);
661                 if (m_autosplit) {
662                         resetLapButton.setEnabled(false);
663                 } else {
664                         resetLapButton.setText(R.string.button_lap);
665                 }
666         }
667
668         /**
669          * Stop.
670          */
671         private void stop() {
672                 long currentTime = System.currentTimeMillis();
673                 Location finishPoint = null;
674                 if (m_useGPS) {
675                         finishPoint = m_locMgr
676                                         .getLastKnownLocation(LocationManager.GPS_PROVIDER);
677                         if (Math.abs(System.currentTimeMillis() - finishPoint.getTime()) > 3 * 1000) {
678                                 Log.d(this.getClass().getName(), "GPS data isn't accurate.");
679                                 finishPoint = null;
680                         } else {
681                                 currentTime = finishPoint.getTime();
682                         }
683                 }
684                 m_running = false;
685                 m_runningRecord.addRecord(currentTime, finishPoint,
686                                 getString(R.string.point_finish));
687
688                 m_elapsedTime.stop();
689                 m_lapTime.stop();
690
691                 Button startStopButton = (Button) findViewById(R.id.button_start_stop);
692                 Button resetLapButton = (Button) findViewById(R.id.button_reset_lap);
693                 startStopButton.setText(R.string.button_start);
694                 if (m_autosplit) {
695                         resetLapButton.setEnabled(true);
696                 } else {
697                         resetLapButton.setText(R.string.button_reset);
698                 }
699
700         }
701
702         /**
703          * Reset.
704          */
705         private void reset() {
706                 m_runningRecord.clearRecord();
707
708                 long elapsedRealTime = SystemClock.elapsedRealtime();
709                 m_elapsedTime.setBase(elapsedRealTime);
710                 m_lapTime.setBase(elapsedRealTime);
711
712                 // 距離
713                 TextView distanceView = (TextView) findViewById(R.id.distance);
714                 distanceView.setText(m_runningRecord.getDistanceString());
715
716                 ArrayAdapter<String> lapHistory = getLapHistoryAdapter();
717                 lapHistory.clear();
718
719         }
720
721         /**
722          * Calculate split and lap.
723          * 
724          * @return the string
725          */
726         private String calculateSplitAndLap() {
727                 long elapsedRealTime = SystemClock.elapsedRealtime();
728                 long splitTimeMillis = elapsedRealTime - m_elapsedTime.getBase();
729                 long lapTimeMillis = elapsedRealTime - m_lapTime.getBase();
730                 String splitTimeStr = DateUtils
731                                 .formatElapsedTime(splitTimeMillis / 1000);
732                 String lapTimeStr = DateUtils.formatElapsedTime(lapTimeMillis / 1000);
733
734                 m_lapTime.setBase(elapsedRealTime);
735
736                 return splitTimeStr + "/" + lapTimeStr;
737
738         }
739
740         /**
741          * Gets the lap history adapter.
742          * 
743          * @return the lap history adapter
744          */
745         @SuppressWarnings("unchecked")
746         private ArrayAdapter<String> getLapHistoryAdapter() {
747                 ListView listLaptime = (ListView) findViewById(R.id.lap_history);
748
749                 return (ArrayAdapter<String>) listLaptime.getAdapter();
750
751         }
752
753         /**
754          * Lap.
755          */
756         private void lap() {
757                 String laptimeStr = calculateSplitAndLap();
758
759                 ArrayAdapter<String> lapHistory = getLapHistoryAdapter();
760
761                 String strLapNo = Integer.toString(lapHistory.getCount() + 1);
762
763                 lapHistory.insert(strLapNo + ": " + laptimeStr, 0);
764
765                 m_runningRecord.addRecord(System.currentTimeMillis(), null, strLapNo);
766
767         }
768
769         /**
770          * Gets the record.
771          * 
772          * @param recordTime the record time
773          * 
774          * @return the record
775          */
776         public static Record getRecord(long recordTime) {
777
778                 return m_runningRecord.getRecord(new Date(recordTime));
779
780         }
781
782         /**
783          * Gets the next record.
784          * 
785          * @param recordTime the record time
786          * 
787          * @return the next record
788          */
789         public static Record getNextRecord(long recordTime) {
790
791                 return m_runningRecord.getNextRecord(new Date(recordTime));
792
793         }
794
795         /**
796          * Gets the record iterator.
797          * 
798          * @return the record iterator
799          */
800         public static Iterator<Record> getRecordIterator() {
801                 return m_runningRecord.getIterator();
802         }
803
804         /* (non-Javadoc)
805          * @see android.app.Activity#dispatchKeyEvent(android.view.KeyEvent)
806          */
807         @Override
808         public boolean dispatchKeyEvent(KeyEvent event) {
809                 return super.dispatchKeyEvent(event);
810         }
811
812         /* (non-Javadoc)
813          * @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
814          */
815         @Override
816         public boolean onKeyDown(int keyCode, KeyEvent event) {
817                 if (keyCode == KeyEvent.KEYCODE_BACK) {
818                         showDialog(Constants.DIALOG_EXIT_ID);
819                         return true;
820                 }
821
822                 return super.onKeyDown(keyCode, event);
823
824         }
825
826 }