PageRenderTime 43ms CodeModel.GetById 1ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  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}