PageRenderTime 51ms CodeModel.GetById 15ms app.highlight 30ms RepoModel.GetById 2ms app.codeStats 0ms

/walkytalky/src/com/googlecode/eyesfree/walkytalky/PositionStatusNotificationService.java

http://eyes-free.googlecode.com/
Java | 236 lines | 156 code | 39 blank | 41 comment | 32 complexity | 1271591983a22016c7b4feaaab4f4b93 MD5 | raw file
  1/*
  2 * Copyright (C) 2010 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 of
  6 * 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 under
 14 * the License.
 15 */
 16
 17package com.googlecode.eyesfree.walkytalky;
 18
 19import com.googlecode.eyesfree.walkytalky.Compass.HeadingListener;
 20import com.googlecode.eyesfree.walkytalky.ReverseGeocoder.OnAddressLocatedListener;
 21
 22import android.app.Notification;
 23import android.app.NotificationManager;
 24import android.app.PendingIntent;
 25import android.app.Service;
 26import android.content.Context;
 27import android.content.Intent;
 28import android.content.SharedPreferences;
 29import android.location.GpsStatus;
 30import android.location.Location;
 31import android.location.LocationListener;
 32import android.location.LocationManager;
 33import android.os.Bundle;
 34import android.os.IBinder;
 35import android.preference.PreferenceManager;
 36import android.speech.tts.TextToSpeech;
 37
 38/**
 39 * Service that will take the user's current location and place it in the status
 40 * notification bar. Note that if the user is running TalkBack, the location
 41 * will automatically be spoken because of the way TalkBack handles status
 42 * notifications.
 43 * 
 44 * @author clchen@google.com (Charles L. Chen)
 45 * @author hiteshk@google.com (Hitesh Khandelwal)
 46 * @author credo@google.com (Tim Credo)
 47 */
 48
 49public class PositionStatusNotificationService extends Service implements OnAddressLocatedListener {
 50
 51    private boolean needReset = true;
 52
 53    private SharedPreferences mPrefs;
 54
 55    private boolean mSpeak = false;
 56
 57    private TextToSpeech mTts;
 58
 59    private Compass mCompass;
 60
 61    private boolean mPostMessage = true;
 62
 63    private PositionStatusNotificationService self;
 64
 65    NotificationManager mNotificationManager;
 66
 67    long locLastUpdateTime = 0;
 68
 69    long gpsLocLastUpdateTime = 0;
 70
 71    private long locationUpdateWaitTime = 15000;
 72
 73    private LocationManager locationManager;
 74
 75    private ReverseGeocoder locator = null;
 76
 77    private Address lastAddress = null;
 78
 79    private LocationListener locationListener = new LocationListener() {
 80        /*
 81         * Use GPS signal by default, fallbacks to network signal if GPS is
 82         * unavailable
 83         */
 84        public void onLocationChanged(Location location) {
 85            if (locLastUpdateTime + locationUpdateWaitTime < System.currentTimeMillis()) {
 86                locLastUpdateTime = System.currentTimeMillis();
 87                if (location.getProvider().equals("gps")) {
 88                    // GPS signal
 89                    locator.getAddressAsync(location.getLatitude(), location.getLongitude());
 90                    gpsLocLastUpdateTime = System.currentTimeMillis();
 91                } else if (gpsLocLastUpdateTime + 2 * locationUpdateWaitTime < System
 92                        .currentTimeMillis()) {
 93                    // Network signal
 94                    locator.getAddressAsync(location.getLatitude(), location.getLongitude());
 95                }
 96            }
 97        }
 98
 99        public void onProviderDisabled(String arg0) {
100            locationManager.removeUpdates(locationListener);
101            gpsLocLastUpdateTime = -1;
102            locLastUpdateTime = -1;
103        }
104
105        public void onProviderEnabled(String arg0) {
106        }
107
108        public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
109        }
110    };
111
112    GpsStatus.Listener mGpsStatusListener = new GpsStatus.Listener() {
113        public void onGpsStatusChanged(int event) {
114            // This is a dummy listener. It's here because the Motorola Droid
115            // GPS does not function correctly unless a status listener is set
116            // for it.
117        }
118    };
119
120    public HeadingListener mHeadingListener = new HeadingListener() {
121        @Override
122        public void onHeadingChanged(String heading) {
123            if (mPrefs.getBoolean("enable_compass", false) && (mTts != null)) {
124                mTts.speak("Heading " + heading, 0, null);
125            }
126        }
127    };
128
129    @Override
130    public void onStart(Intent intent, int startId) {
131        super.onStart(intent, startId);
132        this.setForeground(true);
133
134        String action = intent.getExtras().getString("ACTION");
135        if (action.equals("STOP")) {
136            shutdown();
137            final Service self = this;
138            this.stopSelf();
139            return;
140        }
141
142        // Need to do null checks here since it is possible that these
143        // are already initialized. For example, if the user goes into
144        // navigation and then turns off the screen.
145        if (mTts == null) {
146            mTts = new TextToSpeech(getApplicationContext(), null);
147        }
148        if (mPrefs == null) {
149            mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
150        }
151        if (mCompass == null) {
152            mCompass = new Compass(this, mHeadingListener);
153        }
154
155        if (needReset) {
156            self = this;
157            needReset = false;
158            mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
159            locator = new ReverseGeocoder(self);
160            locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
161            locationManager.requestLocationUpdates(android.location.LocationManager.GPS_PROVIDER,
162                    1000, 1, locationListener);
163            locationManager.requestLocationUpdates(
164                    android.location.LocationManager.NETWORK_PROVIDER, 1000, 1, locationListener);
165            locationManager.addGpsStatusListener(mGpsStatusListener);
166        }
167    }
168
169    public void onAddressLocated(Address address) {
170        if (address != null && address.isValid()) {
171            String addressString = "Near " + address.getStreetNumber() + " " + address.getRoute();
172            String fullAddress = address.getStreetNumber() + " " + address.getRoute() + ", "
173                    + address.getCity() + ", " + address.getPostalCode();
174            // If the city or postal code changes, announce the full address.
175            if (lastAddress == null || !address.getCity().equals(lastAddress.getCity())
176                    || !address.getPostalCode().equals(lastAddress.getPostalCode())) {
177                addressString = "Near " + fullAddress;
178
179            }
180            lastAddress = address;
181            sendNotification(addressString, addressString, "", fullAddress);
182        }
183    }
184
185    public void sendNotification(String ticker, String title, String text, String callbackMsg) {
186        mSpeak = mPrefs.getBoolean("speak", false);
187        mPostMessage = mPrefs.getBoolean("post_status", true);
188        // Post the message to status bar
189        if (mPostMessage) {
190            long when = System.currentTimeMillis();
191
192            Notification notification = new Notification(android.R.drawable.ic_dialog_map, ticker,
193                    when);
194            Context context = getApplicationContext();
195
196            Intent notificationIntent = new Intent(self, LocationBookmarker.class);
197            notificationIntent.putExtra("LOCATION", callbackMsg);
198            PendingIntent contentIntent = PendingIntent.getActivity(self, 0, notificationIntent, 0);
199
200            notification.setLatestEventInfo(context, title, text, contentIntent);
201            mNotificationManager.notify(1, notification);
202        }
203
204        // Speak the text
205        if (mSpeak) {
206            mTts.speak(ticker, 0, null);
207        }
208    }
209
210    @Override
211    public void onDestroy() {
212        shutdown();
213        super.onDestroy();
214    }
215
216    public void shutdown() {
217        if (locationManager != null) {
218            locationManager.removeUpdates(locationListener);
219        }
220        if (mNotificationManager != null) {
221            mNotificationManager.cancel(1);
222        }
223        if (mTts != null) {
224            mTts.shutdown();
225        }
226        if (mCompass != null) {
227            mCompass.shutdown();
228        }
229    }
230
231    @Override
232    public IBinder onBind(Intent arg0) {
233        // Do nothing - we will not be binding to this service
234        return null;
235    }
236}