summaryrefslogtreecommitdiffstats
path: root/policy
diff options
context:
space:
mode:
Diffstat (limited to 'policy')
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java298
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);
+ }
}
}