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