/there/src/com/google/marvin/there/NavigationActivity.java

http://eyes-free.googlecode.com/ · Java · 196 lines · 158 code · 35 blank · 3 comment · 23 complexity · 7ee49d793366c8f0610542b1879f2677 MD5 · raw file

  1. package com.google.marvin.there;
  2. import com.google.tts.TTS;
  3. import android.app.Activity;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.location.Location;
  7. import android.location.LocationListener;
  8. import android.location.LocationManager;
  9. import android.location.LocationProvider;
  10. import android.os.Bundle;
  11. import android.util.Log;
  12. import android.view.KeyEvent;
  13. import android.widget.TextView;
  14. public class NavigationActivity extends Activity {
  15. private LocationManager locationManager;
  16. private Location currentLocation;
  17. private LocationListener gpsLocationListener = new LocationListener() {
  18. public void onLocationChanged(Location arg0) {
  19. currentLocation = arg0;
  20. distanceTextView.setText(Double.toString(currentLocation.getAccuracy()));
  21. }
  22. public void onProviderDisabled(String arg0) {
  23. currentLocation = null;
  24. }
  25. public void onProviderEnabled(String arg0) {
  26. }
  27. public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
  28. if (arg1 != LocationProvider.AVAILABLE) {
  29. currentLocation = null;
  30. distanceTextView.setText("GPS Unavailable");
  31. }
  32. }
  33. };
  34. public TTS tts;
  35. private TTS.InitListener ttsInitListener = new TTS.InitListener() {
  36. public void onInit(int arg0) {
  37. tts.speak("Navigation started. Acquiring GPS.", 0, null);
  38. }
  39. };
  40. private Place destination;
  41. private TextView distanceTextView;
  42. private Compass compass;
  43. /** Called when the activity is first created. */
  44. @Override
  45. public void onCreate(Bundle savedInstanceState) {
  46. super.onCreate(savedInstanceState);
  47. Intent startingIntent = getIntent();
  48. String placeName = startingIntent.getStringExtra("DESTINATION");
  49. DbManager db = new DbManager(this);
  50. destination = db.get(placeName);
  51. if (destination == null) {
  52. finish();
  53. }
  54. compass = new Compass(this);
  55. locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
  56. locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsLocationListener);
  57. setContentView(R.layout.main);
  58. distanceTextView = (TextView) findViewById(R.id.distanceTextView);
  59. tts = new TTS(this, ttsInitListener, true);
  60. }
  61. @Override
  62. protected void onDestroy() {
  63. compass.shutdown();
  64. locationManager.removeUpdates(gpsLocationListener);
  65. tts.shutdown();
  66. super.onDestroy();
  67. }
  68. // Distance returned is in m
  69. private double distanceFromDestination(Location startLocation) {
  70. if (startLocation == null) {
  71. return -1;
  72. }
  73. double lat1 = startLocation.getLatitude();
  74. double lon1 = startLocation.getLongitude();
  75. double lat2 = Double.parseDouble(destination.lat);
  76. double lon2 = Double.parseDouble(destination.lon);
  77. double R = 6371; // earth's mean radius in km
  78. double dLat = (lat2 - lat1) * Math.PI / 180.0;
  79. double dLon = (lon2 - lon1) * Math.PI / 180.0;
  80. lat1 = lat1 * Math.PI / 180.0;
  81. lat2 = lat2 * Math.PI / 180.0;
  82. double a =
  83. Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1) * Math.cos(lat2)
  84. * Math.sin(dLon / 2) * Math.sin(dLon / 2);
  85. double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  86. double d = R * c;
  87. return d * 1000;
  88. }
  89. private double getBearingToDestination(Location startLocation) {
  90. if (startLocation == null) {
  91. return -1;
  92. }
  93. double lat1 = startLocation.getLatitude();
  94. double lon1 = startLocation.getLongitude();
  95. double lat2 = Double.parseDouble(destination.lat);
  96. double lon2 = Double.parseDouble(destination.lon);
  97. lat1 = lat1 * Math.PI / 180.0;
  98. lat2 = lat2 * Math.PI / 180.0;
  99. double dLon = (lon2 - lon1) * Math.PI / 180.0;
  100. double y = Math.sin(dLon) * Math.cos(lat2);
  101. double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
  102. return ((Math.atan2(y, x) * 180 / Math.PI) + 360) % 360;
  103. }
  104. private void speakSimpleDirections() {
  105. if (tts == null) {
  106. return;
  107. }
  108. boolean closeToDest = false;
  109. Location myLocation = currentLocation;
  110. if (myLocation == null) {
  111. tts.speak("GPS unavailable, please retry later.", 0, null);
  112. return;
  113. }
  114. double distance = distanceFromDestination(myLocation);
  115. double accuracy = currentLocation.getAccuracy();
  116. if (accuracy > 50) {
  117. tts.speak("GPS signal weak.", 0, null);
  118. } else {
  119. if (distance < accuracy) {
  120. closeToDest = true;
  121. tts.speak("You are near your destination.", 0, null);
  122. } else {
  123. long roundedDistance = Math.round(distance);
  124. tts.speak("You are about " + roundedDistance + " meters away from your destination.", 0, null);
  125. }
  126. }
  127. if (!closeToDest) {
  128. double currentHeading = compass.getCurrentHeadingValue();
  129. if (currentHeading == -1) {
  130. tts.speak("Please calibrate the compass by shaking your handset.", 1, null);
  131. return;
  132. }
  133. double bearingToDest = getBearingToDestination(myLocation);
  134. double headingDiff = bearingToDest - currentHeading;
  135. if (headingDiff < 0) {
  136. headingDiff = headingDiff + 360;
  137. }
  138. int index = (int) ((headingDiff * 100 + 1125) / 2250);
  139. tts.speak(HEADING_NAMES[index], 1, null);
  140. }
  141. }
  142. /** Called when a key is pressed down */
  143. @Override
  144. public boolean onKeyDown(int keyCode, KeyEvent event) {
  145. Log.i("Nav activity", "key down");
  146. if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
  147. Log.i("Nav activity", "center key");
  148. speakSimpleDirections();
  149. } else {
  150. super.onKeyDown(keyCode, event);
  151. }
  152. return false;
  153. }
  154. private static final String[] HEADING_NAMES =
  155. {"straight ahead", "ahead and a bit to the right", "ahead and to the right",
  156. "to the right and a bit ahead", "to the right", "to the right",
  157. "turn around, then to the left", "turn around, then a bit to the left", "turn around",
  158. "turn around, then a bit to the right", "turn around, then to the right", "to the left",
  159. "to the left", "to the left and a bit ahead", "ahead and to the left",
  160. "ahead and a bit to the left", "ahead"};
  161. }