am b92788aa: Merge "Adds time zone functionality into fw as a hidden api" into gingerbread
Merge commit 'b92788aa040d0971b4e54589aef7675f34d96e5d' into gingerbread-plus-aosp * commit 'b92788aa040d0971b4e54589aef7675f34d96e5d': Adds time zone functionality into fw as a hidden api
This commit is contained in:
@@ -942,6 +942,80 @@ public final class Calendar {
|
||||
public static final String END_MINUTE = "endMinute";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
|
||||
309
core/java/android/util/CalendarUtils.java
Normal file
309
core/java/android/util/CalendarUtils.java
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user