diff options
author | DvTonder <david.vantonder@gmail.com> | 2012-12-27 23:15:20 -0500 |
---|---|---|
committer | DvTonder <david.vantonder@gmail.com> | 2012-12-27 23:23:49 -0500 |
commit | 64090cd997e4f6a9b3f02f5ba96e32e297f6403e (patch) | |
tree | 13bcd3ea42015aaf2f59b69625610fc8ca2132ce /src | |
parent | e8a79ed06bfa47b05a883c2b9722cd5ccadb8b4d (diff) | |
download | android_packages_apps_LockClock-64090cd997e4f6a9b3f02f5ba96e32e297f6403e.tar.gz android_packages_apps_LockClock-64090cd997e4f6a9b3f02f5ba96e32e297f6403e.tar.bz2 android_packages_apps_LockClock-64090cd997e4f6a9b3f02f5ba96e32e297f6403e.zip |
Initial commit
Diffstat (limited to 'src')
-rw-r--r-- | src/com/cyanogenmod/lockclock/ClockWidgetProvider.java | 71 | ||||
-rw-r--r-- | src/com/cyanogenmod/lockclock/ClockWidgetService.java | 379 | ||||
-rw-r--r-- | src/com/cyanogenmod/lockclock/MainActivity.java | 333 | ||||
-rw-r--r-- | src/com/cyanogenmod/lockclock/WidgetUtils.java | 71 | ||||
-rw-r--r-- | src/com/cyanogenmod/lockclock/misc/Constants.java | 25 | ||||
-rw-r--r-- | src/com/cyanogenmod/lockclock/weather/HttpRetriever.java | 152 | ||||
-rw-r--r-- | src/com/cyanogenmod/lockclock/weather/WeatherInfo.java | 115 | ||||
-rw-r--r-- | src/com/cyanogenmod/lockclock/weather/WeatherXmlParser.java | 177 | ||||
-rw-r--r-- | src/com/cyanogenmod/lockclock/weather/YahooPlaceFinder.java | 41 |
9 files changed, 1364 insertions, 0 deletions
diff --git a/src/com/cyanogenmod/lockclock/ClockWidgetProvider.java b/src/com/cyanogenmod/lockclock/ClockWidgetProvider.java new file mode 100644 index 0000000..a4a2dfc --- /dev/null +++ b/src/com/cyanogenmod/lockclock/ClockWidgetProvider.java @@ -0,0 +1,71 @@ +package com.cyanogenmod.lockclock; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.util.Log; + +import com.cyanogenmod.lockclock.misc.Constants; + +import java.util.Date; + +public class ClockWidgetProvider extends AppWidgetProvider { + + private static final String TAG = "ClockWidgetProvider"; + + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + Log.i(TAG, "onUpdate Called"); + + // Get all ids + ComponentName thisWidget = new ComponentName(context, ClockWidgetProvider.class); + int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget); + + // Build the intent to call the service + Intent intent = new Intent(context.getApplicationContext(), ClockWidgetService.class); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds); + + // Update the widget via the service - once only, to get things started + Log.i(TAG, "Do a single update"); + context.startService(intent); + + // Load the required settings from preferences + SharedPreferences prefs = context.getSharedPreferences("LockClock", Context.MODE_MULTI_PROCESS); + int updateFrequency = prefs.getInt(Constants.UPDATE_CHECK_PREF, Constants.UPDATE_FREQ_DEFAULT); + + // If not set to manual updates, handle the ongoing updatesbased on the defined frequency + if (updateFrequency > 0) { + Log.i(TAG, "Scheduling future, repeating update checks."); + scheduleUpdateService(context, intent, updateFrequency * 60000); + } + } + + private void scheduleUpdateService(Context context, Intent intent, int updateFrequency) { + // Load the required settings from preferences + SharedPreferences prefs = context.getSharedPreferences("LockClock", Context.MODE_MULTI_PROCESS); + Date lastCheck = new Date(prefs.getLong(Constants.LAST_UPDATE_CHECK_PREF, 0)); + + // Get the intent ready + PendingIntent pi = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + + // Clear any old alarms and schedule the new alarm + AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + am.cancel(pi); + am.setRepeating(AlarmManager.RTC_WAKEUP, lastCheck.getTime() + updateFrequency, updateFrequency, pi); + } + + @Override + public void onDeleted (Context context, int[] appWidgetIds) { } + + @Override + public void onEnabled (Context context) { } + + @Override + public void onDisabled (Context context) { } + +} diff --git a/src/com/cyanogenmod/lockclock/ClockWidgetService.java b/src/com/cyanogenmod/lockclock/ClockWidgetService.java new file mode 100644 index 0000000..6cc048f --- /dev/null +++ b/src/com/cyanogenmod/lockclock/ClockWidgetService.java @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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.cyanogenmod.lockclock; + +import android.app.PendingIntent; +import android.app.Service; +import android.appwidget.AppWidgetManager; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.location.Criteria; +import android.location.Location; +import android.location.LocationManager; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.text.format.DateUtils; +import android.util.Log; +import android.view.View; +import android.widget.RemoteViews; + +import com.cyanogenmod.lockclock.misc.Constants; +import com.cyanogenmod.lockclock.weather.HttpRetriever; +import com.cyanogenmod.lockclock.weather.WeatherInfo; +import com.cyanogenmod.lockclock.weather.WeatherXmlParser; +import com.cyanogenmod.lockclock.weather.YahooPlaceFinder; + +import org.w3c.dom.Document; + +import java.io.IOException; +import java.util.Date; + +public class ClockWidgetService extends Service { + private static final String TAG = "ClockWidgetService"; + private static final boolean DEBUG = true; + + private Context mContext; + private int[] mWidgetIds; + private AppWidgetManager mAppWidgetManager; + + @Override + public void onCreate() { + mContext = getApplicationContext(); + mAppWidgetManager = AppWidgetManager.getInstance(mContext); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + // Iterate through all the widgets supported by this provider + mWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS); + if (mWidgetIds != null && mWidgetIds.length != 0) { + refreshWeather(); + } + + return START_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + /* + * CyanogenMod Lock screen Weather related functionality + */ + private static final String URL_YAHOO_API_WEATHER = "http://weather.yahooapis.com/forecastrss?w=%s&u="; + private static WeatherInfo mWeatherInfo = new WeatherInfo(); + private static final int QUERY_WEATHER = 0; + private static final int UPDATE_WEATHER = 1; + private boolean mWeatherRefreshing; + + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case QUERY_WEATHER: + Thread queryWeather = new Thread(new Runnable() { + @Override + public void run() { + LocationManager locationManager = + (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); + + final ContentResolver resolver = getBaseContext().getContentResolver(); + boolean useCustomLoc = false; //Settings.System.getInt(resolver, + //Settings.System.WEATHER_USE_CUSTOM_LOCATION, 0) == 1; + String customLoc = "Toronto, Canada"; //Settings.System.getString(resolver, + //Settings.System.WEATHER_CUSTOM_LOCATION); + String woeid = null; + + // custom location + if (customLoc != null && useCustomLoc) { + try { + woeid = YahooPlaceFinder.GeoCode(mContext, customLoc); + if (DEBUG) + Log.d(TAG, "Yahoo location code for " + customLoc + " is " + woeid); + } catch (Exception e) { + Log.e(TAG, "ERROR: Could not get Location code"); + e.printStackTrace(); + } + // network location + } else { + Criteria crit = new Criteria(); + crit.setAccuracy(Criteria.ACCURACY_COARSE); + String bestProvider = locationManager.getBestProvider(crit, true); + Location loc = null; + if (bestProvider != null) { + if (DEBUG) + Log.d(TAG, "getLastKnownLocation - bestProvider"); + loc = locationManager.getLastKnownLocation(bestProvider); + } else { + if (DEBUG) + Log.d(TAG, "getLastKnownLocation - Passive provider"); + loc = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER); + } + try { + if (DEBUG) + Log.d(TAG, "Looking for Yahoo location code for current geolocation. Loc = " + loc); + if (loc != null) { + woeid = YahooPlaceFinder.reverseGeoCode(mContext, loc.getLatitude(), + loc.getLongitude()); + if (DEBUG) + Log.d(TAG, "Yahoo location code for current geolocation is " + woeid); + } + } catch (Exception e) { + Log.e(TAG, "ERROR: Could not get Location code"); + e.printStackTrace(); + } + } + if (DEBUG) { + Log.d(TAG, "Location code is " + woeid); + } + WeatherInfo w = null; + if (woeid != null) { + try { + w = parseXml(getDocument(woeid)); + } catch (Exception e) { + } + } + Message msg = Message.obtain(); + msg.what = UPDATE_WEATHER; + msg.obj = w; + mHandler.sendMessage(msg); + } + }); + mWeatherRefreshing = true; + queryWeather.setPriority(Thread.MIN_PRIORITY); + queryWeather.start(); + break; + case UPDATE_WEATHER: + WeatherInfo w = (WeatherInfo) msg.obj; + if (w != null) { + // Store the last update check time + Date d = new Date(); + SharedPreferences prefs = getSharedPreferences("LockClock", Context.MODE_MULTI_PROCESS); + prefs.edit().putLong(Constants.LAST_UPDATE_CHECK_PREF, d.getTime()).apply(); + + // Update the weather info + mWeatherRefreshing = false; + setWeatherData(w); + mWeatherInfo = w; + } else { + mWeatherRefreshing = false; + if (mWeatherInfo.temp.equals(WeatherInfo.NODATA)) { + setNoWeatherData(); + } else { + setWeatherData(mWeatherInfo); + } + } + break; + } + } + }; + + /** + * Reload the weather forecast + */ + private void refreshWeather() { + final ContentResolver resolver = getBaseContext().getContentResolver(); + SharedPreferences prefs = mContext.getSharedPreferences("LockClock", Context.MODE_MULTI_PROCESS); + boolean showWeather = true; //Settings.System.getInt(resolver,Settings.System.LOCKSCREEN_WEATHER, 0) == 1; + + if (showWeather) { + //showRefreshing(); + + // Load the required settings from preferences + final long interval = prefs.getInt(Constants.UPDATE_CHECK_PREF, Constants.UPDATE_FREQ_DEFAULT); + boolean manualSync = (interval == Constants.UPDATE_FREQ_MANUAL); + if (!manualSync && (((System.currentTimeMillis() - mWeatherInfo.last_sync) / 60000) >= interval)) { + if (!mWeatherRefreshing) { + mHandler.sendEmptyMessage(QUERY_WEATHER); + } + } else if (manualSync && mWeatherInfo.last_sync == 0) { + setNoWeatherData(); + } else { + setWeatherData(mWeatherInfo); + } + } else { + /* Hide the Weather panel view + if (mRemoteViews != null) { + mRemoteViews.setViewVisibility(R.id.weather_panel, View.GONE); + }*/ + } + } + + /** + * Indicate that the widget is refreshing + */ + private void showRefreshing() { + final Resources res = getBaseContext().getResources(); + RemoteViews remoteViews = new RemoteViews(mContext.getPackageName(), R.layout.digital_appwidget); + remoteViews.setTextViewText(R.id.weather_condition, res.getString(R.string.weather_refreshing)); + for (int widgetId : mWidgetIds) { + if (DEBUG) + Log.d(TAG, "Showing refreshing status for Widget ID:" + widgetId); + mAppWidgetManager.updateAppWidget(widgetId, remoteViews); + } + } + + /** + * Display the weather information + * @param w + */ + private void setWeatherData(WeatherInfo w) { + final ContentResolver resolver = getBaseContext().getContentResolver(); + final Resources res = getBaseContext().getResources(); + boolean showLocation = true; //Settings.System.getInt(resolver, + //Settings.System.WEATHER_SHOW_LOCATION, 1) == 1; + boolean showTimestamp = true; //Settings.System.getInt(resolver, + //Settings.System.WEATHER_SHOW_TIMESTAMP, 1) == 1; + boolean invertLowhigh = false; //Settings.System.getInt(resolver, + //Settings.System.WEATHER_INVERT_LOWHIGH, 0) == 1; + RemoteViews remoteViews = new RemoteViews(mContext.getPackageName(), R.layout.digital_appwidget); + + // Weather Image + String conditionCode = w.condition_code; + String condition_filename = "weather_" + conditionCode; + int resID = res.getIdentifier(condition_filename, "drawable", + getBaseContext().getPackageName()); + + if (DEBUG) + Log.d("Weather", "Condition:" + conditionCode + " ID:" + resID); + + if (resID != 0) { + remoteViews.setImageViewResource(R.id.weather_image, resID); + } else { + remoteViews.setImageViewResource(R.id.weather_image, R.drawable.weather_na); + } + + // City + remoteViews.setTextViewText(R.id.weather_city, w.city); + remoteViews.setViewVisibility(R.id.weather_city, showLocation ? View.VISIBLE : View.GONE); + + // Weather Condition + remoteViews.setTextViewText(R.id.weather_condition, w.condition); + remoteViews.setViewVisibility(R.id.weather_condition, View.VISIBLE); + + // Weather Update Time + long now = System.currentTimeMillis(); + if (now - w.last_sync < 60000) { + remoteViews.setTextViewText(R.id.update_time, res.getString(R.string.weather_last_sync_just_now)); + } else { + remoteViews.setTextViewText(R.id.update_time, DateUtils.getRelativeTimeSpanString( + w.last_sync, now, DateUtils.MINUTE_IN_MILLIS)); + } + remoteViews.setViewVisibility(R.id.update_time, showTimestamp ? View.VISIBLE : View.GONE); + + // Weather Temps Panel + remoteViews.setTextViewText(R.id.weather_temp, w.temp); + remoteViews.setTextViewText(R.id.weather_low_high, invertLowhigh ? w.high + " | " + w.low : w.low + " | " + w.high); + remoteViews.setViewVisibility(R.id.weather_temps_panel, View.VISIBLE); + + // Show the Weather panel view + remoteViews.setViewVisibility(R.id.weather_panel, View.VISIBLE); + + // Register an onClickListener on Weather + Intent weatherClickIntent = new Intent(mContext, ClockWidgetProvider.class); + weatherClickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + weatherClickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, mWidgetIds); + PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, weatherClickIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + remoteViews.setOnClickPendingIntent(R.id.weather_panel, pendingIntent); + + // Register an onClickListener on Clock + Intent clockClickIntent = new Intent(mContext, ClockWidgetProvider.class); + clockClickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + clockClickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, mWidgetIds); + PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, clockClickIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + remoteViews.setOnClickPendingIntent(R.id.digital_clock, pi); + + // Update all the widgets and stop + for (int widgetId : mWidgetIds) { + mAppWidgetManager.updateAppWidget(widgetId, remoteViews); + } + stopSelf(); + } + + /** + * There is no data to display, display 'empty' fields and the + * 'Tap to reload' message + */ + private void setNoWeatherData() { + final Resources res = getBaseContext().getResources(); + RemoteViews remoteViews = new RemoteViews(mContext.getPackageName(), R.layout.digital_appwidget); + if (remoteViews != null) { + remoteViews.setImageViewResource(R.id.weather_image, R.drawable.weather_na); + remoteViews.setTextViewText(R.id.weather_city, res.getString(R.string.weather_no_data)); + remoteViews.setViewVisibility(R.id.weather_city, View.VISIBLE); + remoteViews.setTextViewText(R.id.weather_condition, res.getString(R.string.weather_tap_to_refresh)); + remoteViews.setViewVisibility(R.id.update_time, View.GONE); + remoteViews.setViewVisibility(R.id.weather_temps_panel, View.GONE); + + // Show the Weather panel view + remoteViews.setViewVisibility(R.id.weather_panel, View.VISIBLE); + } + + // Update all the widgets and stop + for (int widgetId : mWidgetIds) { + mAppWidgetManager.updateAppWidget(widgetId, remoteViews); + } + stopSelf(); + } + + /** + * Get the weather forecast XML document for a specific location + * @param woeid + * @return + */ + private Document getDocument(String woeid) { + try { + boolean celcius = true; //Settings.System.getInt(getBaseContext().getContentResolver(), + //Settings.System.WEATHER_USE_METRIC, 1) == 1; + String urlWithDegreeUnit; + + if (celcius) { + urlWithDegreeUnit = URL_YAHOO_API_WEATHER + "c"; + } else { + urlWithDegreeUnit = URL_YAHOO_API_WEATHER + "f"; + } + + return new HttpRetriever().getDocumentFromURL(String.format(urlWithDegreeUnit, woeid)); + } catch (IOException e) { + Log.e(TAG, "Error querying Yahoo weather"); + } + + return null; + } + + /** + * Parse the weather XML document + * @param wDoc + * @return + */ + private WeatherInfo parseXml(Document wDoc) { + try { + return new WeatherXmlParser(getBaseContext()).parseWeatherResponse(wDoc); + } catch (Exception e) { + Log.e(TAG, "Error parsing Yahoo weather XML document"); + e.printStackTrace(); + } + return null; + } +}
\ No newline at end of file diff --git a/src/com/cyanogenmod/lockclock/MainActivity.java b/src/com/cyanogenmod/lockclock/MainActivity.java new file mode 100644 index 0000000..b16e838 --- /dev/null +++ b/src/com/cyanogenmod/lockclock/MainActivity.java @@ -0,0 +1,333 @@ + +package com.cyanogenmod.lockclock; + +import android.location.Criteria; +import android.location.Location; +import android.location.LocationManager; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.format.DateUtils; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.app.Activity; +import android.content.ContentResolver; +import android.content.Context; +import android.content.res.Resources; + +import com.cyanogenmod.lockclock.weather.*; + +import org.w3c.dom.Document; + +import java.io.IOException; + +public class MainActivity extends Activity implements View.OnClickListener { + + private static String TAG = "LockClock"; + private boolean DEBUG = true; + + private RelativeLayout mWeatherPanel, mWeatherTempsPanel; + private TextView mWeatherCity, mWeatherCondition, mWeatherLowHigh, mWeatherTemp, mWeatherUpdateTime; + private ImageView mWeatherImage; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.digital_appwidget); + + // Weather panel + mWeatherPanel = (RelativeLayout) findViewById(R.id.weather_panel); + mWeatherCity = (TextView) findViewById(R.id.weather_city); + mWeatherCondition = (TextView) findViewById(R.id.weather_condition); + mWeatherImage = (ImageView) findViewById(R.id.weather_image); + mWeatherTemp = (TextView) findViewById(R.id.weather_temp); + mWeatherLowHigh = (TextView) findViewById(R.id.weather_low_high); + mWeatherUpdateTime = (TextView) findViewById(R.id.update_time); + mWeatherTempsPanel = (RelativeLayout) findViewById(R.id.weather_temps_panel); + + // Hide Weather panel view until we know we need to show it. + if (mWeatherPanel != null) { + mWeatherPanel.setVisibility(View.GONE); + mWeatherPanel.setOnClickListener(this); + } + + refreshWeather(); + } + + @Override + public void onResume() { + super.onResume(); + //refreshWeather(); + } + + public void onClick(View v) { + if (v == mWeatherPanel) { + // Indicate we are refreshing + if (mWeatherCondition != null) { + mWeatherCondition.setText(R.string.weather_refreshing); + } + + if (!mWeatherRefreshing) { + mHandler.sendEmptyMessage(QUERY_WEATHER); + } + } + } + + protected void refresh() { + } + + /* + * CyanogenMod Lock screen Weather related functionality + */ + private static final String URL_YAHOO_API_WEATHER = "http://weather.yahooapis.com/forecastrss?w=%s&u="; + private static WeatherInfo mWeatherInfo = new WeatherInfo(); + private static final int QUERY_WEATHER = 0; + private static final int UPDATE_WEATHER = 1; + private boolean mWeatherRefreshing; + + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case QUERY_WEATHER: + Thread queryWeather = new Thread(new Runnable() { + @Override + public void run() { + LocationManager locationManager = (LocationManager) getBaseContext(). + getSystemService(Context.LOCATION_SERVICE); + final ContentResolver resolver = getBaseContext().getContentResolver(); + boolean useCustomLoc = true; //Settings.System.getInt(resolver, + //Settings.System.WEATHER_USE_CUSTOM_LOCATION, 0) == 1; + String customLoc = "Toronto, Canada"; //Settings.System.getString(resolver, + //Settings.System.WEATHER_CUSTOM_LOCATION); + String woeid = null; + + // custom location + if (customLoc != null && useCustomLoc) { + try { + woeid = YahooPlaceFinder.GeoCode(getBaseContext().getApplicationContext(), customLoc); + if (DEBUG) + Log.d(TAG, "Yahoo location code for " + customLoc + " is " + woeid); + } catch (Exception e) { + Log.e(TAG, "ERROR: Could not get Location code"); + e.printStackTrace(); + } + // network location + } else { + Criteria crit = new Criteria(); + crit.setAccuracy(Criteria.ACCURACY_COARSE); + String bestProvider = locationManager.getBestProvider(crit, true); + Location loc = null; + if (bestProvider != null) { + loc = locationManager.getLastKnownLocation(bestProvider); + } else { + loc = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER); + } + try { + woeid = YahooPlaceFinder.reverseGeoCode(getBaseContext(), loc.getLatitude(), + loc.getLongitude()); + if (DEBUG) + Log.d(TAG, "Yahoo location code for current geolocation is " + woeid); + } catch (Exception e) { + Log.e(TAG, "ERROR: Could not get Location code"); + e.printStackTrace(); + } + } + if (DEBUG) { + Log.d(TAG, "Location code is " + woeid); + } + WeatherInfo w = null; + if (woeid != null) { + try { + w = parseXml(getDocument(woeid)); + } catch (Exception e) { + } + } + Message msg = Message.obtain(); + msg.what = UPDATE_WEATHER; + msg.obj = w; + mHandler.sendMessage(msg); + } + }); + mWeatherRefreshing = true; + queryWeather.setPriority(Thread.MIN_PRIORITY); + queryWeather.start(); + break; + case UPDATE_WEATHER: + WeatherInfo w = (WeatherInfo) msg.obj; + if (w != null) { + mWeatherRefreshing = false; + setWeatherData(w); + mWeatherInfo = w; + } else { + mWeatherRefreshing = false; + if (mWeatherInfo.temp.equals(WeatherInfo.NODATA)) { + setNoWeatherData(); + } else { + setWeatherData(mWeatherInfo); + } + } + break; + } + } + }; + + /** + * Reload the weather forecast + */ + private void refreshWeather() { + final ContentResolver resolver = getBaseContext().getContentResolver(); + boolean showWeather = true; //Settings.System.getInt(resolver,Settings.System.LOCKSCREEN_WEATHER, 0) == 1; + + if (showWeather) { + final long interval = 5; //Settings.System.getLong(resolver, + //Settings.System.WEATHER_UPDATE_INTERVAL, 60); // Default to hourly + boolean manualSync = (interval == 0); + if (!manualSync && (((System.currentTimeMillis() - mWeatherInfo.last_sync) / 60000) >= interval)) { + if (!mWeatherRefreshing) { + mHandler.sendEmptyMessage(QUERY_WEATHER); + } + } else if (manualSync && mWeatherInfo.last_sync == 0) { + setNoWeatherData(); + } else { + setWeatherData(mWeatherInfo); + } + } else { + // Hide the Weather panel view + if (mWeatherPanel != null) { + mWeatherPanel.setVisibility(View.GONE); + } + } + } + + /** + * Display the weather information + * @param w + */ + private void setWeatherData(WeatherInfo w) { + final ContentResolver resolver = getBaseContext().getContentResolver(); + final Resources res = getBaseContext().getResources(); + boolean showLocation = true; //Settings.System.getInt(resolver, + //Settings.System.WEATHER_SHOW_LOCATION, 1) == 1; + boolean showTimestamp = true; //Settings.System.getInt(resolver, + //Settings.System.WEATHER_SHOW_TIMESTAMP, 1) == 1; + boolean invertLowhigh = false; //Settings.System.getInt(resolver, + //Settings.System.WEATHER_INVERT_LOWHIGH, 0) == 1; + + if (mWeatherPanel != null) { + if (mWeatherImage != null) { + String conditionCode = w.condition_code; + String condition_filename = "weather_" + conditionCode; + int resID = res.getIdentifier(condition_filename, "drawable", + getBaseContext().getPackageName()); + + if (DEBUG) + Log.d("Weather", "Condition:" + conditionCode + " ID:" + resID); + + if (resID != 0) { + mWeatherImage.setImageDrawable(res.getDrawable(resID)); + } else { + mWeatherImage.setImageResource(R.drawable.weather_na); + } + } + if (mWeatherCity != null) { + mWeatherCity.setText(w.city); + mWeatherCity.setVisibility(showLocation ? View.VISIBLE : View.GONE); + } + if (mWeatherCondition != null && !mWeatherRefreshing) { + mWeatherCondition.setText(w.condition); + mWeatherCondition.setVisibility(View.VISIBLE); + } + if (mWeatherUpdateTime != null) { + long now = System.currentTimeMillis(); + if (now - w.last_sync < 60000) { + mWeatherUpdateTime.setText(R.string.weather_last_sync_just_now); + } else { + mWeatherUpdateTime.setText(DateUtils.getRelativeTimeSpanString( + w.last_sync, now, DateUtils.MINUTE_IN_MILLIS)); + } + mWeatherUpdateTime.setVisibility(showTimestamp ? View.VISIBLE : View.GONE); + } + if (mWeatherTempsPanel != null && mWeatherTemp != null && mWeatherLowHigh != null) { + mWeatherTemp.setText(w.temp); + mWeatherLowHigh.setText(invertLowhigh ? w.high + " | " + w.low : w.low + " | " + w.high); + mWeatherTempsPanel.setVisibility(View.VISIBLE); + } + + // Show the Weather panel view + mWeatherPanel.setVisibility(View.VISIBLE); + } + } + + /** + * There is no data to display, display 'empty' fields and the + * 'Tap to reload' message + */ + private void setNoWeatherData() { + + if (mWeatherPanel != null) { + if (mWeatherImage != null) { + mWeatherImage.setImageResource(R.drawable.weather_na); + } + if (mWeatherCity != null) { + mWeatherCity.setText(R.string.weather_no_data); + mWeatherCity.setVisibility(View.VISIBLE); + } + if (mWeatherCondition != null && !mWeatherRefreshing) { + mWeatherCondition.setText(R.string.weather_tap_to_refresh); + } + if (mWeatherUpdateTime != null) { + mWeatherUpdateTime.setVisibility(View.GONE); + } + if (mWeatherTempsPanel != null ) { + mWeatherTempsPanel.setVisibility(View.GONE); + } + + // Show the Weather panel view + mWeatherPanel.setVisibility(View.VISIBLE); + } + } + + /** + * Get the weather forecast XML document for a specific location + * @param woeid + * @return + */ + private Document getDocument(String woeid) { + try { + boolean celcius = true; //Settings.System.getInt(getBaseContext().getContentResolver(), + //Settings.System.WEATHER_USE_METRIC, 1) == 1; + String urlWithDegreeUnit; + + if (celcius) { + urlWithDegreeUnit = URL_YAHOO_API_WEATHER + "c"; + } else { + urlWithDegreeUnit = URL_YAHOO_API_WEATHER + "f"; + } + + return new HttpRetriever().getDocumentFromURL(String.format(urlWithDegreeUnit, woeid)); + } catch (IOException e) { + Log.e(TAG, "Error querying Yahoo weather"); + } + + return null; + } + + /** + * Parse the weather XML document + * @param wDoc + * @return + */ + private WeatherInfo parseXml(Document wDoc) { + try { + return new WeatherXmlParser(getBaseContext()).parseWeatherResponse(wDoc); + } catch (Exception e) { + Log.e(TAG, "Error parsing Yahoo weather XML document"); + e.printStackTrace(); + } + return null; + } +} diff --git a/src/com/cyanogenmod/lockclock/WidgetUtils.java b/src/com/cyanogenmod/lockclock/WidgetUtils.java new file mode 100644 index 0000000..96e702c --- /dev/null +++ b/src/com/cyanogenmod/lockclock/WidgetUtils.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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.cyanogenmod.lockclock; + +import android.appwidget.AppWidgetManager; +import android.content.Context; +import android.content.res.Resources; +import android.os.Bundle; +import android.util.Log; +import android.util.TypedValue; +import android.widget.RemoteViews; + +public class WidgetUtils { + static final String TAG = "WidgetUtils"; + + public static void setClockSize(Context context, RemoteViews clock, float scale) { + float fontSize = context.getResources().getDimension(R.dimen.widget_big_font_size); + clock.setTextViewTextSize( + R.id.the_clock1, TypedValue.COMPLEX_UNIT_PX, fontSize * scale); + clock.setTextViewTextSize( + R.id.the_clock2, TypedValue.COMPLEX_UNIT_PX, fontSize * scale); + } + + // Calculate the scale factor of the fonts in the widget + public static float getScaleRatio(Context context, Bundle options, int id) { + AppWidgetManager widgetManager = AppWidgetManager.getInstance(context); + if (options == null) { + options = widgetManager.getAppWidgetOptions(id); + } + if (options != null) { + int minWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH); + if (minWidth == 0) { + // No data , do no scaling + return 1f; + } + Resources res = context.getResources(); + float ratio = minWidth / res.getDimension(R.dimen.def_digital_widget_width); + return (ratio > 1) ? 1 : ratio; + } + return 1; + } + + // Decide if to show the list of world clock. + // Check to see if the widget size is big enough, if it is return true. + public static boolean showList(Context context, int id, float scale) { + Bundle options = AppWidgetManager.getInstance(context).getAppWidgetOptions(id); + if (options == null) { + // no data to make the calculation, show the list anyway + return true; + } + int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT); + int neededSize = (int) context.getResources(). + getDimension(R.dimen.def_digital_widget_height); + return (minHeight > neededSize); + } +} + diff --git a/src/com/cyanogenmod/lockclock/misc/Constants.java b/src/com/cyanogenmod/lockclock/misc/Constants.java new file mode 100644 index 0000000..67ad8f3 --- /dev/null +++ b/src/com/cyanogenmod/lockclock/misc/Constants.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2012 The CyanogenMod Project + * + * * Licensed under the GNU GPLv2 license + * + * The text of the license can be found in the LICENSE file + * or at https://www.gnu.org/licenses/gpl-2.0.txt + */ + +package com.cyanogenmod.lockclock.misc; + +public class Constants { + + public static final String UPDATE_CHECK_PREF = "pref_update_check"; + public static final String LAST_UPDATE_CHECK_PREF = "pref_last_update_check"; + + // Activity start parameters + public static final String CHECK_FOR_UPDATE = "check_for_update"; + public static final String MANUAL_UPDATE = "manual_update"; + + // Update Check items + public static final int UPDATE_FREQ_MANUAL = 0; + public static final int UPDATE_FREQ_DEFAULT = 10; // Should be 60 + +} diff --git a/src/com/cyanogenmod/lockclock/weather/HttpRetriever.java b/src/com/cyanogenmod/lockclock/weather/HttpRetriever.java new file mode 100644 index 0000000..622fe70 --- /dev/null +++ b/src/com/cyanogenmod/lockclock/weather/HttpRetriever.java @@ -0,0 +1,152 @@ +/****************************************************************************** + * Class : HttpConnectHelper.java * + * Main Weather activity, in this demo apps i use API from yahoo, you can * + * use other weather web service which you prefer * + * * + * Version : v1.0 * + * Date : May 09, 2011 * + * Copyright (c)-2011 DatNQ some right reserved * + * You can distribute, modify or what ever you want but WITHOUT ANY WARRANTY * + * Be honest by keep credit of this file * + * * + * If you have any concern, feel free to contact with me via email, i will * + * check email in free time * + * Email: nguyendatnq@gmail.com * + * ---------------------------------------------------------------------------* + * Modification Logs: * + * KEYCHANGE DATE AUTHOR DESCRIPTION * + * ---------------------------------------------------------------------------* + * ------- May 09, 2011 DatNQ Create new * + ******************************************************************************/ + +/** + * Modification into Android-internal HttpRetreiver.java + * Copyright (C) 2012 The AOKP Project + */ + + +package com.cyanogenmod.lockclock.weather; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.util.EntityUtils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; + +import android.util.Log; + +public class HttpRetriever { + + private final String TAG = getClass().getSimpleName(); + private DefaultHttpClient client = new DefaultHttpClient(); + private HttpURLConnection httpConnection; + + public String retrieve(String url) { + HttpGet get = new HttpGet(url); + try { + HttpResponse getResponse = client.execute(get); + HttpEntity getResponseEntity = getResponse.getEntity(); + if (getResponseEntity != null) { + String response = EntityUtils.toString(getResponseEntity); + return response; + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + private void requestConnectServer(String strURL) throws IOException { + httpConnection = (HttpURLConnection) new URL(strURL).openConnection(); + httpConnection.connect(); + + if (httpConnection.getResponseCode() != HttpURLConnection.HTTP_OK) { + Log.e(TAG, "Something wrong with connection"); + httpConnection.disconnect(); + throw new IOException("Error in connection: " + httpConnection.getResponseCode()); + } + } + + private void requestDisconnect() { + if (httpConnection != null) { + httpConnection.disconnect(); + } + } + + public Document getDocumentFromURL(String strURL) throws IOException { + if (strURL == null) { + Log.e(TAG, "Invalid input URL"); + return null; + } + + // Connect to server, get data and close + requestConnectServer(strURL); + String strDocContent = getDataFromConnection(); + requestDisconnect(); + + if (strDocContent == null) { + Log.e(TAG, "Cannot get XML content"); + return null; + } + + int strContentSize = strDocContent.length(); + StringBuffer strBuff = new StringBuffer(); + strBuff.setLength(strContentSize + 1); + strBuff.append(strDocContent); + ByteArrayInputStream is = new ByteArrayInputStream(strDocContent.getBytes()); + + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db; + Document docData = null; + + try { + db = dbf.newDocumentBuilder(); + docData = db.parse(is); + } catch (Exception e) { + Log.e(TAG, "Parser data error"); + return null; + } + return docData; + } + + private String getDataFromConnection() throws IOException { + if (httpConnection == null) { + Log.e(TAG, "Connection is null"); + return null; + } + + String strValue = null; + InputStream inputStream = httpConnection.getInputStream(); + if (inputStream == null) { + Log.e(TAG, "Input stream error"); + return null; + } + + StringBuffer strBuf = new StringBuffer(); + BufferedReader buffReader = new BufferedReader(new InputStreamReader(inputStream)); + String strLine = ""; + + while ((strLine = buffReader.readLine()) != null) { + strBuf.append(strLine + "\n"); + strValue += strLine + "\n"; + } + + // Release resource to system + buffReader.close(); + inputStream.close(); + return strBuf.toString(); + } +} diff --git a/src/com/cyanogenmod/lockclock/weather/WeatherInfo.java b/src/com/cyanogenmod/lockclock/weather/WeatherInfo.java new file mode 100644 index 0000000..bb4a5fa --- /dev/null +++ b/src/com/cyanogenmod/lockclock/weather/WeatherInfo.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2012 The AOKP Project + * + * 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.cyanogenmod.lockclock.weather; + +import android.content.Context; +import com.cyanogenmod.lockclock.R; + +public class WeatherInfo { + + public static final String NODATA = "-"; + + public String city, forecast_date, condition, condition_code, temp, temp_unit, + humidity, wind, wind_dir, speed_unit, low, high; + public long last_sync; + + public WeatherInfo() { + this.city = NODATA; + this.forecast_date = NODATA; + this.condition = NODATA; + this.condition_code = NODATA; + this.temp = NODATA; + this.temp_unit = NODATA; + this.humidity = NODATA; + this.wind = NODATA; + this.wind_dir = NODATA; + this.speed_unit = NODATA; + this.low = NODATA; + this.high = NODATA; + this.last_sync = 0; + } + + public WeatherInfo(Context context, String city, String fdate, String condition, String condition_code, + String temp, String temp_unit, String humidity, + String wind, String wind_dir, String speed_unit, + String low, String high, long last_sync) { + this.city = city; + this.forecast_date = fdate; + this.condition = condition; + this.condition_code = condition_code; + this.humidity = humidity + "%"; + this.wind = calcDirection(context, wind_dir) + " " + trimSpeed(wind) + speed_unit; + this.speed_unit = speed_unit; + this.last_sync = last_sync; + // Only the current temperature gets the temp_unit added. + this.temp_unit = temp_unit; + this.temp = temp + "°" + temp_unit; + this.low = low + "°"; + this.high = high + "°"; + } + + /** + * find the optimal weather string (helper function for translation) + * + * @param conditionCode condition code from Yahoo (this is the main + * identifier which will be used to find a matching translation + * in the project's resources + * @param providedString + * @return either the defaultString (which should be Yahoo's weather + * condition text), or the translated version from resources + */ + public static String getTranslatedConditionString(Context context, int conditionCode, + String providedString) { + int resID = context.getResources().getIdentifier("weather_" + conditionCode, "string", + context.getPackageName()); + return (resID != 0) ? context.getResources().getString(resID) : providedString; + } + + private String calcDirection(Context context, String degrees) { + try { + int deg = Integer.parseInt(degrees); + if (deg >= 338 || deg <= 22) + return context.getResources().getString(R.string.weather_N); + else if (deg < 68) + return context.getResources().getString(R.string.weather_NE); + else if (deg < 113) + return context.getResources().getString(R.string.weather_E); + else if (deg < 158) + return context.getResources().getString(R.string.weather_SE); + else if (deg < 203) + return context.getResources().getString(R.string.weather_S); + else if (deg < 248) + return context.getResources().getString(R.string.weather_SW); + else if (deg < 293) + return context.getResources().getString(R.string.weather_W); + else if (deg < 338) + return context.getResources().getString(R.string.weather_NW); + else + return ""; + } catch (NumberFormatException e) { + return ""; + } + } + + private String trimSpeed(String speed) { + try { + return String.valueOf(Math.round(Float.parseFloat(speed))); + } catch (NumberFormatException e) { + return ""; + } + } +} diff --git a/src/com/cyanogenmod/lockclock/weather/WeatherXmlParser.java b/src/com/cyanogenmod/lockclock/weather/WeatherXmlParser.java new file mode 100644 index 0000000..50c2c98 --- /dev/null +++ b/src/com/cyanogenmod/lockclock/weather/WeatherXmlParser.java @@ -0,0 +1,177 @@ +/****************************************************************************** + * Class : YahooWeatherHelper.java * + * Parser helper for Yahoo * + * * + * Version : v1.0 * + * Date : May 06, 2011 * + * Copyright (c)-2011 DatNQ some right reserved * + * You can distribute, modify or what ever you want but WITHOUT ANY WARRANTY * + * Be honest by keep credit of this file * + * * + * If you have any concern, feel free to contact with me via email, i will * + * check email in free time * + * Email: nguyendatnq@gmail.com * + * ---------------------------------------------------------------------------* + * Modification Logs: * + * KEYCHANGE DATE AUTHOR DESCRIPTION * + * ---------------------------------------------------------------------------* + * ------- May 06, 2011 DatNQ Create new * + ******************************************************************************/ +/* + * Modification into Android-internal WeatherXmlParser.java + * Copyright (C) 2012 The AOKP Project + */ + +package com.cyanogenmod.lockclock.weather; + +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +import android.content.Context; +import android.util.Log; + +public class WeatherXmlParser { + + protected static final String TAG = "WeatherXmlParser"; + + /** Yahoo attributes */ + private static final String PARAM_YAHOO_LOCATION = "yweather:location"; + private static final String PARAM_YAHOO_UNIT = "yweather:units"; + private static final String PARAM_YAHOO_ATMOSPHERE = "yweather:atmosphere"; + private static final String PARAM_YAHOO_CONDITION = "yweather:condition"; + private static final String PARAM_YAHOO_WIND = "yweather:wind"; + private static final String PARAM_YAHOO_FORECAST = "yweather:forecast"; + + private static final String ATT_YAHOO_CITY = "city"; + private static final String ATT_YAHOO_TEMP = "temp"; + private static final String ATT_YAHOO_CODE = "code"; + private static final String ATT_YAHOO_TEMP_UNIT = "temperature"; + private static final String ATT_YAHOO_HUMIDITY = "humidity"; + private static final String ATT_YAHOO_TEXT = "text"; + private static final String ATT_YAHOO_DATE = "date"; + private static final String ATT_YAHOO_SPEED = "speed"; + private static final String ATT_YAHOO_DIRECTION = "direction"; + private static final String ATT_YAHOO_TODAY_HIGH = "high"; + private static final String ATT_YAHOO_TODAY_LOW = "low"; + + private Context mContext; + + public WeatherXmlParser(Context context) { + mContext = context; + } + + public WeatherInfo parseWeatherResponse(Document docWeather) { + if (docWeather == null) { + Log.e(TAG, "Invalid doc weather"); + return null; + } + + String strCity = null; + String strDate = null; + String strCondition = null; + String strCondition_code = null; + String strTemp = null; + String strTempUnit = null; + String strHumidity = null; + String strWindSpeed = null; + String strWindDir = null; + String strSpeedUnit = null; + String strHigh = null; + String strLow = null; + + try { + Element root = docWeather.getDocumentElement(); + root.normalize(); + + NamedNodeMap locationNode = root.getElementsByTagName(PARAM_YAHOO_LOCATION).item(0) + .getAttributes(); + if (locationNode != null) { + strCity = locationNode.getNamedItem(ATT_YAHOO_CITY).getNodeValue(); + } + + NamedNodeMap unitNode = root.getElementsByTagName(PARAM_YAHOO_UNIT).item(0) + .getAttributes(); + + if (locationNode != null) { + strTempUnit = unitNode.getNamedItem(ATT_YAHOO_TEMP_UNIT).getNodeValue(); + strSpeedUnit = unitNode.getNamedItem(ATT_YAHOO_SPEED).getNodeValue(); + } + + NamedNodeMap atmosNode = root.getElementsByTagName(PARAM_YAHOO_ATMOSPHERE).item(0) + .getAttributes(); + if (atmosNode != null) { + strHumidity = atmosNode.getNamedItem(ATT_YAHOO_HUMIDITY).getNodeValue(); + } + + NamedNodeMap conditionNode = root.getElementsByTagName(PARAM_YAHOO_CONDITION).item(0) + .getAttributes(); + if (conditionNode != null) { + strCondition = conditionNode.getNamedItem(ATT_YAHOO_TEXT).getNodeValue(); + strCondition_code = conditionNode.getNamedItem(ATT_YAHOO_CODE).getNodeValue(); + strCondition = WeatherInfo.getTranslatedConditionString(mContext, Integer.parseInt(strCondition_code), strCondition); + strTemp = conditionNode.getNamedItem(ATT_YAHOO_TEMP).getNodeValue(); + strDate = conditionNode.getNamedItem(ATT_YAHOO_DATE).getNodeValue(); + } + + NamedNodeMap temNode = root.getElementsByTagName(PARAM_YAHOO_WIND).item(0) + .getAttributes(); + if (temNode != null) { + strWindSpeed = temNode.getNamedItem(ATT_YAHOO_SPEED).getNodeValue(); + strWindDir = temNode.getNamedItem(ATT_YAHOO_DIRECTION).getNodeValue(); + } + + NamedNodeMap fcNode = root.getElementsByTagName(PARAM_YAHOO_FORECAST).item(0).getAttributes(); + if (fcNode != null) { + strHigh = fcNode.getNamedItem(ATT_YAHOO_TODAY_HIGH).getNodeValue(); + strLow = fcNode.getNamedItem(ATT_YAHOO_TODAY_LOW).getNodeValue(); + } + } catch (Exception e) { + Log.e(TAG, "Something wrong with parser data: " + e.toString()); + return null; + } + + /* Weather info */ + WeatherInfo yahooWeatherInfo = new WeatherInfo(mContext, strCity, strDate, strCondition, strCondition_code, strTemp, + strTempUnit, strHumidity, strWindSpeed, strWindDir, strSpeedUnit, strLow, strHigh, System.currentTimeMillis()); + + Log.d(TAG, "Weather updated for " + strCity + ": " + strDate + ", " + strCondition + "(" + strCondition_code + + "), " + strTemp + strTempUnit + ", " + strHumidity + "% humidity, " + ", wind: " + strWindDir + " at " + + strWindSpeed + strSpeedUnit + ", low: " + strLow + strTempUnit + " high: " + strHigh + strTempUnit); + + return yahooWeatherInfo; + } + + public String parsePlaceFinderResponse(String response) { + try { + + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document doc = db.parse(new InputSource(new StringReader(response))); + + NodeList resultNodes = doc.getElementsByTagName("Result"); + + Node resultNode = resultNodes.item(0); + NodeList attrsList = resultNode.getChildNodes(); + + for (int i = 0; i < attrsList.getLength(); i++) { + Node node = attrsList.item(i); + Node firstChild = node.getFirstChild(); + if ("woeid".equalsIgnoreCase(node.getNodeName()) && firstChild != null) { + return firstChild.getNodeValue(); + } + } + } catch (Exception e) { + Log.e(TAG, e.toString()); + } + return null; + } +} diff --git a/src/com/cyanogenmod/lockclock/weather/YahooPlaceFinder.java b/src/com/cyanogenmod/lockclock/weather/YahooPlaceFinder.java new file mode 100644 index 0000000..569cef1 --- /dev/null +++ b/src/com/cyanogenmod/lockclock/weather/YahooPlaceFinder.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2012 The AOKP Project + * + * 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.cyanogenmod.lockclock.weather; + +import android.content.Context; + +public class YahooPlaceFinder { + + private static final String YAHOO_API_BASE_REV_URL = "http://where.yahooapis.com/geocode?appid=jYkTZp64&q=%1$s,+%2$s&gflags=R"; + private static final String YAHOO_API_BASE_URL = "http://where.yahooapis.com/geocode?appid=jYkTZp64&q=%1$s"; + + public static String reverseGeoCode(Context c, double latitude, double longitude) { + + String url = String.format(YAHOO_API_BASE_REV_URL, String.valueOf(latitude), + String.valueOf(longitude)); + String response = new HttpRetriever().retrieve(url); + return new WeatherXmlParser(c).parsePlaceFinderResponse(response); + + } + + public static String GeoCode(Context c, String location) { + String url = String.format(YAHOO_API_BASE_URL, location).replace(' ', '+'); + String response = new HttpRetriever().retrieve(url); + return new WeatherXmlParser(c).parsePlaceFinderResponse(response); + } + +} |