--- /dev/null
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := eng development
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := AlarmClock
+
+include $(BUILD_PACKAGE)
--- /dev/null
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.alarmclock">
+
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+ <uses-permission android:name="android.permission.WAKE_LOCK"/>
+ <uses-permission android:name="android.permission.VIBRATE"/>
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+ <application android:label="@string/app_label"
+ android:icon="@drawable/ic_launcher_alarmclock">
+
+ <provider android:name="AlarmProvider" android:authorities="com.android.alarmclock" />
+
+ <activity android:name="AlarmClock" android:label="@string/app_label">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="SetAlarm" android:label="@string/set_alarm" />
+
+ <activity android:name="AlarmAlert" android:label="@string/alert_title"
+ android:excludeFromRecents="true"
+ android:theme="@android:style/Theme.Dialog"
+ android:launchMode="singleTask"
+ android:taskAffinity=":AlarmAlert"
+ android:configChanges="orientation|keyboardHidden|keyboard|navigation" />
+
+ <activity android:name="ClockPicker" />
+
+ <receiver android:name="AlarmReceiver">
+ <intent-filter>
+ <action android:name="com.android.alarmclock.ALARM_ALERT" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="AlarmInitReceiver">
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ <action android:name="android.intent.action.TIME_SET" />
+ <action android:name="android.intent.action.TIMEZONE_CHANGED" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="AnalogGadgetProvider" android:label="@string/analog_gadget">
+ <intent-filter>
+ <action android:name="android.gadget.action.GADGET_UPDATE" />
+ </intent-filter>
+ <meta-data android:name="android.gadget.provider" android:resource="@xml/analog_gadget" />
+ </receiver>
+ </application>
+</manifest>
+
--- /dev/null
+
+ Copyright (c) 2005-2008, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Chewie... the hyperdrive ain't working -->
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+ android:oneshot="false" android:visible="true">
+ <item android:drawable="@drawable/circle0" android:duration="80" />
+ <item android:drawable="@drawable/circle1" android:duration="80" />
+ <item android:drawable="@drawable/circle2" android:duration="80" />
+ <item android:drawable="@drawable/circle3" android:duration="80" />
+</animation-list>
+
+
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/root"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:paddingTop="2dp">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/clockView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"/>
+
+ <TextView android:id="@+id/silencedText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="4dp"
+ android:paddingTop="2dp"
+ android:paddingBottom="2dp"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:visibility="gone"
+ android:gravity="center"
+ android:textColor="@color/red"
+ android:text="@string/alarm_alert_alert_silenced"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <Button
+ android:id="@+id/snooze"
+ android:layout_width="108dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/alarm_alert_snooze_text" />
+
+ <!-- blank stretchable view -->
+ <View
+ android:layout_width="2dip"
+ android:layout_gravity="fill_vertical"
+ android:layout_weight="1"
+ android:layout_height="2dip"/>
+
+ <Button
+ android:id="@+id/dismiss"
+ android:layout_width="108dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/alarm_alert_dismiss_text" />
+
+ </LinearLayout>
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/base_layout"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="center_vertical">
+
+ <FrameLayout
+ android:id="@+id/clock_layout"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="8dip"/>
+
+ <ListView
+ android:id="@+id/alarms_list"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/root"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/clockView"
+ android:layout_width="208dip"
+ android:layout_height="wrap_content"
+ android:gravity="center"/>
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="4dp">
+
+ <Button
+ android:id="@+id/snooze"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingBottom="24dp"
+ android:layout_weight="3"
+ android:text="@string/alarm_alert_snooze_text" />
+
+ <!-- blank stretchable view -->
+ <View
+ android:layout_width="2dip"
+ android:layout_height="2dip"
+ android:layout_gravity="fill_horizontal"
+ android:layout_weight="1"/>
+
+ <Button
+ android:id="@+id/dismiss"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingBottom="24dp"
+ android:layout_weight="3"
+ android:text="@string/alarm_alert_dismiss_text" />
+
+ </LinearLayout>
+
+ <TextView android:id="@+id/silencedText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="2dp"
+ android:paddingBottom="2dp"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:visibility="gone"
+ android:gravity="center"
+ android:textColor="@color/red"/>
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/base_layout"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_marginTop="6dip"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/clock_layout"
+ android:layout_width="fill_parent"
+ android:layout_height="208dip"
+ android:layout_marginBottom="8dip"
+ android:gravity="center"/>
+
+ <ListView
+ android:id="@+id/alarms_list"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1.0" />
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <!-- A layout that displays the time. Shows time, am/pm (if 12-hour),
+ and an optional line below, used for day/days of week -->
+
+ <com.android.alarmclock.DigitalClock android:id="@+id/digitalClock"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:focusable="true"
+ android:layout_weight="1"
+ android:layout_gravity="center_vertical"
+ android:orientation="vertical"
+ android:paddingTop="4dp"
+ android:paddingLeft="8dp"
+ android:background="@android:drawable/menuitem_background">
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="left">
+
+ <TextView android:id="@+id/timeDisplay"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="-4dp"
+ android:paddingBottom="-4dp"
+ android:textSize="28sp"
+ android:gravity="left"
+ android:textColor="@color/white"/>
+
+ <LinearLayout android:id="@+id/am_pm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:orientation="vertical">
+
+ <TextView android:id="@+id/am"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="3dp"
+ android:text="@string/am"
+ android:textSize="12sp"/>
+ <TextView android:id="@+id/pm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-4dp"
+ android:text="@string/pm"
+ android:textSize="12sp"/>
+ </LinearLayout>
+ </LinearLayout>
+
+ <TextView android:id="@+id/daysOfWeek"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textSize="10sp"
+ android:textColor="@color/ltgrey"
+ android:layout_marginLeft="2dp"
+ android:gravity="left"/>
+
+ </com.android.alarmclock.DigitalClock>
+
+ <CheckBox android:id="@+id/alarmButton"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
+ android:layout_gravity="center_vertical"/>
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
+ android:dial="@drawable/gadget_clock_dial"
+ android:hand_hour="@drawable/gadget_clock_hour"
+ android:hand_minute="@drawable/gadget_clock_minute"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/clock"
+ style="@style/analogClock"
+ android:dial="@drawable/clock_dial"
+ android:hand_hour="@drawable/clock_hour"
+ android:hand_minute="@drawable/clock_minute"/>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/clock"
+ style="@style/analogClock"
+ android:dial="@drawable/clockdroid2_dial"
+ android:hand_hour="@drawable/clockdroid2_hour"
+ android:hand_minute="@drawable/clockdroid2_minute"/>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/clock"
+ style="@style/analogClock"
+ android:dial="@drawable/clockdroids_dial"
+ android:hand_hour="@drawable/clockdroids_hour"
+ android:hand_minute="@drawable/clockdroids_minute"/>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/clock"
+ style="@style/analogClock"
+ android:dial="@drawable/clockgoog_dial"
+ android:hand_hour="@drawable/clockgoog_hour"
+ android:hand_minute="@drawable/clockgoog_minute"/>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:id="@+id/instructions"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="5dip"
+ android:background="#70000000"
+ android:text="@string/clock_instructions"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ />
+ <LinearLayout
+ android:id="@+id/clock_layout"
+ android:layout_width="fill_parent"
+ android:layout_below="@+id/instructions"
+ android:layout_height="208dip"
+ android:gravity="center"/>
+
+ <Gallery android:id="@+id/gallery"
+ android:background="#70000000"
+ android:layout_width="fill_parent"
+ android:layout_height="80dip"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:gravity="center_vertical"
+ android:spacing="16dp"
+ />
+
+</RelativeLayout>
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.alarmclock.DigitalClock android:id="@+id/digitalClock"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="208dip"
+ android:gravity="center">
+
+ <!-- Includes vertical padding so animated background doesn't
+ stretch much -->
+ <TextView android:id="@+id/timeDisplay"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="64sp"
+ android:paddingRight="4dip"
+ android:paddingTop="48dip"
+ android:paddingBottom="48dip"
+ android:textColor="@color/white"/>
+
+ <LinearLayout android:id="@+id/am_pm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView android:id="@+id/am"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-7dp"
+ android:text="@string/am"
+ android:textSize="28sp"/>
+ <TextView android:id="@+id/pm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-4dp"
+ android:text="@string/pm"
+ android:textSize="28sp"/>
+ </LinearLayout>
+</com.android.alarmclock.DigitalClock>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"Budík"</string>
+ <string name="add_alarm">"Přidat upozornění"</string>
+ <string name="delete_alarm">"Smazat upozornění"</string>
+ <string name="delete_alarm_confirm">"Toto upozornění bude odstraněno."</string>
+ <string name="show_clock">"Zobrazit hodiny"</string>
+ <string name="hide_clock">"Skrýt hodiny"</string>
+ <string name="set_alarm">"Nastavit upozornění"</string>
+ <string name="enable">"Zapnout upozornění"</string>
+ <string name="alarm_vibrate">"Vibrace"</string>
+ <string name="alarm_repeat">"Opakovat"</string>
+ <string name="alert">"Vyzváněcí tón"</string>
+ <string name="time">"Čas"</string>
+ <string name="alert_title">"Upozornění"</string>
+ <string name="alarm_alert_dismiss_text">"Zavřít"</string>
+ <string name="alarm_alert_alert_silenced">"Upozornění ztišeno po uplynutí <xliff:g id="MINUTES">%d</xliff:g> min."</string>
+ <string name="alarm_alert_snooze_text">"Odložit"</string>
+ <string name="alarm_alert_snooze_set">"Upozornění odloženo o <xliff:g id="MINUTES">%d</xliff:g> min."</string>
+ <string name="alarm_alert_snooze_not_set">"Upozornění nebylo odloženo – další upozornění v <xliff:g id="TIME">%s</xliff:g>."</string>
+ <string name="alarm_set">"Toto upozornění bude aktivováno za: <xliff:g id="TIME_DELTA">%s</xliff:g>."</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"1 den"</string>
+ <string name="days">"dní: <xliff:g id="DAYS">%s</xliff:g>"</string>
+ <string name="hour">"1 hodina"</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> hod."</string>
+ <string name="and">" a "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"méně než 1 minuta"</string>
+ <string name="minute">"1 minuta"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> min"</string>
+ <string name="am">"dop."</string>
+ <string name="pm">"odp."</string>
+ <string name="every_day">"Každý den"</string>
+ <string name="never">"Nikdy"</string>
+ <string name="day_concat">", "</string>
+ <string name="clock_instructions">"Vyberte hodiny, které mají být zobrazeny."</string>
+ <string name="error">"Upozornění není nastaveno"</string>
+ <string name="dberror">"Upozornění bohužel nelze nastavit."</string>
+ <string name="analog_gadget">"Analogové hodiny"</string>
+ <string-array name="days_of_week">
+ <item>"Pondělí"</item>
+ <item>"Úterý"</item>
+ <item>"Středa"</item>
+ <item>"Čtvrtek"</item>
+ <item>"Pátek"</item>
+ <item>"Sobota"</item>
+ <item>"Neděle"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"Po"</item>
+ <item>"Út"</item>
+ <item>"St"</item>
+ <item>"Čt"</item>
+ <item>"Pá"</item>
+ <item>"So"</item>
+ <item>"Ne"</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"Wecker"</string>
+ <string name="add_alarm">"Wecker hinzufügen"</string>
+ <string name="delete_alarm">"Wecker löschen"</string>
+ <string name="delete_alarm_confirm">"Dieser Alarm wird gelöscht."</string>
+ <string name="show_clock">"Uhr anzeigen"</string>
+ <string name="hide_clock">"Uhr ausblenden"</string>
+ <string name="set_alarm">"Wecker einstellen"</string>
+ <string name="enable">"Wecker aktivieren"</string>
+ <string name="alarm_vibrate">"Vibrieren"</string>
+ <string name="alarm_repeat">"Wiederholen"</string>
+ <string name="alert">"Klingelton"</string>
+ <string name="time">"Uhrzeit"</string>
+ <string name="alert_title">"Wecker"</string>
+ <string name="alarm_alert_dismiss_text">"Verwerfen"</string>
+ <string name="alarm_alert_alert_silenced">"Der Wecker verstummte nach <xliff:g id="MINUTES">%d</xliff:g> Minuten"</string>
+ <string name="alarm_alert_snooze_text">"Snooze-Funktion"</string>
+ <string name="alarm_alert_snooze_set">"Snooze-Funktion aktiviert für <xliff:g id="MINUTES">%d</xliff:g> Minuten"</string>
+ <string name="alarm_alert_snooze_not_set">"Snooze-Funktion nicht aktiviert - nächster Wecker klingelt <xliff:g id="TIME">%s</xliff:g>."</string>
+ <string name="alarm_set">"Dieser Wecker klingelt in <xliff:g id="TIME_DELTA">%s</xliff:g>."</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"1 Tag"</string>
+ <string name="days">"<xliff:g id="DAYS">%s</xliff:g> Tagen"</string>
+ <string name="hour">"1 Stunde"</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> Stunden"</string>
+ <string name="and">" und "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"weniger als 1 Minute"</string>
+ <string name="minute">"1 Minute"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> Minuten"</string>
+ <string name="am">"AM"</string>
+ <string name="pm">"PM"</string>
+ <string name="every_day">"Täglich"</string>
+ <string name="never">"Nie"</string>
+ <string name="day_concat">", "</string>
+ <string name="clock_instructions">"Wählen Sie die anzuzeigende Uhr aus."</string>
+ <string name="error">"Wecker nicht eingestellt"</string>
+ <string name="dberror">"Der Wecker konnte nicht eingestellt werden."</string>
+ <string name="analog_gadget">"Analoguhr"</string>
+ <string-array name="days_of_week">
+ <item>"Montag"</item>
+ <item>"Dienstag"</item>
+ <item>"Mittwoch"</item>
+ <item>"Donnerstag"</item>
+ <item>"Freitag"</item>
+ <item>"Samstag"</item>
+ <item>"Sonntag"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"Mo"</item>
+ <item>"Di"</item>
+ <item>"Mi"</item>
+ <item>"Do"</item>
+ <item>"Fr"</item>
+ <item>"Sa"</item>
+ <item>"So"</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"Alarma"</string>
+ <string name="add_alarm">"Añadir alarma"</string>
+ <string name="delete_alarm">"Eliminar alarma"</string>
+ <string name="delete_alarm_confirm">"Esta alarma se eliminará."</string>
+ <string name="show_clock">"Mostrar reloj"</string>
+ <string name="hide_clock">"Ocultar reloj"</string>
+ <string name="set_alarm">"Establecer alarma"</string>
+ <string name="enable">"Activar alarma"</string>
+ <string name="alarm_vibrate">"Vibración"</string>
+ <string name="alarm_repeat">"Repetir"</string>
+ <string name="alert">"Tono"</string>
+ <string name="time">"Hora"</string>
+ <string name="alert_title">"Alarma"</string>
+ <string name="alarm_alert_dismiss_text">"Descartar"</string>
+ <string name="alarm_alert_alert_silenced">"La alarma se ha silenciado después de <xliff:g id="MINUTES">%d</xliff:g> minutos."</string>
+ <string name="alarm_alert_snooze_text">"Posponer"</string>
+ <string name="alarm_alert_snooze_set">"La alarma volverá a sonar en <xliff:g id="MINUTES">%d</xliff:g> minutos."</string>
+ <string name="alarm_alert_snooze_not_set">"No se ha pospuesto la alarma, ya que la siguiente alarma sonará a las <xliff:g id="TIME">%s</xliff:g>."</string>
+ <string name="alarm_set">"La alarma sonará en <xliff:g id="TIME_DELTA">%s</xliff:g> ."</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"1 día"</string>
+ <string name="days">"<xliff:g id="DAYS">%s</xliff:g> días"</string>
+ <string name="hour">"1 hora"</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> horas"</string>
+ <string name="and">" y "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"menos de 1 minuto"</string>
+ <string name="minute">"1 minuto"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> minutos"</string>
+ <string name="am">"a.m."</string>
+ <string name="pm">"p.m."</string>
+ <string name="every_day">"todos los días"</string>
+ <string name="never">"Nunca"</string>
+ <string name="day_concat">", "</string>
+ <string name="clock_instructions">"Selecciona el reloj que quieras ver."</string>
+ <string name="error">"Alarma no establecida"</string>
+ <string name="dberror">"No se ha podido establecer la alarma."</string>
+ <string name="analog_gadget">"Reloj analógico"</string>
+ <string-array name="days_of_week">
+ <item>"Lunes"</item>
+ <item>"Martes"</item>
+ <item>"Miércoles"</item>
+ <item>"Jueves"</item>
+ <item>"Viernes"</item>
+ <item>"Sábado"</item>
+ <item>"Domingo"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"Lun."</item>
+ <item>"Mar."</item>
+ <item>"Mié."</item>
+ <item>"Jue."</item>
+ <item>"Vie."</item>
+ <item>"Sáb."</item>
+ <item>"Dom."</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"Réveil"</string>
+ <string name="add_alarm">"Ajouter alarme"</string>
+ <string name="delete_alarm">"Désactiver l\'alarme"</string>
+ <string name="delete_alarm_confirm">"Cette alarme va être supprimée."</string>
+ <string name="show_clock">"Afficher l\'horloge"</string>
+ <string name="hide_clock">"Masquer l\'horloge"</string>
+ <string name="set_alarm">"Régler l\'alarme"</string>
+ <string name="enable">"Activer l\'alarme"</string>
+ <string name="alarm_vibrate">"Vibreur"</string>
+ <string name="alarm_repeat">"Répéter"</string>
+ <string name="alert">"Sonnerie"</string>
+ <string name="time">"Heure"</string>
+ <string name="alert_title">"Alarme"</string>
+ <string name="alarm_alert_dismiss_text">"Quitter"</string>
+ <string name="alarm_alert_alert_silenced">"Alarme interrompue après <xliff:g id="MINUTES">%d</xliff:g> minutes"</string>
+ <string name="alarm_alert_snooze_text">"Répéter"</string>
+ <string name="alarm_alert_snooze_set">"Répétition dans <xliff:g id="MINUTES">%d</xliff:g> minutes."</string>
+ <string name="alarm_alert_snooze_not_set">"Répétition non activée : prochaine alarme à <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="alarm_set">"Prochaine alarme dans <xliff:g id="TIME_DELTA">%s</xliff:g>."</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"1 jour"</string>
+ <string name="days">"<xliff:g id="DAYS">%s</xliff:g> jours"</string>
+ <string name="hour">"1 heure"</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> heures"</string>
+ <string name="and">" et "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"moins d\'une minute"</string>
+ <string name="minute">"1 minute"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> minutes"</string>
+ <string name="am">"a.m."</string>
+ <string name="pm">"p.m."</string>
+ <string name="every_day">"Tous les jours"</string>
+ <string name="never">"Jamais"</string>
+ <string name="day_concat">", "</string>
+ <string name="clock_instructions">"Sélectionnez une horloge à afficher."</string>
+ <string name="error">"Alarme non activée"</string>
+ <string name="dberror">"Désolé, impossible de régler l\'alarme."</string>
+ <string name="analog_gadget">"Horloge analogique"</string>
+ <string-array name="days_of_week">
+ <item>"Lundi"</item>
+ <item>"Mardi"</item>
+ <item>"Mercredi"</item>
+ <item>"Jeudi"</item>
+ <item>"Vendredi"</item>
+ <item>"Samedi"</item>
+ <item>"Dimanche"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"Lun"</item>
+ <item>"Mar"</item>
+ <item>"Mer"</item>
+ <item>"Jeu"</item>
+ <item>"Ven"</item>
+ <item>"Sam"</item>
+ <item>"Dim"</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"Sveglia"</string>
+ <string name="add_alarm">"Aggiungi allarme"</string>
+ <string name="delete_alarm">"Elimina allarme"</string>
+ <string name="delete_alarm_confirm">"Questa sveglia verrà eliminata."</string>
+ <string name="show_clock">"Mostra orologio"</string>
+ <string name="hide_clock">"Nascondi orologio"</string>
+ <string name="set_alarm">"Imposta allarme"</string>
+ <string name="enable">"Attiva allarme"</string>
+ <string name="alarm_vibrate">"Vibrazione"</string>
+ <string name="alarm_repeat">"Ripeti"</string>
+ <string name="alert">"Suoneria"</string>
+ <string name="time">"Ora"</string>
+ <string name="alert_title">"Allarme"</string>
+ <string name="alarm_alert_dismiss_text">"Spegni"</string>
+ <string name="alarm_alert_alert_silenced">"Tono allarme disattivato dopo <xliff:g id="MINUTES">%d</xliff:g> minuti"</string>
+ <string name="alarm_alert_snooze_text">"Posponi"</string>
+ <string name="alarm_alert_snooze_set">"Sospensione per <xliff:g id="MINUTES">%d</xliff:g> minuti."</string>
+ <string name="alarm_alert_snooze_not_set">"Sospensione non impostata. Prossimo allarme alle <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="alarm_set">"L\'allarme sarà attivato fra <xliff:g id="TIME_DELTA">%s</xliff:g>."</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"1 giorno"</string>
+ <string name="days">"<xliff:g id="DAYS">%s</xliff:g> giorni"</string>
+ <string name="hour">"1 ora"</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> ore"</string>
+ <string name="and">" e "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"meno di 1 minuto"</string>
+ <string name="minute">"1 minuto"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> minuti"</string>
+ <string name="am">"am"</string>
+ <string name="pm">"pm"</string>
+ <string name="every_day">"Ogni giorno"</string>
+ <string name="never">"Mai"</string>
+ <string name="day_concat">", "</string>
+ <string name="clock_instructions">"Seleziona un orologio."</string>
+ <string name="error">"Allarme non impostato"</string>
+ <string name="dberror">"Spiacenti. Impossibile impostare l\'allarme."</string>
+ <string name="analog_gadget">"Orologio analogico"</string>
+ <string-array name="days_of_week">
+ <item>"Lunedì"</item>
+ <item>"Martedì"</item>
+ <item>"Mercoledì"</item>
+ <item>"Giovedì"</item>
+ <item>"Venerdì"</item>
+ <item>"Sabato"</item>
+ <item>"Domenica"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"Lun"</item>
+ <item>"Mar"</item>
+ <item>"Mer"</item>
+ <item>"Gio"</item>
+ <item>"Ven"</item>
+ <item>"Sab"</item>
+ <item>"Dom"</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"アラーム"</string>
+ <string name="add_alarm">"アラームの設定"</string>
+ <string name="delete_alarm">"アラームを削除"</string>
+ <string name="delete_alarm_confirm">"このアラームを削除します。"</string>
+ <string name="show_clock">"時計を表示"</string>
+ <string name="hide_clock">"時計を隠す"</string>
+ <string name="set_alarm">"アラームの設定"</string>
+ <string name="enable">"アラームをONにする"</string>
+ <string name="alarm_vibrate">"バイブレーション"</string>
+ <string name="alarm_repeat">"繰り返し"</string>
+ <string name="alert">"アラーム音"</string>
+ <string name="time">"時刻"</string>
+ <string name="alert_title">"アラーム"</string>
+ <string name="alarm_alert_dismiss_text">"停止"</string>
+ <string name="alarm_alert_alert_silenced">"アラームは<xliff:g id="MINUTES">%d</xliff:g>分間鳴って止まりました"</string>
+ <string name="alarm_alert_snooze_text">"スヌーズ"</string>
+ <string name="alarm_alert_snooze_set">"<xliff:g id="MINUTES">%d</xliff:g>分間スヌーズ"</string>
+ <string name="alarm_alert_snooze_not_set">"スヌーズ設定エラー: <xliff:g id="TIME">%s</xliff:g>に次のアラームがセットされています"</string>
+ <string name="alarm_set">"<xliff:g id="TIME_DELTA">%s</xliff:g>後にセットしました"</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"1日"</string>
+ <string name="days">"<xliff:g id="DAYS">%s</xliff:g>日"</string>
+ <string name="hour">"1時間"</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g>時間"</string>
+ <string name="and">" と "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"1分未満"</string>
+ <string name="minute">"1分"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g>分"</string>
+ <string name="am">"AM"</string>
+ <string name="pm">"PM"</string>
+ <string name="every_day">"毎日"</string>
+ <string name="never">"繰り返しなし"</string>
+ <string name="day_concat">"、 "</string>
+ <string name="clock_instructions">"表示する時計を選択してください。"</string>
+ <string name="error">"アラームを設定できません"</string>
+ <string name="dberror">"アラームを設定できません"</string>
+ <string name="analog_gadget">"アナログ時計"</string>
+ <string-array name="days_of_week">
+ <item>"月曜日"</item>
+ <item>"火曜日"</item>
+ <item>"水曜日"</item>
+ <item>"木曜日"</item>
+ <item>"金曜日"</item>
+ <item>"土曜日"</item>
+ <item>"日曜日"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"(月)"</item>
+ <item>"(火)"</item>
+ <item>"(水)"</item>
+ <item>"(木)"</item>
+ <item>"(金)"</item>
+ <item>"(土)"</item>
+ <item>"(日)"</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"알람 시계"</string>
+ <string name="add_alarm">"알람 추가"</string>
+ <string name="delete_alarm">"알람 삭제"</string>
+ <string name="delete_alarm_confirm">"알람이 삭제됩니다."</string>
+ <string name="show_clock">"시계 표시"</string>
+ <string name="hide_clock">"시계 숨기기"</string>
+ <string name="set_alarm">"알람 설정"</string>
+ <string name="enable">"알람 켜기"</string>
+ <string name="alarm_vibrate">"진동"</string>
+ <string name="alarm_repeat">"반복"</string>
+ <string name="alert">"벨소리"</string>
+ <string name="time">"시간"</string>
+ <string name="alert_title">"알람"</string>
+ <string name="alarm_alert_dismiss_text">"해제"</string>
+ <string name="alarm_alert_alert_silenced">"<xliff:g id="MINUTES">%d</xliff:g>분 후에 알람이 꺼집니다."</string>
+ <string name="alarm_alert_snooze_text">"스누즈"</string>
+ <string name="alarm_alert_snooze_set">"<xliff:g id="MINUTES">%d</xliff:g>분 동안 스누즈"</string>
+ <string name="alarm_alert_snooze_not_set">"스누즈 설정되지 않음. <xliff:g id="TIME">%s</xliff:g>에 다음 알람이 설정되어 있음."</string>
+ <string name="alarm_set">"이 알람은 지금부터 <xliff:g id="TIME_DELTA">%s</xliff:g> 동안 설정됩니다."</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"1일"</string>
+ <string name="days">"<xliff:g id="DAYS">%s</xliff:g>일"</string>
+ <string name="hour">"1시간"</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g>시간"</string>
+ <string name="and">" 및 "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"1분 미만"</string>
+ <string name="minute">"1분"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g>분"</string>
+ <string name="am">"am"</string>
+ <string name="pm">"pm"</string>
+ <string name="every_day">"매일"</string>
+ <string name="never">"안 함"</string>
+ <string name="day_concat">", "</string>
+ <string name="clock_instructions">"표시할 시계를 선택하세요."</string>
+ <string name="error">"알람이 설정되지 않음"</string>
+ <string name="dberror">"죄송합니다. 알람을 설정할 수 없습니다."</string>
+ <string name="analog_gadget">"아날로그 시계"</string>
+ <string-array name="days_of_week">
+ <item>"월요일"</item>
+ <item>"화요일"</item>
+ <item>"수요일"</item>
+ <item>"목요일"</item>
+ <item>"금요일"</item>
+ <item>"토요일"</item>
+ <item>"일요일"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"월"</item>
+ <item>"화"</item>
+ <item>"수"</item>
+ <item>"목"</item>
+ <item>"금"</item>
+ <item>"토"</item>
+ <item>"일"</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"Alarm"</string>
+ <string name="add_alarm">"Legg til alarm"</string>
+ <string name="delete_alarm">"Slett alarm"</string>
+ <string name="delete_alarm_confirm">"Denne alarmen vil bli slettet."</string>
+ <string name="show_clock">"Vis klokke"</string>
+ <string name="hide_clock">"Fjern klokke"</string>
+ <string name="set_alarm">"Sett alarm"</string>
+ <string name="enable">"Slå på alarm"</string>
+ <string name="alarm_vibrate">"Vibrer"</string>
+ <string name="alarm_repeat">"Gjenta"</string>
+ <string name="alert">"Ringetone"</string>
+ <string name="time">"Tidspunkt"</string>
+ <string name="alert_title">"Alarm"</string>
+ <string name="alarm_alert_dismiss_text">"OK"</string>
+ <string name="alarm_alert_alert_silenced">"Alarmen ble stilnet etter <xliff:g id="MINUTES">%d</xliff:g> minutter"</string>
+ <string name="alarm_alert_snooze_text">"Slumre"</string>
+ <string name="alarm_alert_snooze_set">"Slumrer i <xliff:g id="MINUTES">%d</xliff:g> minutter."</string>
+ <string name="alarm_alert_snooze_not_set">"Slumrer ikke -- neste alarm vil gå av <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="alarm_set">"Alarmen vil gå av <xliff:g id="TIME_DELTA">%s</xliff:g> fra nå."</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"en dag"</string>
+ <string name="days">"<xliff:g id="DAYS">%s</xliff:g> dager"</string>
+ <string name="hour">"en time"</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> timer"</string>
+ <string name="and">" og "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"mindre enn et minutt"</string>
+ <string name="minute">"et minutt"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> minutter"</string>
+ <string name="am">"am"</string>
+ <string name="pm">"pm"</string>
+ <string name="every_day">"hver dag"</string>
+ <string name="never">"Aldri"</string>
+ <string name="day_concat">", "</string>
+ <string name="clock_instructions">"Velg klokken som skal vises."</string>
+ <string name="error">"Alarmen ble ikke satt"</string>
+ <string name="dberror">"Beklager, kunne ikke sette alarmen."</string>
+ <string name="analog_gadget">"Analog klokke"</string>
+ <string-array name="days_of_week">
+ <item>"Mandag"</item>
+ <item>"Tirsdag"</item>
+ <item>"Onsdag"</item>
+ <item>"Torsdag"</item>
+ <item>"Fredag"</item>
+ <item>"Lørdag"</item>
+ <item>"Søndag"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"man"</item>
+ <item>"tir"</item>
+ <item>"ons"</item>
+ <item>"tor"</item>
+ <item>"fre"</item>
+ <item>"lør"</item>
+ <item>"søn"</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"Wekker"</string>
+ <string name="add_alarm">"Alarm toevoegen"</string>
+ <string name="delete_alarm">"Alarm verwijderen"</string>
+ <string name="delete_alarm_confirm">"Dit alarm wordt verwijderd."</string>
+ <string name="show_clock">"Klok weergeven"</string>
+ <string name="hide_clock">"Klok verbergen"</string>
+ <string name="set_alarm">"Alarm instellen"</string>
+ <string name="enable">"Alarm inschakelen"</string>
+ <string name="alarm_vibrate">"Trillen"</string>
+ <string name="alarm_repeat">"Herhalen"</string>
+ <string name="alert">"Beltoon"</string>
+ <string name="time">"Tijd"</string>
+ <string name="alert_title">"Alarm"</string>
+ <string name="alarm_alert_dismiss_text">"Negeren"</string>
+ <string name="alarm_alert_alert_silenced">"Alarm gaat uit na <xliff:g id="MINUTES">%d</xliff:g> minuten"</string>
+ <string name="alarm_alert_snooze_text">"Snooze"</string>
+ <string name="alarm_alert_snooze_set">"Snooze is ingesteld op <xliff:g id="MINUTES">%d</xliff:g> minuten."</string>
+ <string name="alarm_alert_snooze_not_set">"Snooze is niet ingesteld - volgende alarm is ingesteld op <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="alarm_set">"Dit alarm is ingesteld op <xliff:g id="TIME_DELTA">%s</xliff:g> vanaf nu."</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"1 dag"</string>
+ <string name="days">"<xliff:g id="DAYS">%s</xliff:g> dagen"</string>
+ <string name="hour">"1 uur"</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> uur"</string>
+ <string name="and">" en "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"minder dan 1 minuut"</string>
+ <string name="minute">"1 minuut"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> minuten"</string>
+ <string name="am">"am"</string>
+ <string name="pm">"pm"</string>
+ <string name="every_day">"elke dag"</string>
+ <string name="never">"Nooit"</string>
+ <string name="day_concat">", "</string>
+ <string name="clock_instructions">"Selecteer een klok die u wilt weergeven."</string>
+ <string name="error">"Alarm is niet ingesteld"</string>
+ <string name="dberror">"Het alarm kan niet worden ingesteld."</string>
+ <string name="analog_gadget">"Analoge klok"</string>
+ <string-array name="days_of_week">
+ <item>"Maandag"</item>
+ <item>"Dinsdag"</item>
+ <item>"Woensdag"</item>
+ <item>"Donderdag"</item>
+ <item>"Vrijdag"</item>
+ <item>"Zaterdag"</item>
+ <item>"Zondag"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"Ma"</item>
+ <item>"Di"</item>
+ <item>"Wo"</item>
+ <item>"Do"</item>
+ <item>"Vr"</item>
+ <item>"Za"</item>
+ <item>"Zo"</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"Budzik"</string>
+ <string name="add_alarm">"Dodaj alarm"</string>
+ <string name="delete_alarm">"Usuń alarm"</string>
+ <string name="delete_alarm_confirm">"Ten zegar zostanie usunięty."</string>
+ <string name="show_clock">"Pokaż zegar"</string>
+ <string name="hide_clock">"Ukryj zegar"</string>
+ <string name="set_alarm">"Ustaw alarm"</string>
+ <string name="enable">"Włącz alarm"</string>
+ <string name="alarm_vibrate">"Wibracje"</string>
+ <string name="alarm_repeat">"Powtarzanie"</string>
+ <string name="alert">"Dzwonek"</string>
+ <string name="time">"Godzina"</string>
+ <string name="alert_title">"Alarm"</string>
+ <string name="alarm_alert_dismiss_text">"Zamknij"</string>
+ <string name="alarm_alert_alert_silenced">"Alarm jest wyciszany po <xliff:g id="MINUTES">%d</xliff:g> min."</string>
+ <string name="alarm_alert_snooze_text">"Drzemka"</string>
+ <string name="alarm_alert_snooze_set">"Drzemka przez <xliff:g id="MINUTES">%d</xliff:g> min."</string>
+ <string name="alarm_alert_snooze_not_set">"Nie ustawiono drzemki – następny alarm: <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="alarm_set">"Ustawiony alarm zadzwoni za <xliff:g id="TIME_DELTA">%s</xliff:g>"</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"1 dzień"</string>
+ <string name="days">"<xliff:g id="DAYS">%s</xliff:g> dni"</string>
+ <string name="hour">"1 godz."</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> godz."</string>
+ <string name="and">" oraz "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"mniej niż 1 min"</string>
+ <string name="minute">"1 min"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> min"</string>
+ <string name="am">"AM"</string>
+ <string name="pm">"PM"</string>
+ <string name="every_day">"codziennie"</string>
+ <string name="never">"Nigdy"</string>
+ <string name="day_concat">", "</string>
+ <string name="clock_instructions">"Wybierz wyświetlany zegar."</string>
+ <string name="error">"Alarm nieustawiony"</string>
+ <string name="dberror">"Niestety, nie można ustawić alarmu."</string>
+ <string name="analog_gadget">"Zegar analogowy"</string>
+ <string-array name="days_of_week">
+ <item>"poniedziałek"</item>
+ <item>"wtorek"</item>
+ <item>"środa"</item>
+ <item>"czwartek"</item>
+ <item>"piątek"</item>
+ <item>"sobota"</item>
+ <item>"niedziela"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"Pn"</item>
+ <item>"Wt"</item>
+ <item>"Śr"</item>
+ <item>"Cz"</item>
+ <item>"Pt"</item>
+ <item>"So"</item>
+ <item>"Ndz"</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"Будильник"</string>
+ <string name="add_alarm">"Добавить будильник"</string>
+ <string name="delete_alarm">"Удалить будильник"</string>
+ <string name="delete_alarm_confirm">"Сигнал будет удален."</string>
+ <string name="show_clock">"Показать часы"</string>
+ <string name="hide_clock">"Скрыть часы"</string>
+ <string name="set_alarm">"Установить будильник"</string>
+ <string name="enable">"Включить будильник"</string>
+ <string name="alarm_vibrate">"Вибрация"</string>
+ <string name="alarm_repeat">"Повтор"</string>
+ <string name="alert">"Мелодия звонка"</string>
+ <string name="time">"Время"</string>
+ <string name="alert_title">"Будильник"</string>
+ <string name="alarm_alert_dismiss_text">"Закрыть"</string>
+ <string name="alarm_alert_alert_silenced">"Будильник отключается через <xliff:g id="MINUTES">%d</xliff:g> минут(ы)"</string>
+ <string name="alarm_alert_snooze_text">"Отсрочка"</string>
+ <string name="alarm_alert_snooze_set">"Отсрочка на <xliff:g id="MINUTES">%d</xliff:g> минут(ы)."</string>
+ <string name="alarm_alert_snooze_not_set">"Отсрочка не установлена – следующий будильник установлен на <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="alarm_set">"Будильник прозвонит через <xliff:g id="TIME_DELTA">%s</xliff:g>"</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"1 день"</string>
+ <string name="days">"<xliff:g id="DAYS">%s</xliff:g> дня(ей)"</string>
+ <string name="hour">"1 час"</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> часа(ов)"</string>
+ <string name="and">" и "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"менее 1 минуты"</string>
+ <string name="minute">"1 минута"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> минут(ы)"</string>
+ <string name="am">"до полудня"</string>
+ <string name="pm">"после полудня"</string>
+ <string name="every_day">"ежедневно"</string>
+ <string name="never">"Никогда"</string>
+ <string name="day_concat">", "</string>
+ <string name="clock_instructions">"Выберите часы для отображения"</string>
+ <string name="error">"Будильник не установлен"</string>
+ <string name="dberror">"К сожалению, установить будильник не удалось."</string>
+ <string name="analog_gadget">"Часы со стрелками"</string>
+ <string-array name="days_of_week">
+ <item>"Понедельник"</item>
+ <item>"Вторник"</item>
+ <item>"Среда"</item>
+ <item>"Четверг"</item>
+ <item>"Пятница"</item>
+ <item>"Суббота"</item>
+ <item>"Воскресенье"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"Пн"</item>
+ <item>"Вт"</item>
+ <item>"Ср"</item>
+ <item>"Чт"</item>
+ <item>"Пт"</item>
+ <item>"Сб"</item>
+ <item>"Вс"</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"闹钟时钟"</string>
+ <string name="add_alarm">"添加闹钟"</string>
+ <string name="delete_alarm">"取消闹钟"</string>
+ <string name="delete_alarm_confirm">"将会删除此警报。"</string>
+ <string name="show_clock">"显示时钟"</string>
+ <string name="hide_clock">"隐藏时钟"</string>
+ <string name="set_alarm">"设置闹钟"</string>
+ <string name="enable">"开启闹钟"</string>
+ <string name="alarm_vibrate">"振动"</string>
+ <string name="alarm_repeat">"重复"</string>
+ <string name="alert">"铃声"</string>
+ <string name="time">"时间"</string>
+ <string name="alert_title">"闹钟"</string>
+ <string name="alarm_alert_dismiss_text">"取消"</string>
+ <string name="alarm_alert_alert_silenced">"闹钟在 <xliff:g id="MINUTES">%d</xliff:g> 分钟后静音"</string>
+ <string name="alarm_alert_snooze_text">"再响"</string>
+ <string name="alarm_alert_snooze_set">"<xliff:g id="MINUTES">%d</xliff:g> 分钟后再响。"</string>
+ <string name="alarm_alert_snooze_not_set">"未设置再响 - 下次闹钟设置在 <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="alarm_set">"该闹钟设置为从现在起 <xliff:g id="TIME_DELTA">%s</xliff:g> 后再提醒。"</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"1 天"</string>
+ <string name="days">"<xliff:g id="DAYS">%s</xliff:g> 天"</string>
+ <string name="hour">"1 小时"</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> 小时"</string>
+ <string name="and">" 和 "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"短于 1 分钟"</string>
+ <string name="minute">"1 分钟"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> 分钟"</string>
+ <string name="am">"上午"</string>
+ <string name="pm">"下午"</string>
+ <string name="every_day">"每天"</string>
+ <string name="never">"永不"</string>
+ <string name="day_concat">"、 "</string>
+ <string name="clock_instructions">"选择要显示的时钟。"</string>
+ <string name="error">"未设置闹钟"</string>
+ <string name="dberror">"抱歉,无法设置该闹钟。"</string>
+ <string name="analog_gadget">"模拟时钟"</string>
+ <string-array name="days_of_week">
+ <item>"周一"</item>
+ <item>"周二"</item>
+ <item>"周三"</item>
+ <item>"周四"</item>
+ <item>"周五"</item>
+ <item>"周六"</item>
+ <item>"周日"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"周一"</item>
+ <item>"周二"</item>
+ <item>"周三"</item>
+ <item>"周四"</item>
+ <item>"周五"</item>
+ <item>"周六"</item>
+ <item>"周日"</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">"鬧鐘"</string>
+ <string name="add_alarm">"新增鬧鐘"</string>
+ <string name="delete_alarm">"刪除鬧鐘"</string>
+ <string name="delete_alarm_confirm">"將刪除此鬧鐘。"</string>
+ <string name="show_clock">"顯示時鐘"</string>
+ <string name="hide_clock">"隱藏時鐘"</string>
+ <string name="set_alarm">"設定鬧鐘"</string>
+ <string name="enable">"開啟鬧鐘"</string>
+ <string name="alarm_vibrate">"震動"</string>
+ <string name="alarm_repeat">"重複"</string>
+ <string name="alert">"鈴聲"</string>
+ <string name="time">"時間"</string>
+ <string name="alert_title">"鬧鐘"</string>
+ <string name="alarm_alert_dismiss_text">"關閉"</string>
+ <string name="alarm_alert_alert_silenced">"鬧鐘 <xliff:g id="MINUTES">%d</xliff:g> 分鐘後靜音"</string>
+ <string name="alarm_alert_snooze_text">"貪睡"</string>
+ <string name="alarm_alert_snooze_set">"再貪睡 <xliff:g id="MINUTES">%d</xliff:g> 分鐘。"</string>
+ <string name="alarm_alert_snooze_not_set">"未設定貪睡鬧鐘 -- 下一次鬧鐘時間為 <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="alarm_set">"還有 <xliff:g id="TIME_DELTA">%s</xliff:g> 會啟動鬧鐘。"</string>
+ <!-- no translation found for combiner (3170916241487451546) -->
+ <skip />
+ <string name="day">"1 天"</string>
+ <string name="days">"<xliff:g id="DAYS">%s</xliff:g> 天"</string>
+ <string name="hour">"1 小時"</string>
+ <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> 小時"</string>
+ <string name="and">" 又 "</string>
+ <!-- no translation found for space (5294521584675021576) -->
+ <skip />
+ <string name="subminute">"少於 1 分鐘"</string>
+ <string name="minute">"1 分鐘"</string>
+ <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> 分鐘"</string>
+ <string name="am">"am"</string>
+ <string name="pm">"pm"</string>
+ <string name="every_day">"每天"</string>
+ <string name="never">"從不"</string>
+ <string name="day_concat">"、 "</string>
+ <string name="clock_instructions">"選取顯示的時鐘。"</string>
+ <string name="error">"鬧鐘未設定"</string>
+ <string name="dberror">"抱歉,無法設定鬧鐘。"</string>
+ <string name="analog_gadget">"類比時鐘"</string>
+ <string-array name="days_of_week">
+ <item>"星期一"</item>
+ <item>"星期二"</item>
+ <item>"星期三"</item>
+ <item>"星期四"</item>
+ <item>"星期五"</item>
+ <item>"星期六"</item>
+ <item>"星期日"</item>
+ </string-array>
+ <string-array name="days_of_week_short">
+ <item>"週一"</item>
+ <item>"週二"</item>
+ <item>"週三"</item>
+ <item>"週四"</item>
+ <item>"週五"</item>
+ <item>"週六"</item>
+ <item>"週日"</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <color name="ampm_off">#ff404040</color>
+ <color name="ampm_on">#ffffffff</color>
+
+ <color name="white">#ffffffff</color>
+ <color name="red">#ffee0000</color>
+ <color name="ltgrey">#ffe0e0e0</color>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- -->
+ <!-- Label shown on launcher icon -->
+ <string name="app_label">Alarm Clock</string>
+
+ <!-- Menu item on Alarm Clock screen: Add alarm -->
+ <string name="add_alarm">Add alarm</string>
+
+ <!-- Context Menu Item on Alarm Settings screen: Delete alarm -->
+ <string name="delete_alarm">Delete alarm</string>
+
+ <!-- Delete alarm confirmation dialog message. -->
+ <string name="delete_alarm_confirm">This alarm will be deleted.</string>
+
+ <!-- Menu item on Alarm Clock screen: Show clock -->
+ <string name="show_clock">Show clock</string>
+
+ <!-- Menu item on Alarm Clock screen: Hide clock -->
+ <string name="hide_clock">Hide clock</string>
+
+ <!-- Preference category on Alarm Settings screen: Set alarm -->
+ <string name="set_alarm">Set alarm</string>
+
+ <!-- Setting labels on Set alarm screen: Enable alarm -->
+ <string name="enable">Turn on alarm</string>
+
+ <!-- Setting labels on Set alarm screen: Vibration on or off -->
+ <string name="alarm_vibrate">Vibrate</string>
+
+ <!-- Setting labels on Set alarm screen: Repeat -->
+ <string name="alarm_repeat">Repeat</string>
+
+ <!-- Setting labels on Set alarm screen: Select alarm ringtone -->
+ <string name="alert">Ringtone</string>
+
+ <!-- Setting labels on Set alarm screen: Set time -->
+ <string name="time">Time</string>
+
+
+ <!-- Title of the alarm alert -->
+ <string name="alert_title">Alarm</string>
+
+ <!-- Button labels on the alarm dialog: Dismiss -->
+ <string name="alarm_alert_dismiss_text">Dismiss</string>
+
+ <!-- Alarm Alert screen: this message is shown after an alarm rung
+ unattended for a number of minutes. It tells the user that
+ the alarm has been silenced.-->
+ <string name="alarm_alert_alert_silenced">Alarm silenced after <xliff:g id="minutes">%d</xliff:g> minutes</string>
+
+ <!-- Button labels on the alarm dialog: Snooze -->
+ <string name="alarm_alert_snooze_text">Snooze</string>
+
+ <!-- Toast that appears after Alarm is snoozed from the Alarm
+ dialog. Says the alarm will snooze for xxx minutes. -->
+ <string name="alarm_alert_snooze_set">Snoozing for <xliff:g id="minutes">%d</xliff:g> minutes.</string>
+
+ <!-- Toast that appears after Alarm is snoozed from the Alarm
+ dialog. Shown if snooze cannot be set because the next alarm
+ would fire before the snooze alrm. "Snooze not set - next
+ alarm set for xxx." -->
+ <string name="alarm_alert_snooze_not_set">Snooze not set -- next alarm set for <xliff:g id="time">%s</xliff:g></string>
+
+
+ <!-- Alarm confirmation toast: Describes how long from now until
+ alarm fires -->
+ <string name="alarm_set">This alarm is set for <xliff:g id="time_delta">%s</xliff:g> from now.</string>
+
+ <!-- Alarm confirmation toast: A combiner that orders the segments
+ that follow -->
+ <string name="combiner"><xliff:g id="xxx">%1$s</xliff:g><xliff:g id="xxx">%2$s</xliff:g><xliff:g id="xxx">%3$s</xliff:g><xliff:g id="xxx">%4$s</xliff:g><xliff:g id="xxx">%5$s</xliff:g></string>
+
+ <!-- Alarm confirmation toast: singular day -->
+ <string name="day">"1 day"</string>
+
+ <!-- Alarm confirmation toast: plural days -->
+ <string name="days">"<xliff:g id="days">%s</xliff:g> days"</string>
+
+ <!-- Alarm confirmation toast: singular hour -->
+ <string name="hour">1 hour</string>
+
+ <!-- Alarm confirmation toast: plural hours -->
+ <string name="hours"><xliff:g id="hours">%s</xliff:g> hours</string>
+
+ <!-- Alarm confirmation toast: "and" to join hours and minutes -->
+ <string name="and">" and "</string>
+
+ <!-- Alarm confirmation toast: space -->
+ <string name="space">" "</string>
+
+ <!-- Alarm confirmation toast: time less than one minute -->
+ <string name="subminute">"less than 1 minute"</string>
+
+ <!-- Alarm confirmation toast: singular minute -->
+ <string name="minute">"1 minute"</string>
+
+ <!-- Alarm confirmation toast: plural minutes -->
+ <string name="minutes">"<xliff:g id="minutes">%s</xliff:g> minutes"</string>
+
+ <!-- Alarm confirmation toast: Ante Meridiem, or am -->
+ <string name="am">am</string>
+
+ <!-- Alarm confirmation toast: Post Meridiem, or pm -->
+ <string name="pm">pm</string>
+
+ <!-- Repeat options that appear under an alarm on main Alarm Clock
+ screen to identify repetition schedule: special case for when
+ the alarm is set to repeat every day -->
+ <string name="every_day">every day</string>
+
+ <!-- Repeat options that appear under an alarm on main Alarm Clock
+ screen to identify repetition schedule: special case for when
+ the alarm is set to never repeat -->
+ <string name="never">Never</string>
+
+ <!-- Repeat options that appear under an alarm on main Alarm Clock
+ screen to identify repetition schedule: concatenate days with
+ this character, i.e. "Mon, Tue, Wed" -->
+ <string name="day_concat">", "</string>
+
+ <!-- Appears at the top of the Clock Picker screen: Tell user to
+ select a clock to display -->
+ <string name="clock_instructions">Select a clock to display.</string>
+
+ <!-- Error dialog title: Alarm not set. Appears only on critical
+ failure -->
+ <string name="error">Alarm not set</string>
+
+ <!-- Error dialog message. Appears only on critical
+ failure -->
+ <string name="dberror">Sorry, the alarm could not be set.</string>
+
+ <!-- Label for analog clock gadget, shown in list of all gadgets -->
+ <string name="analog_gadget">Analog clock</string>
+
+ <!-- Days of week -->
+ <string-array name="days_of_week">
+ <!-- Day of week: Monday -->
+ <item>Monday</item>
+ <!-- Day of week: Tuesday -->
+ <item>Tuesday</item>
+ <!-- Day of week: Wednesday -->
+ <item>Wednesday</item>
+ <!-- Day of week: Thursday -->
+ <item>Thursday</item>
+ <!-- Day of week: Friday -->
+ <item>Friday</item>
+ <!-- Day of week: Saturday -->
+ <item>Saturday</item>
+ <!-- Day of week: Sunday -->
+ <item>Sunday</item>
+ </string-array>
+
+ <!-- Short Day of week -->
+ <string-array name="days_of_week_short">
+ <!-- Short Day of week: Mon -->
+ <item>Mon</item>
+ <!-- Short Day of week: Tue -->
+ <item>Tue</item>
+ <!-- Short Day of week: Wed -->
+ <item>Wed</item>
+ <!-- Short Day of week: Thu -->
+ <item>Thu</item>
+ <!-- Short Day of week: Fri -->
+ <item>Fri</item>
+ <!-- Short Day of week: Sat -->
+ <item>Sat</item>
+ <!-- Short Day of week: Sun -->
+ <item>Sun</item>
+ </string-array>
+
+</resources>
+
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <style name="analogClock">
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:layout_height">fill_parent</item>
+ <item name="android:layout_gravity">center_horizontal</item>
+ </style>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/set_alarm">
+ <CheckBoxPreference android:key="on"
+ android:title="@string/enable"/>
+ <Preference android:key="time"
+ android:title="@string/time"/>
+ <com.android.alarmclock.AlarmPreference
+ android:key="alarm"
+ android:title="@string/alert"
+ android:ringtoneType="alarm"
+ android:showDefault="false"
+ android:showSilent="false" />
+ <CheckBoxPreference android:key="vibrate"
+ android:title="@string/alarm_vibrate"/>
+ <com.android.alarmclock.RepeatPreference
+ android:key="setRepeat"
+ android:title="@string/alarm_repeat"
+ android:entries="@array/days_of_week"
+ android:entryValues="@array/days_of_week"/>
+</PreferenceScreen>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<gadget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+ android:minWidth="146dip"
+ android:minHeight="146dip"
+ android:updatePeriodMillis="0"
+ android:initialLayout="@layout/analog_gadget"
+ >
+</gadget-provider>
--- /dev/null
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.graphics.PixelFormat;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.Toast;
+import android.widget.TextView;
+
+import java.util.Calendar;
+
+/**
+ * Alarm Clock alarm alert: pops visible indicator and plays alarm
+ * tone
+ */
+public class AlarmAlert extends Activity {
+
+ private static final int SNOOZE_MINUTES = 10;
+ private static final int UNKNOWN = 0;
+ private static final int SNOOZE = 1;
+ private static final int DISMISS = 2;
+ private static final int KILLED = 3;
+
+ private KeyguardManager mKeyguardManager;
+ private KeyguardManager.KeyguardLock mKeyguardLock = null;
+ private Button mSnoozeButton;
+ private int mState = UNKNOWN;
+
+ private AlarmKlaxon mKlaxon;
+ private int mAlarmId;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ /* FIXME Intentionally verbose: always log this until we've
+ fully debugged the app failing to start up */
+ Log.v("AlarmAlert.onCreate()");
+
+ mKlaxon = AlarmKlaxon.getInstance();
+
+ // Popup alert over black screen
+ WindowManager.LayoutParams lp = getWindow().getAttributes();
+ lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;
+ lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ // XXX DO NOT COPY THIS!!! THIS IS BOGUS! Making an activity have
+ // a system alert type is completely broken, because the activity
+ // manager will still hide/show it as if it is part of the normal
+ // activity stack. If this is really what you want and you want it
+ // to work correctly, you should create and show your own custom window.
+ lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
+ lp.token = null;
+ getWindow().setAttributes(lp);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+
+ mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
+
+ mAlarmId = getIntent().getIntExtra(Alarms.ID, -1);
+
+ /* allow next alarm to trigger while this activity is
+ active */
+ Alarms.disableSnoozeAlert(AlarmAlert.this);
+ Alarms.disableAlert(AlarmAlert.this, mAlarmId);
+ Alarms.setNextAlert(this);
+
+ mKlaxon.setKillerCallback(new AlarmKlaxon.KillerCallback() {
+ public void onKilled() {
+ if (Log.LOGV) Log.v("onKilled()");
+ updateSilencedText();
+
+ /* don't allow snooze */
+ mSnoozeButton.setEnabled(false);
+
+ // Dismiss the alarm but mark the state as killed so if the
+ // config changes, we show the silenced message and disable
+ // snooze.
+ dismiss();
+ mState = KILLED;
+ }
+ });
+
+ updateLayout();
+ }
+
+ private void updateSilencedText() {
+ TextView silenced = (TextView) findViewById(R.id.silencedText);
+ silenced.setText(getString(R.string.alarm_alert_alert_silenced,
+ AlarmKlaxon.ALARM_TIMEOUT_SECONDS / 60));
+ silenced.setVisibility(View.VISIBLE);
+ }
+
+ private void updateLayout() {
+ setContentView(R.layout.alarm_alert);
+
+ /* set clock face */
+ LayoutInflater mFactory = LayoutInflater.from(this);
+ SharedPreferences settings =
+ getSharedPreferences(AlarmClock.PREFERENCES, 0);
+ int face = settings.getInt(AlarmClock.PREF_CLOCK_FACE, 0);
+ if (face < 0 || face >= AlarmClock.CLOCKS.length) {
+ face = 0;
+ }
+ View clockLayout =
+ (View) mFactory.inflate(AlarmClock.CLOCKS[face], null);
+ ViewGroup clockView = (ViewGroup) findViewById(R.id.clockView);
+ clockView.addView(clockLayout);
+ if (clockLayout instanceof DigitalClock) {
+ ((DigitalClock) clockLayout).setAnimate();
+ }
+
+ /* snooze behavior: pop a snooze confirmation view, kick alarm
+ manager. */
+ mSnoozeButton = (Button) findViewById(R.id.snooze);
+ mSnoozeButton.requestFocus();
+ // If this was a configuration change, keep the silenced text if the
+ // alarm was killed.
+ if (mState == KILLED) {
+ updateSilencedText();
+ mSnoozeButton.setEnabled(false);
+ } else {
+ mSnoozeButton.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ snooze();
+ finish();
+ }
+ });
+ }
+
+ /* dismiss button: close notification */
+ findViewById(R.id.dismiss).setOnClickListener(
+ new Button.OnClickListener() {
+ public void onClick(View v) {
+ dismiss();
+ finish();
+ }
+ });
+ }
+
+ // Attempt to snooze this alert.
+ private void snooze() {
+ if (mState != UNKNOWN) {
+ return;
+ }
+ // If the next alarm is set for sooner than the snooze interval, don't
+ // snooze. Instead, toast the user that the snooze will not be set.
+ final long snoozeTime = System.currentTimeMillis()
+ + (1000 * 60 * SNOOZE_MINUTES);
+ final long nextAlarm =
+ Alarms.calculateNextAlert(AlarmAlert.this).getAlert();
+ String displayTime = null;
+ if (nextAlarm < snoozeTime) {
+ final Calendar c = Calendar.getInstance();
+ c.setTimeInMillis(nextAlarm);
+ displayTime = getString(R.string.alarm_alert_snooze_not_set,
+ Alarms.formatTime(AlarmAlert.this, c));
+ mState = DISMISS;
+ } else {
+ Alarms.saveSnoozeAlert(AlarmAlert.this, mAlarmId, snoozeTime);
+ Alarms.setNextAlert(AlarmAlert.this);
+ displayTime = getString(R.string.alarm_alert_snooze_set,
+ SNOOZE_MINUTES);
+ mState = SNOOZE;
+ }
+ // Intentionally log the snooze time for debugging.
+ Log.v(displayTime);
+ // Display the snooze minutes in a toast.
+ Toast.makeText(AlarmAlert.this, displayTime, Toast.LENGTH_LONG).show();
+ mKlaxon.stop(this, mState == SNOOZE);
+ releaseLocks();
+ }
+
+ // Dismiss the alarm.
+ private void dismiss() {
+ if (mState != UNKNOWN) {
+ return;
+ }
+ mState = DISMISS;
+ mKlaxon.stop(this, false);
+ releaseLocks();
+ }
+
+ /**
+ * this is called when a second alarm is triggered while a
+ * previous alert window is still active.
+ */
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ if (Log.LOGV) Log.v("AlarmAlert.OnNewIntent()");
+ mState = UNKNOWN;
+ mSnoozeButton.setEnabled(true);
+ disableKeyguard();
+
+ mAlarmId = intent.getIntExtra(Alarms.ID, -1);
+
+ /* unset silenced message */
+ TextView silenced = (TextView)findViewById(R.id.silencedText);
+ silenced.setVisibility(View.GONE);
+
+ Alarms.setNextAlert(this);
+ setIntent(intent);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (Log.LOGV) Log.v("AlarmAlert.onResume()");
+ disableKeyguard();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ if (Log.LOGV) Log.v("AlarmAlert.onStop()");
+ // As a last resort, try to snooze if this activity is stopped.
+ snooze();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration config) {
+ super.onConfigurationChanged(config);
+ updateLayout();
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ // Do this on key down to handle a few of the system keys. Only handle
+ // the snooze and dismiss this alert if the state is unknown.
+ boolean up = event.getAction() == KeyEvent.ACTION_UP;
+ boolean dismiss = false;
+ switch (event.getKeyCode()) {
+ case KeyEvent.KEYCODE_DPAD_UP:
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ // Ignore ENDCALL because we do not receive the event if the screen
+ // is on. However, we do receive the key up for ENDCALL if the
+ // screen was off.
+ case KeyEvent.KEYCODE_ENDCALL:
+ break;
+ // Volume keys dismiss the alarm
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ dismiss = true;
+ // All other keys will snooze the alarm
+ default:
+ // Check for UNKNOWN here so that we intercept both key events
+ // and prevent the volume keys from triggering their default
+ // behavior.
+ if (mState == UNKNOWN && up) {
+ if (dismiss) {
+ dismiss();
+ } else {
+ snooze();
+ }
+ finish();
+ }
+ return true;
+ }
+ return super.dispatchKeyEvent(event);
+ }
+
+ private synchronized void enableKeyguard() {
+ if (mKeyguardLock != null) {
+ mKeyguardLock.reenableKeyguard();
+ mKeyguardLock = null;
+ }
+ }
+
+ private synchronized void disableKeyguard() {
+ if (mKeyguardLock == null) {
+ mKeyguardLock = mKeyguardManager.newKeyguardLock(Log.LOGTAG);
+ mKeyguardLock.disableKeyguard();
+ }
+ }
+
+ /**
+ * release wake and keyguard locks
+ */
+ private synchronized void releaseLocks() {
+ AlarmAlertWakeLock.release();
+ enableKeyguard();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.content.Context;
+import android.os.PowerManager;
+
+/**
+ * Hold a wakelock that can be acquired in the AlarmReceiver and
+ * released in the AlarmAlert activity
+ */
+class AlarmAlertWakeLock {
+
+ private static PowerManager.WakeLock sWakeLock;
+
+ static void acquire(Context context) {
+ if (sWakeLock != null) {
+ sWakeLock.release();
+ }
+
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+
+ sWakeLock = pm.newWakeLock(
+ PowerManager.FULL_WAKE_LOCK |
+ PowerManager.ACQUIRE_CAUSES_WAKEUP |
+ PowerManager.ON_AFTER_RELEASE, Log.LOGTAG);
+ sWakeLock.acquire();
+ }
+
+ static void release() {
+ if (Log.LOGV) Log.v("AlarmAlertWakeLock release");
+ if (sWakeLock != null) {
+ sWakeLock.release();
+ sWakeLock = null;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.provider.Settings;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.CheckBox;
+
+import java.util.Calendar;
+
+/**
+ * AlarmClock application.
+ */
+public class AlarmClock extends Activity {
+
+ final static String PREFERENCES = "AlarmClock";
+ final static int SET_ALARM = 1;
+ final static String PREF_CLOCK_FACE = "face";
+ final static String PREF_SHOW_CLOCK = "show_clock";
+
+ /** Cap alarm count at this number */
+ final static int MAX_ALARM_COUNT = 12;
+
+ /** This must be false for production. If true, turns on logging,
+ test code, etc. */
+ final static boolean DEBUG = false;
+
+ private SharedPreferences mPrefs;
+ private LayoutInflater mFactory;
+ private ViewGroup mClockLayout;
+ private View mClock = null;
+ private MenuItem mAddAlarmItem;
+ private MenuItem mToggleClockItem;
+ private ListView mAlarmsList;
+ private Cursor mCursor;
+
+ /**
+ * Which clock face to show
+ */
+ private int mFace = -1;
+
+ /*
+ * FIXME: it would be nice for this to live in an xml config file.
+ */
+ final static int[] CLOCKS = {
+ R.layout.clock_basic_bw,
+ R.layout.clock_googly,
+ R.layout.clock_droid2,
+ R.layout.clock_droids,
+ R.layout.digital_clock
+ };
+
+ private class AlarmTimeAdapter extends CursorAdapter {
+ public AlarmTimeAdapter(Context context, Cursor cursor) {
+ super(context, cursor);
+ }
+
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ View ret = mFactory.inflate(R.layout.alarm_time, parent, false);
+ DigitalClock digitalClock = (DigitalClock)ret.findViewById(R.id.digitalClock);
+ digitalClock.setLive(false);
+ if (Log.LOGV) Log.v("newView " + cursor.getPosition());
+ return ret;
+ }
+
+ public void bindView(View view, Context context, Cursor cursor) {
+ final int id = cursor.getInt(Alarms.AlarmColumns.ALARM_ID_INDEX);
+ final int hour = cursor.getInt(Alarms.AlarmColumns.ALARM_HOUR_INDEX);
+ final int minutes = cursor.getInt(Alarms.AlarmColumns.ALARM_MINUTES_INDEX);
+ final Alarms.DaysOfWeek daysOfWeek = new Alarms.DaysOfWeek(
+ cursor.getInt(Alarms.AlarmColumns.ALARM_DAYS_OF_WEEK_INDEX));
+ final boolean enabled = cursor.getInt(Alarms.AlarmColumns.ALARM_ENABLED_INDEX) == 1;
+
+ CheckBox onButton = (CheckBox)view.findViewById(R.id.alarmButton);
+ onButton.setChecked(enabled);
+ onButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ boolean isChecked = ((CheckBox) v).isChecked();
+ Alarms.enableAlarm(AlarmClock.this, id, isChecked);
+ if (isChecked) {
+ SetAlarm.popAlarmSetToast(
+ AlarmClock.this, hour, minutes, daysOfWeek);
+ }
+ }
+ });
+
+ DigitalClock digitalClock = (DigitalClock)view.findViewById(R.id.digitalClock);
+ if (Log.LOGV) Log.v("bindView " + cursor.getPosition() + " " + id + " " + hour +
+ ":" + minutes + " " + daysOfWeek.toString(context, true) + " dc " + digitalClock);
+
+ digitalClock.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ if (true) {
+ Intent intent = new Intent(AlarmClock.this, SetAlarm.class);
+ intent.putExtra(Alarms.ID, id);
+ startActivityForResult(intent, SET_ALARM);
+ } else {
+ // TESTING: immediately pop alarm
+ Intent fireAlarm = new Intent(AlarmClock.this, AlarmAlert.class);
+ fireAlarm.putExtra(Alarms.ID, id);
+ fireAlarm.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(fireAlarm);
+ }
+ }
+ });
+
+ // set the alarm text
+ final Calendar c = Calendar.getInstance();
+ c.set(Calendar.HOUR_OF_DAY, hour);
+ c.set(Calendar.MINUTE, minutes);
+ digitalClock.updateTime(c);
+ TextView daysOfWeekView = (TextView) digitalClock.findViewById(R.id.daysOfWeek);
+ daysOfWeekView.setText(daysOfWeek.toString(AlarmClock.this, false));
+
+ // Build context menu
+ digitalClock.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
+ public void onCreateContextMenu(ContextMenu menu, View view,
+ ContextMenuInfo menuInfo) {
+ menu.setHeaderTitle(Alarms.formatTime(AlarmClock.this, c));
+ MenuItem deleteAlarmItem = menu.add(0, id, 0, R.string.delete_alarm);
+ }
+ });
+ }
+ };
+
+ @Override
+ public boolean onContextItemSelected(final MenuItem item) {
+ // Confirm that the alarm will be deleted.
+ new AlertDialog.Builder(this)
+ .setTitle(getString(R.string.delete_alarm))
+ .setMessage(getString(R.string.delete_alarm_confirm))
+ .setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface d, int w) {
+ Alarms.deleteAlarm(AlarmClock.this,
+ item.getItemId());
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, null)
+ .show();
+ return true;
+ }
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ // sanity check -- no database, no clock
+ if (getContentResolver() == null) {
+ new AlertDialog.Builder(this)
+ .setTitle(getString(R.string.error))
+ .setMessage(getString(R.string.dberror))
+ .setPositiveButton(
+ android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ })
+ .setOnCancelListener(
+ new DialogInterface.OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ finish();
+ }})
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .create().show();
+ return;
+ }
+
+ setContentView(R.layout.alarm_clock);
+ mFactory = LayoutInflater.from(this);
+ mPrefs = getSharedPreferences(PREFERENCES, 0);
+
+ mCursor = Alarms.getAlarmsCursor(getContentResolver());
+ mAlarmsList = (ListView) findViewById(R.id.alarms_list);
+ mAlarmsList.setAdapter(new AlarmTimeAdapter(this, mCursor));
+ mAlarmsList.setVerticalScrollBarEnabled(true);
+ mAlarmsList.setItemsCanFocus(true);
+
+ mClockLayout = (ViewGroup) findViewById(R.id.clock_layout);
+ mClockLayout.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ final Intent intent = new Intent(AlarmClock.this, ClockPicker.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ }
+ });
+
+ setClockVisibility(mPrefs.getBoolean(PREF_SHOW_CLOCK, true));
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ int face = mPrefs.getInt(PREF_CLOCK_FACE, 0);
+ if (mFace != face) {
+ if (face < 0 || face >= AlarmClock.CLOCKS.length)
+ mFace = 0;
+ else
+ mFace = face;
+ inflateClock();
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ ToastMaster.cancelToast();
+ mCursor.deactivate();
+ }
+
+ protected void inflateClock() {
+ if (mClock != null) {
+ mClockLayout.removeView(mClock);
+ }
+ mClock = mFactory.inflate(CLOCKS[mFace], null);
+ mClockLayout.addView(mClock, 0);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ mAddAlarmItem = menu.add(0, 0, 0, R.string.add_alarm);
+ mAddAlarmItem.setIcon(android.R.drawable.ic_menu_add);
+
+ mToggleClockItem = menu.add(0, 0, 0, R.string.hide_clock);
+ mToggleClockItem.setIcon(R.drawable.ic_menu_clock_face);
+
+ return true;
+ }
+
+ /**
+ * Only allow user to add a new alarm if there are fewer than
+ * MAX_ALARM_COUNT
+ */
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ mAddAlarmItem.setVisible(mAlarmsList.getChildCount() < MAX_ALARM_COUNT);
+ mToggleClockItem.setTitle(getClockVisibility() ? R.string.hide_clock :
+ R.string.show_clock);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item == mAddAlarmItem) {
+ Uri uri = Alarms.addAlarm(getContentResolver());
+ // FIXME: scroll to new item. mAlarmsList.requestChildRectangleOnScreen() ?
+ String segment = uri.getPathSegments().get(1);
+ int newId = Integer.parseInt(segment);
+ if (Log.LOGV) Log.v("In AlarmClock, new alarm id = " + newId);
+ Intent intent = new Intent(AlarmClock.this, SetAlarm.class);
+ intent.putExtra(Alarms.ID, newId);
+ startActivityForResult(intent, SET_ALARM);
+ return true;
+ } else if (item == mToggleClockItem) {
+ setClockVisibility(!getClockVisibility());
+ saveClockVisibility();
+ return true;
+ }
+
+ return false;
+ }
+
+
+ private boolean getClockVisibility() {
+ return mClockLayout.getVisibility() == View.VISIBLE;
+ }
+
+ private void setClockVisibility(boolean visible) {
+ mClockLayout.setVisibility(visible ? View.VISIBLE : View.GONE);
+ }
+
+ private void saveClockVisibility() {
+ mPrefs.edit().putBoolean(PREF_SHOW_CLOCK, getClockVisibility()).commit();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.BroadcastReceiver;
+
+public class AlarmInitReceiver extends BroadcastReceiver {
+
+ /**
+ * Sets alarm on ACTION_BOOT_COMPLETED. Resets alarm on
+ * TIME_SET, TIMEZONE_CHANGED
+ */
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Log.LOGV) Log.v("AlarmInitReceiver" + action);
+
+ if (context.getContentResolver() == null) {
+ Log.e("AlarmInitReceiver: FAILURE unable to get content resolver. Alarms inactive.");
+ return;
+ }
+ if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
+ Alarms.disableSnoozeAlert(context);
+ Alarms.disableExpiredAlarms(context);
+ }
+ Alarms.setNextAlert(context);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnErrorListener;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Vibrator;
+
+/**
+ * Manages alarms and vibe. Singleton, so it can be initiated in
+ * AlarmReceiver and shut down in the AlarmAlert activity
+ */
+class AlarmKlaxon implements Alarms.AlarmSettings {
+
+ interface KillerCallback {
+ public void onKilled();
+ }
+
+ /** Play alarm up to 10 minutes before silencing */
+ final static int ALARM_TIMEOUT_SECONDS = 10 * 60;
+
+ private static long[] sVibratePattern = new long[] { 500, 500 };
+
+ private static AlarmKlaxon sInstance;
+
+ private int mAlarmId;
+ private String mAlert;
+ private Alarms.DaysOfWeek mDaysOfWeek;
+ private boolean mVibrate;
+
+ private boolean mPlaying = false;
+
+ private Vibrator mVibrator;
+ private MediaPlayer mMediaPlayer;
+
+ private Handler mTimeout;
+ private KillerCallback mKillerCallback;
+
+
+ static synchronized AlarmKlaxon getInstance() {
+ if (sInstance == null) sInstance = new AlarmKlaxon();
+ return sInstance;
+ }
+
+ private AlarmKlaxon() {
+ mVibrator = new Vibrator();
+ }
+
+ public void reportAlarm(
+ int idx, boolean enabled, int hour, int minutes,
+ Alarms.DaysOfWeek daysOfWeek, boolean vibrate, String message,
+ String alert) {
+ if (Log.LOGV) Log.v("AlarmKlaxon.reportAlarm: " + idx + " " + hour +
+ " " + minutes + " dow " + daysOfWeek);
+ mAlert = alert;
+ mDaysOfWeek = daysOfWeek;
+ mVibrate = vibrate;
+ }
+
+ synchronized void play(Context context, int alarmId) {
+ ContentResolver contentResolver = context.getContentResolver();
+
+ if (mPlaying) stop(context, false);
+
+ mAlarmId = alarmId;
+
+ /* this will call reportAlarm() callback */
+ Alarms.getAlarm(contentResolver, this, mAlarmId);
+
+ if (Log.LOGV) Log.v("AlarmKlaxon.play() " + mAlarmId + " alert " + mAlert);
+
+ /* play audio alert */
+ if (mAlert == null) {
+ Log.e("Unable to play alarm: no audio file available");
+ } else {
+ /* we need a new MediaPlayer when we change media URLs */
+ mMediaPlayer = new MediaPlayer();
+ mMediaPlayer.setOnErrorListener(new OnErrorListener() {
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ Log.e("Error occurred while playing audio.");
+ mp.stop();
+ mp.release();
+ mMediaPlayer = null;
+ return true;
+ }
+ });
+
+ try {
+ mMediaPlayer.setDataSource(context, Uri.parse(mAlert));
+ } catch (Exception ex) {
+ Log.v("Using the fallback ringtone");
+ /* The alert may be on the sd card which could be busy right
+ * now. Use the fallback ringtone. */
+ AssetFileDescriptor afd =
+ context.getResources().openRawResourceFd(
+ com.android.internal.R.raw.fallbackring);
+ if (afd != null) {
+ try {
+ mMediaPlayer.setDataSource(afd.getFileDescriptor(),
+ afd.getStartOffset(), afd.getLength());
+ afd.close();
+ } catch (Exception ex2) {
+ Log.e("Failed to play fallback ringtone", ex2);
+ /* At this point we just don't play anything */
+ }
+ }
+ }
+ /* Now try to play the alert. */
+ try {
+ mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
+ mMediaPlayer.setLooping(true);
+ mMediaPlayer.prepare();
+ mMediaPlayer.start();
+ } catch (Exception ex) {
+ Log.e("Error playing alarm: " + mAlert, ex);
+ }
+ }
+
+ /* Start the vibrator after everything is ok with the media player */
+ if (mVibrate) {
+ mVibrator.vibrate(sVibratePattern, 0);
+ } else {
+ mVibrator.cancel();
+ }
+
+ enableKiller();
+ mPlaying = true;
+ }
+
+
+ /**
+ * Stops alarm audio and disables alarm if it not snoozed and not
+ * repeating
+ */
+ synchronized void stop(Context context, boolean snoozed) {
+ if (Log.LOGV) Log.v("AlarmKlaxon.stop() " + mAlarmId);
+ if (mPlaying) {
+ mPlaying = false;
+
+ // Stop audio playing
+ if (mMediaPlayer != null) {
+ mMediaPlayer.stop();
+ mMediaPlayer.release();
+ mMediaPlayer = null;
+ }
+
+ // Stop vibrator
+ mVibrator.cancel();
+
+ /* disable alarm only if it is not set to repeat */
+ if (!snoozed && ((mDaysOfWeek == null || !mDaysOfWeek.isRepeatSet()))) {
+ Alarms.enableAlarm(context, mAlarmId, false);
+ }
+ }
+ disableKiller();
+ }
+
+ /**
+ * This callback called when alarm killer times out unattended
+ * alarm
+ */
+ void setKillerCallback(KillerCallback killerCallback) {
+ mKillerCallback = killerCallback;
+ }
+
+ /**
+ * Kills alarm audio after ALARM_TIMEOUT_SECONDS, so the alarm
+ * won't run all day.
+ *
+ * This just cancels the audio, but leaves the notification
+ * popped, so the user will know that the alarm tripped.
+ */
+ private void enableKiller() {
+ mTimeout = new Handler();
+ mTimeout.postDelayed(new Runnable() {
+ public void run() {
+ if (Log.LOGV) Log.v("*********** Alarm killer triggered *************");
+ if (mKillerCallback != null) mKillerCallback.onKilled();
+ }
+ }, 1000 * ALARM_TIMEOUT_SECONDS);
+ }
+
+ private void disableKiller() {
+ if (mTimeout != null) {
+ mTimeout.removeCallbacksAndMessages(null);
+ mTimeout = null;
+ }
+ }
+
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.content.Context;
+import android.net.Uri;
+import android.preference.RingtonePreference;
+import android.util.AttributeSet;
+
+public class AlarmPreference extends RingtonePreference {
+ public Uri mAlert;
+ private IRingtoneChangedListener mRingtoneChangedListener;
+
+ public interface IRingtoneChangedListener {
+ public void onRingtoneChanged(Uri ringtoneUri);
+ };
+
+ public AlarmPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void setRingtoneChangedListener(IRingtoneChangedListener listener) {
+ mRingtoneChangedListener = listener;
+ }
+
+ @Override
+ protected void onSaveRingtone(Uri ringtoneUri) {
+ if (ringtoneUri != null) {
+ mAlert = ringtoneUri;
+ if (mRingtoneChangedListener != null) {
+ mRingtoneChangedListener.onRingtoneChanged(ringtoneUri);
+ }
+ }
+ }
+
+ @Override
+ protected Uri onRestoreRingtone() {
+ return mAlert;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.text.TextUtils;
+
+public class AlarmProvider extends ContentProvider {
+ private SQLiteOpenHelper mOpenHelper;
+
+ private static final int ALARMS = 1;
+ private static final int ALARMS_ID = 2;
+ private static final UriMatcher sURLMatcher = new UriMatcher(
+ UriMatcher.NO_MATCH);
+
+ static {
+ sURLMatcher.addURI("com.android.alarmclock", "alarm", ALARMS);
+ sURLMatcher.addURI("com.android.alarmclock", "alarm/#", ALARMS_ID);
+ }
+
+ private static class DatabaseHelper extends SQLiteOpenHelper {
+ private static final String DATABASE_NAME = "alarms.db";
+ private static final int DATABASE_VERSION = 5;
+
+ public DatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE alarms (" +
+ "_id INTEGER PRIMARY KEY," +
+ "hour INTEGER, " +
+ "minutes INTEGER, " +
+ "daysofweek INTEGER, " +
+ "alarmtime INTEGER, " +
+ "enabled INTEGER, " +
+ "vibrate INTEGER, " +
+ "message TEXT, " +
+ "alert TEXT);");
+
+ // insert default alarms
+ String insertMe = "INSERT INTO alarms " +
+ "(hour, minutes, daysofweek, alarmtime, enabled, vibrate, message, alert) " +
+ "VALUES ";
+ db.execSQL(insertMe + "(7, 0, 127, 0, 0, 1, '', '');");
+ db.execSQL(insertMe + "(8, 30, 31, 0, 0, 1, '', '');");
+ db.execSQL(insertMe + "(9, 00, 0, 0, 0, 1, '', '');");
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
+ if (Log.LOGV) Log.v(
+ "Upgrading alarms database from version " +
+ oldVersion + " to " + currentVersion +
+ ", which will destroy all old data");
+ db.execSQL("DROP TABLE IF EXISTS alarms");
+ onCreate(db);
+ }
+ }
+
+ public AlarmProvider() {
+ }
+
+ @Override
+ public boolean onCreate() {
+ mOpenHelper = new DatabaseHelper(getContext());
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri url, String[] projectionIn, String selection,
+ String[] selectionArgs, String sort) {
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+
+ // Generate the body of the query
+ int match = sURLMatcher.match(url);
+ switch (match) {
+ case ALARMS:
+ qb.setTables("alarms");
+ break;
+ case ALARMS_ID:
+ qb.setTables("alarms");
+ qb.appendWhere("_id=");
+ qb.appendWhere(url.getPathSegments().get(1));
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown URL " + url);
+ }
+
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor ret = qb.query(db, projectionIn, selection, selectionArgs,
+ null, null, sort);
+
+ if (ret == null) {
+ if (Log.LOGV) Log.v("Alarms.query: failed");
+ } else {
+ ret.setNotificationUri(getContext().getContentResolver(), url);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String getType(Uri url) {
+ int match = sURLMatcher.match(url);
+ switch (match) {
+ case ALARMS:
+ return "vnd.android.cursor.dir/alarms";
+ case ALARMS_ID:
+ return "vnd.android.cursor.item/alarms";
+ default:
+ throw new IllegalArgumentException("Unknown URL");
+ }
+ }
+
+ @Override
+ public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
+ int count;
+ long rowId = 0;
+ int match = sURLMatcher.match(url);
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ switch (match) {
+ case ALARMS_ID: {
+ String segment = url.getPathSegments().get(1);
+ rowId = Long.parseLong(segment);
+ count = db.update("alarms", values, "_id=" + rowId, null);
+ break;
+ }
+ default: {
+ throw new UnsupportedOperationException(
+ "Cannot update URL: " + url);
+ }
+ }
+ if (Log.LOGV) Log.v("*** notifyChange() rowId: " + rowId + " url " + url);
+ getContext().getContentResolver().notifyChange(url, null);
+ return count;
+ }
+
+ @Override
+ public Uri insert(Uri url, ContentValues initialValues) {
+ if (sURLMatcher.match(url) != ALARMS) {
+ throw new IllegalArgumentException("Cannot insert into URL: " + url);
+ }
+
+ ContentValues values;
+ if (initialValues != null)
+ values = new ContentValues(initialValues);
+ else
+ values = new ContentValues();
+
+ if (!values.containsKey(Alarms.AlarmColumns.HOUR))
+ values.put(Alarms.AlarmColumns.HOUR, 0);
+
+ if (!values.containsKey(Alarms.AlarmColumns.MINUTES))
+ values.put(Alarms.AlarmColumns.MINUTES, 0);
+
+ if (!values.containsKey(Alarms.AlarmColumns.DAYS_OF_WEEK))
+ values.put(Alarms.AlarmColumns.DAYS_OF_WEEK, 0);
+
+ if (!values.containsKey(Alarms.AlarmColumns.ALARM_TIME))
+ values.put(Alarms.AlarmColumns.ALARM_TIME, 0);
+
+ if (!values.containsKey(Alarms.AlarmColumns.ENABLED))
+ values.put(Alarms.AlarmColumns.ENABLED, 0);
+
+ if (!values.containsKey(Alarms.AlarmColumns.VIBRATE))
+ values.put(Alarms.AlarmColumns.VIBRATE, 1);
+
+ if (!values.containsKey(Alarms.AlarmColumns.MESSAGE))
+ values.put(Alarms.AlarmColumns.MESSAGE, "");
+
+ if (!values.containsKey(Alarms.AlarmColumns.ALERT))
+ values.put(Alarms.AlarmColumns.ALERT, "");
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ long rowId = db.insert("alarms", Alarms.AlarmColumns.MESSAGE, values);
+ if (rowId < 0) {
+ throw new SQLException("Failed to insert row into " + url);
+ }
+ if (Log.LOGV) Log.v("Added alarm rowId = " + rowId);
+
+ Uri newUrl = ContentUris.withAppendedId(Alarms.AlarmColumns.CONTENT_URI, rowId);
+ getContext().getContentResolver().notifyChange(newUrl, null);
+ return newUrl;
+ }
+
+ public int delete(Uri url, String where, String[] whereArgs) {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count;
+ long rowId = 0;
+ switch (sURLMatcher.match(url)) {
+ case ALARMS:
+ count = db.delete("alarms", where, whereArgs);
+ break;
+ case ALARMS_ID:
+ String segment = url.getPathSegments().get(1);
+ rowId = Long.parseLong(segment);
+ if (TextUtils.isEmpty(where)) {
+ where = "_id=" + segment;
+ } else {
+ where = "_id=" + segment + " AND (" + where + ")";
+ }
+ count = db.delete("alarms", where, whereArgs);
+ break;
+ default:
+ throw new IllegalArgumentException("Cannot delete from URL: " + url);
+ }
+
+ getContext().getContentResolver().notifyChange(url, null);
+ return count;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.BroadcastReceiver;
+
+/**
+ * Glue class: connects AlarmAlert IntentReceiver to AlarmAlert
+ * activity. Passes through Alarm ID.
+ */
+public class AlarmReceiver extends BroadcastReceiver {
+
+ /** If the alarm is older than STALE_WINDOW seconds, ignore. It
+ is probably the result of a time or timezone change */
+ private final static int STALE_WINDOW = 60 * 30;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ long now = System.currentTimeMillis();
+ int id = intent.getIntExtra(Alarms.ID, 0);
+ long setFor = intent.getLongExtra(Alarms.TIME, 0);
+
+ /* FIXME Intentionally verbose: always log this until we've
+ fully debugged the app failing to start up */
+ Log.v("AlarmReceiver.onReceive() id " + id + " setFor " + setFor +
+ " now " + now);
+
+ if (now > setFor + STALE_WINDOW * 1000) {
+ if (Log.LOGV) Log.v("AlarmReceiver ignoring stale alarm intent id"
+ + id + " setFor " + setFor + " now " + now);
+ return;
+ }
+
+ /* wake device */
+ AlarmAlertWakeLock.acquire(context);
+
+ /* start audio/vibe */
+ AlarmKlaxon klaxon = AlarmKlaxon.getInstance();
+ klaxon.play(context, id);
+
+ /* Close dialogs and window shade */
+ Intent i = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ context.sendBroadcast(i);
+
+ /* launch UI, explicitly stating that this is not due to user action
+ * so that the current app's notification management is not disturbed */
+ Intent fireAlarm = new Intent(context, AlarmAlert.class);
+ fireAlarm.putExtra(Alarms.ID, id);
+ fireAlarm.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
+ context.startActivity(fireAlarm);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.BaseColumns;
+import android.provider.Settings;
+import android.text.format.DateFormat;
+
+import java.util.Calendar;
+
+/**
+ * The Alarms provider supplies info about Alarm Clock settings
+ */
+public class Alarms {
+
+ public final static String ALARM_ALERT_ACTION = "com.android.alarmclock.ALARM_ALERT";
+ public final static String ID = "alarm_id";
+ public final static String TIME = "alarm_time";
+
+ final static String PREF_SNOOZE_ID = "snooze_id";
+ final static String PREF_SNOOZE_TIME = "snooze_time";
+
+ private final static String DM12 = "E h:mm aa";
+ private final static String DM24 = "E k:mm";
+
+ private final static String M12 = "h:mm aa";
+ private final static String M24 = "k:mm";
+
+ static class DaysOfWeek {
+
+ int mDays;
+
+ /**
+ * Days of week coded as single int, convenient for DB
+ * storage:
+ *
+ * 0x00: no day
+ * 0x01: Monday
+ * 0x02: Tuesday
+ * 0x04: Wednesday
+ * 0x08: Thursday
+ * 0x10: Friday
+ * 0x20: Saturday
+ * 0x40: Sunday
+ */
+ DaysOfWeek() {
+ this(0);
+ }
+
+ DaysOfWeek(int days) {
+ mDays = days;
+ }
+
+ public String toString(Context context, boolean showNever) {
+ StringBuilder ret = new StringBuilder();
+
+ /* no days */
+ if (mDays == 0) return showNever ? context.getText(
+ R.string.never).toString() : "";
+
+ /* every day */
+ if (mDays == 0x7f) {
+ return context.getText(R.string.every_day).toString();
+ }
+
+ /* count selected days */
+ int dayCount = 0, days = mDays;
+ while (days > 0) {
+ if ((days & 1) == 1) dayCount++;
+ days >>= 1;
+ }
+
+ /* short or long form? */
+ CharSequence[] strings =
+ context.getResources().getTextArray(
+ (dayCount > 1) ? R.array.days_of_week_short :
+ R.array.days_of_week);
+
+ /* selected days */
+ for (int i = 0; i < 7; i++) {
+ if ((mDays & (1 << i)) != 0) {
+ ret.append(strings[i]);
+ dayCount -= 1;
+ if (dayCount > 0) ret.append(
+ context.getText(R.string.day_concat));
+ }
+ }
+ return ret.toString();
+ }
+
+ /**
+ * @param day Mon=0 ... Sun=6
+ * @return true if given day is set
+ */
+ public boolean isSet(int day) {
+ return ((mDays & (1 << day)) > 0);
+ }
+
+ public void set(int day, boolean set) {
+ if (set) {
+ mDays |= (1 << day);
+ } else {
+ mDays &= ~(1 << day);
+ }
+ }
+
+ public void set(DaysOfWeek dow) {
+ mDays = dow.mDays;
+ }
+
+ public int getCoded() {
+ return mDays;
+ }
+
+ public boolean equals(DaysOfWeek dow) {
+ return mDays == dow.mDays;
+ }
+
+ // Returns days of week encoded in an array of booleans.
+ public boolean[] getBooleanArray() {
+ boolean[] ret = new boolean[7];
+ for (int i = 0; i < 7; i++) {
+ ret[i] = isSet(i);
+ }
+ return ret;
+ }
+
+ public void setCoded(int days) {
+ mDays = days;
+ }
+
+ /**
+ * @return true if alarm is set to repeat
+ */
+ public boolean isRepeatSet() {
+ return mDays != 0;
+ }
+
+ /**
+ * @return true if alarm is set to repeat every day
+ */
+ public boolean isEveryDaySet() {
+ return mDays == 0x7f;
+ }
+
+
+ /**
+ * returns number of days from today until next alarm
+ * @param c must be set to today
+ */
+ public int getNextAlarm(Calendar c) {
+ if (mDays == 0) return -1;
+ int today = (c.get(Calendar.DAY_OF_WEEK) + 5) % 7;
+
+ int day, dayCount;
+ for (dayCount = 0; dayCount < 7; dayCount++) {
+ day = (today + dayCount) % 7;
+ if ((mDays & (1 << day)) > 0) {
+ break;
+ }
+ }
+ return dayCount;
+ }
+ }
+
+ public static class AlarmColumns implements BaseColumns {
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://com.android.alarmclock/alarm");
+
+ public static final String _ID = "_id";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "_id ASC";
+
+ /**
+ * Hour in 24-hour localtime 0 - 23.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String HOUR = "hour";
+
+ /**
+ * Minutes in localtime 0 - 59
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MINUTES = "minutes";
+
+ /**
+ * Days of week coded as integer
+ * <P>Type: INTEGER</P>
+ */
+ public static final String DAYS_OF_WEEK = "daysofweek";
+
+ /**
+ * Alarm time in UTC milliseconds from the epoch.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ALARM_TIME = "alarmtime";
+
+ /**
+ * True if alarm is active
+ * <P>Type: BOOLEAN</P>
+ */
+ public static final String ENABLED = "enabled";
+
+ /**
+ * True if alarm should vibrate
+ * <P>Type: BOOLEAN</P>
+ */
+ public static final String VIBRATE = "vibrate";
+
+ /**
+ * Message to show when alarm triggers
+ * Note: not currently used
+ * <P>Type: STRING</P>
+ */
+ public static final String MESSAGE = "message";
+
+ /**
+ * Audio alert to play when alarm triggers
+ * <P>Type: STRING</P>
+ */
+ public static final String ALERT = "alert";
+
+ static final String[] ALARM_QUERY_COLUMNS = {
+ _ID, HOUR, MINUTES, DAYS_OF_WEEK, ALARM_TIME,
+ ENABLED, VIBRATE, MESSAGE, ALERT};
+
+ /**
+ * These save calls to cursor.getColumnIndexOrThrow()
+ * THEY MUST BE KEPT IN SYNC WITH ABOVE QUERY COLUMNS
+ */
+ public static final int ALARM_ID_INDEX = 0;
+ public static final int ALARM_HOUR_INDEX = 1;
+ public static final int ALARM_MINUTES_INDEX = 2;
+ public static final int ALARM_DAYS_OF_WEEK_INDEX = 3;
+ public static final int ALARM_TIME_INDEX = 4;
+ public static final int ALARM_ENABLED_INDEX = 5;
+ public static final int ALARM_VIBRATE_INDEX = 6;
+ public static final int ALARM_MESSAGE_INDEX = 7;
+ public static final int ALARM_ALERT_INDEX = 8;
+ }
+
+ /**
+ * getAlarm and getAlarms call this interface to report alarms in
+ * the database
+ */
+ static interface AlarmSettings {
+ void reportAlarm(
+ int idx, boolean enabled, int hour, int minutes,
+ DaysOfWeek daysOfWeek, boolean vibrate, String message,
+ String alert);
+ }
+
+ /**
+ * Creates a new Alarm.
+ */
+ public synchronized static Uri addAlarm(ContentResolver contentResolver) {
+ ContentValues values = new ContentValues();
+ values.put(Alarms.AlarmColumns.HOUR, 8);
+ return contentResolver.insert(AlarmColumns.CONTENT_URI, values);
+ }
+
+ /**
+ * Removes an existing Alarm. If this alarm is snoozing, disables
+ * snooze. Sets next alert.
+ */
+ public synchronized static void deleteAlarm(
+ Context context, int alarmId) {
+
+ ContentResolver contentResolver = context.getContentResolver();
+ /* If alarm is snoozing, lose it */
+ int snoozeId = getSnoozeAlarmId(context);
+ if (snoozeId == alarmId) disableSnoozeAlert(context);
+
+ Uri uri = ContentUris.withAppendedId(AlarmColumns.CONTENT_URI, alarmId);
+ deleteAlarm(contentResolver, uri);
+
+ setNextAlert(context);
+ }
+
+ private synchronized static void deleteAlarm(
+ ContentResolver contentResolver, Uri uri) {
+ contentResolver.delete(uri, "", null);
+ }
+
+ /**
+ * Queries all alarms
+ * @return cursor over all alarms
+ */
+ public synchronized static Cursor getAlarmsCursor(
+ ContentResolver contentResolver) {
+ return contentResolver.query(
+ AlarmColumns.CONTENT_URI, AlarmColumns.ALARM_QUERY_COLUMNS,
+ null, null, AlarmColumns.DEFAULT_SORT_ORDER);
+ }
+
+ /**
+ * Calls the AlarmSettings.reportAlarm interface on all alarms found in db.
+ */
+ public synchronized static void getAlarms(
+ ContentResolver contentResolver, AlarmSettings alarmSettings) {
+ Cursor cursor = getAlarmsCursor(contentResolver);
+ getAlarms(alarmSettings, cursor);
+ cursor.close();
+ }
+
+ private synchronized static void getAlarms(
+ AlarmSettings alarmSettings, Cursor cur) {
+ if (cur.moveToFirst()) {
+ do {
+ // Get the field values
+ int id = cur.getInt(AlarmColumns.ALARM_ID_INDEX);
+ int hour = cur.getInt(AlarmColumns.ALARM_HOUR_INDEX);
+ int minutes = cur.getInt(AlarmColumns.ALARM_MINUTES_INDEX);
+ int daysOfWeek = cur.getInt(AlarmColumns.ALARM_DAYS_OF_WEEK_INDEX);
+ boolean enabled = cur.getInt(AlarmColumns.ALARM_ENABLED_INDEX) == 1 ? true : false;
+ boolean vibrate = cur.getInt(AlarmColumns.ALARM_VIBRATE_INDEX) == 1 ? true : false;
+ String message = cur.getString(AlarmColumns.ALARM_MESSAGE_INDEX);
+ String alert = cur.getString(AlarmColumns.ALARM_ALERT_INDEX);
+ alarmSettings.reportAlarm(
+ id, enabled, hour, minutes, new DaysOfWeek(daysOfWeek),
+ vibrate, message, alert);
+ } while (cur.moveToNext());
+ }
+ }
+
+ /**
+ * Calls the AlarmSettings.reportAlarm interface on alarm with given
+ * alarmId
+ */
+ public synchronized static void getAlarm(
+ ContentResolver contentResolver, AlarmSettings alarmSetting,
+ int alarmId) {
+ Cursor cursor = contentResolver.query(
+ ContentUris.withAppendedId(AlarmColumns.CONTENT_URI, alarmId),
+ AlarmColumns.ALARM_QUERY_COLUMNS,
+ null, null, AlarmColumns.DEFAULT_SORT_ORDER);
+
+ getAlarms(alarmSetting, cursor);
+ cursor.close();
+ }
+
+
+ /**
+ * A convenience method to set an alarm in the Alarms
+ * content provider.
+ *
+ * @param id corresponds to the _id column
+ * @param enabled corresponds to the ENABLED column
+ * @param hour corresponds to the HOUR column
+ * @param minutes corresponds to the MINUTES column
+ * @param daysOfWeek corresponds to the DAYS_OF_WEEK column
+ * @param time corresponds to the ALARM_TIME column
+ * @param vibrate corresponds to the VIBRATE column
+ * @param message corresponds to the MESSAGE column
+ * @param alert corresponds to the ALERT column
+ */
+ public synchronized static void setAlarm(
+ Context context, int id, boolean enabled, int hour, int minutes,
+ DaysOfWeek daysOfWeek, boolean vibrate, String message,
+ String alert) {
+
+ ContentValues values = new ContentValues(8);
+ ContentResolver resolver = context.getContentResolver();
+ long time = calculateAlarm(hour, minutes, daysOfWeek).getTimeInMillis();
+
+ if (Log.LOGV) Log.v(
+ "** setAlarm * idx " + id + " hour " + hour + " minutes " +
+ minutes + " enabled " + enabled + " time " + time);
+
+ values.put(AlarmColumns.ENABLED, enabled ? 1 : 0);
+ values.put(AlarmColumns.HOUR, hour);
+ values.put(AlarmColumns.MINUTES, minutes);
+ values.put(AlarmColumns.ALARM_TIME, time);
+ values.put(AlarmColumns.DAYS_OF_WEEK, daysOfWeek.getCoded());
+ values.put(AlarmColumns.VIBRATE, vibrate);
+ values.put(AlarmColumns.MESSAGE, message);
+ values.put(AlarmColumns.ALERT, alert);
+ resolver.update(ContentUris.withAppendedId(AlarmColumns.CONTENT_URI, id),
+ values, null, null);
+
+ int aid = disableSnoozeAlert(context);
+ if (aid != -1 && aid != id) enableAlarmInternal(context, aid, false);
+ setNextAlert(context);
+ }
+
+ /**
+ * A convenience method to enable or disable an alarm.
+ *
+ * @param id corresponds to the _id column
+ * @param enabled corresponds to the ENABLED column
+ */
+
+ public synchronized static void enableAlarm(
+ final Context context, final int id, boolean enabled) {
+ int aid = disableSnoozeAlert(context);
+ if (aid != -1 && aid != id) enableAlarmInternal(context, aid, false);
+ enableAlarmInternal(context, id, enabled);
+ setNextAlert(context);
+ }
+
+ private synchronized static void enableAlarmInternal(
+ final Context context, final int id, boolean enabled) {
+ ContentResolver resolver = context.getContentResolver();
+
+ class EnableAlarm implements AlarmSettings {
+ public int mHour;
+ public int mMinutes;
+ public DaysOfWeek mDaysOfWeek;
+
+ public void reportAlarm(
+ int idx, boolean enabled, int hour, int minutes,
+ DaysOfWeek daysOfWeek, boolean vibrate, String message,
+ String alert) {
+ mHour = hour;
+ mMinutes = minutes;
+ mDaysOfWeek = daysOfWeek;
+ }
+ }
+
+ ContentValues values = new ContentValues(2);
+ values.put(AlarmColumns.ENABLED, enabled ? 1 : 0);
+
+ /* If we are enabling the alarm, load hour/minutes/daysOfWeek
+ from db, so we can calculate alarm time */
+ if (enabled) {
+ EnableAlarm enableAlarm = new EnableAlarm();
+ getAlarm(resolver, enableAlarm, id);
+ if (enableAlarm.mDaysOfWeek == null) {
+ /* Under monkey, sometimes reportAlarm is never
+ called */
+ Log.e("** enableAlarmInternal failed " + id + " h " +
+ enableAlarm.mHour + " m " + enableAlarm.mMinutes);
+ return;
+ }
+
+ long time = calculateAlarm(enableAlarm.mHour, enableAlarm.mMinutes,
+ enableAlarm.mDaysOfWeek).getTimeInMillis();
+ values.put(AlarmColumns.ALARM_TIME, time);
+ }
+
+ resolver.update(ContentUris.withAppendedId(AlarmColumns.CONTENT_URI, id),
+ values, null, null);
+ }
+
+
+ /**
+ * Calculates next scheduled alert
+ */
+ static class AlarmCalculator implements AlarmSettings {
+ public long mMinAlert = Long.MAX_VALUE;
+ public int mMinIdx = -1;
+
+ /**
+ * returns next scheduled alert, MAX_VALUE if none
+ */
+ public long getAlert() {
+ return mMinAlert;
+ }
+ public int getIndex() {
+ return mMinIdx;
+ }
+
+ public void reportAlarm(
+ int idx, boolean enabled, int hour, int minutes,
+ DaysOfWeek daysOfWeek, boolean vibrate, String message,
+ String alert) {
+ if (enabled) {
+ long atTime = calculateAlarm(hour, minutes,
+ daysOfWeek).getTimeInMillis();
+ /* Log.i("** SET ALERT* idx " + idx + " hour " + hour + " minutes " +
+ minutes + " enabled " + enabled + " calc " + atTime); */
+ if (atTime < mMinAlert) {
+ mMinIdx = idx;
+ mMinAlert = atTime;
+ }
+ }
+ }
+ }
+
+ static AlarmCalculator calculateNextAlert(final Context context) {
+ ContentResolver resolver = context.getContentResolver();
+ AlarmCalculator alarmCalc = new AlarmCalculator();
+ getAlarms(resolver, alarmCalc);
+ return alarmCalc;
+ }
+
+ /**
+ * Disables non-repeating alarms that have passed. Called at
+ * boot.
+ */
+ public static void disableExpiredAlarms(final Context context) {
+ Cursor cur = getAlarmsCursor(context.getContentResolver());
+ long now = System.currentTimeMillis();
+
+ if (cur.moveToFirst()) {
+ do {
+ // Get the field values
+ int id = cur.getInt(AlarmColumns.ALARM_ID_INDEX);
+ boolean enabled = cur.getInt(
+ AlarmColumns.ALARM_ENABLED_INDEX) == 1 ? true : false;
+ DaysOfWeek daysOfWeek = new DaysOfWeek(
+ cur.getInt(AlarmColumns.ALARM_DAYS_OF_WEEK_INDEX));
+ long time = cur.getLong(AlarmColumns.ALARM_TIME_INDEX);
+
+ if (enabled && !daysOfWeek.isRepeatSet() && time < now) {
+ if (Log.LOGV) Log.v(
+ "** DISABLE " + id + " now " + now +" set " + time);
+ enableAlarmInternal(context, id, false);
+ }
+ } while (cur.moveToNext());
+ }
+ cur.close();
+ }
+
+ private static NotificationManager getNotificationManager(
+ final Context context) {
+ return (NotificationManager) context.getSystemService(
+ context.NOTIFICATION_SERVICE);
+ }
+
+ /**
+ * Called at system startup, on time/timezone change, and whenever
+ * the user changes alarm settings. Activates snooze if set,
+ * otherwise loads all alarms, activates next alert.
+ */
+ public static void setNextAlert(final Context context) {
+ int snoozeId = getSnoozeAlarmId(context);
+ if (snoozeId == -1) {
+ AlarmCalculator ac = calculateNextAlert(context);
+ int id = ac.getIndex();
+ long atTime = ac.getAlert();
+
+ if (atTime < Long.MAX_VALUE) {
+ enableAlert(context, id, atTime);
+ } else {
+ disableAlert(context, id);
+ }
+ } else {
+ enableSnoozeAlert(context);
+ }
+ }
+
+ /**
+ * Sets alert in AlarmManger and StatusBar. This is what will
+ * actually launch the alert when the alarm triggers.
+ *
+ * Note: In general, apps should call setNextAlert() instead of
+ * this method. setAlert() is only used outside this class when
+ * the alert is not to be driven by the state of the db. "Snooze"
+ * uses this API, as we do not want to alter the alarm in the db
+ * with each snooze.
+ *
+ * @param id Alarm ID.
+ * @param atTimeInMillis milliseconds since epoch
+ */
+ static void enableAlert(Context context, int id, long atTimeInMillis) {
+ AlarmManager am = (AlarmManager)
+ context.getSystemService(Context.ALARM_SERVICE);
+
+ Intent intent = new Intent(ALARM_ALERT_ACTION);
+ if (Log.LOGV) Log.v("** setAlert id " + id + " atTime " + atTimeInMillis);
+ intent.putExtra(ID, id);
+ intent.putExtra(TIME, atTimeInMillis);
+ PendingIntent sender = PendingIntent.getBroadcast(
+ context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+
+ if (true) {
+ am.set(AlarmManager.RTC_WAKEUP, atTimeInMillis, sender);
+ } else {
+ // a five-second alarm, for testing
+ am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5000,
+ sender);
+ }
+
+ setStatusBarIcon(context, true);
+
+ Calendar c = Calendar.getInstance();
+ c.setTime(new java.util.Date(atTimeInMillis));
+ String timeString = formatDayAndTime(context, c);
+ saveNextAlarm(context, timeString);
+ }
+
+ /**
+ * Disables alert in AlarmManger and StatusBar.
+ *
+ * @param id Alarm ID.
+ */
+ static void disableAlert(Context context, int id) {
+ AlarmManager am = (AlarmManager)
+ context.getSystemService(Context.ALARM_SERVICE);
+ Intent intent = new Intent(ALARM_ALERT_ACTION);
+ intent.putExtra(ID, id);
+ PendingIntent sender = PendingIntent.getBroadcast(
+ context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+ am.cancel(sender);
+ setStatusBarIcon(context, false);
+ saveNextAlarm(context, "");
+ }
+
+ static void saveSnoozeAlert(final Context context, int id,
+ long atTimeInMillis) {
+ SharedPreferences prefs = context.getSharedPreferences(
+ AlarmClock.PREFERENCES, 0);
+ SharedPreferences.Editor ed = prefs.edit();
+ ed.putInt(PREF_SNOOZE_ID, id);
+ ed.putLong(PREF_SNOOZE_TIME, atTimeInMillis);
+ ed.commit();
+ }
+
+ /**
+ * @return ID of alarm disabled, if disabled, -1 otherwise
+ */
+ static int disableSnoozeAlert(final Context context) {
+ int id = getSnoozeAlarmId(context);
+ if (id == -1) return -1;
+ saveSnoozeAlert(context, -1, 0);
+ return id;
+ }
+
+ /**
+ * @return alarm ID of snoozing alarm, -1 if snooze unset
+ */
+ private static int getSnoozeAlarmId(final Context context) {
+ SharedPreferences prefs = context.getSharedPreferences(
+ AlarmClock.PREFERENCES, 0);
+ return prefs.getInt(PREF_SNOOZE_ID, -1);
+ }
+
+ /**
+ * If there is a snooze set, enable it in AlarmManager
+ * @return true if snooze is set
+ */
+ private static boolean enableSnoozeAlert(final Context context) {
+ SharedPreferences prefs = context.getSharedPreferences(
+ AlarmClock.PREFERENCES, 0);
+
+ int id = prefs.getInt(PREF_SNOOZE_ID, -1);
+ if (id == -1) return false;
+ long atTimeInMillis = prefs.getLong(PREF_SNOOZE_TIME, -1);
+ if (id == -1) return false;
+ enableAlert(context, id, atTimeInMillis);
+ return true;
+ }
+
+
+ /**
+ * Tells the StatusBar whether the alarm is enabled or disabled
+ */
+ private static void setStatusBarIcon(Context context, boolean enabled) {
+ Intent alarmChanged = new Intent(Intent.ACTION_ALARM_CHANGED);
+ alarmChanged.putExtra("alarmSet", enabled);
+ context.sendBroadcast(alarmChanged);
+ }
+
+ /**
+ * Given an alarm in hours and minutes, return a time suitable for
+ * setting in AlarmManager.
+ * @param hour Always in 24 hour 0-23
+ * @param minute 0-59
+ * @param daysOfWeek 0-59
+ */
+ static Calendar calculateAlarm(int hour, int minute, DaysOfWeek daysOfWeek) {
+
+ // start with now
+ Calendar c = Calendar.getInstance();
+ c.setTimeInMillis(System.currentTimeMillis());
+
+ int nowHour = c.get(Calendar.HOUR_OF_DAY);
+ int nowMinute = c.get(Calendar.MINUTE);
+
+ // if alarm is behind current time, advance one day
+ if (hour < nowHour ||
+ hour == nowHour && minute <= nowMinute) {
+ c.add(Calendar.DAY_OF_YEAR, 1);
+ }
+ c.set(Calendar.HOUR_OF_DAY, hour);
+ c.set(Calendar.MINUTE, minute);
+ c.set(Calendar.SECOND, 0);
+ c.set(Calendar.MILLISECOND, 0);
+
+ int addDays = daysOfWeek.getNextAlarm(c);
+ /* Log.v("** TIMES * " + c.getTimeInMillis() + " hour " + hour +
+ " minute " + minute + " dow " + c.get(Calendar.DAY_OF_WEEK) + " from now " +
+ addDays); */
+ if (addDays > 0) c.add(Calendar.DAY_OF_WEEK, addDays);
+ return c;
+ }
+
+ static String formatTime(final Context context, int hour, int minute,
+ DaysOfWeek daysOfWeek) {
+ Calendar c = calculateAlarm(hour, minute, daysOfWeek);
+ return formatTime(context, c);
+ }
+
+ /* used by AlarmAlert */
+ static String formatTime(final Context context, Calendar c) {
+ String format = get24HourMode(context) ? M24 : M12;
+ return (c == null) ? "" : (String)DateFormat.format(format, c);
+ }
+
+ /**
+ * Shows day and time -- used for lock screen
+ */
+ private static String formatDayAndTime(final Context context, Calendar c) {
+ String format = get24HourMode(context) ? DM24 : DM12;
+ return (c == null) ? "" : (String)DateFormat.format(format, c);
+ }
+
+ /**
+ * Save time of the next alarm, as a formatted string, into the system
+ * settings so those who care can make use of it.
+ */
+ static void saveNextAlarm(final Context context, String timeString) {
+ Settings.System.putString(context.getContentResolver(),
+ Settings.System.NEXT_ALARM_FORMATTED,
+ timeString);
+ }
+
+ /**
+ * @return true if clock is set to 24-hour mode
+ */
+ static boolean get24HourMode(final Context context) {
+ return android.text.format.DateFormat.is24HourFormat(context);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.gadget.GadgetManager;
+import android.graphics.PorterDuff;
+import android.net.Uri;
+import android.provider.Calendar;
+import android.provider.Calendar.Attendees;
+import android.provider.Calendar.Calendars;
+import android.provider.Calendar.EventsColumns;
+import android.provider.Calendar.Instances;
+import android.provider.Calendar.Reminders;
+import android.text.format.DateFormat;
+import android.text.format.DateUtils;
+import android.util.Config;
+import android.util.Log;
+import android.view.View;
+import android.widget.RemoteViews;
+
+import java.util.Arrays;
+
+/**
+ * Simple gadget to show analog clock.
+ */
+public class AnalogGadgetProvider extends BroadcastReceiver {
+ static final String TAG = "AnalogGadgetProvider";
+
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+
+ if (GadgetManager.ACTION_GADGET_UPDATE.equals(action)) {
+ RemoteViews views = new RemoteViews(context.getPackageName(),
+ R.layout.analog_gadget);
+
+ int[] gadgetIds = intent.getIntArrayExtra(GadgetManager.EXTRA_GADGET_IDS);
+
+ GadgetManager gm = GadgetManager.getInstance(context);
+ gm.updateGadget(gadgetIds, views);
+ }
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Gallery;
+
+/**
+ * Clock face picker for the Alarm Clock application.
+ */
+public class ClockPicker extends Activity implements
+ AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
+
+ private LayoutInflater mFactory;
+ private Gallery mGallery;
+
+ private SharedPreferences mPrefs;
+ private View mClock;
+ private ViewGroup mClockLayout;
+ private int mPosition;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+ mFactory = LayoutInflater.from(this);
+ setContentView(R.layout.clockpicker);
+
+ mGallery = (Gallery) findViewById(R.id.gallery);
+ mGallery.setAdapter(new ClockAdapter());
+ mGallery.setOnItemSelectedListener(this);
+ mGallery.setOnItemClickListener(this);
+
+ mPrefs = getSharedPreferences(AlarmClock.PREFERENCES, 0);
+ int face = mPrefs.getInt(AlarmClock.PREF_CLOCK_FACE, 0);
+ if (face < 0 || face >= AlarmClock.CLOCKS.length) face = 0;
+
+ mClockLayout = (ViewGroup) findViewById(R.id.clock_layout);
+ mClockLayout.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ selectClock(mPosition);
+ }
+ });
+
+ mGallery.setSelection(face, false);
+ }
+
+ public void onItemSelected(AdapterView parent, View v, int position, long id) {
+ if (mClock != null) {
+ mClockLayout.removeView(mClock);
+ }
+ mClock = mFactory.inflate(AlarmClock.CLOCKS[position], null);
+ mClockLayout.addView(mClock, 0);
+ mPosition = position;
+ }
+
+ public void onItemClick(AdapterView parent, View v, int position, long id) {
+ selectClock(position);
+ }
+
+ private synchronized void selectClock(int position) {
+ SharedPreferences.Editor ed = mPrefs.edit();
+ ed.putInt("face", position);
+ ed.commit();
+
+ setResult(RESULT_OK);
+ finish();
+ }
+
+ public void onNothingSelected(AdapterView parent) {
+ }
+
+ class ClockAdapter extends BaseAdapter {
+
+ public ClockAdapter() {
+ }
+
+ public int getCount() {
+ return AlarmClock.CLOCKS.length;
+ }
+
+ public Object getItem(int position) {
+ return position;
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ View clock = mFactory.inflate(AlarmClock.CLOCKS[position], null);
+ return clock;
+ }
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.provider.Settings;
+import android.text.format.DateFormat;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.util.Calendar;
+
+/**
+ * Displays the time
+ */
+public class DigitalClock extends LinearLayout {
+
+ private final static String M12 = "h:mm";
+ private final static String M24 = "k:mm";
+
+ private Calendar mCalendar;
+ private String mFormat;
+ private TextView mTimeDisplay;
+ private AmPm mAmPm;
+ private boolean mAnimate;
+ private ContentObserver mFormatChangeObserver;
+ private boolean mLive = true;
+ private boolean mAttached;
+
+ /* called by system on minute ticks */
+ private final Handler mHandler = new Handler();
+ private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mLive && intent.getAction().equals(
+ Intent.ACTION_TIMEZONE_CHANGED)) {
+ mCalendar = Calendar.getInstance();
+ }
+ updateTime();
+ }
+ };
+
+ static class AmPm {
+ private int mColorOn, mColorOff;
+
+ private LinearLayout mAmPmLayout;
+ private TextView mAm, mPm;
+
+ AmPm(View parent) {
+ mAmPmLayout = (LinearLayout) parent.findViewById(R.id.am_pm);
+ mAm = (TextView)mAmPmLayout.findViewById(R.id.am);
+ mPm = (TextView)mAmPmLayout.findViewById(R.id.pm);
+
+ Resources r = parent.getResources();
+ mColorOn = r.getColor(R.color.ampm_on);
+ mColorOff = r.getColor(R.color.ampm_off);
+ }
+
+ void setShowAmPm(boolean show) {
+ mAmPmLayout.setVisibility(show ? View.VISIBLE : View.GONE);
+ }
+
+ void setIsMorning(boolean isMorning) {
+ mAm.setTextColor(isMorning ? mColorOn : mColorOff);
+ mPm.setTextColor(isMorning ? mColorOff : mColorOn);
+ }
+ }
+
+ private class FormatChangeObserver extends ContentObserver {
+ public FormatChangeObserver() {
+ super(new Handler());
+ }
+ @Override
+ public void onChange(boolean selfChange) {
+ setDateFormat();
+ updateTime();
+ }
+ }
+
+ public DigitalClock(Context context) {
+ this(context, null);
+ }
+
+ public DigitalClock(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mTimeDisplay = (TextView) findViewById(R.id.timeDisplay);
+ mAmPm = new AmPm(this);
+ mCalendar = Calendar.getInstance();
+
+ setDateFormat();
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ if (Log.LOGV) Log.v("onAttachedToWindow " + this);
+
+ if (mAttached) return;
+ mAttached = true;
+
+ if (mAnimate) {
+ AnimationDrawable frameAnimation =
+ (AnimationDrawable) mContext.getResources().getDrawable(
+ R.drawable.animate_circle);
+ View digitalClock = findViewById(R.id.digitalClock);
+ digitalClock.setBackgroundDrawable(frameAnimation);
+ /* Start the animation (looped playback by default). */
+ ((AnimationDrawable) digitalClock.getBackground()).start();
+ /* No luck wrapping animation or individual bitmaps in a
+ ScaleDrawable */
+ digitalClock.requestLayout();
+ }
+
+ if (mLive) {
+ /* monitor time ticks, time changed, timezone */
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_TIME_TICK);
+ filter.addAction(Intent.ACTION_TIME_CHANGED);
+ filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+ mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
+ }
+
+ /* monitor 12/24-hour display preference */
+ mFormatChangeObserver = new FormatChangeObserver();
+ mContext.getContentResolver().registerContentObserver(
+ Settings.System.CONTENT_URI, true, mFormatChangeObserver);
+
+ updateTime();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ if (!mAttached) return;
+ mAttached = false;
+
+ Drawable background = getBackground();
+ if (background instanceof AnimationDrawable) {
+ ((AnimationDrawable) background).stop();
+ }
+
+ if (mLive) {
+ mContext.unregisterReceiver(mIntentReceiver);
+ }
+ mContext.getContentResolver().unregisterContentObserver(
+ mFormatChangeObserver);
+ }
+
+
+ void updateTime(Calendar c) {
+ mCalendar = c;
+ updateTime();
+ }
+
+ private void updateTime() {
+ if (mLive) {
+ mCalendar.setTimeInMillis(System.currentTimeMillis());
+ }
+
+ CharSequence newTime = DateFormat.format(mFormat, mCalendar);
+ mTimeDisplay.setText(newTime);
+ mAmPm.setIsMorning(mCalendar.get(Calendar.AM_PM) == 0);
+ }
+
+ private void setDateFormat() {
+ mFormat = Alarms.get24HourMode(mContext) ? M24 : M12;
+ mAmPm.setShowAmPm(mFormat == M12);
+ }
+
+ void setAnimate() {
+ mAnimate = true;
+ }
+
+ void setLive(boolean live) {
+ mLive = live;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * package-level logging flag
+ */
+
+package com.android.alarmclock;
+
+import android.os.SystemClock;
+import android.util.Config;
+
+class Log {
+ public final static String LOGTAG = "AlarmClock";
+
+ static final boolean LOGV = AlarmClock.DEBUG ? Config.LOGD : Config.LOGV;
+
+ static void v(String logMe) {
+ android.util.Log.v(LOGTAG, /* SystemClock.uptimeMillis() + " " + */ logMe);
+ }
+
+ static void e(String logMe) {
+ android.util.Log.e(LOGTAG, logMe);
+ }
+
+ static void e(String logMe, Exception ex) {
+ android.util.Log.e(LOGTAG, logMe, ex);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.preference.ListPreference;
+import android.util.AttributeSet;
+
+public class RepeatPreference extends ListPreference {
+
+ private Alarms.DaysOfWeek mDaysOfWeek = new Alarms.DaysOfWeek();
+ private OnRepeatChangedObserver mOnRepeatChangedObserver;
+
+ public interface OnRepeatChangedObserver {
+ /** RepeatPrefrence calls this to get initial state */
+ public Alarms.DaysOfWeek getDaysOfWeek();
+
+ /** Called when this preference has changed */
+ public void onRepeatChanged(Alarms.DaysOfWeek daysOfWeek);
+ }
+
+ public RepeatPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ void setOnRepeatChangedObserver(OnRepeatChangedObserver onRepeatChangedObserver) {
+ mOnRepeatChangedObserver = onRepeatChangedObserver;
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ if (positiveResult) {
+ mOnRepeatChangedObserver.onRepeatChanged(mDaysOfWeek);
+ } else {
+ /* no change -- reset to initial state */
+ mDaysOfWeek.set(mOnRepeatChangedObserver.getDaysOfWeek());
+ }
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(Builder builder) {
+ CharSequence[] entries = getEntries();
+ CharSequence[] entryValues = getEntryValues();
+
+ if (entries == null || entryValues == null) {
+ throw new IllegalStateException(
+ "RepeatPreference requires an entries array and an entryValues array.");
+ }
+
+ mDaysOfWeek.set(mOnRepeatChangedObserver.getDaysOfWeek());
+
+ builder.setMultiChoiceItems(
+ entries, mDaysOfWeek.getBooleanArray(),
+ new DialogInterface.OnMultiChoiceClickListener() {
+ public void onClick(DialogInterface dialog, int which, boolean isChecked) {
+ mDaysOfWeek.set(which, isChecked);
+ }
+ });
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.TimePickerDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.CheckBoxPreference;
+import android.preference.PreferenceScreen;
+import android.text.format.DateFormat;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.TimePicker;
+import android.widget.Toast;
+
+/**
+ * Manages each alarm
+ */
+public class SetAlarm extends PreferenceActivity
+ implements Alarms.AlarmSettings, TimePickerDialog.OnTimeSetListener {
+
+ private CheckBoxPreference mAlarmOnPref;
+ private Preference mTimePref;
+ private AlarmPreference mAlarmPref;
+ private CheckBoxPreference mVibratePref;
+ private RepeatPreference mRepeatPref;
+ private ContentObserver mAlarmsChangeObserver;
+ private MenuItem mDeleteAlarmItem;
+ private MenuItem mTestAlarmItem;
+
+ private int mId;
+ private int mHour;
+ private int mMinutes;
+ private Alarms.DaysOfWeek mDaysOfWeek = new Alarms.DaysOfWeek();
+
+ private boolean mReportAlarmCalled;
+
+ private static final int DIALOG_TIMEPICKER = 0;
+
+ private class RingtoneChangedListener implements AlarmPreference.IRingtoneChangedListener {
+ public void onRingtoneChanged(Uri ringtoneUri) {
+ saveAlarm(false);
+ }
+ }
+
+ private class OnRepeatChangedObserver implements RepeatPreference.OnRepeatChangedObserver {
+ public void onRepeatChanged(Alarms.DaysOfWeek daysOfWeek) {
+ if (!mDaysOfWeek.equals(daysOfWeek)) {
+ mDaysOfWeek.set(daysOfWeek);
+ saveAlarm(true);
+ }
+ }
+ public Alarms.DaysOfWeek getDaysOfWeek() {
+ return mDaysOfWeek;
+ }
+ }
+
+ private class AlarmsChangeObserver extends ContentObserver {
+ public AlarmsChangeObserver() {
+ super(new Handler());
+ }
+ @Override
+ public void onChange(boolean selfChange) {
+ Alarms.getAlarm(getContentResolver(), SetAlarm.this, mId);
+ }
+ }
+
+ /**
+ * Set an alarm. Requires an Alarms.ID to be passed in as an
+ * extra
+ */
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ addPreferencesFromResource(R.xml.alarm_prefs);
+ mAlarmOnPref = (CheckBoxPreference)findPreference("on");
+ mTimePref = findPreference("time");
+ mAlarmPref = (AlarmPreference) findPreference("alarm");
+ mVibratePref = (CheckBoxPreference) findPreference("vibrate");
+ mRepeatPref = (RepeatPreference) findPreference("setRepeat");
+
+ Intent i = getIntent();
+ mId = i.getIntExtra(Alarms.ID, -1);
+ if (Log.LOGV) Log.v("In SetAlarm, alarm id = " + mId);
+
+ mReportAlarmCalled = false;
+ /* load alarm details from database */
+ Alarms.getAlarm(getContentResolver(), this, mId);
+ /* This should never happen, but does occasionally with the monkey.
+ * I believe it's a race condition where a deleted alarm is opened
+ * before the alarm list is refreshed. */
+ if (!mReportAlarmCalled) {
+ Log.e("reportAlarm never called!");
+ finish();
+ }
+
+ mAlarmsChangeObserver = new AlarmsChangeObserver();
+ getContentResolver().registerContentObserver(
+ Alarms.AlarmColumns.CONTENT_URI, true, mAlarmsChangeObserver);
+
+ mAlarmPref.setRingtoneChangedListener(new RingtoneChangedListener());
+ mRepeatPref.setOnRepeatChangedObserver(new OnRepeatChangedObserver());
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ getContentResolver().unregisterContentObserver(mAlarmsChangeObserver);
+ }
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ Dialog d;
+
+ switch (id) {
+ case DIALOG_TIMEPICKER:
+ d = new TimePickerDialog(
+ SetAlarm.this,
+ this,
+ 0,
+ 0,
+ DateFormat.is24HourFormat(SetAlarm.this));
+ d.setTitle(getResources().getString(R.string.time));
+ break;
+ default:
+ d = null;
+ }
+
+ return d;
+ }
+
+ @Override
+ protected void onPrepareDialog(int id, Dialog dialog) {
+ super.onPrepareDialog(id, dialog);
+
+ switch (id) {
+ case DIALOG_TIMEPICKER:
+ TimePickerDialog timePicker = (TimePickerDialog)dialog;
+ timePicker.updateTime(mHour, mMinutes);
+ break;
+ }
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+
+ if (preference == mTimePref) {
+ showDialog(DIALOG_TIMEPICKER);
+ } else if (preference == mAlarmOnPref) {
+ saveAlarm(true);
+ } else if (preference == mVibratePref) {
+ saveAlarm(false);
+ }
+
+ return super.onPreferenceTreeClick(preferenceScreen, preference);
+ }
+
+ public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
+ mHour = hourOfDay;
+ mMinutes = minute;
+ mAlarmOnPref.setChecked(true);
+ saveAlarm(true);
+ }
+
+ /**
+ * Alarms.AlarmSettings implementation. Database feeds current
+ * settings in through this call
+ */
+ public void reportAlarm(
+ int idx, boolean enabled, int hour, int minutes,
+ Alarms.DaysOfWeek daysOfWeek, boolean vibrate,String message,
+ String alert) {
+
+ mHour = hour;
+ mMinutes = minutes;
+ mAlarmOnPref.setChecked(enabled);
+ mDaysOfWeek.set(daysOfWeek);
+ mVibratePref.setChecked(vibrate);
+
+ if (alert == null || alert.length() == 0) {
+ if (Log.LOGV) Log.v("****** reportAlarm null or 0-length alert");
+ mAlarmPref.mAlert = getDefaultAlarm();
+ if (mAlarmPref.mAlert == null) {
+ Log.e("****** Default Alarm null");
+ }
+ } else {
+ mAlarmPref.mAlert = Uri.parse(alert);
+ if (mAlarmPref.mAlert == null) {
+ Log.e("****** Parsed null alarm. URI: " + alert);
+ }
+ }
+ if (Log.LOGV) Log.v("****** reportAlarm uri " + alert + " alert " +
+ mAlarmPref.mAlert);
+ updateTime();
+ updateRepeat();
+ updateAlarm(mAlarmPref.mAlert);
+
+ mReportAlarmCalled = true;
+ }
+
+ /**
+ * picks the first alarm available
+ */
+ private Uri getDefaultAlarm() {
+ RingtoneManager ringtoneManager = new RingtoneManager(this);
+ ringtoneManager.setType(RingtoneManager.TYPE_ALARM);
+ return ringtoneManager.getRingtoneUri(0);
+ }
+
+ private void updateTime() {
+ if (Log.LOGV) Log.v("updateTime " + mId);
+ mTimePref.setSummary(Alarms.formatTime(this, mHour, mMinutes, mDaysOfWeek));
+ }
+
+ private void updateAlarm(Uri ringtoneUri) {
+ if (Log.LOGV) Log.v("updateAlarm " + mId);
+ Ringtone ringtone = RingtoneManager.getRingtone(SetAlarm.this, ringtoneUri);
+ if (ringtone != null) {
+ mAlarmPref.setSummary(ringtone.getTitle(SetAlarm.this));
+ }
+ }
+
+ private void updateRepeat() {
+ if (Log.LOGV) Log.v("updateRepeat " + mId);
+ mRepeatPref.setSummary(mDaysOfWeek.toString(this, true));
+ }
+
+ private void saveAlarm(boolean popToast) {
+ if (mReportAlarmCalled && mAlarmPref.mAlert != null) {
+ String alertString = mAlarmPref.mAlert.toString();
+ saveAlarm(this, mId, mAlarmOnPref.isChecked(), mHour, mMinutes,
+ mDaysOfWeek, mVibratePref.isChecked(), alertString,
+ popToast);
+ }
+ }
+
+ /**
+ * Write alarm out to persistent store and pops toast if alarm
+ * enabled
+ */
+ private static void saveAlarm(
+ Context context, int id, boolean enabled, int hour, int minute,
+ Alarms.DaysOfWeek daysOfWeek, boolean vibrate, String alert,
+ boolean popToast) {
+ if (Log.LOGV) Log.v("** saveAlarm " + id + " " + enabled + " " + hour +
+ " " + minute + " vibe " + vibrate);
+
+ // Fix alert string first
+ Alarms.setAlarm(context, id, enabled, hour, minute, daysOfWeek, vibrate,
+ "", alert);
+
+ if (enabled && popToast) {
+ popAlarmSetToast(context, hour, minute, daysOfWeek);
+ }
+ }
+
+ /**
+ * Display a toast that tells the user how long until the alarm
+ * goes off. This helps prevent "am/pm" mistakes.
+ */
+ static void popAlarmSetToast(Context context, int hour, int minute,
+ Alarms.DaysOfWeek daysOfWeek) {
+
+ String toastText = formatToast(context, hour, minute, daysOfWeek);
+ Toast toast = Toast.makeText(context, toastText, Toast.LENGTH_LONG);
+ ToastMaster.setToast(toast);
+ toast.show();
+ }
+
+ /**
+ * format "Alarm set for 2 days 7 hours and 53 minutes from
+ * now"
+ */
+ static String formatToast(Context context, int hour, int minute,
+ Alarms.DaysOfWeek daysOfWeek) {
+ long alarm = Alarms.calculateAlarm(hour, minute,
+ daysOfWeek).getTimeInMillis();
+ long delta = alarm - System.currentTimeMillis();;
+ long hours = delta / (1000 * 60 * 60);
+ long minutes = delta / (1000 * 60) % 60;
+ long days = hours / 24;
+ hours = hours % 24;
+
+ String daySeq = (days == 0) ? "" :
+ (days == 1) ? context.getString(R.string.day) :
+ context.getString(R.string.days, Long.toString(days));
+
+ String minSeq = (minutes == 0) ? "" :
+ (minutes == 1) ? context.getString(R.string.minute) :
+ context.getString(R.string.minutes, Long.toString(minutes));
+
+ String hourSeq = (hours == 0) ? "" :
+ (hours == 1) ? context.getString(R.string.hour) :
+ context.getString(R.string.hours, Long.toString(hours));
+
+ boolean dispDays = days > 0;
+ boolean dispHour = hours > 0;
+ boolean dispMinute = minutes > 0;
+
+ String ret;
+ if (!(dispDays || dispHour || dispMinute)) {
+ ret = context.getString(R.string.subminute);
+ } else {
+ String parts[] = new String[5];
+ parts[0] = daySeq;
+ parts[1] = !dispDays ? "" :
+ dispHour && dispMinute ? context.getString(R.string.space) :
+ !dispHour && !dispMinute ? "" :
+ context.getString(R.string.and);
+ parts[2] = dispHour ? hourSeq : "";
+ parts[3] = dispHour && dispMinute ? context.getString(R.string.and) : "";
+ parts[4] = dispMinute ? minSeq : "";
+ ret = context.getString(R.string.combiner, (Object[])parts);
+ }
+
+ ret = context.getString(R.string.alarm_set, ret);
+ /* if (Log.LOGV) Log.v("** TOAST daySeq " + daySeq + " hourSeq " + hourSeq +
+ " minSeq " + minSeq + " ret " + ret); */
+ return ret;
+ }
+
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ mDeleteAlarmItem = menu.add(0, 0, 0, R.string.delete_alarm);
+ mDeleteAlarmItem.setIcon(android.R.drawable.ic_menu_delete);
+
+ if (AlarmClock.DEBUG) {
+ mTestAlarmItem = menu.add(0, 0, 0, "test alarm");
+ }
+
+
+ return true;
+ }
+
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item == mDeleteAlarmItem) {
+ Alarms.deleteAlarm(this, mId);
+ finish();
+ return true;
+ }
+ if (AlarmClock.DEBUG) {
+ if (item == mTestAlarmItem) {
+ setTestAlarm();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Test code: this is disabled for production build. Sets
+ * this alarm to go off on the next minute
+ */
+ void setTestAlarm() {
+
+ // start with now
+ java.util.Calendar c = java.util.Calendar.getInstance();
+ c.setTimeInMillis(System.currentTimeMillis());
+
+ int nowHour = c.get(java.util.Calendar.HOUR_OF_DAY);
+ int nowMinute = c.get(java.util.Calendar.MINUTE);
+
+ int minutes = (nowMinute + 1) % 60;
+ int hour = nowHour + (nowMinute == 0? 1 : 0);
+
+ saveAlarm(this, mId, true, hour, minutes, mDaysOfWeek, true,
+ mAlarmPref.mAlert.toString(), true);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.widget.Toast;
+
+public class ToastMaster {
+
+ private static Toast sToast = null;
+
+ private ToastMaster() {
+
+ }
+
+ public static void setToast(Toast toast) {
+ if (sToast != null)
+ sToast.cancel();
+ sToast = toast;
+ }
+
+ public static void cancelToast() {
+ if (sToast != null)
+ sToast.cancel();
+ sToast = null;
+ }
+
+}