171ad58c751eb12a500916556c41e704a93895801Erik/* 271ad58c751eb12a500916556c41e704a93895801Erik * Copyright (C) 2010 The Android Open Source Project 371ad58c751eb12a500916556c41e704a93895801Erik * 471ad58c751eb12a500916556c41e704a93895801Erik * Licensed under the Apache License, Version 2.0 (the "License"); 571ad58c751eb12a500916556c41e704a93895801Erik * you may not use this file except in compliance with the License. 671ad58c751eb12a500916556c41e704a93895801Erik * You may obtain a copy of the License at 771ad58c751eb12a500916556c41e704a93895801Erik * 871ad58c751eb12a500916556c41e704a93895801Erik * http://www.apache.org/licenses/LICENSE-2.0 971ad58c751eb12a500916556c41e704a93895801Erik * 1071ad58c751eb12a500916556c41e704a93895801Erik * Unless required by applicable law or agreed to in writing, software 1171ad58c751eb12a500916556c41e704a93895801Erik * distributed under the License is distributed on an "AS IS" BASIS, 1271ad58c751eb12a500916556c41e704a93895801Erik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1371ad58c751eb12a500916556c41e704a93895801Erik * See the License for the specific language governing permissions and 1471ad58c751eb12a500916556c41e704a93895801Erik * limitations under the License. 1571ad58c751eb12a500916556c41e704a93895801Erik */ 1671ad58c751eb12a500916556c41e704a93895801Erik 1771ad58c751eb12a500916556c41e704a93895801Erikpackage android.util; 1871ad58c751eb12a500916556c41e704a93895801Erik 1971ad58c751eb12a500916556c41e704a93895801Erikimport android.content.AsyncQueryHandler; 2071ad58c751eb12a500916556c41e704a93895801Erikimport android.content.ContentResolver; 2171ad58c751eb12a500916556c41e704a93895801Erikimport android.content.ContentValues; 2271ad58c751eb12a500916556c41e704a93895801Erikimport android.content.Context; 2371ad58c751eb12a500916556c41e704a93895801Erikimport android.content.SharedPreferences; 2471ad58c751eb12a500916556c41e704a93895801Erikimport android.database.Cursor; 2571ad58c751eb12a500916556c41e704a93895801Erikimport android.provider.Calendar.CalendarCache; 2671ad58c751eb12a500916556c41e704a93895801Erikimport android.text.TextUtils; 2771ad58c751eb12a500916556c41e704a93895801Erikimport android.text.format.DateUtils; 2871ad58c751eb12a500916556c41e704a93895801Erikimport android.text.format.Time; 2971ad58c751eb12a500916556c41e704a93895801Erik 3071ad58c751eb12a500916556c41e704a93895801Erikimport java.util.Formatter; 3171ad58c751eb12a500916556c41e704a93895801Erikimport java.util.HashSet; 3271ad58c751eb12a500916556c41e704a93895801Erikimport java.util.Locale; 3371ad58c751eb12a500916556c41e704a93895801Erik 3471ad58c751eb12a500916556c41e704a93895801Erik/** 3571ad58c751eb12a500916556c41e704a93895801Erik * A class containing utility methods related to Calendar apps. 3671ad58c751eb12a500916556c41e704a93895801Erik * 3771ad58c751eb12a500916556c41e704a93895801Erik * @hide 3871ad58c751eb12a500916556c41e704a93895801Erik */ 3971ad58c751eb12a500916556c41e704a93895801Erikpublic class CalendarUtils { 4071ad58c751eb12a500916556c41e704a93895801Erik private static final boolean DEBUG = false; 4171ad58c751eb12a500916556c41e704a93895801Erik private static final String TAG = "CalendarUtils"; 4271ad58c751eb12a500916556c41e704a93895801Erik 4371ad58c751eb12a500916556c41e704a93895801Erik /** 4471ad58c751eb12a500916556c41e704a93895801Erik * This class contains methods specific to reading and writing time zone 4571ad58c751eb12a500916556c41e704a93895801Erik * values. 4671ad58c751eb12a500916556c41e704a93895801Erik */ 4771ad58c751eb12a500916556c41e704a93895801Erik public static class TimeZoneUtils { 48426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik private static final String[] TIMEZONE_TYPE_ARGS = { CalendarCache.TIMEZONE_KEY_TYPE }; 49426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik private static final String[] TIMEZONE_INSTANCES_ARGS = 50426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik { CalendarCache.TIMEZONE_KEY_INSTANCES }; 51426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik 5271ad58c751eb12a500916556c41e704a93895801Erik private static StringBuilder mSB = new StringBuilder(50); 5371ad58c751eb12a500916556c41e704a93895801Erik private static Formatter mF = new Formatter(mSB, Locale.getDefault()); 5471ad58c751eb12a500916556c41e704a93895801Erik private volatile static boolean mFirstTZRequest = true; 5571ad58c751eb12a500916556c41e704a93895801Erik private volatile static boolean mTZQueryInProgress = false; 5671ad58c751eb12a500916556c41e704a93895801Erik 5771ad58c751eb12a500916556c41e704a93895801Erik private volatile static boolean mUseHomeTZ = false; 5871ad58c751eb12a500916556c41e704a93895801Erik private volatile static String mHomeTZ = Time.getCurrentTimezone(); 5971ad58c751eb12a500916556c41e704a93895801Erik 6071ad58c751eb12a500916556c41e704a93895801Erik private static HashSet<Runnable> mTZCallbacks = new HashSet<Runnable>(); 6171ad58c751eb12a500916556c41e704a93895801Erik private static int mToken = 1; 6271ad58c751eb12a500916556c41e704a93895801Erik private static AsyncTZHandler mHandler; 6371ad58c751eb12a500916556c41e704a93895801Erik 6471ad58c751eb12a500916556c41e704a93895801Erik // The name of the shared preferences file. This name must be maintained for historical 6571ad58c751eb12a500916556c41e704a93895801Erik // reasons, as it's what PreferenceManager assigned the first time the file was created. 6671ad58c751eb12a500916556c41e704a93895801Erik private final String mPrefsName; 6771ad58c751eb12a500916556c41e704a93895801Erik 6871ad58c751eb12a500916556c41e704a93895801Erik /** 6971ad58c751eb12a500916556c41e704a93895801Erik * This is the key used for writing whether or not a home time zone should 7071ad58c751eb12a500916556c41e704a93895801Erik * be used in the Calendar app to the Calendar Preferences. 7171ad58c751eb12a500916556c41e704a93895801Erik */ 7271ad58c751eb12a500916556c41e704a93895801Erik public static final String KEY_HOME_TZ_ENABLED = "preferences_home_tz_enabled"; 7371ad58c751eb12a500916556c41e704a93895801Erik /** 7471ad58c751eb12a500916556c41e704a93895801Erik * This is the key used for writing the time zone that should be used if 7571ad58c751eb12a500916556c41e704a93895801Erik * home time zones are enabled for the Calendar app. 7671ad58c751eb12a500916556c41e704a93895801Erik */ 7771ad58c751eb12a500916556c41e704a93895801Erik public static final String KEY_HOME_TZ = "preferences_home_tz"; 7871ad58c751eb12a500916556c41e704a93895801Erik 7971ad58c751eb12a500916556c41e704a93895801Erik /** 8071ad58c751eb12a500916556c41e704a93895801Erik * This is a helper class for handling the async queries and updates for the 8171ad58c751eb12a500916556c41e704a93895801Erik * time zone settings in Calendar. 8271ad58c751eb12a500916556c41e704a93895801Erik */ 8371ad58c751eb12a500916556c41e704a93895801Erik private class AsyncTZHandler extends AsyncQueryHandler { 8471ad58c751eb12a500916556c41e704a93895801Erik public AsyncTZHandler(ContentResolver cr) { 8571ad58c751eb12a500916556c41e704a93895801Erik super(cr); 8671ad58c751eb12a500916556c41e704a93895801Erik } 8771ad58c751eb12a500916556c41e704a93895801Erik 8871ad58c751eb12a500916556c41e704a93895801Erik @Override 8971ad58c751eb12a500916556c41e704a93895801Erik protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 9071ad58c751eb12a500916556c41e704a93895801Erik synchronized (mTZCallbacks) { 9171ad58c751eb12a500916556c41e704a93895801Erik boolean writePrefs = false; 9271ad58c751eb12a500916556c41e704a93895801Erik // Check the values in the db 9371ad58c751eb12a500916556c41e704a93895801Erik int keyColumn = cursor.getColumnIndexOrThrow(CalendarCache.KEY); 9471ad58c751eb12a500916556c41e704a93895801Erik int valueColumn = cursor.getColumnIndexOrThrow(CalendarCache.VALUE); 9571ad58c751eb12a500916556c41e704a93895801Erik while(cursor.moveToNext()) { 9671ad58c751eb12a500916556c41e704a93895801Erik String key = cursor.getString(keyColumn); 9771ad58c751eb12a500916556c41e704a93895801Erik String value = cursor.getString(valueColumn); 9871ad58c751eb12a500916556c41e704a93895801Erik if (TextUtils.equals(key, CalendarCache.TIMEZONE_KEY_TYPE)) { 9971ad58c751eb12a500916556c41e704a93895801Erik boolean useHomeTZ = !TextUtils.equals( 10071ad58c751eb12a500916556c41e704a93895801Erik value, CalendarCache.TIMEZONE_TYPE_AUTO); 10171ad58c751eb12a500916556c41e704a93895801Erik if (useHomeTZ != mUseHomeTZ) { 10271ad58c751eb12a500916556c41e704a93895801Erik writePrefs = true; 10371ad58c751eb12a500916556c41e704a93895801Erik mUseHomeTZ = useHomeTZ; 10471ad58c751eb12a500916556c41e704a93895801Erik } 10571ad58c751eb12a500916556c41e704a93895801Erik } else if (TextUtils.equals( 10671ad58c751eb12a500916556c41e704a93895801Erik key, CalendarCache.TIMEZONE_KEY_INSTANCES_PREVIOUS)) { 10771ad58c751eb12a500916556c41e704a93895801Erik if (!TextUtils.isEmpty(value) && !TextUtils.equals(mHomeTZ, value)) { 10871ad58c751eb12a500916556c41e704a93895801Erik writePrefs = true; 10971ad58c751eb12a500916556c41e704a93895801Erik mHomeTZ = value; 11071ad58c751eb12a500916556c41e704a93895801Erik } 11171ad58c751eb12a500916556c41e704a93895801Erik } 11271ad58c751eb12a500916556c41e704a93895801Erik } 1135ba5de93c71218c505f28d0b05c638afa6f4d1d3Erik cursor.close(); 11471ad58c751eb12a500916556c41e704a93895801Erik if (writePrefs) { 11571ad58c751eb12a500916556c41e704a93895801Erik SharedPreferences prefs = getSharedPreferences((Context)cookie, mPrefsName); 11671ad58c751eb12a500916556c41e704a93895801Erik // Write the prefs 11771ad58c751eb12a500916556c41e704a93895801Erik setSharedPreference(prefs, KEY_HOME_TZ_ENABLED, mUseHomeTZ); 11871ad58c751eb12a500916556c41e704a93895801Erik setSharedPreference(prefs, KEY_HOME_TZ, mHomeTZ); 11971ad58c751eb12a500916556c41e704a93895801Erik } 12071ad58c751eb12a500916556c41e704a93895801Erik 12171ad58c751eb12a500916556c41e704a93895801Erik mTZQueryInProgress = false; 12271ad58c751eb12a500916556c41e704a93895801Erik for (Runnable callback : mTZCallbacks) { 12371ad58c751eb12a500916556c41e704a93895801Erik if (callback != null) { 12471ad58c751eb12a500916556c41e704a93895801Erik callback.run(); 12571ad58c751eb12a500916556c41e704a93895801Erik } 12671ad58c751eb12a500916556c41e704a93895801Erik } 12771ad58c751eb12a500916556c41e704a93895801Erik mTZCallbacks.clear(); 12871ad58c751eb12a500916556c41e704a93895801Erik } 12971ad58c751eb12a500916556c41e704a93895801Erik } 13071ad58c751eb12a500916556c41e704a93895801Erik } 13171ad58c751eb12a500916556c41e704a93895801Erik 13271ad58c751eb12a500916556c41e704a93895801Erik /** 13371ad58c751eb12a500916556c41e704a93895801Erik * The name of the file where the shared prefs for Calendar are stored 13471ad58c751eb12a500916556c41e704a93895801Erik * must be provided. All activities within an app should provide the 13571ad58c751eb12a500916556c41e704a93895801Erik * same preferences name or behavior may become erratic. 13671ad58c751eb12a500916556c41e704a93895801Erik * 13771ad58c751eb12a500916556c41e704a93895801Erik * @param prefsName 13871ad58c751eb12a500916556c41e704a93895801Erik */ 13971ad58c751eb12a500916556c41e704a93895801Erik public TimeZoneUtils(String prefsName) { 14071ad58c751eb12a500916556c41e704a93895801Erik mPrefsName = prefsName; 14171ad58c751eb12a500916556c41e704a93895801Erik } 14271ad58c751eb12a500916556c41e704a93895801Erik 14371ad58c751eb12a500916556c41e704a93895801Erik /** 14471ad58c751eb12a500916556c41e704a93895801Erik * Formats a date or a time range according to the local conventions. 14571ad58c751eb12a500916556c41e704a93895801Erik * 14671ad58c751eb12a500916556c41e704a93895801Erik * This formats a date/time range using Calendar's time zone and the 14771ad58c751eb12a500916556c41e704a93895801Erik * local conventions for the region of the device. 14871ad58c751eb12a500916556c41e704a93895801Erik * 149d762a347fb6459d7b7c87d6f09a58b210400cb95Erik * If the {@link DateUtils#FORMAT_UTC} flag is used it will pass in 150d762a347fb6459d7b7c87d6f09a58b210400cb95Erik * the UTC time zone instead. 151d762a347fb6459d7b7c87d6f09a58b210400cb95Erik * 15271ad58c751eb12a500916556c41e704a93895801Erik * @param context the context is required only if the time is shown 15371ad58c751eb12a500916556c41e704a93895801Erik * @param startMillis the start time in UTC milliseconds 15471ad58c751eb12a500916556c41e704a93895801Erik * @param endMillis the end time in UTC milliseconds 15571ad58c751eb12a500916556c41e704a93895801Erik * @param flags a bit mask of options See 15671ad58c751eb12a500916556c41e704a93895801Erik * {@link DateUtils#formatDateRange(Context, Formatter, long, long, int, String) formatDateRange} 15771ad58c751eb12a500916556c41e704a93895801Erik * @return a string containing the formatted date/time range. 15871ad58c751eb12a500916556c41e704a93895801Erik */ 15971ad58c751eb12a500916556c41e704a93895801Erik public String formatDateRange(Context context, long startMillis, 16071ad58c751eb12a500916556c41e704a93895801Erik long endMillis, int flags) { 16171ad58c751eb12a500916556c41e704a93895801Erik String date; 162d762a347fb6459d7b7c87d6f09a58b210400cb95Erik String tz; 163d762a347fb6459d7b7c87d6f09a58b210400cb95Erik if ((flags & DateUtils.FORMAT_UTC) != 0) { 164d762a347fb6459d7b7c87d6f09a58b210400cb95Erik tz = Time.TIMEZONE_UTC; 165d762a347fb6459d7b7c87d6f09a58b210400cb95Erik } else { 166d762a347fb6459d7b7c87d6f09a58b210400cb95Erik tz = getTimeZone(context, null); 167d762a347fb6459d7b7c87d6f09a58b210400cb95Erik } 16871ad58c751eb12a500916556c41e704a93895801Erik synchronized (mSB) { 16971ad58c751eb12a500916556c41e704a93895801Erik mSB.setLength(0); 17071ad58c751eb12a500916556c41e704a93895801Erik date = DateUtils.formatDateRange(context, mF, startMillis, endMillis, flags, 171d762a347fb6459d7b7c87d6f09a58b210400cb95Erik tz).toString(); 17271ad58c751eb12a500916556c41e704a93895801Erik } 17371ad58c751eb12a500916556c41e704a93895801Erik return date; 17471ad58c751eb12a500916556c41e704a93895801Erik } 17571ad58c751eb12a500916556c41e704a93895801Erik 17671ad58c751eb12a500916556c41e704a93895801Erik /** 17771ad58c751eb12a500916556c41e704a93895801Erik * Writes a new home time zone to the db. 17871ad58c751eb12a500916556c41e704a93895801Erik * 17971ad58c751eb12a500916556c41e704a93895801Erik * Updates the home time zone in the db asynchronously and updates 18071ad58c751eb12a500916556c41e704a93895801Erik * the local cache. Sending a time zone of 18171ad58c751eb12a500916556c41e704a93895801Erik * {@link CalendarCache#TIMEZONE_TYPE_AUTO} will cause it to be set 18271ad58c751eb12a500916556c41e704a93895801Erik * to the device's time zone. null or empty tz will be ignored. 18371ad58c751eb12a500916556c41e704a93895801Erik * 18471ad58c751eb12a500916556c41e704a93895801Erik * @param context The calling activity 18571ad58c751eb12a500916556c41e704a93895801Erik * @param timeZone The time zone to set Calendar to, or 18671ad58c751eb12a500916556c41e704a93895801Erik * {@link CalendarCache#TIMEZONE_TYPE_AUTO} 18771ad58c751eb12a500916556c41e704a93895801Erik */ 18871ad58c751eb12a500916556c41e704a93895801Erik public void setTimeZone(Context context, String timeZone) { 18971ad58c751eb12a500916556c41e704a93895801Erik if (TextUtils.isEmpty(timeZone)) { 19071ad58c751eb12a500916556c41e704a93895801Erik if (DEBUG) { 19171ad58c751eb12a500916556c41e704a93895801Erik Log.d(TAG, "Empty time zone, nothing to be done."); 19271ad58c751eb12a500916556c41e704a93895801Erik } 19371ad58c751eb12a500916556c41e704a93895801Erik return; 19471ad58c751eb12a500916556c41e704a93895801Erik } 19571ad58c751eb12a500916556c41e704a93895801Erik boolean updatePrefs = false; 19671ad58c751eb12a500916556c41e704a93895801Erik synchronized (mTZCallbacks) { 19771ad58c751eb12a500916556c41e704a93895801Erik if (CalendarCache.TIMEZONE_TYPE_AUTO.equals(timeZone)) { 19871ad58c751eb12a500916556c41e704a93895801Erik if (mUseHomeTZ) { 19971ad58c751eb12a500916556c41e704a93895801Erik updatePrefs = true; 20071ad58c751eb12a500916556c41e704a93895801Erik } 20171ad58c751eb12a500916556c41e704a93895801Erik mUseHomeTZ = false; 20271ad58c751eb12a500916556c41e704a93895801Erik } else { 20371ad58c751eb12a500916556c41e704a93895801Erik if (!mUseHomeTZ || !TextUtils.equals(mHomeTZ, timeZone)) { 20471ad58c751eb12a500916556c41e704a93895801Erik updatePrefs = true; 20571ad58c751eb12a500916556c41e704a93895801Erik } 20671ad58c751eb12a500916556c41e704a93895801Erik mUseHomeTZ = true; 20771ad58c751eb12a500916556c41e704a93895801Erik mHomeTZ = timeZone; 20871ad58c751eb12a500916556c41e704a93895801Erik } 20971ad58c751eb12a500916556c41e704a93895801Erik } 21071ad58c751eb12a500916556c41e704a93895801Erik if (updatePrefs) { 21171ad58c751eb12a500916556c41e704a93895801Erik // Write the prefs 21271ad58c751eb12a500916556c41e704a93895801Erik SharedPreferences prefs = getSharedPreferences(context, mPrefsName); 21371ad58c751eb12a500916556c41e704a93895801Erik setSharedPreference(prefs, KEY_HOME_TZ_ENABLED, mUseHomeTZ); 21471ad58c751eb12a500916556c41e704a93895801Erik setSharedPreference(prefs, KEY_HOME_TZ, mHomeTZ); 21571ad58c751eb12a500916556c41e704a93895801Erik 21671ad58c751eb12a500916556c41e704a93895801Erik // Update the db 21771ad58c751eb12a500916556c41e704a93895801Erik ContentValues values = new ContentValues(); 21809bd4bf85e357fc8eaa5c6a219a8827159e865daErik if (mHandler != null) { 21909bd4bf85e357fc8eaa5c6a219a8827159e865daErik mHandler.cancelOperation(mToken); 22071ad58c751eb12a500916556c41e704a93895801Erik } 22171ad58c751eb12a500916556c41e704a93895801Erik 22209bd4bf85e357fc8eaa5c6a219a8827159e865daErik mHandler = new AsyncTZHandler(context.getContentResolver()); 22371ad58c751eb12a500916556c41e704a93895801Erik 22471ad58c751eb12a500916556c41e704a93895801Erik // skip 0 so query can use it 22571ad58c751eb12a500916556c41e704a93895801Erik if (++mToken == 0) { 22671ad58c751eb12a500916556c41e704a93895801Erik mToken = 1; 22771ad58c751eb12a500916556c41e704a93895801Erik } 22871ad58c751eb12a500916556c41e704a93895801Erik 22971ad58c751eb12a500916556c41e704a93895801Erik // Write the use home tz setting 23071ad58c751eb12a500916556c41e704a93895801Erik values.put(CalendarCache.VALUE, mUseHomeTZ ? CalendarCache.TIMEZONE_TYPE_HOME 23171ad58c751eb12a500916556c41e704a93895801Erik : CalendarCache.TIMEZONE_TYPE_AUTO); 23271ad58c751eb12a500916556c41e704a93895801Erik mHandler.startUpdate(mToken, null, CalendarCache.URI, values, CalendarCache.WHERE, 233426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik TIMEZONE_TYPE_ARGS); 23471ad58c751eb12a500916556c41e704a93895801Erik 23571ad58c751eb12a500916556c41e704a93895801Erik // If using a home tz write it to the db 23671ad58c751eb12a500916556c41e704a93895801Erik if (mUseHomeTZ) { 237426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik ContentValues values2 = new ContentValues(); 238426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik values2.put(CalendarCache.VALUE, mHomeTZ); 239426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik mHandler.startUpdate(mToken, null, CalendarCache.URI, values2, 240426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik CalendarCache.WHERE, TIMEZONE_INSTANCES_ARGS); 24171ad58c751eb12a500916556c41e704a93895801Erik } 24271ad58c751eb12a500916556c41e704a93895801Erik } 24371ad58c751eb12a500916556c41e704a93895801Erik } 24471ad58c751eb12a500916556c41e704a93895801Erik 24571ad58c751eb12a500916556c41e704a93895801Erik /** 24671ad58c751eb12a500916556c41e704a93895801Erik * Gets the time zone that Calendar should be displayed in 24771ad58c751eb12a500916556c41e704a93895801Erik * 24871ad58c751eb12a500916556c41e704a93895801Erik * This is a helper method to get the appropriate time zone for Calendar. If this 24971ad58c751eb12a500916556c41e704a93895801Erik * is the first time this method has been called it will initiate an asynchronous 25071ad58c751eb12a500916556c41e704a93895801Erik * query to verify that the data in preferences is correct. The callback supplied 25171ad58c751eb12a500916556c41e704a93895801Erik * will only be called if this query returns a value other than what is stored in 25271ad58c751eb12a500916556c41e704a93895801Erik * preferences and should cause the calling activity to refresh anything that 25371ad58c751eb12a500916556c41e704a93895801Erik * depends on calling this method. 25471ad58c751eb12a500916556c41e704a93895801Erik * 25571ad58c751eb12a500916556c41e704a93895801Erik * @param context The calling activity 25671ad58c751eb12a500916556c41e704a93895801Erik * @param callback The runnable that should execute if a query returns new values 25771ad58c751eb12a500916556c41e704a93895801Erik * @return The string value representing the time zone Calendar should display 25871ad58c751eb12a500916556c41e704a93895801Erik */ 25971ad58c751eb12a500916556c41e704a93895801Erik public String getTimeZone(Context context, Runnable callback) { 26071ad58c751eb12a500916556c41e704a93895801Erik synchronized (mTZCallbacks){ 26171ad58c751eb12a500916556c41e704a93895801Erik if (mFirstTZRequest) { 26271ad58c751eb12a500916556c41e704a93895801Erik mTZQueryInProgress = true; 26371ad58c751eb12a500916556c41e704a93895801Erik mFirstTZRequest = false; 26471ad58c751eb12a500916556c41e704a93895801Erik 26571ad58c751eb12a500916556c41e704a93895801Erik SharedPreferences prefs = getSharedPreferences(context, mPrefsName); 26671ad58c751eb12a500916556c41e704a93895801Erik mUseHomeTZ = prefs.getBoolean(KEY_HOME_TZ_ENABLED, false); 26771ad58c751eb12a500916556c41e704a93895801Erik mHomeTZ = prefs.getString(KEY_HOME_TZ, Time.getCurrentTimezone()); 26871ad58c751eb12a500916556c41e704a93895801Erik 26971ad58c751eb12a500916556c41e704a93895801Erik // When the async query returns it should synchronize on 27071ad58c751eb12a500916556c41e704a93895801Erik // mTZCallbacks, update mUseHomeTZ, mHomeTZ, and the 27171ad58c751eb12a500916556c41e704a93895801Erik // preferences, set mTZQueryInProgress to false, and call all 27271ad58c751eb12a500916556c41e704a93895801Erik // the runnables in mTZCallbacks. 27371ad58c751eb12a500916556c41e704a93895801Erik if (mHandler == null) { 27471ad58c751eb12a500916556c41e704a93895801Erik mHandler = new AsyncTZHandler(context.getContentResolver()); 27571ad58c751eb12a500916556c41e704a93895801Erik } 27671ad58c751eb12a500916556c41e704a93895801Erik mHandler.startQuery(0, context, CalendarCache.URI, CalendarCache.POJECTION, 27771ad58c751eb12a500916556c41e704a93895801Erik null, null, null); 27871ad58c751eb12a500916556c41e704a93895801Erik } 27971ad58c751eb12a500916556c41e704a93895801Erik if (mTZQueryInProgress) { 28071ad58c751eb12a500916556c41e704a93895801Erik mTZCallbacks.add(callback); 28171ad58c751eb12a500916556c41e704a93895801Erik } 28271ad58c751eb12a500916556c41e704a93895801Erik } 28371ad58c751eb12a500916556c41e704a93895801Erik return mUseHomeTZ ? mHomeTZ : Time.getCurrentTimezone(); 28471ad58c751eb12a500916556c41e704a93895801Erik } 285426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik 286426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik /** 287426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik * Forces a query of the database to check for changes to the time zone. 288426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik * This should be called if another app may have modified the db. If a 289426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik * query is already in progress the callback will be added to the list 290426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik * of callbacks to be called when it returns. 291426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik * 292426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik * @param context The calling activity 293426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik * @param callback The runnable that should execute if a query returns 294426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik * new values 295426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik */ 296426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik public void forceDBRequery(Context context, Runnable callback) { 297426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik synchronized (mTZCallbacks){ 298426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik if (mTZQueryInProgress) { 299426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik mTZCallbacks.add(callback); 300426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik return; 301426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik } 302426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik mFirstTZRequest = true; 303426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik getTimeZone(context, callback); 304426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik } 305426ee7f22eeaa016cdbf0addbb7b2cc6b6cc3487Erik } 30671ad58c751eb12a500916556c41e704a93895801Erik } 30771ad58c751eb12a500916556c41e704a93895801Erik 30871ad58c751eb12a500916556c41e704a93895801Erik /** 30971ad58c751eb12a500916556c41e704a93895801Erik * A helper method for writing a String value to the preferences 31071ad58c751eb12a500916556c41e704a93895801Erik * asynchronously. 31171ad58c751eb12a500916556c41e704a93895801Erik * 31271ad58c751eb12a500916556c41e704a93895801Erik * @param context A context with access to the correct preferences 31371ad58c751eb12a500916556c41e704a93895801Erik * @param key The preference to write to 31471ad58c751eb12a500916556c41e704a93895801Erik * @param value The value to write 31571ad58c751eb12a500916556c41e704a93895801Erik */ 31671ad58c751eb12a500916556c41e704a93895801Erik public static void setSharedPreference(SharedPreferences prefs, String key, String value) { 31771ad58c751eb12a500916556c41e704a93895801Erik// SharedPreferences prefs = getSharedPreferences(context); 31871ad58c751eb12a500916556c41e704a93895801Erik SharedPreferences.Editor editor = prefs.edit(); 31971ad58c751eb12a500916556c41e704a93895801Erik editor.putString(key, value); 32071ad58c751eb12a500916556c41e704a93895801Erik editor.apply(); 32171ad58c751eb12a500916556c41e704a93895801Erik } 32271ad58c751eb12a500916556c41e704a93895801Erik 32371ad58c751eb12a500916556c41e704a93895801Erik /** 32471ad58c751eb12a500916556c41e704a93895801Erik * A helper method for writing a boolean value to the preferences 32571ad58c751eb12a500916556c41e704a93895801Erik * asynchronously. 32671ad58c751eb12a500916556c41e704a93895801Erik * 32771ad58c751eb12a500916556c41e704a93895801Erik * @param context A context with access to the correct preferences 32871ad58c751eb12a500916556c41e704a93895801Erik * @param key The preference to write to 32971ad58c751eb12a500916556c41e704a93895801Erik * @param value The value to write 33071ad58c751eb12a500916556c41e704a93895801Erik */ 33171ad58c751eb12a500916556c41e704a93895801Erik public static void setSharedPreference(SharedPreferences prefs, String key, boolean value) { 33271ad58c751eb12a500916556c41e704a93895801Erik// SharedPreferences prefs = getSharedPreferences(context, prefsName); 33371ad58c751eb12a500916556c41e704a93895801Erik SharedPreferences.Editor editor = prefs.edit(); 33471ad58c751eb12a500916556c41e704a93895801Erik editor.putBoolean(key, value); 33571ad58c751eb12a500916556c41e704a93895801Erik editor.apply(); 33671ad58c751eb12a500916556c41e704a93895801Erik } 33771ad58c751eb12a500916556c41e704a93895801Erik 33871ad58c751eb12a500916556c41e704a93895801Erik /** Return a properly configured SharedPreferences instance */ 33971ad58c751eb12a500916556c41e704a93895801Erik public static SharedPreferences getSharedPreferences(Context context, String prefsName) { 34071ad58c751eb12a500916556c41e704a93895801Erik return context.getSharedPreferences(prefsName, Context.MODE_PRIVATE); 34171ad58c751eb12a500916556c41e704a93895801Erik } 34271ad58c751eb12a500916556c41e704a93895801Erik} 343