diff options
| author | Erik <roboerik@android.com> | 2010-09-14 12:21:53 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-09-14 12:21:53 -0700 |
| commit | b92788aa040d0971b4e54589aef7675f34d96e5d (patch) | |
| tree | 207c8d8912ff53fab753255016c6c2c3f12f993f | |
| parent | 934516e10150874fd1db5ab9e0be3ae793441fd8 (diff) | |
| parent | 71ad58c751eb12a500916556c41e704a93895801 (diff) | |
| download | frameworks_base-b92788aa040d0971b4e54589aef7675f34d96e5d.zip frameworks_base-b92788aa040d0971b4e54589aef7675f34d96e5d.tar.gz frameworks_base-b92788aa040d0971b4e54589aef7675f34d96e5d.tar.bz2 | |
Merge "Adds time zone functionality into fw as a hidden api" into gingerbread
| -rw-r--r-- | core/java/android/provider/Calendar.java | 74 | ||||
| -rw-r--r-- | core/java/android/util/CalendarUtils.java | 309 |
2 files changed, 383 insertions, 0 deletions
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java index 9a09805..6355a9c 100644 --- a/core/java/android/provider/Calendar.java +++ b/core/java/android/provider/Calendar.java @@ -943,6 +943,80 @@ public final class Calendar { } /** + * CalendarCache stores some settings for calendar including the current + * time zone for the app. These settings are stored using a key/value + * scheme. + */ + public interface CalendarCacheColumns { + /** + * The key for the setting. Keys are defined in CalendarChache in the + * Calendar provider. + * TODO Add keys to this file + */ + public static final String KEY = "key"; + + /** + * The value of the given setting. + */ + public static final String VALUE = "value"; + } + + public static class CalendarCache implements CalendarCacheColumns { + /** + * The URI to use for retrieving the properties from the Calendar db. + */ + public static final Uri URI = + Uri.parse("content://" + AUTHORITY + "/properties"); + public static final String[] POJECTION = { KEY, VALUE }; + + /** + * If updating a property, this must be provided as the selection. All + * other selections will fail. For queries this field can be omitted to + * retrieve all properties or used to query a single property. Valid + * keys include {@link #TIMEZONE_KEY_TYPE}, + * {@link #TIMEZONE_KEY_INSTANCES}, and + * {@link #TIMEZONE_KEY_INSTANCES_PREVIOUS}, though the last one can + * only be read, not written. + */ + public static final String WHERE = "key=?"; + + /** + * They key for updating the use of auto/home time zones in Calendar. + * Valid values are {@link #TIMEZONE_TYPE_AUTO} or + * {@link #TIMEZONE_TYPE_HOME}. + */ + public static final String TIMEZONE_KEY_TYPE = "timezoneType"; + + /** + * The key for updating the time zone used by the provider when it + * generates the instances table. This should only be written if the + * type is set to {@link #TIMEZONE_TYPE_HOME}. A valid time zone id + * should be written to this field. + */ + public static final String TIMEZONE_KEY_INSTANCES = "timezoneInstances"; + + /** + * The key for reading the last time zone set by the user. This should + * only be read by apps and it will be automatically updated whenever + * {@link #TIMEZONE_KEY_INSTANCES} is updated with + * {@link #TIMEZONE_TYPE_HOME} set. + */ + public static final String TIMEZONE_KEY_INSTANCES_PREVIOUS = "timezoneInstancesPrevious"; + + /** + * The value to write to {@link #TIMEZONE_KEY_TYPE} if the provider + * should stay in sync with the device's time zone. + */ + public static final String TIMEZONE_TYPE_AUTO = "auto"; + + /** + * The value to write to {@link #TIMEZONE_KEY_TYPE} if the provider + * should use a fixed time zone set by the user. + */ + public static final String TIMEZONE_TYPE_HOME = "home"; + } + + /** * A few Calendar globals are needed in the CalendarProvider for expanding * the Instances table and these are all stored in the first (and only) * row of the CalendarMetaData table. diff --git a/core/java/android/util/CalendarUtils.java b/core/java/android/util/CalendarUtils.java new file mode 100644 index 0000000..81709d7 --- /dev/null +++ b/core/java/android/util/CalendarUtils.java @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2010 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 android.util; + +import android.content.AsyncQueryHandler; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.provider.Calendar.CalendarCache; +import android.text.TextUtils; +import android.text.format.DateUtils; +import android.text.format.Time; + +import java.util.Formatter; +import java.util.HashSet; +import java.util.Locale; + +/** + * A class containing utility methods related to Calendar apps. + * + * @hide + */ +public class CalendarUtils { + private static final boolean DEBUG = false; + private static final String TAG = "CalendarUtils"; + + /** + * This class contains methods specific to reading and writing time zone + * values. + */ + public static class TimeZoneUtils { + private static StringBuilder mSB = new StringBuilder(50); + private static Formatter mF = new Formatter(mSB, Locale.getDefault()); + private volatile static boolean mFirstTZRequest = true; + private volatile static boolean mTZQueryInProgress = false; + + private volatile static boolean mUseHomeTZ = false; + private volatile static String mHomeTZ = Time.getCurrentTimezone(); + + private static HashSet<Runnable> mTZCallbacks = new HashSet<Runnable>(); + private static int mToken = 1; + private static AsyncTZHandler mHandler; + + // The name of the shared preferences file. This name must be maintained for historical + // reasons, as it's what PreferenceManager assigned the first time the file was created. + private final String mPrefsName; + + /** + * This is the key used for writing whether or not a home time zone should + * be used in the Calendar app to the Calendar Preferences. + */ + public static final String KEY_HOME_TZ_ENABLED = "preferences_home_tz_enabled"; + /** + * This is the key used for writing the time zone that should be used if + * home time zones are enabled for the Calendar app. + */ + public static final String KEY_HOME_TZ = "preferences_home_tz"; + + /** + * This is a helper class for handling the async queries and updates for the + * time zone settings in Calendar. + */ + private class AsyncTZHandler extends AsyncQueryHandler { + public AsyncTZHandler(ContentResolver cr) { + super(cr); + } + + @Override + protected void onQueryComplete(int token, Object cookie, Cursor cursor) { + synchronized (mTZCallbacks) { + boolean writePrefs = false; + // Check the values in the db + int keyColumn = cursor.getColumnIndexOrThrow(CalendarCache.KEY); + int valueColumn = cursor.getColumnIndexOrThrow(CalendarCache.VALUE); + while(cursor.moveToNext()) { + String key = cursor.getString(keyColumn); + String value = cursor.getString(valueColumn); + if (TextUtils.equals(key, CalendarCache.TIMEZONE_KEY_TYPE)) { + boolean useHomeTZ = !TextUtils.equals( + value, CalendarCache.TIMEZONE_TYPE_AUTO); + if (useHomeTZ != mUseHomeTZ) { + writePrefs = true; + mUseHomeTZ = useHomeTZ; + } + } else if (TextUtils.equals( + key, CalendarCache.TIMEZONE_KEY_INSTANCES_PREVIOUS)) { + if (!TextUtils.isEmpty(value) && !TextUtils.equals(mHomeTZ, value)) { + writePrefs = true; + mHomeTZ = value; + } + } + } + if (writePrefs) { + SharedPreferences prefs = getSharedPreferences((Context)cookie, mPrefsName); + // Write the prefs + setSharedPreference(prefs, KEY_HOME_TZ_ENABLED, mUseHomeTZ); + setSharedPreference(prefs, KEY_HOME_TZ, mHomeTZ); + } + + mTZQueryInProgress = false; + for (Runnable callback : mTZCallbacks) { + if (callback != null) { + callback.run(); + } + } + mTZCallbacks.clear(); + } + } + } + + /** + * The name of the file where the shared prefs for Calendar are stored + * must be provided. All activities within an app should provide the + * same preferences name or behavior may become erratic. + * + * @param prefsName + */ + public TimeZoneUtils(String prefsName) { + mPrefsName = prefsName; + } + + /** + * Formats a date or a time range according to the local conventions. + * + * This formats a date/time range using Calendar's time zone and the + * local conventions for the region of the device. + * + * @param context the context is required only if the time is shown + * @param startMillis the start time in UTC milliseconds + * @param endMillis the end time in UTC milliseconds + * @param flags a bit mask of options See + * {@link DateUtils#formatDateRange(Context, Formatter, long, long, int, String) formatDateRange} + * @return a string containing the formatted date/time range. + */ + public String formatDateRange(Context context, long startMillis, + long endMillis, int flags) { + String date; + synchronized (mSB) { + mSB.setLength(0); + date = DateUtils.formatDateRange(context, mF, startMillis, endMillis, flags, + getTimeZone(context, null)).toString(); + } + return date; + } + + /** + * Writes a new home time zone to the db. + * + * Updates the home time zone in the db asynchronously and updates + * the local cache. Sending a time zone of + * {@link CalendarCache#TIMEZONE_TYPE_AUTO} will cause it to be set + * to the device's time zone. null or empty tz will be ignored. + * + * @param context The calling activity + * @param timeZone The time zone to set Calendar to, or + * {@link CalendarCache#TIMEZONE_TYPE_AUTO} + */ + public void setTimeZone(Context context, String timeZone) { + if (TextUtils.isEmpty(timeZone)) { + if (DEBUG) { + Log.d(TAG, "Empty time zone, nothing to be done."); + } + return; + } + boolean updatePrefs = false; + synchronized (mTZCallbacks) { + if (CalendarCache.TIMEZONE_TYPE_AUTO.equals(timeZone)) { + if (mUseHomeTZ) { + updatePrefs = true; + } + mUseHomeTZ = false; + } else { + if (!mUseHomeTZ || !TextUtils.equals(mHomeTZ, timeZone)) { + updatePrefs = true; + } + mUseHomeTZ = true; + mHomeTZ = timeZone; + } + } + if (updatePrefs) { + // Write the prefs + SharedPreferences prefs = getSharedPreferences(context, mPrefsName); + setSharedPreference(prefs, KEY_HOME_TZ_ENABLED, mUseHomeTZ); + setSharedPreference(prefs, KEY_HOME_TZ, mHomeTZ); + + // Update the db + ContentValues values = new ContentValues(); + if (mHandler == null) { + mHandler = new AsyncTZHandler(context.getContentResolver()); + } + + mHandler.cancelOperation(mToken); + + // skip 0 so query can use it + if (++mToken == 0) { + mToken = 1; + } + + // Write the use home tz setting + String[] selArgs = new String[] { CalendarCache.TIMEZONE_KEY_TYPE }; + values.put(CalendarCache.VALUE, mUseHomeTZ ? CalendarCache.TIMEZONE_TYPE_HOME + : CalendarCache.TIMEZONE_TYPE_AUTO); + mHandler.startUpdate(mToken, null, CalendarCache.URI, values, CalendarCache.WHERE, + selArgs); + + // If using a home tz write it to the db + if (mUseHomeTZ) { + selArgs[0] = CalendarCache.TIMEZONE_KEY_INSTANCES; + values.clear(); + values.put(CalendarCache.VALUE, mHomeTZ); + mHandler.startUpdate( + mToken, null, CalendarCache.URI, values, CalendarCache.WHERE, selArgs); + } + } + } + + /** + * Gets the time zone that Calendar should be displayed in + * + * This is a helper method to get the appropriate time zone for Calendar. If this + * is the first time this method has been called it will initiate an asynchronous + * query to verify that the data in preferences is correct. The callback supplied + * will only be called if this query returns a value other than what is stored in + * preferences and should cause the calling activity to refresh anything that + * depends on calling this method. + * + * @param context The calling activity + * @param callback The runnable that should execute if a query returns new values + * @return The string value representing the time zone Calendar should display + */ + public String getTimeZone(Context context, Runnable callback) { + synchronized (mTZCallbacks){ + if (mFirstTZRequest) { + mTZQueryInProgress = true; + mFirstTZRequest = false; + + SharedPreferences prefs = getSharedPreferences(context, mPrefsName); + mUseHomeTZ = prefs.getBoolean(KEY_HOME_TZ_ENABLED, false); + mHomeTZ = prefs.getString(KEY_HOME_TZ, Time.getCurrentTimezone()); + + // When the async query returns it should synchronize on + // mTZCallbacks, update mUseHomeTZ, mHomeTZ, and the + // preferences, set mTZQueryInProgress to false, and call all + // the runnables in mTZCallbacks. + if (mHandler == null) { + mHandler = new AsyncTZHandler(context.getContentResolver()); + } + mHandler.startQuery(0, context, CalendarCache.URI, CalendarCache.POJECTION, + null, null, null); + } + if (mTZQueryInProgress) { + mTZCallbacks.add(callback); + } + } + return mUseHomeTZ ? mHomeTZ : Time.getCurrentTimezone(); + } + } + + /** + * A helper method for writing a String value to the preferences + * asynchronously. + * + * @param context A context with access to the correct preferences + * @param key The preference to write to + * @param value The value to write + */ + public static void setSharedPreference(SharedPreferences prefs, String key, String value) { +// SharedPreferences prefs = getSharedPreferences(context); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(key, value); + editor.apply(); + } + + /** + * A helper method for writing a boolean value to the preferences + * asynchronously. + * + * @param context A context with access to the correct preferences + * @param key The preference to write to + * @param value The value to write + */ + public static void setSharedPreference(SharedPreferences prefs, String key, boolean value) { +// SharedPreferences prefs = getSharedPreferences(context, prefsName); + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(key, value); + editor.apply(); + } + + /** Return a properly configured SharedPreferences instance */ + public static SharedPreferences getSharedPreferences(Context context, String prefsName) { + return context.getSharedPreferences(prefsName, Context.MODE_PRIVATE); + } +} |
