summaryrefslogtreecommitdiffstats
path: root/policy
diff options
context:
space:
mode:
authorDavid van Tonder <david.vantonder@gmail.com>2012-05-15 22:30:37 -0400
committerelektroschmock <elektroschmock78@googlemail.com>2012-05-26 22:08:52 +0200
commitb0a4ed8386abed54a88a22352c6800855398dbfb (patch)
tree955cb3853e573f5f059cdd0d6a306ce4fd0ce64d /policy
parent2dddab5176a697d0ab99edb129186d939c190de1 (diff)
downloadframeworks_base-b0a4ed8386abed54a88a22352c6800855398dbfb.zip
frameworks_base-b0a4ed8386abed54a88a22352c6800855398dbfb.tar.gz
frameworks_base-b0a4ed8386abed54a88a22352c6800855398dbfb.tar.bz2
Framework: Lock screen weather (Part 2 of 2)
This commit adds the framework side support for displaying the current weather forecast on the lock screen. Special thanks to Devatwork for his help with the update code, Blunden for his help with the weather images and the AOKP team for the original Yahoo! Weather parsing code. Patch set 2 - Whitespace cleanup Patch set 3 - Default show location, timestamp and metric to on Patch set 4 - Adds AOKP copyright to util classes Patch set 5 - Fixes derp introduced by Ps4 Patch set 6 - Fixes (incl music control widget size) Patch set 7 - Minor tweak to the music control widget size Patch set 8 - Better 'error' message on startup Patch set 9 - Even better start up message and Cid image Patch set 10 - German translation Change-Id: Ib12951f163d4fe04cbfa2e4ae9fc59058b71f47e
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);
+ }
}
}