/WhereAbout/src/com/google/marvin/whereabout/WhereAbout.java
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}