ClockView.java revision 109f1fd80c90409c0d7f21d49989641dfdf2ad1b
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.policy.impl.keyguard; 18 19import android.content.BroadcastReceiver; 20import android.content.Context; 21import android.content.Intent; 22import android.content.IntentFilter; 23import android.database.ContentObserver; 24import android.graphics.Typeface; 25import android.os.Handler; 26import android.provider.Settings; 27import android.text.format.DateFormat; 28import android.util.AttributeSet; 29import android.view.View; 30import android.widget.RelativeLayout; 31import android.widget.TextView; 32 33import java.lang.ref.WeakReference; 34import java.text.DateFormatSymbols; 35import java.util.Calendar; 36 37import com.android.internal.R; 38 39/** 40 * Displays the time 41 */ 42public class ClockView extends RelativeLayout { 43 private final static String M12 = "h:mm"; 44 private final static String M24 = "kk:mm"; 45 46 private Calendar mCalendar; 47 private String mFormat; 48 private TextView mTimeView; 49 private AmPm mAmPm; 50 private ContentObserver mFormatChangeObserver; 51 private int mAttached = 0; // for debugging - tells us whether attach/detach is unbalanced 52 53 /* called by system on minute ticks */ 54 private final Handler mHandler = new Handler(); 55 private BroadcastReceiver mIntentReceiver; 56 57 private static class TimeChangedReceiver extends BroadcastReceiver { 58 private WeakReference<ClockView> mClock; 59 private Context mContext; 60 61 public TimeChangedReceiver(ClockView clock) { 62 mClock = new WeakReference<ClockView>(clock); 63 mContext = clock.getContext(); 64 } 65 66 @Override 67 public void onReceive(Context context, Intent intent) { 68 // Post a runnable to avoid blocking the broadcast. 69 final boolean timezoneChanged = 70 intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED); 71 final ClockView clock = mClock.get(); 72 if (clock != null) { 73 clock.mHandler.post(new Runnable() { 74 public void run() { 75 if (timezoneChanged) { 76 clock.mCalendar = Calendar.getInstance(); 77 } 78 clock.updateTime(); 79 } 80 }); 81 } else { 82 try { 83 mContext.unregisterReceiver(this); 84 } catch (RuntimeException e) { 85 // Shouldn't happen 86 } 87 } 88 } 89 }; 90 91 static class AmPm { 92 private TextView mAmPmTextView; 93 private String mAmString, mPmString; 94 95 AmPm(View parent, Typeface tf) { 96 // No longer used, uncomment if we decide to use AM/PM indicator again 97 // mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm); 98 if (mAmPmTextView != null && tf != null) { 99 mAmPmTextView.setTypeface(tf); 100 } 101 102 String[] ampm = new DateFormatSymbols().getAmPmStrings(); 103 mAmString = ampm[0]; 104 mPmString = ampm[1]; 105 } 106 107 void setShowAmPm(boolean show) { 108 if (mAmPmTextView != null) { 109 mAmPmTextView.setVisibility(show ? View.VISIBLE : View.GONE); 110 } 111 } 112 113 void setIsMorning(boolean isMorning) { 114 if (mAmPmTextView != null) { 115 mAmPmTextView.setText(isMorning ? mAmString : mPmString); 116 } 117 } 118 } 119 120 private static class FormatChangeObserver extends ContentObserver { 121 private WeakReference<ClockView> mClock; 122 private Context mContext; 123 public FormatChangeObserver(ClockView clock) { 124 super(new Handler()); 125 mClock = new WeakReference<ClockView>(clock); 126 mContext = clock.getContext(); 127 } 128 @Override 129 public void onChange(boolean selfChange) { 130 ClockView digitalClock = mClock.get(); 131 if (digitalClock != null) { 132 digitalClock.setDateFormat(); 133 digitalClock.updateTime(); 134 } else { 135 try { 136 mContext.getContentResolver().unregisterContentObserver(this); 137 } catch (RuntimeException e) { 138 // Shouldn't happen 139 } 140 } 141 } 142 } 143 144 public ClockView(Context context) { 145 this(context, null); 146 } 147 148 public ClockView(Context context, AttributeSet attrs) { 149 super(context, attrs); 150 } 151 152 @Override 153 protected void onFinishInflate() { 154 super.onFinishInflate(); 155 mTimeView = (TextView) findViewById(R.id.clock_text); 156 mTimeView.setTypeface(Typeface.create("sans-serif-thin", Typeface.NORMAL)); 157 mAmPm = new AmPm(this, null); 158 mCalendar = Calendar.getInstance(); 159 setDateFormat(); 160 } 161 162 @Override 163 protected void onAttachedToWindow() { 164 super.onAttachedToWindow(); 165 166 mAttached++; 167 168 /* monitor time ticks, time changed, timezone */ 169 if (mIntentReceiver == null) { 170 mIntentReceiver = new TimeChangedReceiver(this); 171 IntentFilter filter = new IntentFilter(); 172 filter.addAction(Intent.ACTION_TIME_TICK); 173 filter.addAction(Intent.ACTION_TIME_CHANGED); 174 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 175 mContext.registerReceiver(mIntentReceiver, filter); 176 } 177 178 /* monitor 12/24-hour display preference */ 179 if (mFormatChangeObserver == null) { 180 mFormatChangeObserver = new FormatChangeObserver(this); 181 mContext.getContentResolver().registerContentObserver( 182 Settings.System.CONTENT_URI, true, mFormatChangeObserver); 183 } 184 185 updateTime(); 186 } 187 188 @Override 189 protected void onDetachedFromWindow() { 190 super.onDetachedFromWindow(); 191 192 mAttached--; 193 194 if (mIntentReceiver != null) { 195 mContext.unregisterReceiver(mIntentReceiver); 196 } 197 if (mFormatChangeObserver != null) { 198 mContext.getContentResolver().unregisterContentObserver( 199 mFormatChangeObserver); 200 } 201 202 mFormatChangeObserver = null; 203 mIntentReceiver = null; 204 } 205 206 void updateTime(Calendar c) { 207 mCalendar = c; 208 updateTime(); 209 } 210 211 public void updateTime() { 212 mCalendar.setTimeInMillis(System.currentTimeMillis()); 213 214 CharSequence newTime = DateFormat.format(mFormat, mCalendar); 215 mTimeView.setText(newTime); 216 mAmPm.setIsMorning(mCalendar.get(Calendar.AM_PM) == 0); 217 } 218 219 private void setDateFormat() { 220 mFormat = android.text.format.DateFormat.is24HourFormat(getContext()) ? M24 : M12; 221 mAmPm.setShowAmPm(mFormat.equals(M12)); 222 } 223} 224