/* * Copyright (C) 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.altitudeannouncer; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.zip.GZIPInputStream; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech.OnInitListener; import android.util.Log; /** * Service that runs in the background and checks the server for the altitude. * The server is expected to give the altitude in meters, and AltitudeAnnouncerService * will automatically convert it to feet before announcing it. * * @author clchen@google.com (Charles L. Chen) */ public class AltitudeAnnouncerService extends Service { public static final int ACTION_STOP = 0; public static final int ACTION_START = 1; private TextToSpeech mTts; private String mHttpTargetUrl = "http://www.google.com"; private boolean keepGoing = false; /* * (non-Javadoc) * * @see android.app.Service#onBind(android.content.Intent) */ @Override public IBinder onBind(Intent arg0) { // TODO(clchen): Auto-generated method stub return null; } @Override public void onDestroy() { keepGoing = false; if (mTts != null) { mTts.shutdown(); } } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); if (intent == null){ keepGoing = false; this.stopSelf(); return; } if (intent.getIntExtra("ACTION", ACTION_STOP) == ACTION_STOP) { keepGoing = false; this.stopSelf(); return; } mHttpTargetUrl = intent.getStringExtra("URL"); altDelta = intent.getIntExtra("DELTA", 1666); initialThreshold = intent.getIntExtra("INITIAL_THRESHOLD", 3333); mTts = new TextToSpeech(this, new OnInitListener() { @Override public void onInit(int status) { mTts.speak("Android Altitude Announcer ready", 0, null); } }); Log.e("server", "starting server"); keepGoing = true; new Thread(incomingDataProcessor).start(); } public String getPage() { Log.e("Android Altitude Announcer", "Fetching content from:" + mHttpTargetUrl); try { // Download the HTML content URL sourceURL = new URL(mHttpTargetUrl); // obtain the connection HttpURLConnection sourceConnection = (HttpURLConnection) sourceURL .openConnection(); // add parameters to the connection HttpURLConnection.setFollowRedirects(true); // allow both GZip and Deflate (ZLib) encodings sourceConnection.setRequestProperty("Accept-Encoding", "gzip"); // establish connection, get response headers sourceConnection.connect(); // obtain the encoding returned by the server String encoding = sourceConnection.getContentEncoding(); InputStream stream = null; // create the appropriate stream wrapper based on // the encoding type if (encoding != null && encoding.equalsIgnoreCase("gzip")) { stream = new GZIPInputStream(sourceConnection.getInputStream()); } else { stream = sourceConnection.getInputStream(); } StringBuffer htmlContent = new StringBuffer(); byte buf[] = new byte[128000]; do { int numread = stream.read(buf); if (numread <= 0) { break; } htmlContent.append(new String(buf, 0, numread)); } while (true); String result = htmlContent.toString(); Log.e("Android Altitude Announcer", "Received:" + result); return result; } catch (Exception e) { e.printStackTrace(); return ""; } } private int getAltitude() { int answer = -1; String pageContents = getPage(); try { if (pageContents.length() > 0) { Float alt = Float.parseFloat(pageContents); answer = Math.round(alt); } } catch (Exception e) { e.printStackTrace(); } finally { return answer; } } private int lastAlt = 0; // in meters private int altDelta = 1666; // in meters private int initialThreshold = 3333; // in meters private int timesFailedToIncrease = 0; private int highestKnownAltitude = 0; private long lastSpokenTime = 0; private float mToFeetFactor = 3.2808399f; private Runnable incomingDataProcessor = new Runnable() { @Override public void run() { try { while (keepGoing) { int alt = getAltitude(); if (alt >= initialThreshold) { if (alt >= (lastAlt + altDelta)) { int altInFeet = Math.round(alt * mToFeetFactor); String message = altInFeet + " feet"; if (lastAlt == 0) { message = "To infinity and beyond! We just reached " + message + "!"; } mTts.speak(message, 0, null); lastAlt = alt; } if (alt > highestKnownAltitude){ highestKnownAltitude = alt; timesFailedToIncrease = 0; } else if (alt <= highestKnownAltitude){ timesFailedToIncrease++; } if (timesFailedToIncrease > 9){ int highestKnownAltitudeInFeet = Math.round(highestKnownAltitude * mToFeetFactor); mTts.speak("Highest known altitude was " + highestKnownAltitudeInFeet + " feet.", 0, null); timesFailedToIncrease = 0; } } Thread.sleep(1000); } } catch (Exception e) { e.printStackTrace(); } } }; }