1 /* 2 * Copyright (C) 2008 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 17 package com.android.deskclock; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.database.ContentObserver; 24 import android.os.Handler; 25 import android.provider.Settings; 26 import android.text.format.DateFormat; 27 import android.util.AttributeSet; 28 import android.view.View; 29 import android.widget.RelativeLayout; 30 31 import java.text.DateFormatSymbols; 32 import java.util.Calendar; 33 34 /** 35 * Displays the time 36 */ 37 public class DigitalClock extends RelativeLayout { 38 39 private final static String M12 = "h:mm"; 40 41 private Calendar mCalendar; 42 private String mFormat; 43 private AndroidClockTextView mTimeDisplay; 44 private AmPm mAmPm; 45 private ContentObserver mFormatChangeObserver; 46 private boolean mLive = true; 47 private boolean mAttached; 48 49 /* called by system on minute ticks */ 50 private final Handler mHandler = new Handler(); 51 private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 52 @Override 53 public void onReceive(Context context, Intent intent) { 54 if (mLive && intent.getAction().equals( 55 Intent.ACTION_TIMEZONE_CHANGED)) { 56 mCalendar = Calendar.getInstance(); 57 } 58 // Post a runnable to avoid blocking the broadcast. 59 mHandler.post(new Runnable() { 60 public void run() { 61 updateTime(); 62 } 63 }); 64 } 65 }; 66 67 static class AmPm { 68 private AndroidClockTextView mAmPm; 69 private String mAmString, mPmString; 70 71 AmPm(View parent) { 72 mAmPm = (AndroidClockTextView) parent.findViewById(R.id.am_pm); 73 74 String[] ampm = new DateFormatSymbols().getAmPmStrings(); 75 mAmString = ampm[0]; 76 mPmString = ampm[1]; 77 } 78 79 void setShowAmPm(boolean show) { 80 mAmPm.setVisibility(show ? View.VISIBLE : View.INVISIBLE); 81 } 82 83 void setIsMorning(boolean isMorning) { 84 mAmPm.setText(isMorning ? mAmString : mPmString); 85 } 86 } 87 88 private class FormatChangeObserver extends ContentObserver { 89 public FormatChangeObserver() { 90 super(new Handler()); 91 } 92 @Override 93 public void onChange(boolean selfChange) { 94 setDateFormat(); 95 updateTime(); 96 } 97 } 98 99 public DigitalClock(Context context) { 100 this(context, null); 101 } 102 103 public DigitalClock(Context context, AttributeSet attrs) { 104 super(context, attrs); 105 } 106 107 @Override 108 protected void onFinishInflate() { 109 super.onFinishInflate(); 110 111 mTimeDisplay = (AndroidClockTextView) findViewById(R.id.timeDisplay); 112 mAmPm = new AmPm(this); 113 mCalendar = Calendar.getInstance(); 114 115 setDateFormat(); 116 } 117 118 @Override 119 protected void onAttachedToWindow() { 120 super.onAttachedToWindow(); 121 122 if (Log.LOGV) Log.v("onAttachedToWindow " + this); 123 124 if (mAttached) return; 125 mAttached = true; 126 127 if (mLive) { 128 /* monitor time ticks, time changed, timezone */ 129 IntentFilter filter = new IntentFilter(); 130 filter.addAction(Intent.ACTION_TIME_TICK); 131 filter.addAction(Intent.ACTION_TIME_CHANGED); 132 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 133 getContext().registerReceiver(mIntentReceiver, filter); 134 } 135 136 /* monitor 12/24-hour display preference */ 137 mFormatChangeObserver = new FormatChangeObserver(); 138 getContext().getContentResolver().registerContentObserver( 139 Settings.System.CONTENT_URI, true, mFormatChangeObserver); 140 141 updateTime(); 142 } 143 144 @Override 145 protected void onDetachedFromWindow() { 146 super.onDetachedFromWindow(); 147 148 if (!mAttached) return; 149 mAttached = false; 150 151 if (mLive) { 152 getContext().unregisterReceiver(mIntentReceiver); 153 } 154 getContext().getContentResolver().unregisterContentObserver( 155 mFormatChangeObserver); 156 } 157 158 159 void updateTime(Calendar c) { 160 mCalendar = c; 161 updateTime(); 162 } 163 164 private void updateTime() { 165 if (mLive) { 166 mCalendar.setTimeInMillis(System.currentTimeMillis()); 167 } 168 169 CharSequence newTime = DateFormat.format(mFormat, mCalendar); 170 mTimeDisplay.setText(newTime); 171 mAmPm.setIsMorning(mCalendar.get(Calendar.AM_PM) == 0); 172 } 173 174 private void setDateFormat() { 175 mFormat = Alarms.get24HourMode(getContext()) ? Alarms.M24 : M12; 176 mAmPm.setShowAmPm(mFormat == M12); 177 } 178 179 void setLive(boolean live) { 180 mLive = live; 181 } 182 } 183