PageRenderTime 65ms CodeModel.GetById 14ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 1ms

/WhereAbout/src/com/google/marvin/whereabout/WhereAbout.java

http://eyes-free.googlecode.com/
Java | 253 lines | 173 code | 20 blank | 60 comment | 32 complexity | 908ac95651c49a78cf4ae1fba3aedd6f MD5 | raw file
  1/*
  2 * Copyright (C) 2008 Google Inc.
  3 * 
  4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5 * use this file except in compliance with the License. You may obtain a copy
  6 * of the License at
  7 * 
  8 * http://www.apache.org/licenses/LICENSE-2.0
  9 * 
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 13 * License for the specific language governing permissions and limitations
 14 * under the License.
 15 */
 16package com.google.marvin.whereabout;
 17
 18import com.google.tts.TTS;
 19import com.google.tts.TTS.InitListener;
 20
 21import android.app.Activity;
 22import android.app.ProgressDialog;
 23import android.content.Context;
 24import android.location.Location;
 25import android.location.LocationListener;
 26import android.location.LocationManager;
 27import android.location.LocationProvider;
 28import android.os.Bundle;
 29import android.os.Handler;
 30import android.os.Message;
 31import android.util.Log;
 32import android.view.KeyEvent;
 33import android.widget.TextView;
 34
 35/**
 36 * This activity allows the user to obtain the current street, address,
 37 * or intersection. The location is displayed on the screen as well as
 38 * spoken to the user.
 39 * 
 40 * @author chaitanyag@google.com (Chaitanya Gharpure)
 41 *
 42 */
 43public class WhereAbout extends Activity implements Runnable {
 44
 45  private ProgressDialog progressDiag = null;
 46  private TextView mainText = null;
 47  private LocationManager locationManager = null;
 48  private Location currentLocation = null;
 49  private TTS tts = null;
 50  private WhereAboutListener locListener = null;
 51  
 52  private boolean ttsLoaded = false;
 53  private long timeDown, pressTime;
 54  private float accuracy;
 55  
 56  /** Called when the activity is first created. */
 57  @Override
 58  public void onCreate(Bundle savedInstanceState) {
 59    super.onCreate(savedInstanceState);
 60    tts = new TTS(this, new InitListener() {
 61      public void onInit(int arg0) {
 62         ttsLoaded = true;
 63      }}, true);
 64    locationManager =
 65      (LocationManager) getSystemService(Context.LOCATION_SERVICE);
 66    this.locListener = new WhereAboutListener();
 67    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
 68        0, 0, locListener);
 69    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
 70        0, 0, locListener);
 71    setContentView(R.layout.main);
 72    mainText = (TextView) findViewById(R.id.mainText);
 73  }
 74  
 75  /** Called when a key is pressed down */
 76  public boolean onKeyDown(int keyCode, KeyEvent event) {
 77    if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
 78      timeDown = System.currentTimeMillis();
 79      if (ttsLoaded) {
 80        tts.stop();
 81      }
 82    } else {
 83      super.onKeyDown(keyCode, event);
 84    }
 85    return false;
 86  }
 87
 88  /** called when a key is released */ 
 89  public boolean onKeyUp(int keyCode, KeyEvent event) {
 90    if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
 91      pressTime = System.currentTimeMillis() - timeDown;
 92      progressDiag =
 93          ProgressDialog.show(this, getString(R.string.progress_title),
 94          getString(R.string.progress_msg), true, false);
 95      if (ttsLoaded) {
 96        tts.speak(getString(R.string.progress_msg), 0, null);
 97      }
 98      (new Thread(this)).start();
 99    } else {
100      super.onKeyUp(keyCode, event);
101    }
102    return false;
103  }
104
105  public synchronized void run() {
106    // if pressTime > 500: Long press: intersection
107    // else Short press: absolute street address
108    locate(pressTime > 500);
109  }
110  
111  /**
112   * Obtains the address and presents it to the user by appending
113   * appropriate prefixes.
114   * @param abs Whether the full street address was requested
115   */
116  private void locate(boolean abs) {
117    Location loc = null;
118    String prefix = "";
119    loc = currentLocation;
120    if (loc != null) {
121      accuracy = loc.getAccuracy();
122      if (accuracy < 10) {              // Probably a GPS fix
123        prefix = getString(R.string.abs_loc_prefix);
124      } else if (accuracy < 200) {      // Probably a Wifi fix
125        prefix = getString(R.string.wifi_loc_prefix);
126      } else {                          // Probably a Cell tower fix
127        prefix = getString(R.string.nw_loc_prefix);
128      }
129    } else {                            // Cannot find a fix
130      loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
131      prefix = getString(R.string.unknown_loc_prefix) + " " +
132          getString(R.string.prev_loc_prefix);
133    }
134    String address = null;
135    String speakStr = "";
136    if (abs) {
137      address = getAbsAddress(loc);
138      speakStr = prefix + " " + address;
139    } else {
140      address = getIntersection(loc);
141      if (address.contains(" and ")) {  // Intersection
142        speakStr = prefix + " " + getString(R.string.insersection_prefix) +
143            address;
144      } else {  // Not an intersection
145        speakStr = prefix + " " + address;
146      }
147    }
148    Bundle data = new Bundle();
149    data.putString("address", address);
150    data.putString("speakstr", speakStr);
151    Message msg = new Message();
152    msg.setData(data);
153    handler.sendMessage(msg);
154  }
155
156  /**
157   * Dismisses th progress dialog, and displays result.
158   */
159  private Handler handler = new Handler() {
160    @Override
161    public void handleMessage(Message msg) {
162        progressDiag.dismiss();
163        displayAndSpeak(msg.getData().getString("address"),
164            msg.getData().getString("speakstr"));
165    }
166  };
167
168  /**
169   * Displays the specified string on the screen and speaks it.
170   * @param dispStr The string to display
171   * @param speakStr The string to speak
172   */
173  private void displayAndSpeak(String dispStr, String speakStr) {
174    if (dispStr == null || speakStr == null) {
175      return;
176    }
177    mainText.setText(dispStr);
178    if (ttsLoaded) {
179      Log.d("Locator", "Speaking: " + speakStr);
180      tts.speak(speakStr, 0, null);
181    }
182  }
183
184  /**
185   * Obtains the reverse geocoded address for the specified location
186   * @param currentLocation The location to reverse geocode
187   * @return
188   */
189  private String getAbsAddress(Location loc) {
190    
191    String address = 
192        StreetLocator.getAddress(loc.getLatitude(), loc.getLongitude());
193    if (address != null) {
194      return address;
195    } else {
196      return getString(R.string.failed_abs);
197    }
198  }
199  
200  /**
201   * Obtains the street names at the specified location.
202   * @param currentLocation The location to find streets names at
203   * @return
204   */
205  private String getIntersection(Location loc) {
206    String[] addr =
207        StreetLocator.getStreetIntersection(loc.getLatitude(),
208        loc.getLongitude());
209    String address = "";
210    if (addr.length == 0) {
211      return getString(R.string.failed_intersection);
212    }
213    for (String ad : addr) {
214      address += ad + " and ";
215    }
216    address = address.substring(0, address.length() - 4);
217    return address;
218  }
219  
220  @Override
221  public void onDestroy() {
222    locationManager.removeUpdates(locListener);
223    super.onDestroy();
224  }
225  
226  /**
227   * Listener to register for location updates.  
228   */
229  private class WhereAboutListener implements LocationListener {
230    /**
231     * Called when the location changes.
232     */
233    public void onLocationChanged(Location arg0) {
234      currentLocation = arg0;
235    }
236
237    /**
238     * Called when the location provider's status changes.
239     */
240    public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
241      if (arg1 != LocationProvider.AVAILABLE) {
242        currentLocation = null;
243      }
244    }
245
246    public void onProviderDisabled(String provider) {
247      currentLocation = null;
248    }
249    
250    public void onProviderEnabled(String provider) {
251    }
252  }  
253}