package vandy.mooc.model.services; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URI; import java.net.URL; import java.util.List; import vandy.mooc.common.ExecutorServiceTimeoutCache; import vandy.mooc.common.GenericSingleton; import vandy.mooc.common.LifecycleLoggingService; import vandy.mooc.model.aidl.WeatherData; import vandy.mooc.model.aidl.WeatherDataJsonParser; import android.util.Log; /** * This is the super class for both WeatherServiceSync and * WeatherServiceAsync. It factors out fields and methods that are * shared by both Service implementations. */ public class WeatherServiceBase extends LifecycleLoggingService { /** * Appid needed to access the service. TODO -- fill in with your Appid. */ private final String mAppid = ""; /** * URL to the Weather Service web service. */ private String mWeatherServiceURL = "http://api.openweathermap.org/data/2.5/weather?&APPID=" + mAppid + "&q="; /** * Default timeout is 10 seconds, after which the Cache data * expires. In a production app this value should be much higher * (e.g., 10 minutes) - we keep it small here to help with * testing. */ private int DEFAULT_CACHE_TIMEOUT = 10; /** * Define a class that will cache the WeatherData since it doesn't * change rapidly. This class is passed to the * GenericSingleton.instance() method to retrieve the one and only * instance of the WeatherCache. */ public static class WeatherCache extends ExecutorServiceTimeoutCache<String, List<WeatherData>> {} /** * Hook method called when the Service is created. */ @Override public void onCreate() { super.onCreate(); // TODO -- you fill in here. } /** * Hook method called when the last client unbinds from the * Service. */ @Override public void onDestroy() { super.onDestroy(); // TODO -- you fill in here. } /** * Contitionally queries the Weather Service web service to obtain * a List of WeatherData corresponding to the @a location if it's * been more than 10 seconds since the last query to the Weather * Service. Otherwise, simply return the cached results. */ protected List<WeatherData> getWeatherResults(String location) { Log.d(TAG, "Looking up results in the cache for " + location); // TODO -- you fill in here. } } /** * Actually query the Weather Service web service to get the * current WeatherData. Usually only returns a single element in * the List, but can return multiple elements if they are sent * back from the Weather Service. */ private List<WeatherData> getResultsFromWeatherService(String location) { // Create a List that will return the WeatherData obtained // from the Weather Service web service. List<WeatherData> returnList = null; try { // Create a URL that points to desired location the // Weather Service. URL url = new URL(mWeatherServiceURL + location); final URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef()); url = uri.toURL(); // Opens a connection to the Weather Service. HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); // Sends the GET request and returns a stream containing // the Json results. try (InputStream in = new BufferedInputStream(urlConnection.getInputStream())) { // Create the parser. final WeatherDataJsonParser parser = new WeatherDataJsonParser(); // Parse the Json results and create List of // WeatherData objects. returnList = parser.parseJsonStream(in); } finally { urlConnection.disconnect(); } } catch (Exception e) { e.printStackTrace(); return null; } // See if we parsed any valid data. if (returnList != null && returnList.size() > 0 && returnList.get(0).getMessage() == null) { // Return the List of WeatherData. return returnList; } else { Log.d(TAG, returnList.get(0).getMessage() + " \"" + location + "\""); return null; } } }