/*
* 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.androsz.electricsleepbeta.alarmclock;
import java.util.Calendar;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.androsz.electricsleepbeta.R;
import com.androsz.electricsleepbeta.app.SettingsActivity;
/**
* Alarm Clock alarm alert: pops visible indicator and plays alarm tone. This
* activity is the full screen version which shows over the lock screen with the
* wallpaper as the background.
*/
public class AlarmAlertFullScreen extends Activity {
// These defaults must match the values in res/xml/settings.xml
private static final String DEFAULT_SNOOZE = "5";
private static final String DEFAULT_VOLUME_BEHAVIOR = "0";
protected static final String SCREEN_OFF = "screen_off";
protected Alarm mAlarm;
// Receives the ALARM_KILLED action from the AlarmKlaxon,
// and also ALARM_SNOOZE_ACTION / ALARM_DISMISS_ACTION from other
// applications
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
if (action.equals(Alarms.ALARM_SNOOZE_ACTION)) {
snooze();
} else if (action.equals(Alarms.ALARM_DISMISS_ACTION)) {
dismiss(false);
} else if (action.equals(Alarms.ALARM_KILLED)) {
final Alarm alarm = intent.getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);
if (alarm != null && mAlarm.id == alarm.id) {
dismiss(true);
}
}
}
};
private int mVolumeBehavior;
// Dismiss the alarm.
private void dismiss(final boolean killed) {
Log.i(killed ? "Alarm killed" : "Alarm dismissed by user");
// The service told us that the alarm has been killed, do not modify
// the notification or stop the service.
if (!killed) {
// Cancel the notification and stop playing the alarm
final NotificationManager nm = getNotificationManager();
nm.cancel(mAlarm.id);
stopService(new Intent(Alarms.ALARM_ALERT_ACTION));
sendBroadcast(new Intent(Alarms.ALARM_DISMISSED_BY_USER_ACTION));
}
finish();
}
@Override
public boolean dispatchKeyEvent(final KeyEvent event) {
// Do this on key down to handle a few of the system keys.
final boolean up = event.getAction() == KeyEvent.ACTION_UP;
switch (event.getKeyCode()) {
// Volume keys and camera keys dismiss the alarm
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_CAMERA:
case KeyEvent.KEYCODE_FOCUS:
if (up) {
switch (mVolumeBehavior) {
case 1:
snooze();
break;
case 2:
dismiss(false);
break;
default:
break;
}
}
return true;
default:
break;
}
return super.dispatchKeyEvent(event);
}
private NotificationManager getNotificationManager() {
return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
@Override
public void onBackPressed() {
// Don't allow back to dismiss. This method is overriden by AlarmAlert
// so that the dialog is dismissed.
return;
}
@Override
protected void onCreate(final Bundle icicle) {
super.onCreate(icicle);
setTheme(R.style.Theme_Sherlock);
mAlarm = getIntent().getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);
// Get the volume/camera button behavior setting
final String vol = getSharedPreferences(SettingsActivity.PREFERENCES, 0).getString(
SettingsActivity.KEY_VOLUME_BEHAVIOR, DEFAULT_VOLUME_BEHAVIOR);
mVolumeBehavior = Integer.parseInt(vol);
requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
// Turn on the screen unless we are being launched from the AlarmAlert
// subclass.
final boolean screenOff = getIntent().getBooleanExtra(SCREEN_OFF, false);
if (!screenOff) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
// API 8+
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
} else {
// API 7 or less
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
}
updateLayout();
// Register to get the alarm killed/snooze/dismiss intent.
final IntentFilter filter = new IntentFilter(Alarms.ALARM_KILLED);
filter.addAction(Alarms.ALARM_SNOOZE_ACTION);
filter.addAction(Alarms.ALARM_DISMISS_ACTION);
registerReceiver(mReceiver, filter);
}
@Override
public void onDestroy() {
super.onDestroy();
if (Log.LOGV) {
Log.v("AlarmAlert.onDestroy()");
}
// No longer care about the alarm being killed.
unregisterReceiver(mReceiver);
}
/**
* this is called when a second alarm is triggered while a previous alert
* window is still active.
*/
@Override
protected void onNewIntent(final Intent intent) {
super.onNewIntent(intent);
if (Log.LOGV) {
Log.v("AlarmAlert.OnNewIntent()");
}
mAlarm = intent.getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);
setTitle();
}
@Override
protected void onResume() {
super.onResume();
// If the alarm was deleted at some point, disable snooze.
if (Alarms.getAlarm(getContentResolver(), mAlarm.id) == null) {
final Button snooze = (Button) findViewById(R.id.snooze);
snooze.setEnabled(false);
}
}
private void setTitle() {
final String label = mAlarm.getLabelOrDefault(this);
final TextView title = (TextView) findViewById(R.id.alertTitle);
title.setText(label);
}
// Attempt to snooze this alert.
private void snooze() {
// Do not snooze if the snooze button is disabled.
if (!findViewById(R.id.snooze).isEnabled()) {
dismiss(false);
return;
}
new AsyncTask<Void, Void, Integer>() {
final Calendar c = Calendar.getInstance();
@Override
protected Integer doInBackground(Void... params) {
final String snooze = getSharedPreferences(SettingsActivity.PREFERENCES, 0)
.getString(SettingsActivity.KEY_ALARM_SNOOZE, DEFAULT_SNOOZE);
final int snoozeMinutes = Integer.parseInt(snooze);
final long snoozeTime = System.currentTimeMillis() + 1000 * 60 * snoozeMinutes;
Alarms.saveSnoozeAlert(AlarmAlertFullScreen.this, mAlarm.id, snoozeTime);
// Get the display time for the snooze and update the
// notification.
c.setTimeInMillis(snoozeTime);
return snoozeMinutes;
}
@Override
protected void onPostExecute(Integer snoozeMinutes) {
// Append (snoozed) to the label.
String label = mAlarm.getLabelOrDefault(AlarmAlertFullScreen.this);
label = getString(R.string.alarm_notify_snooze_label, label);
// Notify the user that the alarm has been snoozed.
final Intent cancelSnooze = new Intent(AlarmAlertFullScreen.this,
AlarmReceiver.class);
cancelSnooze.setAction(Alarms.CANCEL_SNOOZE);
cancelSnooze.putExtra(Alarms.ALARM_ID, mAlarm.id);
final PendingIntent broadcast = PendingIntent.getBroadcast(
AlarmAlertFullScreen.this, mAlarm.id, cancelSnooze, 0);
final NotificationManager nm = getNotificationManager();
final Notification n = new Notification(R.drawable.ic_alarm_neutral, label, 0);
n.setLatestEventInfo(
AlarmAlertFullScreen.this,
label,
getString(R.string.alarm_notify_snooze_text,
Alarms.formatTime(AlarmAlertFullScreen.this, c)), broadcast);
n.flags |= Notification.FLAG_AUTO_CANCEL | Notification.FLAG_ONGOING_EVENT;
nm.notify(mAlarm.id, n);
final String displayTime = getString(R.string.alarm_alert_snooze_set, snoozeMinutes);
// Intentionally log the snooze time for debugging.
Log.v(displayTime);
// Display the snooze minutes in a toast.
Toast.makeText(AlarmAlertFullScreen.this, displayTime, Toast.LENGTH_LONG).show();
stopService(new Intent(Alarms.ALARM_ALERT_ACTION));
finish();
}
}.execute();
}
private void updateLayout() {
final LayoutInflater inflater = LayoutInflater.from(this);
setContentView(inflater.inflate(R.layout.alarm_alert, null));
/*
* snooze behavior: pop a snooze confirmation view, kick alarm manager.
*/
final Button snooze = (Button) findViewById(R.id.snooze);
snooze.requestFocus();
snooze.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(final View v) {
snooze();
}
});
/* dismiss button: close notification */
findViewById(R.id.dismiss).setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(final View v) {
dismiss(false);
}
});
/* Set the title from the passed in alarm */
setTitle();
}
}