Home | History | Annotate | Download | only in deskclock
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.deskclock;
     18 
     19 import android.app.Activity;
     20 import android.app.Notification;
     21 import android.app.NotificationManager;
     22 import android.app.PendingIntent;
     23 import android.content.Context;
     24 import android.content.BroadcastReceiver;
     25 import android.content.Intent;
     26 import android.content.IntentFilter;
     27 import android.content.SharedPreferences;
     28 import android.content.res.Configuration;
     29 import android.os.Bundle;
     30 import android.preference.PreferenceManager;
     31 import android.view.KeyEvent;
     32 import android.view.View;
     33 import android.view.ViewGroup;
     34 import android.view.LayoutInflater;
     35 import android.view.Window;
     36 import android.view.WindowManager;
     37 import android.widget.Button;
     38 import android.widget.Toast;
     39 import android.widget.TextView;
     40 
     41 import java.util.Calendar;
     42 
     43 /**
     44  * Alarm Clock alarm alert: pops visible indicator and plays alarm
     45  * tone. This activity is the full screen version which shows over the lock
     46  * screen with the wallpaper as the background.
     47  */
     48 public class AlarmAlertFullScreen extends Activity {
     49 
     50     // These defaults must match the values in res/xml/settings.xml
     51     private static final String DEFAULT_SNOOZE = "10";
     52     private static final String DEFAULT_VOLUME_BEHAVIOR = "2";
     53     protected static final String SCREEN_OFF = "screen_off";
     54 
     55     protected Alarm mAlarm;
     56     private int mVolumeBehavior;
     57 
     58     // Receives the ALARM_KILLED action from the AlarmKlaxon,
     59     // and also ALARM_SNOOZE_ACTION / ALARM_DISMISS_ACTION from other applications
     60     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
     61         @Override
     62         public void onReceive(Context context, Intent intent) {
     63             String action = intent.getAction();
     64             if (action.equals(Alarms.ALARM_SNOOZE_ACTION)) {
     65                 snooze();
     66             } else if (action.equals(Alarms.ALARM_DISMISS_ACTION)) {
     67                 dismiss(false);
     68             } else {
     69                 Alarm alarm = intent.getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);
     70                 if (alarm != null && mAlarm.id == alarm.id) {
     71                     dismiss(true);
     72                 }
     73             }
     74         }
     75     };
     76 
     77     @Override
     78     protected void onCreate(Bundle icicle) {
     79         super.onCreate(icicle);
     80 
     81         mAlarm = getIntent().getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);
     82 
     83         // Get the volume/camera button behavior setting
     84         final String vol =
     85                 PreferenceManager.getDefaultSharedPreferences(this)
     86                 .getString(SettingsActivity.KEY_VOLUME_BEHAVIOR,
     87                         DEFAULT_VOLUME_BEHAVIOR);
     88         mVolumeBehavior = Integer.parseInt(vol);
     89 
     90         requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
     91 
     92         final Window win = getWindow();
     93         win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
     94                 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
     95         // Turn on the screen unless we are being launched from the AlarmAlert
     96         // subclass.
     97         if (!getIntent().getBooleanExtra(SCREEN_OFF, false)) {
     98             win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
     99                     | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
    100                     | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
    101         }
    102 
    103         updateLayout();
    104 
    105         // Register to get the alarm killed/snooze/dismiss intent.
    106         IntentFilter filter = new IntentFilter(Alarms.ALARM_KILLED);
    107         filter.addAction(Alarms.ALARM_SNOOZE_ACTION);
    108         filter.addAction(Alarms.ALARM_DISMISS_ACTION);
    109         registerReceiver(mReceiver, filter);
    110     }
    111 
    112     private void setTitle() {
    113         String label = mAlarm.getLabelOrDefault(this);
    114         TextView title = (TextView) findViewById(R.id.alertTitle);
    115         title.setText(label);
    116     }
    117 
    118     private void updateLayout() {
    119         LayoutInflater inflater = LayoutInflater.from(this);
    120 
    121         setContentView(inflater.inflate(R.layout.alarm_alert, null));
    122 
    123         /* snooze behavior: pop a snooze confirmation view, kick alarm
    124            manager. */
    125         Button snooze = (Button) findViewById(R.id.snooze);
    126         snooze.requestFocus();
    127         snooze.setOnClickListener(new Button.OnClickListener() {
    128             public void onClick(View v) {
    129                 snooze();
    130             }
    131         });
    132 
    133         /* dismiss button: close notification */
    134         findViewById(R.id.dismiss).setOnClickListener(
    135                 new Button.OnClickListener() {
    136                     public void onClick(View v) {
    137                         dismiss(false);
    138                     }
    139                 });
    140 
    141         /* Set the title from the passed in alarm */
    142         setTitle();
    143     }
    144 
    145     // Attempt to snooze this alert.
    146     private void snooze() {
    147         // Do not snooze if the snooze button is disabled.
    148         if (!findViewById(R.id.snooze).isEnabled()) {
    149             dismiss(false);
    150             return;
    151         }
    152         final String snooze =
    153                 PreferenceManager.getDefaultSharedPreferences(this)
    154                 .getString(SettingsActivity.KEY_ALARM_SNOOZE, DEFAULT_SNOOZE);
    155         int snoozeMinutes = Integer.parseInt(snooze);
    156 
    157         final long snoozeTime = System.currentTimeMillis()
    158                 + (1000 * 60 * snoozeMinutes);
    159         Alarms.saveSnoozeAlert(AlarmAlertFullScreen.this, mAlarm.id,
    160                 snoozeTime);
    161 
    162         // Get the display time for the snooze and update the notification.
    163         final Calendar c = Calendar.getInstance();
    164         c.setTimeInMillis(snoozeTime);
    165 
    166         // Append (snoozed) to the label.
    167         String label = mAlarm.getLabelOrDefault(this);
    168         label = getString(R.string.alarm_notify_snooze_label, label);
    169 
    170         // Notify the user that the alarm has been snoozed.
    171         Intent cancelSnooze = new Intent(this, AlarmReceiver.class);
    172         cancelSnooze.setAction(Alarms.CANCEL_SNOOZE);
    173         cancelSnooze.putExtra(Alarms.ALARM_ID, mAlarm.id);
    174         PendingIntent broadcast =
    175                 PendingIntent.getBroadcast(this, mAlarm.id, cancelSnooze, 0);
    176         NotificationManager nm = getNotificationManager();
    177         Notification n = new Notification(R.drawable.stat_notify_alarm,
    178                 label, 0);
    179         n.setLatestEventInfo(this, label,
    180                 getString(R.string.alarm_notify_snooze_text,
    181                     Alarms.formatTime(this, c)), broadcast);
    182         n.flags |= Notification.FLAG_AUTO_CANCEL
    183                 | Notification.FLAG_ONGOING_EVENT;
    184         nm.notify(mAlarm.id, n);
    185 
    186         String displayTime = getString(R.string.alarm_alert_snooze_set,
    187                 snoozeMinutes);
    188         // Intentionally log the snooze time for debugging.
    189         Log.v(displayTime);
    190 
    191         // Display the snooze minutes in a toast.
    192         Toast.makeText(AlarmAlertFullScreen.this, displayTime,
    193                 Toast.LENGTH_LONG).show();
    194         stopService(new Intent(Alarms.ALARM_ALERT_ACTION));
    195         finish();
    196     }
    197 
    198     private NotificationManager getNotificationManager() {
    199         return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    200     }
    201 
    202     // Dismiss the alarm.
    203     private void dismiss(boolean killed) {
    204         Log.i(killed ? "Alarm killed" : "Alarm dismissed by user");
    205         // The service told us that the alarm has been killed, do not modify
    206         // the notification or stop the service.
    207         if (!killed) {
    208             // Cancel the notification and stop playing the alarm
    209             NotificationManager nm = getNotificationManager();
    210             nm.cancel(mAlarm.id);
    211             stopService(new Intent(Alarms.ALARM_ALERT_ACTION));
    212         }
    213         finish();
    214     }
    215 
    216     /**
    217      * this is called when a second alarm is triggered while a
    218      * previous alert window is still active.
    219      */
    220     @Override
    221     protected void onNewIntent(Intent intent) {
    222         super.onNewIntent(intent);
    223 
    224         if (Log.LOGV) Log.v("AlarmAlert.OnNewIntent()");
    225 
    226         mAlarm = intent.getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);
    227 
    228         setTitle();
    229     }
    230 
    231     @Override
    232     protected void onResume() {
    233         super.onResume();
    234         // If the alarm was deleted at some point, disable snooze.
    235         if (Alarms.getAlarm(getContentResolver(), mAlarm.id) == null) {
    236             Button snooze = (Button) findViewById(R.id.snooze);
    237             snooze.setEnabled(false);
    238         }
    239     }
    240 
    241     @Override
    242     public void onDestroy() {
    243         super.onDestroy();
    244         if (Log.LOGV) Log.v("AlarmAlert.onDestroy()");
    245         // No longer care about the alarm being killed.
    246         unregisterReceiver(mReceiver);
    247     }
    248 
    249     @Override
    250     public boolean dispatchKeyEvent(KeyEvent event) {
    251         // Do this on key down to handle a few of the system keys.
    252         boolean up = event.getAction() == KeyEvent.ACTION_UP;
    253         switch (event.getKeyCode()) {
    254             // Volume keys and camera keys dismiss the alarm
    255             case KeyEvent.KEYCODE_VOLUME_UP:
    256             case KeyEvent.KEYCODE_VOLUME_DOWN:
    257             case KeyEvent.KEYCODE_CAMERA:
    258             case KeyEvent.KEYCODE_FOCUS:
    259                 if (up) {
    260                     switch (mVolumeBehavior) {
    261                         case 1:
    262                             snooze();
    263                             break;
    264 
    265                         case 2:
    266                             dismiss(false);
    267                             break;
    268 
    269                         default:
    270                             break;
    271                     }
    272                 }
    273                 return true;
    274             default:
    275                 break;
    276         }
    277         return super.dispatchKeyEvent(event);
    278     }
    279 
    280     @Override
    281     public void onBackPressed() {
    282         // Don't allow back to dismiss. This method is overriden by AlarmAlert
    283         // so that the dialog is dismissed.
    284         return;
    285     }
    286 }
    287