1d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson/* 2d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * Copyright (C) 2012 The Android Open Source Project 3d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * 4d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * Licensed under the Apache License, Version 2.0 (the "License"); 5d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * you may not use this file except in compliance with the License. 6d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * You may obtain a copy of the License at 7d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * 8d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * http://www.apache.org/licenses/LICENSE-2.0 9d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * 10d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * Unless required by applicable law or agreed to in writing, software 11d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * distributed under the License is distributed on an "AS IS" BASIS, 12d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * See the License for the specific language governing permissions and 14d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * limitations under the License. 15d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson */ 16d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 17d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonpackage com.android.deskclock; 18d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 1978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.animation.Animator; 2078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.animation.AnimatorSet; 2178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.animation.ObjectAnimator; 2278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.animation.TimeInterpolator; 230b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultasimport android.app.AlarmManager; 24d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.content.Context; 25d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.content.Intent; 26de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelsonimport android.content.SharedPreferences; 27d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.content.pm.PackageInfo; 28d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.content.pm.PackageManager.NameNotFoundException; 29d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelsonimport android.content.res.Resources; 3078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.graphics.Color; 3178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.graphics.Paint; 3278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.graphics.PorterDuff; 3378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.graphics.PorterDuffColorFilter; 3480eafdf26fc496ffa112b9eb1b44d7b80333c80arachelzhangimport android.graphics.Typeface; 35d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.net.Uri; 364fd80b58da8ad66e0e4a23cbf7c900174727fb4eRobyn Coultasimport android.os.Build; 3778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.os.Handler; 38287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzsteinimport android.os.SystemClock; 3978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.preference.PreferenceManager; 40690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelsonimport android.text.Spannable; 41690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelsonimport android.text.SpannableString; 42d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.text.TextUtils; 4378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.text.format.DateFormat; 4462b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kungimport android.text.format.DateUtils; 45eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultasimport android.text.format.Time; 46690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelsonimport android.text.style.AbsoluteSizeSpan; 47690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelsonimport android.text.style.StyleSpan; 48690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelsonimport android.text.style.TypefaceSpan; 49d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.view.MenuItem; 5078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.view.View; 5178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.view.animation.AccelerateInterpolator; 5278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.view.animation.DecelerateInterpolator; 53690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelsonimport android.widget.TextClock; 5478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.widget.TextView; 55d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 56de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelsonimport com.android.deskclock.stopwatch.Stopwatches; 5798b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultasimport com.android.deskclock.timer.Timers; 58d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelsonimport com.android.deskclock.worldclock.CityObj; 59de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson 6035300f84cef68e7f5666ec88591496aaaad242d1Isaac Katzenelsonimport java.text.SimpleDateFormat; 6178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport java.util.Calendar; 6235300f84cef68e7f5666ec88591496aaaad242d1Isaac Katzenelsonimport java.util.Date; 63419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhangimport java.util.GregorianCalendar; 64d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport java.util.Locale; 6562b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kungimport java.util.TimeZone; 66d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 67d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 68d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonpublic class Utils { 69d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson private final static String PARAM_LANGUAGE_CODE = "hl"; 70d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 71d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson /** 72d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * Help URL query parameter key for the app version. 73d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson */ 74d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson private final static String PARAM_VERSION = "version"; 75d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 76d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson /** 77d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * Cached version code to prevent repeated calls to the package manager. 78d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson */ 79d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson private static String sCachedVersionCode = null; 80d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 81419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang /** 82419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang * Array of single-character day of week symbols {'S', 'M', 'T', 'W', 'T', 'F', 'S'} 83419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang */ 84419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang private static String[] sShortWeekdays = null; 85419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang 8678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein /** Types that may be used for clock displays. **/ 8778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein public static final String CLOCK_TYPE_DIGITAL = "digital"; 8878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein public static final String CLOCK_TYPE_ANALOG = "analog"; 89d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 90d48339f270ba72bb8416fd194b4a0d1aeb3bd958rachelzhang /** The background colors of the app, it changes thru out the day to mimic the sky. **/ 91bfd25edaf38efb6df428ff261d127a99025d0622rachelzhang public static final String[] BACKGROUND_SPECTRUM = { "#212121", "#27232e", "#2d253a", 92bfd25edaf38efb6df428ff261d127a99025d0622rachelzhang "#332847", "#382a53", "#3e2c5f", "#442e6c", "#393a7a", "#2e4687", "#235395", "#185fa2", 93bfd25edaf38efb6df428ff261d127a99025d0622rachelzhang "#0d6baf", "#0277bd", "#0d6cb1", "#1861a6", "#23569b", "#2d4a8f", "#383f84", "#433478", 94bfd25edaf38efb6df428ff261d127a99025d0622rachelzhang "#3d3169", "#382e5b", "#322b4d", "#2c273e", "#272430" }; 95d48339f270ba72bb8416fd194b4a0d1aeb3bd958rachelzhang 967048625adb7c349deab4c00b2d85bcf65c164ae5Isaac Katzenelson /** 97f1ce98a6e2972854968488d2a28adbc29364b0f9Isaac Katzenelson * Returns whether the SDK is KitKat or later 984fd80b58da8ad66e0e4a23cbf7c900174727fb4eRobyn Coultas */ 99f1ce98a6e2972854968488d2a28adbc29364b0f9Isaac Katzenelson public static boolean isKitKatOrLater() { 100f1ce98a6e2972854968488d2a28adbc29364b0f9Isaac Katzenelson return Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2; 1014fd80b58da8ad66e0e4a23cbf7c900174727fb4eRobyn Coultas } 1024fd80b58da8ad66e0e4a23cbf7c900174727fb4eRobyn Coultas 1037048625adb7c349deab4c00b2d85bcf65c164ae5Isaac Katzenelson 104d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson public static void prepareHelpMenuItem(Context context, MenuItem helpMenuItem) { 105d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson String helpUrlString = context.getResources().getString(R.string.desk_clock_help_url); 106d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson if (TextUtils.isEmpty(helpUrlString)) { 107d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // The help url string is empty or null, so set the help menu item to be invisible. 108d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson helpMenuItem.setVisible(false); 109d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson return; 110d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson } 111d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // The help url string exists, so first add in some extra query parameters. 87 112d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson final Uri fullUri = uriWithAddedParameters(context, Uri.parse(helpUrlString)); 113d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 114d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // Then, create an intent that will be fired when the user 115d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // selects this help menu item. 116d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson Intent intent = new Intent(Intent.ACTION_VIEW, fullUri); 117d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 118d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 119d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 120d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // Set the intent to the help menu item, show the help menu item in the overflow 121d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // menu, and make it visible. 122d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson helpMenuItem.setIntent(intent); 123d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson helpMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); 124d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson helpMenuItem.setVisible(true); 125d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson } 126d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 127d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson /** 128d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * Adds two query parameters into the Uri, namely the language code and the version code 1298322b2fa9d474fee9e7950fec68bd35e03fc9861Robyn Coultas * of the application's package as gotten via the context. 130d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * @return the uri with added query parameters 131d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson */ 132d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson private static Uri uriWithAddedParameters(Context context, Uri baseUri) { 133d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson Uri.Builder builder = baseUri.buildUpon(); 134d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 135d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // Add in the preferred language 136d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson builder.appendQueryParameter(PARAM_LANGUAGE_CODE, Locale.getDefault().toString()); 137d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 138d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // Add in the package version code 139d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson if (sCachedVersionCode == null) { 140d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // There is no cached version code, so try to get it from the package manager. 141d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson try { 142d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // cache the version code 143d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson PackageInfo info = context.getPackageManager().getPackageInfo( 144d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson context.getPackageName(), 0); 145d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson sCachedVersionCode = Integer.toString(info.versionCode); 146d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 147d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // append the version code to the uri 148d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson builder.appendQueryParameter(PARAM_VERSION, sCachedVersionCode); 149d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson } catch (NameNotFoundException e) { 150d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // Cannot find the package name, so don't add in the version parameter 151d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // This shouldn't happen. 152cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen LogUtils.wtf("Invalid package name for context " + e); 153d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson } 154d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson } else { 155d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson builder.appendQueryParameter(PARAM_VERSION, sCachedVersionCode); 156d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson } 157d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 158d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson // Build the full uri and return it 159d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson return builder.build(); 160d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson } 161d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson 162287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein public static long getTimeNow() { 163287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein return SystemClock.elapsedRealtime(); 164287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein } 165287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein 16600cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein /** 16700cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein * Calculate the amount by which the radius of a CircleTimerView should be offset by the any 16800cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein * of the extra painted objects. 16900cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein */ 17000cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein public static float calculateRadiusOffset( 1718322b2fa9d474fee9e7950fec68bd35e03fc9861Robyn Coultas float strokeSize, float dotStrokeSize, float markerStrokeSize) { 1728322b2fa9d474fee9e7950fec68bd35e03fc9861Robyn Coultas return Math.max(strokeSize, Math.max(dotStrokeSize, markerStrokeSize)); 17300cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein } 17400cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein 175efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas /** 176efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas * Uses {@link Utils#calculateRadiusOffset(float, float, float)} after fetching the values 177efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas * from the resources just as {@link CircleTimerView#init(android.content.Context)} does. 178efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas */ 179efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas public static float calculateRadiusOffset(Resources resources) { 180efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas if (resources != null) { 181efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas float strokeSize = resources.getDimension(R.dimen.circletimer_circle_size); 1828322b2fa9d474fee9e7950fec68bd35e03fc9861Robyn Coultas float dotStrokeSize = resources.getDimension(R.dimen.circletimer_dot_size); 183efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas float markerStrokeSize = resources.getDimension(R.dimen.circletimer_marker_size); 1848322b2fa9d474fee9e7950fec68bd35e03fc9861Robyn Coultas return calculateRadiusOffset(strokeSize, dotStrokeSize, markerStrokeSize); 185efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas } else { 186efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas return 0f; 187efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas } 188efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas } 189efc4ad3bce5f68e6a64c4aeac4f2359ab9bae5a8Robyn Coultas 19072332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein /** The pressed color used throughout the app. If this method is changed, it will not have 19172332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein * any effect on the button press states, and those must be changed separately. 19272332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein **/ 19372332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein public static int getPressedColorId() { 19469a4b4f2810100f19e997b4e539f1b0e56b0afb5rachelzhang return R.color.hot_pink; 19572332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein } 19672332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein 19772332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein /** The un-pressed color used throughout the app. If this method is changed, it will not have 19872332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein * any effect on the button press states, and those must be changed separately. 19972332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein **/ 20072332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein public static int getGrayColorId() { 20172332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein return R.color.clock_gray; 20272332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein } 203de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson 204de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson /** 205de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson * Clears the persistent data of stopwatch (start time, state, laps, etc...). 206de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson */ 207de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson public static void clearSwSharedPref(SharedPreferences prefs) { 208de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson SharedPreferences.Editor editor = prefs.edit(); 209de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson editor.remove (Stopwatches.PREF_START_TIME); 210de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson editor.remove (Stopwatches.PREF_ACCUM_TIME); 211de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson editor.remove (Stopwatches.PREF_STATE); 212de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson int lapNum = prefs.getInt(Stopwatches.PREF_LAP_NUM, Stopwatches.STOPWATCH_RESET); 213de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson for (int i = 0; i < lapNum; i++) { 214de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson String key = Stopwatches.PREF_LAP_TIME + Integer.toString(i); 215de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson editor.remove(key); 216de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson } 217de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson editor.remove(Stopwatches.PREF_LAP_NUM); 218de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson editor.apply(); 219de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson } 22098b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas 22198b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas /** 22298b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas * Broadcast a message to show the in-use timers in the notifications 22398b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas */ 22498b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas public static void showInUseNotifications(Context context) { 22598b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas Intent timerIntent = new Intent(); 22698b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas timerIntent.setAction(Timers.NOTIF_IN_USE_SHOW); 22798b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas context.sendBroadcast(timerIntent); 22898b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas } 22978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 230e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas /** 231e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas * Broadcast a message to show the in-use timers in the notifications 232e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas */ 233e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas public static void showTimesUpNotifications(Context context) { 234e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas Intent timerIntent = new Intent(); 235e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas timerIntent.setAction(Timers.NOTIF_TIMES_UP_SHOW); 236e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas context.sendBroadcast(timerIntent); 237e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas } 238e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas 239e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas /** 240e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas * Broadcast a message to cancel the in-use timers in the notifications 241e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas */ 242e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas public static void cancelTimesUpNotifications(Context context) { 243e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas Intent timerIntent = new Intent(); 244e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas timerIntent.setAction(Timers.NOTIF_TIMES_UP_CANCEL); 245e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas context.sendBroadcast(timerIntent); 246e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas } 247e332c5744e5741a6149afd226e1f193111dcb7deRobyn Coultas 24878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein /** Runnable for use with screensaver and dream, to move the clock every minute. 24978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein * registerViews() must be called prior to posting. 25078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein */ 25178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein public static class ScreensaverMoveSaverRunnable implements Runnable { 25278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein static final long MOVE_DELAY = 60000; // DeskClock.SCREEN_SAVER_MOVE_DELAY; 25378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein static final long SLIDE_TIME = 10000; 25478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein static final long FADE_TIME = 3000; 25578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 25678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein static final boolean SLIDE = false; 25778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 25878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein private View mContentView, mSaverView; 25978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein private final Handler mHandler; 26078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 26178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein private static TimeInterpolator mSlowStartWithBrakes; 26278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 26378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 26478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein public ScreensaverMoveSaverRunnable(Handler handler) { 26578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein mHandler = handler; 26678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein mSlowStartWithBrakes = new TimeInterpolator() { 26778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein @Override 26878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein public float getInterpolation(float x) { 26978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein return (float)(Math.cos((Math.pow(x,3) + 1) * Math.PI) / 2.0f) + 0.5f; 27078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 27178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein }; 27278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 27378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 27478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein public void registerViews(View contentView, View saverView) { 27578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein mContentView = contentView; 27678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein mSaverView = saverView; 27778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 27878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 27978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein @Override 28078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein public void run() { 28178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein long delay = MOVE_DELAY; 28278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein if (mContentView == null || mSaverView == null) { 28378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein mHandler.removeCallbacks(this); 28478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein mHandler.postDelayed(this, delay); 28578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein return; 28678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 28778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 28878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein final float xrange = mContentView.getWidth() - mSaverView.getWidth(); 28978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein final float yrange = mContentView.getHeight() - mSaverView.getHeight(); 29078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 29178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein if (xrange == 0 && yrange == 0) { 29278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein delay = 500; // back in a split second 29378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } else { 29478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein final int nextx = (int) (Math.random() * xrange); 29578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein final int nexty = (int) (Math.random() * yrange); 29678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 29778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein if (mSaverView.getAlpha() == 0f) { 29878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein // jump right there 29978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein mSaverView.setX(nextx); 30078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein mSaverView.setY(nexty); 30178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein ObjectAnimator.ofFloat(mSaverView, "alpha", 0f, 1f) 30278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein .setDuration(FADE_TIME) 30378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein .start(); 30478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } else { 30578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein AnimatorSet s = new AnimatorSet(); 30678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein Animator xMove = ObjectAnimator.ofFloat(mSaverView, 30778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein "x", mSaverView.getX(), nextx); 30878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein Animator yMove = ObjectAnimator.ofFloat(mSaverView, 30978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein "y", mSaverView.getY(), nexty); 31078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 31178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein Animator xShrink = ObjectAnimator.ofFloat(mSaverView, "scaleX", 1f, 0.85f); 31278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein Animator xGrow = ObjectAnimator.ofFloat(mSaverView, "scaleX", 0.85f, 1f); 31378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 31478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein Animator yShrink = ObjectAnimator.ofFloat(mSaverView, "scaleY", 1f, 0.85f); 31578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein Animator yGrow = ObjectAnimator.ofFloat(mSaverView, "scaleY", 0.85f, 1f); 31678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein AnimatorSet shrink = new AnimatorSet(); shrink.play(xShrink).with(yShrink); 31778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein AnimatorSet grow = new AnimatorSet(); grow.play(xGrow).with(yGrow); 31878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 31978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein Animator fadeout = ObjectAnimator.ofFloat(mSaverView, "alpha", 1f, 0f); 32078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein Animator fadein = ObjectAnimator.ofFloat(mSaverView, "alpha", 0f, 1f); 32178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 32278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 32378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein if (SLIDE) { 32478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein s.play(xMove).with(yMove); 32578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein s.setDuration(SLIDE_TIME); 32678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 32778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein s.play(shrink.setDuration(SLIDE_TIME/2)); 32878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein s.play(grow.setDuration(SLIDE_TIME/2)).after(shrink); 32978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein s.setInterpolator(mSlowStartWithBrakes); 33078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } else { 33178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein AccelerateInterpolator accel = new AccelerateInterpolator(); 33278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein DecelerateInterpolator decel = new DecelerateInterpolator(); 33378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 33478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein shrink.setDuration(FADE_TIME).setInterpolator(accel); 33578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein fadeout.setDuration(FADE_TIME).setInterpolator(accel); 33678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein grow.setDuration(FADE_TIME).setInterpolator(decel); 33778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein fadein.setDuration(FADE_TIME).setInterpolator(decel); 33878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein s.play(shrink); 33978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein s.play(fadeout); 34078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein s.play(xMove.setDuration(0)).after(FADE_TIME); 34178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein s.play(yMove.setDuration(0)).after(FADE_TIME); 34278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein s.play(fadein).after(FADE_TIME); 34378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein s.play(grow).after(FADE_TIME); 34478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 34578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein s.start(); 34678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 34778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 34878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein long now = System.currentTimeMillis(); 34978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein long adjust = (now % 60000); 35078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein delay = delay 35178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein + (MOVE_DELAY - adjust) // minute aligned 35278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein - (SLIDE ? 0 : FADE_TIME) // start moving before the fade 35378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein ; 35478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 35578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 35678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein mHandler.removeCallbacks(this); 35778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein mHandler.postDelayed(this, delay); 35878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 35978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 36078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 36178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein /** Setup to find out when the quarter-hour changes (e.g. Kathmandu is GMT+5:45) **/ 3623bb9d29c12584480f3651ccbef86f2777c0b7818Robyn Coultas public static long getAlarmOnQuarterHour() { 36378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein Calendar nextQuarter = Calendar.getInstance(); 36478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein // Set 1 second to ensure quarter-hour threshold passed. 36578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein nextQuarter.set(Calendar.SECOND, 1); 366851c662d9f02e76c9fd23426c9e6713521e01aacIsaac Katzenelson nextQuarter.set(Calendar.MILLISECOND, 0); 36778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein int minute = nextQuarter.get(Calendar.MINUTE); 36878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein nextQuarter.add(Calendar.MINUTE, 15 - (minute % 15)); 36978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein long alarmOnQuarterHour = nextQuarter.getTimeInMillis(); 370851c662d9f02e76c9fd23426c9e6713521e01aacIsaac Katzenelson long now = System.currentTimeMillis(); 371851c662d9f02e76c9fd23426c9e6713521e01aacIsaac Katzenelson long delta = alarmOnQuarterHour - now; 372851c662d9f02e76c9fd23426c9e6713521e01aacIsaac Katzenelson if (0 >= delta || delta > 901000) { 373851c662d9f02e76c9fd23426c9e6713521e01aacIsaac Katzenelson // Something went wrong in the calculation, schedule something that is 374851c662d9f02e76c9fd23426c9e6713521e01aacIsaac Katzenelson // about 15 minutes. Next time , it will align with the 15 minutes border. 375851c662d9f02e76c9fd23426c9e6713521e01aacIsaac Katzenelson alarmOnQuarterHour = now + 901000; 37678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 37778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein return alarmOnQuarterHour; 37878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 37978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 380eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas // Setup a thread that starts at midnight plus one second. The extra second is added to ensure 381eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas // the date has changed. 382eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas public static void setMidnightUpdater(Handler handler, Runnable runnable) { 383eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas String timezone = TimeZone.getDefault().getID(); 384eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas if (handler == null || runnable == null || timezone == null) { 385eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas return; 386eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas } 387eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas long now = System.currentTimeMillis(); 388eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas Time time = new Time(timezone); 389eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas time.set(now); 390eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas long runInMillis = ((24 - time.hour) * 3600 - time.minute * 60 - time.second + 1) * 1000; 391eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas handler.removeCallbacks(runnable); 392eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas handler.postDelayed(runnable, runInMillis); 393eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas } 394eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas 395eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas // Stop the midnight update thread 3963bb9d29c12584480f3651ccbef86f2777c0b7818Robyn Coultas public static void cancelMidnightUpdater(Handler handler, Runnable runnable) { 397eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas if (handler == null || runnable == null) { 398eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas return; 399eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas } 400eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas handler.removeCallbacks(runnable); 4019096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas } 4029096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas 4039096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas // Setup a thread that starts at the quarter-hour plus one second. The extra second is added to 4049096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas // ensure dates have changed. 4059096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas public static void setQuarterHourUpdater(Handler handler, Runnable runnable) { 4069096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas String timezone = TimeZone.getDefault().getID(); 4079096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas if (handler == null || runnable == null || timezone == null) { 4089096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas return; 4099096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas } 4109096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas long runInMillis = getAlarmOnQuarterHour() - System.currentTimeMillis(); 4119096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas // Ensure the delay is at least one second. 4129096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas if (runInMillis < 1000) { 4139096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas runInMillis = 1000; 4149096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas } 4159096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas handler.removeCallbacks(runnable); 4169096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas handler.postDelayed(runnable, runInMillis); 4179096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas } 4189096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas 4199096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas // Stop the quarter-hour update thread 4209096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas public static void cancelQuarterHourUpdater(Handler handler, Runnable runnable) { 4219096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas if (handler == null || runnable == null) { 4229096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas return; 4239096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas } 4249096dcec19f88883933e74b2d446eb94e6196089Robyn Coultas handler.removeCallbacks(runnable); 425eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas } 426eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas 42778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein /** 42878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein * For screensavers to set whether the digital or analog clock should be displayed. 42978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein * Returns the view to be displayed. 43078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein */ 43178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein public static View setClockStyle(Context context, View digitalClock, View analogClock, 43278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein String clockStyleKey) { 43378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); 43478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein String defaultClockStyle = context.getResources().getString(R.string.default_clock_style); 43578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein String style = sharedPref.getString(clockStyleKey, defaultClockStyle); 43678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein View returnView; 43778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein if (style.equals(CLOCK_TYPE_ANALOG)) { 43878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein digitalClock.setVisibility(View.GONE); 43978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein analogClock.setVisibility(View.VISIBLE); 44078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein returnView = analogClock; 44178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } else { 44278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein digitalClock.setVisibility(View.VISIBLE); 44378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein analogClock.setVisibility(View.GONE); 44478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein returnView = digitalClock; 44578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 44678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 44778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein return returnView; 44878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 44978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 45078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein /** 45178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein * For screensavers to dim the lights if necessary. 45278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein */ 45378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein public static void dimClockView(boolean dim, View clockView) { 45478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein Paint paint = new Paint(); 45578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein paint.setColor(Color.WHITE); 45678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein paint.setColorFilter(new PorterDuffColorFilter( 457e8709b46a14defe610515a1a4c4fefa32ec9b044Isaac Katzenelson (dim ? 0x40FFFFFF : 0xC0FFFFFF), 45878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein PorterDuff.Mode.MULTIPLY)); 45978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein clockView.setLayerType(View.LAYER_TYPE_HARDWARE, paint); 46078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 46178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 462c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos /** 463c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos * @return The next alarm from {@link AlarmManager} 464c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos */ 465c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos public static String getNextAlarm(Context context) { 466c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos String timeString = null; 467a855a071a5cf2c1252389c0d650eba25f7b0be5fBudi Kusmiantoro final AlarmManager.AlarmClockInfo info = ((AlarmManager) context.getSystemService( 468a855a071a5cf2c1252389c0d650eba25f7b0be5fBudi Kusmiantoro Context.ALARM_SERVICE)).getNextAlarmClock(); 469a855a071a5cf2c1252389c0d650eba25f7b0be5fBudi Kusmiantoro if (info != null) { 470a855a071a5cf2c1252389c0d650eba25f7b0be5fBudi Kusmiantoro final long triggerTime = info.getTriggerTime(); 471a855a071a5cf2c1252389c0d650eba25f7b0be5fBudi Kusmiantoro final Calendar alarmTime = Calendar.getInstance(); 472a855a071a5cf2c1252389c0d650eba25f7b0be5fBudi Kusmiantoro alarmTime.setTimeInMillis(triggerTime); 473a855a071a5cf2c1252389c0d650eba25f7b0be5fBudi Kusmiantoro timeString = AlarmUtils.getFormattedTime(context, alarmTime); 474a855a071a5cf2c1252389c0d650eba25f7b0be5fBudi Kusmiantoro } 475c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos return timeString; 476c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos } 477c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos 47878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein /** Clock views can call this to refresh their alarm to the next upcoming value. **/ 479b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson public static void refreshAlarm(Context context, View clock) { 480c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos final String nextAlarm = getNextAlarm(context); 48178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein TextView nextAlarmView; 482b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson nextAlarmView = (TextView) clock.findViewById(R.id.nextAlarm); 48378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein if (!TextUtils.isEmpty(nextAlarm) && nextAlarmView != null) { 48478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein nextAlarmView.setText( 48578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein context.getString(R.string.control_set_alarm_with_existing, nextAlarm)); 48678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein nextAlarmView.setContentDescription(context.getResources().getString( 48778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein R.string.next_alarm_description, nextAlarm)); 48878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein nextAlarmView.setVisibility(View.VISIBLE); 48978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } else { 49078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein nextAlarmView.setVisibility(View.GONE); 49178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 49278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 49378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 49478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein /** Clock views can call this to refresh their date. **/ 495b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson public static void updateDate( 496b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson String dateFormat, String dateFormatForAccessibility, View clock) { 49778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 49835300f84cef68e7f5666ec88591496aaaad242d1Isaac Katzenelson Date now = new Date(); 49978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein TextView dateDisplay; 500b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson dateDisplay = (TextView) clock.findViewById(R.id.date); 50178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein if (dateDisplay != null) { 50235300f84cef68e7f5666ec88591496aaaad242d1Isaac Katzenelson final Locale l = Locale.getDefault(); 50335300f84cef68e7f5666ec88591496aaaad242d1Isaac Katzenelson String fmt = DateFormat.getBestDateTimePattern(l, dateFormat); 50435300f84cef68e7f5666ec88591496aaaad242d1Isaac Katzenelson SimpleDateFormat sdf = new SimpleDateFormat(fmt, l); 50535300f84cef68e7f5666ec88591496aaaad242d1Isaac Katzenelson dateDisplay.setText(sdf.format(now)); 50678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein dateDisplay.setVisibility(View.VISIBLE); 50735300f84cef68e7f5666ec88591496aaaad242d1Isaac Katzenelson fmt = DateFormat.getBestDateTimePattern(l, dateFormatForAccessibility); 50835300f84cef68e7f5666ec88591496aaaad242d1Isaac Katzenelson sdf = new SimpleDateFormat(fmt, l); 50935300f84cef68e7f5666ec88591496aaaad242d1Isaac Katzenelson dateDisplay.setContentDescription(sdf.format(now)); 51078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 51178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein } 51278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein 513690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelson /*** 5143a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson * Formats the time in the TextClock according to the Locale with a special 515690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelson * formatting treatment for the am/pm label. 516690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelson * @param clock - TextClock to format 5173a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson * @param amPmFontSize - size of the am/pm label since it is usually smaller 5183a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson * than the clock time size. 519690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelson */ 520690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelson public static void setTimeFormat(TextClock clock, int amPmFontSize) { 521690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelson if (clock != null) { 5223a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson // Get the best format for 12 hours mode according to the locale 5238b8542c44a744b7afc5c9af34bbfec924e13a963Isaac Katzenelson clock.setFormat12Hour(get12ModeFormat(amPmFontSize)); 5243a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson // Get the best format for 24 hours mode according to the locale 5258b8542c44a744b7afc5c9af34bbfec924e13a963Isaac Katzenelson clock.setFormat24Hour(get24ModeFormat()); 526690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelson } 527690f451a6aea35d944cb2eaddf488d3acf377184Isaac Katzenelson } 5288b8542c44a744b7afc5c9af34bbfec924e13a963Isaac Katzenelson /*** 5298b8542c44a744b7afc5c9af34bbfec924e13a963Isaac Katzenelson * @param amPmFontSize - size of am/pm label (label removed is size is 0). 5308b8542c44a744b7afc5c9af34bbfec924e13a963Isaac Katzenelson * @return format string for 12 hours mode time 5318b8542c44a744b7afc5c9af34bbfec924e13a963Isaac Katzenelson */ 5328b8542c44a744b7afc5c9af34bbfec924e13a963Isaac Katzenelson public static CharSequence get12ModeFormat(int amPmFontSize) { 53336ac292d66cf5b5a5776460cc9800be792e10adfIsaac Katzenelson String skeleton = "hma"; 5343a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton); 53536ac292d66cf5b5a5776460cc9800be792e10adfIsaac Katzenelson // Remove the am/pm 53636ac292d66cf5b5a5776460cc9800be792e10adfIsaac Katzenelson if (amPmFontSize <= 0) { 53736ac292d66cf5b5a5776460cc9800be792e10adfIsaac Katzenelson pattern.replaceAll("a", "").trim(); 53836ac292d66cf5b5a5776460cc9800be792e10adfIsaac Katzenelson } 5393a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson // Replace spaces with "Hair Space" 5403a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson pattern = pattern.replaceAll(" ", "\u200A"); 5413a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson // Build a spannable so that the am/pm will be formatted 5423a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson int amPmPos = pattern.indexOf('a'); 5433a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson if (amPmPos == -1) { 5443a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson return pattern; 5453a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson } 5463a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson Spannable sp = new SpannableString(pattern); 54780eafdf26fc496ffa112b9eb1b44d7b80333c80arachelzhang sp.setSpan(new StyleSpan(Typeface.NORMAL), amPmPos, amPmPos + 1, 5483a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson Spannable.SPAN_POINT_MARK); 5493a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson sp.setSpan(new AbsoluteSizeSpan(amPmFontSize), amPmPos, amPmPos + 1, 5503a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson Spannable.SPAN_POINT_MARK); 55180eafdf26fc496ffa112b9eb1b44d7b80333c80arachelzhang sp.setSpan(new TypefaceSpan("sans-serif"), amPmPos, amPmPos + 1, 5523a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson Spannable.SPAN_POINT_MARK); 5533a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson return sp; 5543a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson } 5553a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson 5568b8542c44a744b7afc5c9af34bbfec924e13a963Isaac Katzenelson public static CharSequence get24ModeFormat() { 5573a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson String skeleton = "Hm"; 5583a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson return DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton); 5593a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson } 5603a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson 56162b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung public static CityObj[] loadCitiesFromXml(Context c) { 562d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson Resources r = c.getResources(); 563d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson // Read strings array of name,timezone, id 564d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson // make sure the list are the same length 565d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson String[] cities = r.getStringArray(R.array.cities_names); 566d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson String[] timezones = r.getStringArray(R.array.cities_tz); 567d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson String[] ids = r.getStringArray(R.array.cities_id); 56825ca0e1b5e70386b30171d8aba8810593baffecbIsaac Katzenelson int minLength = cities.length; 569d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson if (cities.length != timezones.length || ids.length != cities.length) { 57025ca0e1b5e70386b30171d8aba8810593baffecbIsaac Katzenelson minLength = Math.min(cities.length, Math.min(timezones.length, ids.length)); 571cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen LogUtils.e("City lists sizes are not the same, truncating"); 572d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson } 57325ca0e1b5e70386b30171d8aba8810593baffecbIsaac Katzenelson CityObj[] tempList = new CityObj[minLength]; 574d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson for (int i = 0; i < cities.length; i++) { 575d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson tempList[i] = new CityObj(cities[i], timezones[i], ids[i]); 576d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson } 577d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson return tempList; 578d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson } 579d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson 58062b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung /** 58162b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung * Returns string denoting the timezone hour offset (e.g. GMT-8:00) 58262b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung */ 58362b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung public static String getGMTHourOffset(TimeZone timezone, boolean showMinutes) { 58462b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung StringBuilder sb = new StringBuilder(); 58557cb1dbcead54ff08e8f07e727d0b1c842301440rachelzhang sb.append("GMT "); 58662b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung int gmtOffset = timezone.getRawOffset(); 58762b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung if (gmtOffset < 0) { 58862b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung sb.append('-'); 58962b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung } else { 59062b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung sb.append('+'); 59162b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung } 59262b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung sb.append(Math.abs(gmtOffset) / DateUtils.HOUR_IN_MILLIS); // Hour 59362b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung 59462b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung if (showMinutes) { 59562b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung final int min = (Math.abs(gmtOffset) / (int) DateUtils.MINUTE_IN_MILLIS) % 60; 59662b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung sb.append(':'); 59762b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung if (min < 10) { 59862b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung sb.append('0'); 59962b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung } 60062b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung sb.append(min); 60162b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung } 60262b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung 60362b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung return sb.toString(); 60462b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung } 60562b9f3d89a2be17f70d2fe45c1c94f732e0224a4James Kung 606d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson public static String getCityName(CityObj city, CityObj dbCity) { 607d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson return (city.mCityId == null || dbCity == null) ? city.mCityName : dbCity.mCityName; 608d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson } 609d48339f270ba72bb8416fd194b4a0d1aeb3bd958rachelzhang 610d48339f270ba72bb8416fd194b4a0d1aeb3bd958rachelzhang public static int getCurrentHourColor() { 611d48339f270ba72bb8416fd194b4a0d1aeb3bd958rachelzhang final int hourOfDay = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); 612d48339f270ba72bb8416fd194b4a0d1aeb3bd958rachelzhang return Color.parseColor(BACKGROUND_SPECTRUM[hourOfDay]); 613d48339f270ba72bb8416fd194b4a0d1aeb3bd958rachelzhang } 614419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang 6153f98d14fd4a98ffb90b7babc10e63218f9a43b2brachelzhang public static int getNextHourColor() { 6163f98d14fd4a98ffb90b7babc10e63218f9a43b2brachelzhang final int currHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); 6173f98d14fd4a98ffb90b7babc10e63218f9a43b2brachelzhang return Color.parseColor(BACKGROUND_SPECTRUM[currHour < 24 ? currHour + 1 : 1]); 6183f98d14fd4a98ffb90b7babc10e63218f9a43b2brachelzhang } 6193f98d14fd4a98ffb90b7babc10e63218f9a43b2brachelzhang 620419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang /** 621419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang * To get an array of single-character day of week symbols {'S', 'M', 'T', 'W', 'T', 'F', 'S'} 622419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang * @return the array of symbols 623419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang */ 624419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang public static String[] getShortWeekdays() { 625419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang if (sShortWeekdays == null) { 626419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang final String[] shortWeekdays = new String[7]; 627419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang final SimpleDateFormat format = new SimpleDateFormat("EEEEE"); 628419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang // Create a date (2014/07/20) that is a Sunday 629419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang long aSunday = new GregorianCalendar(2014, Calendar.JULY, 20).getTimeInMillis(); 630419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang for (int day = 0; day < 7; day++) { 631419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang shortWeekdays[day] = format.format(new Date(aSunday + day * DateUtils.DAY_IN_MILLIS)); 632419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang } 633419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang sShortWeekdays = shortWeekdays; 634419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang } 635419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang return sShortWeekdays; 636419659ca21953a0cd3bbc3e9f481b5c69ff519cbrachelzhang } 637d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson} 638