com.better.alarm.presenter.alert.AlarmAlertReceiver.java Source code

Java tutorial

Introduction

Here is the source code for com.better.alarm.presenter.alert.AlarmAlertReceiver.java

Source

/*
 * Copyright (C) 2007 The Android Open Source Project
 * Copyright (C) 2012 Yuriy Kulikov yuriy.kulikov.87@gmail.com
 *
 * 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.better.alarm.presenter.alert;

import java.util.Calendar;

import android.app.KeyguardManager;
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.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.text.format.DateFormat;

import com.better.alarm.R;
import com.better.alarm.model.AlarmsManager;
import com.better.alarm.model.interfaces.Alarm;
import com.better.alarm.model.interfaces.AlarmNotFoundException;
import com.better.alarm.model.interfaces.IAlarmsManager;
import com.better.alarm.model.interfaces.Intents;
import com.better.alarm.model.interfaces.PresentationToModelIntents;
import com.better.alarm.presenter.TransparentActivity;
import com.github.androidutils.logger.Logger;

/**
 * Glue class: connects AlarmAlert IntentReceiver to AlarmAlert activity. Passes
 * through Alarm ID.
 */
public class AlarmAlertReceiver extends BroadcastReceiver {

    private static final String ACTION_CANCEL_NOTIFICATION = "AlarmAlertReceiver.ACTION_CANCEL_NOTIFICATION";
    private static final String DM12 = "E h:mm aa";
    private static final String DM24 = "E kk:mm";
    private static final int NOTIFICATION_OFFSET = 1000;
    Context mContext;
    NotificationManager nm;
    IAlarmsManager alarmsManager;
    Alarm alarm;

    @Override
    public void onReceive(final Context context, final Intent intent) {
        mContext = context;
        alarmsManager = AlarmsManager.getAlarmsManager();
        nm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        String action = intent.getAction();
        int id = intent.getIntExtra(Intents.EXTRA_ID, -1);
        try {
            if (id != -1) {
                alarm = alarmsManager.getAlarm(id);
            }

            if (action.equals(Intents.ALARM_ALERT_ACTION) || action.equals(Intents.ALARM_PREALARM_ACTION)) {
                // our alarm fired again, remove snooze notification
                nm.cancel(id + NOTIFICATION_OFFSET);
                onAlert(alarm);

            } else if (action.equals(Intents.ALARM_DISMISS_ACTION)) {
                nm.cancel(id);
                nm.cancel(id + NOTIFICATION_OFFSET);

            } else if (action.equals(Intents.ACTION_CANCEL_SNOOZE)) {
                nm.cancel(id);
                nm.cancel(id + NOTIFICATION_OFFSET);

            } else if (action.equals(Intents.ALARM_SNOOZE_ACTION)) {
                nm.cancel(id);
                onSnoozed(id);

            } else if (action.equals(Intents.ACTION_SOUND_EXPIRED)) {
                onSoundExpired(id);

            } else if (action.equals(ACTION_CANCEL_NOTIFICATION)) {
                alarmsManager.dismiss(alarm);
            }
        } catch (AlarmNotFoundException e) {
            Logger.getDefaultLogger().d("Alarm not found");
            nm.cancel(id);
            nm.cancel(id + NOTIFICATION_OFFSET);
        }
    }

    private void onAlert(Alarm alarm) {
        int id = alarm.getId();

        /* Close dialogs and window shade */
        Intent closeDialogs = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        mContext.sendBroadcast(closeDialogs);

        // Decide which activity to start based on the state of the
        // keyguard - is the screen locked or not.
        Class<? extends AlarmAlertFullScreen> c = AlarmAlert.class;
        KeyguardManager km = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
        if (km.inKeyguardRestrictedInputMode()) {
            // Use the full screen activity to unlock the screen.
            c = AlarmAlertFullScreen.class;
        }

        // Trigger a notification that, when clicked, will show the alarm
        // alert dialog. No need to check for fullscreen since this will always
        // be launched from a user action.
        Intent notify = new Intent(mContext, c);
        notify.putExtra(Intents.EXTRA_ID, id);
        PendingIntent pendingNotify = PendingIntent.getActivity(mContext, id, notify, 0);
        PendingIntent pendingSnooze = PresentationToModelIntents.createPendingIntent(mContext,
                PresentationToModelIntents.ACTION_REQUEST_SNOOZE, id);
        PendingIntent pendingDismiss = PresentationToModelIntents.createPendingIntent(mContext,
                PresentationToModelIntents.ACTION_REQUEST_DISMISS, id);

        //@formatter:off
        Notification status = new NotificationCompat.Builder(mContext)
                .setContentTitle(alarm.getLabelOrDefault(mContext))
                .setContentText(mContext.getString(R.string.alarm_notify_text))
                .setSmallIcon(R.drawable.stat_notify_alarm)
                // setFullScreenIntent to show the user AlarmAlert dialog at the same time 
                // when the Notification Bar was created.
                .setFullScreenIntent(pendingNotify, true)
                // setContentIntent to show the user AlarmAlert dialog  
                // when he will click on the Notification Bar.
                .setContentIntent(pendingNotify).setOngoing(true)
                .addAction(R.drawable.ic_action_snooze, mContext.getString(R.string.alarm_alert_snooze_text),
                        pendingSnooze)
                .addAction(R.drawable.ic_action_dismiss, mContext.getString(R.string.alarm_alert_dismiss_text),
                        pendingDismiss)
                .setDefaults(Notification.DEFAULT_LIGHTS).build();
        //@formatter:on

        // Send the notification using the alarm id to easily identify the
        // correct notification.
        nm.notify(id, status);
    }

    private void onSnoozed(int id) {

        // What to do, when a user clicks on the notification bar
        Intent cancelSnooze = new Intent(mContext, AlarmAlertReceiver.class);
        cancelSnooze.setAction(ACTION_CANCEL_NOTIFICATION);
        cancelSnooze.putExtra(Intents.EXTRA_ID, id);
        PendingIntent pCancelSnooze = PendingIntent.getBroadcast(mContext, id, cancelSnooze, 0);

        // When button Reschedule is clicked, the TransparentActivity with
        // TimePickerFragment to set new alarm time is launched
        Intent reschedule = new Intent(mContext, TransparentActivity.class);
        reschedule.putExtra(Intents.EXTRA_ID, id);
        PendingIntent pendingReschedule = PendingIntent.getActivity(mContext, id, reschedule, 0);

        PendingIntent pendingDismiss = PresentationToModelIntents.createPendingIntent(mContext,
                PresentationToModelIntents.ACTION_REQUEST_DISMISS, id);

        String label = alarm.getLabelOrDefault(mContext);

        //@formatter:off
        Notification status = new NotificationCompat.Builder(mContext)
                // Get the display time for the snooze and update the notification.
                .setContentTitle(mContext.getString(R.string.alarm_notify_snooze_label, label))
                .setContentText(mContext.getString(R.string.alarm_notify_snooze_text, formatTimeString()))
                .setSmallIcon(R.drawable.stat_notify_alarm).setContentIntent(pCancelSnooze).setOngoing(true)
                .addAction(R.drawable.ic_action_reschedule_snooze,
                        mContext.getString(R.string.alarm_alert_reschedule_text), pendingReschedule)
                .addAction(R.drawable.ic_action_dismiss, mContext.getString(R.string.alarm_alert_dismiss_text),
                        pendingDismiss)
                .setDefaults(Notification.DEFAULT_LIGHTS).build();
        //@formatter:on

        // Send the notification using the alarm id to easily identify the
        // correct notification.
        nm.notify(id + NOTIFICATION_OFFSET, status);
    }

    private String formatTimeString() {
        String format = android.text.format.DateFormat.is24HourFormat(mContext) ? DM24 : DM12;
        Calendar calendar = alarm.getSnoozedTime();
        String timeString = (String) DateFormat.format(format, calendar);
        return timeString;
    }

    private void onSoundExpired(int id) {
        Intent dismissAlarm = new Intent(mContext, AlarmAlertReceiver.class);
        dismissAlarm.setAction(ACTION_CANCEL_NOTIFICATION);
        dismissAlarm.putExtra(Intents.EXTRA_ID, id);
        PendingIntent intent = PendingIntent.getBroadcast(mContext, id, dismissAlarm, 0);
        // Update the notification to indicate that the alert has been
        // silenced.
        String label = alarm.getLabelOrDefault(mContext);
        int autoSilenceMinutes = Integer
                .parseInt(PreferenceManager.getDefaultSharedPreferences(mContext).getString("auto_silence", "10"));
        String text = mContext.getString(R.string.alarm_alert_alert_silenced, autoSilenceMinutes);

        Notification.Builder nb = new Notification.Builder(mContext);
        nb.setAutoCancel(true);
        nb.setSmallIcon(R.drawable.stat_notify_alarm);
        nb.setWhen(Calendar.getInstance().getTimeInMillis());
        nb.setContentIntent(intent);
        nb.setContentTitle(label);
        nb.setContentText(text);
        nb.setTicker(text);
        Notification n = nb.getNotification();

        // We have to cancel the original notification since it is in the
        // ongoing section and we want the "killed" notification to be a plain
        // notification.
        nm.cancel(id);
        nm.notify(id, n);
    }
}