diff options
Diffstat (limited to 'policy')
-rw-r--r-- | policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java | 298 |
1 files changed, 291 insertions, 7 deletions
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java index 76d3df0..150d3bb 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java @@ -16,20 +16,22 @@ package com.android.internal.policy.impl; -import com.android.internal.R; -import com.android.internal.telephony.IccCard; -import com.android.internal.telephony.IccCard.State; -import com.android.internal.widget.LockPatternUtils; -import com.android.internal.widget.TransportControlView; -import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback; - +import java.io.IOException; import java.util.ArrayList; import java.util.Date; import libcore.util.MutableInt; +import org.w3c.dom.Document; + import android.content.ContentResolver; import android.content.Context; +import android.content.res.Resources; +import android.location.Criteria; +import android.location.Location; +import android.location.LocationManager; +import android.os.Handler; +import android.os.Message; import android.provider.Settings; import android.text.TextUtils; import android.text.format.DateFormat; @@ -37,8 +39,21 @@ import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; +import android.widget.ImageView; +import android.widget.RelativeLayout; import android.widget.TextView; +import com.android.internal.R; +import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback; +import com.android.internal.telephony.IccCard; +import com.android.internal.telephony.IccCard.State; +import com.android.internal.util.weather.HttpRetriever; +import com.android.internal.util.weather.WeatherInfo; +import com.android.internal.util.weather.WeatherXmlParser; +import com.android.internal.util.weather.YahooPlaceFinder; +import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.TransportControlView; + /*** * Manages a number of views inside of LockScreen layouts. See below for a list of widgets * @@ -72,6 +87,9 @@ class KeyguardStatusViewManager implements OnClickListener { private TextView mOwnerInfoView; private TextView mAlarmStatusView; private TransportControlView mTransportView; + private RelativeLayout mWeatherPanel; + private TextView mWeatherCity, mWeatherCondition, mWeatherLowHigh, mWeatherTemp, mUpdateTime; + private ImageView mWeatherImage; // Top-level container view for above views private View mContainer; @@ -182,6 +200,21 @@ class KeyguardStatusViewManager implements OnClickListener { mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton); mEmergencyCallButtonEnabledInScreen = emergencyButtonEnabledInScreen; + // 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); + mUpdateTime = (TextView) findViewById(R.id.update_time); + + // Hide Weather panel view until we know we need to show it. + if (mWeatherPanel != null) { + mWeatherPanel.setVisibility(View.GONE); + mWeatherPanel.setOnClickListener(this); + } + // Hide transport control view until we know we need to show it. if (mTransportView != null) { mTransportView.setVisibility(View.GONE); @@ -201,6 +234,7 @@ class KeyguardStatusViewManager implements OnClickListener { resetStatusInfo(); refreshDate(); updateOwnerInfo(); + refreshWeather(); // Required to get Marquee to work. final View scrollableViews[] = { mCarrierView, mDateView, mStatus1View, mOwnerInfoView, @@ -212,6 +246,252 @@ class KeyguardStatusViewManager implements OnClickListener { } } + /* + * 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 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) getContext(). + getSystemService(Context.LOCATION_SERVICE); + final ContentResolver resolver = getContext().getContentResolver(); + boolean useCustomLoc = Settings.System.getInt(resolver, + Settings.System.WEATHER_USE_CUSTOM_LOCATION, 0) == 1; + String customLoc = Settings.System.getString(resolver, + Settings.System.WEATHER_CUSTOM_LOCATION); + String woeid = null; + + // custom location + if (customLoc != null && useCustomLoc) { + try { + woeid = YahooPlaceFinder.GeoCode(getContext().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(getContext(), 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(); + } + } + Message msg = Message.obtain(); + msg.what = UPDATE_WEATHER; + msg.obj = woeid; + mHandler.sendMessage(msg); + } + }); + queryWeather.setPriority(Thread.MIN_PRIORITY); + queryWeather.start(); + break; + case UPDATE_WEATHER: + String woeid = (String) msg.obj; + if (woeid != null) { + if (DEBUG) { + Log.d(TAG, "Location code is " + woeid); + } + WeatherInfo w = null; + try { + w = parseXml(getDocument(woeid)); + } catch (Exception e) { + } + if (w == null) { + setNoWeatherData(); + } else { + setWeatherData(w); + mWeatherInfo = w; + } + } else { + if (mWeatherInfo.temp.equals(WeatherInfo.NODATA)) { + setNoWeatherData(); + } else { + setWeatherData(mWeatherInfo); + } + } + break; + } + } + }; + + /** + * Reload the weather forecast + */ + private void refreshWeather() { + final ContentResolver resolver = getContext().getContentResolver(); + boolean showWeather = Settings.System.getInt(resolver,Settings.System.LOCKSCREEN_WEATHER, 0) == 1; + if (showWeather) { + final long interval = Settings.System.getLong(resolver, + Settings.System.WEATHER_UPDATE_INTERVAL, 60); // Default to hourly + if (((System.currentTimeMillis() - mWeatherInfo.last_sync) / 60000) >= interval) { + mHandler.sendEmptyMessage(QUERY_WEATHER); + } 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 = getContext().getContentResolver(); + final Resources res = getContext().getResources(); + boolean showLocation = Settings.System.getInt(resolver, + Settings.System.WEATHER_SHOW_LOCATION, 1) == 1; + boolean showTimestamp = Settings.System.getInt(resolver, + Settings.System.WEATHER_SHOW_TIMESTAMP, 1) == 1; + + if (mWeatherPanel != null) { + if (mWeatherCity != null) { + mWeatherCity.setText(w.city); + mWeatherCity.setVisibility(showLocation ? View.VISIBLE : View.GONE); + } + if (mWeatherCondition != null) { + mWeatherCondition.setText(w.condition); + } + if (mUpdateTime != null) { + Date lastTime = new Date(mWeatherInfo.last_sync); + String date = DateFormat.getDateFormat(getContext()).format(lastTime); + String time = DateFormat.getTimeFormat(getContext()).format(lastTime); + mUpdateTime.setText(date + " " + time); + mUpdateTime.setVisibility(showTimestamp ? View.VISIBLE : View.GONE); + } + if (mWeatherTemp != null) { + mWeatherTemp.setText(w.temp); + } + if (mWeatherLowHigh != null) { + mWeatherLowHigh.setText(w.low + " | " + w.high); + } + + if (mWeatherImage != null) { + String conditionCode = w.condition_code; + String condition_filename = "weather_" + conditionCode; + int resID = res.getIdentifier(condition_filename, "drawable", + getContext().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); + } + } + + // 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() { + final ContentResolver resolver = getContext().getContentResolver(); + boolean useMetric = Settings.System.getInt(resolver, + Settings.System.WEATHER_USE_METRIC, 1) == 1; + + if (mWeatherPanel != null) { + if (mWeatherCity != null) { + mWeatherCity.setText("CM Weather"); //Hard coding this on purpose + mWeatherCity.setVisibility(View.VISIBLE); + } + if (mWeatherCondition != null) { + mWeatherCondition.setText(R.string.weather_tap_to_refresh); + } + if (mUpdateTime != null) { + mUpdateTime.setVisibility(View.GONE); + } + if (mWeatherTemp != null) { + mWeatherTemp.setText(useMetric ? "0°c" : "0°f"); + } + if (mWeatherLowHigh != null) { + mWeatherLowHigh.setText("0° | 0°"); + } + if (mWeatherImage != null) { + mWeatherImage.setImageResource(R.drawable.weather_na_cid); + } + + // 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 = Settings.System.getInt(getContext().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(getContext()).parseWeatherResponse(wDoc); + } catch (Exception e) { + Log.e(TAG, "Error parsing Yahoo weather XML document"); + e.printStackTrace(); + } + return null; + } + private boolean inWidgetMode() { return mTransportView != null && mTransportView.getVisibility() == View.VISIBLE; } @@ -663,6 +943,10 @@ class KeyguardStatusViewManager implements OnClickListener { public void onClick(View v) { if (v == mEmergencyCallButton) { mCallback.takeEmergencyCallAction(); + } else if (v == mWeatherPanel) { + if (!mHandler.hasMessages(QUERY_WEATHER)) { + mHandler.sendEmptyMessage(QUERY_WEATHER); + } } } |