2 * Copyright (C) 2007 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.deskclock;
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.content.Context;
22 import android.content.DialogInterface;
23 import android.content.Intent;
24 import android.content.SharedPreferences;
25 import android.content.res.Configuration;
26 import android.database.Cursor;
27 import android.graphics.Typeface;
28 import android.net.Uri;
29 import android.os.Bundle;
30 import android.os.Handler;
31 import android.provider.Settings;
32 import android.view.ContextMenu;
33 import android.view.ContextMenu.ContextMenuInfo;
34 import android.view.LayoutInflater;
35 import android.view.Menu;
36 import android.view.MenuItem;
37 import android.view.View;
38 import android.view.View.OnClickListener;
39 import android.view.View.OnCreateContextMenuListener;
40 import android.view.ViewGroup;
41 import android.widget.AdapterView;
42 import android.widget.AdapterView.AdapterContextMenuInfo;
43 import android.widget.AdapterView.OnItemClickListener;
44 import android.widget.Button;
45 import android.widget.CheckBox;
46 import android.widget.CursorAdapter;
47 import android.widget.ImageButton;
48 import android.widget.ImageView;
49 import android.widget.ListView;
50 import android.widget.TextView;
51 import android.os.SystemProperties;
52 import android.media.AudioManager;
54 import java.util.Calendar;
57 * AlarmClock application.
59 public class AlarmClock extends Activity implements OnItemClickListener {
61 final static String PREFERENCES = "AlarmClock";
63 /** This must be false for production. If true, turns on logging,
65 final static boolean DEBUG = false;
67 private SharedPreferences mPrefs;
68 private LayoutInflater mFactory;
69 private ListView mAlarmsList;
70 private Cursor mCursor;
71 private static boolean volumeAdjustable;
73 private void updateIndicatorAndAlarm(boolean enabled, ImageView bar,
75 bar.setImageResource(enabled ? R.drawable.ic_indicator_on
76 : R.drawable.ic_indicator_off);
77 Alarms.enableAlarm(this, alarm.id, enabled);
79 SetAlarm.popAlarmSetToast(this, alarm.hour, alarm.minutes,
84 private class AlarmTimeAdapter extends CursorAdapter {
85 public AlarmTimeAdapter(Context context, Cursor cursor) {
86 super(context, cursor);
89 public View newView(Context context, Cursor cursor, ViewGroup parent) {
90 View ret = mFactory.inflate(R.layout.alarm_time, parent, false);
92 DigitalClock digitalClock = (DigitalClock) ret.findViewById(R.id.digitalClock);
93 digitalClock.setLive(false);
94 if (Log.LOGV) Log.v("newView " + cursor.getPosition());
98 public void bindView(View view, Context context, Cursor cursor) {
99 final Alarm alarm = new Alarm(cursor);
101 View indicator = view.findViewById(R.id.indicator);
103 // Set the initial resource for the bar image.
104 final ImageView barOnOff =
105 (ImageView) indicator.findViewById(R.id.bar_onoff);
106 barOnOff.setImageResource(alarm.enabled ?
107 R.drawable.ic_indicator_on : R.drawable.ic_indicator_off);
109 // Set the initial state of the clock "checkbox"
110 final CheckBox clockOnOff =
111 (CheckBox) indicator.findViewById(R.id.clock_onoff);
112 clockOnOff.setChecked(alarm.enabled);
114 // Clicking outside the "checkbox" should also change the state.
115 indicator.setOnClickListener(new OnClickListener() {
116 public void onClick(View v) {
118 updateIndicatorAndAlarm(clockOnOff.isChecked(),
123 DigitalClock digitalClock =
124 (DigitalClock) view.findViewById(R.id.digitalClock);
126 // set the alarm text
127 final Calendar c = Calendar.getInstance();
128 c.set(Calendar.HOUR_OF_DAY, alarm.hour);
129 c.set(Calendar.MINUTE, alarm.minutes);
130 digitalClock.updateTime(c);
131 digitalClock.setTypeface(Typeface.DEFAULT);
133 // Set the repeat text or leave it blank if it does not repeat.
134 TextView daysOfWeekView =
135 (TextView) digitalClock.findViewById(R.id.daysOfWeek);
136 final String daysOfWeekStr =
137 alarm.daysOfWeek.toString(AlarmClock.this, false);
138 if (daysOfWeekStr != null && daysOfWeekStr.length() != 0) {
139 daysOfWeekView.setText(daysOfWeekStr);
140 daysOfWeekView.setVisibility(View.VISIBLE);
142 daysOfWeekView.setVisibility(View.GONE);
147 (TextView) view.findViewById(R.id.label);
148 if (alarm.label != null && alarm.label.length() != 0) {
149 labelView.setText(alarm.label);
150 labelView.setVisibility(View.VISIBLE);
152 labelView.setVisibility(View.GONE);
158 public boolean onContextItemSelected(final MenuItem item) {
159 final AdapterContextMenuInfo info =
160 (AdapterContextMenuInfo) item.getMenuInfo();
161 final int id = (int) info.id;
162 switch (item.getItemId()) {
163 case R.id.delete_alarm:
164 // Confirm that the alarm will be deleted.
165 new AlertDialog.Builder(this)
166 .setTitle(getString(R.string.delete_alarm))
167 .setMessage(getString(R.string.delete_alarm_confirm))
168 .setPositiveButton(android.R.string.ok,
169 new DialogInterface.OnClickListener() {
170 public void onClick(DialogInterface d,
172 Alarms.deleteAlarm(AlarmClock.this, id);
175 .setNegativeButton(android.R.string.cancel, null)
179 case R.id.enable_alarm:
180 final Cursor c = (Cursor) mAlarmsList.getAdapter()
181 .getItem(info.position);
182 final Alarm alarm = new Alarm(c);
183 Alarms.enableAlarm(this, alarm.id, !alarm.enabled);
184 if (!alarm.enabled) {
185 SetAlarm.popAlarmSetToast(this, alarm.hour, alarm.minutes,
190 case R.id.edit_alarm:
191 Intent intent = new Intent(this, SetAlarm.class);
192 intent.putExtra(Alarms.ALARM_ID, id);
193 startActivity(intent);
199 return super.onContextItemSelected(item);
203 protected void onCreate(Bundle icicle) {
204 super.onCreate(icicle);
205 volumeAdjustable=SystemProperties.getBoolean("ro.alarm.volume.adjustable",false);
206 AlarmClock.setVolumeControlForPlatform(this);
208 mFactory = LayoutInflater.from(this);
209 mPrefs = getSharedPreferences(PREFERENCES, 0);
210 mCursor = Alarms.getAlarmsCursor(getContentResolver());
215 private void updateLayout() {
216 setContentView(R.layout.alarm_clock);
217 mAlarmsList = (ListView) findViewById(R.id.alarms_list);
218 AlarmTimeAdapter adapter = new AlarmTimeAdapter(this, mCursor);
219 mAlarmsList.setAdapter(adapter);
220 mAlarmsList.setVerticalScrollBarEnabled(true);
221 mAlarmsList.setOnItemClickListener(this);
222 mAlarmsList.setOnCreateContextMenuListener(this);
224 View addAlarm = findViewById(R.id.add_alarm);
225 addAlarm.setOnClickListener(new View.OnClickListener() {
226 public void onClick(View v) {
230 // Make the entire view selected when focused.
231 addAlarm.setOnFocusChangeListener(new View.OnFocusChangeListener() {
232 public void onFocusChange(View v, boolean hasFocus) {
233 v.setSelected(hasFocus);
237 ImageButton deskClock =
238 (ImageButton) findViewById(R.id.desk_clock_button);
239 deskClock.setOnClickListener(new View.OnClickListener() {
240 public void onClick(View v) {
241 startActivity(new Intent(AlarmClock.this, DeskClock.class));
246 // Version of addNewAlarm that can be called from any activity, e.g. DeskClock
247 protected static void addNewAlarm(Context context) {
248 final Uri uri = Alarms.addAlarm(context.getContentResolver());
249 final String segment = uri.getPathSegments().get(1);
250 int newId = Integer.parseInt(segment);
252 Log.v("In AlarmClock, new alarm id = " + newId);
254 final Intent intent = new Intent(context, SetAlarm.class);
255 intent.putExtra(Alarms.ALARM_ID, newId);
256 context.startActivity(intent);
259 private void addNewAlarm() {
264 protected void onDestroy() {
266 ToastMaster.cancelToast();
267 mCursor.deactivate();
271 public void onCreateContextMenu(ContextMenu menu, View view,
272 ContextMenuInfo menuInfo) {
273 // Inflate the menu from xml.
274 getMenuInflater().inflate(R.menu.context_menu, menu);
276 // Use the current item to create a custom view for the header.
277 final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
279 (Cursor) mAlarmsList.getAdapter().getItem((int) info.position);
280 final Alarm alarm = new Alarm(c);
282 // Construct the Calendar to compute the time.
283 final Calendar cal = Calendar.getInstance();
284 cal.set(Calendar.HOUR_OF_DAY, alarm.hour);
285 cal.set(Calendar.MINUTE, alarm.minutes);
286 final String time = Alarms.formatTime(this, cal);
288 // Inflate the custom view and set each TextView's text.
289 final View v = mFactory.inflate(R.layout.context_menu_header, null);
290 TextView textView = (TextView) v.findViewById(R.id.header_time);
291 textView.setText(time);
292 textView = (TextView) v.findViewById(R.id.header_label);
293 textView.setText(alarm.label);
295 // Set the custom view on the menu.
296 menu.setHeaderView(v);
297 // Change the text based on the state of the alarm.
299 menu.findItem(R.id.enable_alarm).setTitle(R.string.disable_alarm);
304 public boolean onOptionsItemSelected(MenuItem item) {
305 switch (item.getItemId()) {
306 case R.id.menu_item_settings:
307 startActivity(new Intent(this, SettingsActivity.class));
309 case R.id.menu_item_desk_clock:
310 startActivity(new Intent(this, DeskClock.class));
312 case R.id.menu_item_add_alarm:
318 return super.onOptionsItemSelected(item);
322 public boolean onCreateOptionsMenu(Menu menu) {
323 getMenuInflater().inflate(R.menu.alarm_list_menu, menu);
324 return super.onCreateOptionsMenu(menu);
327 public void onItemClick(AdapterView parent, View v, int pos, long id) {
328 Intent intent = new Intent(this, SetAlarm.class);
329 intent.putExtra(Alarms.ALARM_ID, (int) id);
330 startActivity(intent);
333 public static void setVolumeControlForPlatform(Activity context){
334 if (isVolumeAdjustable()){
335 context.setVolumeControlStream(AudioManager.STREAM_ALARM);
337 //Use default stream type,the default type use a fixed volume
338 context.setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE);
341 public static boolean isVolumeAdjustable(){
342 return volumeAdjustable;