ca.zadrox.dota2esportticker.service.ReminderAlarmService.java Source code

Java tutorial

Introduction

Here is the source code for ca.zadrox.dota2esportticker.service.ReminderAlarmService.java

Source

/*
 * Copyright 2014 Nicholas Liu
 *
 * 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 ca.zadrox.dota2esportticker.service;

import android.app.AlarmManager;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;

import ca.zadrox.dota2esportticker.R;
import ca.zadrox.dota2esportticker.data.MatchContract;
import ca.zadrox.dota2esportticker.ui.MatchActivity;
import ca.zadrox.dota2esportticker.ui.MatchDetailActivity;
import ca.zadrox.dota2esportticker.util.PrefUtils;
import ca.zadrox.dota2esportticker.util.TimeUtils;

import static ca.zadrox.dota2esportticker.util.LogUtils.LOGD;

/**
 * Created by Acco on 11/12/2014.
 */
public class ReminderAlarmService extends IntentService {

    private static final String TAG = ReminderAlarmService.class.getSimpleName();

    public static final String ACTION_NOTIFY_MATCH = "ca.zadrox.dota2esportticker.action.NOTIFY_MATCH";
    public static final String ACTION_SCHEDULE_ALL_STARRED_MATCHES = "ca.zadrox.dota2esportticker.action.SCHEDULE_ALL_STARRED_MATCHES";
    public static final String ACTION_SCHEDULE_STARRED_MATCH = "ca.zadrox.dota2esportticker.action.SCHEDULE_STARRED_MATCH";
    public static final String ACTION_UNSCHEDULE_STARRED_MATCH = "ca.zadrox.dota2esportticker.action.UNSCHEDULE_STARRED_MATCH";
    public static final String ACTION_NOTIFY_DEBUG = "ca.zadrox.dota2esportticker.action.NOTIFY_DEBUG";
    public static final String EXTRA_MATCH_ID = "ca.zadrox.dota2esportticker.extra.MATCH_ID";
    public static final String EXTRA_MATCH_START = "ca.zadrox.dota2esportticker.extra.MATCH_START";

    public static final int NOTIFICATION_ID = 100;

    private static final int NOTIFICATION_LED_ON_MS = 200;
    private static final int NOTIFICATION_LED_OFF_MS = 5000;
    private static final int NOTIFICATION_ARGB_COLOR = 0xFFDD0000;

    private static final long MILLI_TEN_MINUTES = 600000;

    private static final long UNDEFINED_ALARM_OFFSET = -1;
    private static final long UNDEFINED_VALUE = -1;

    public static final String KEY_MATCH_ID = "match-id";

    public ReminderAlarmService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        final String action = intent.getAction();

        if (ACTION_NOTIFY_DEBUG.equals(action)) {
            notifyDebug();
            return;
        }

        if (ACTION_SCHEDULE_ALL_STARRED_MATCHES.equals(action)) {
            scheduleAllStarredMatches();
            return;
        }

        final long matchId = intent.getLongExtra(ReminderAlarmService.EXTRA_MATCH_ID, UNDEFINED_VALUE);

        if (matchId == UNDEFINED_VALUE) {
            return;
        }

        if (ACTION_NOTIFY_MATCH.equals(action)) {
            notifyMatch(matchId);
        }

        final long matchStartTime = intent.getLongExtra(ReminderAlarmService.EXTRA_MATCH_START, UNDEFINED_VALUE);

        if (matchStartTime == UNDEFINED_VALUE) {
            return;
        }

        if (ACTION_SCHEDULE_STARRED_MATCH.equals(action)) {
            scheduleAlarm(matchId, matchStartTime);
        }

        if (ACTION_UNSCHEDULE_STARRED_MATCH.equals(action)) {
            cancelAlarm(matchId, matchStartTime);
        }
    }

    private void cancelAlarm(final long matchId, final long matchStart) {
        final long currentTime = TimeUtils.getUTCTime();

        LOGD(TAG, "Unscheduling Alarm");

        if (currentTime > matchStart) {
            LOGD(TAG, "wat.");
            return;
        }

        final Intent notifIntent = new Intent(ACTION_NOTIFY_MATCH, null, this, ReminderAlarmService.class);

        notifIntent.setData(
                new Uri.Builder().authority("ca.zadrox.dota2esportticker").path(String.valueOf(matchId)).build());

        notifIntent.putExtra(ReminderAlarmService.EXTRA_MATCH_ID, matchId);
        notifIntent.putExtra(ReminderAlarmService.EXTRA_MATCH_START, matchStart);

        PendingIntent pi = PendingIntent.getService(this, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        final AlarmManager am = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);

        am.cancel(pi);
    }

    private void scheduleAlarm(final long matchId, final long matchStart) {

        final long currentTime = TimeUtils.getUTCTime();
        LOGD(TAG, "Schedule Alarm");

        if (currentTime > matchStart) {
            LOGD(TAG, "CurrentTime > matchStart");
            return;
        }

        long alarmTime = matchStart - MILLI_TEN_MINUTES;

        final Intent notifIntent = new Intent(ACTION_NOTIFY_MATCH, null, this, ReminderAlarmService.class);

        notifIntent.setData(
                new Uri.Builder().authority("ca.zadrox.dota2esportticker").path(String.valueOf(matchId)).build());

        notifIntent.putExtra(ReminderAlarmService.EXTRA_MATCH_ID, matchId);
        notifIntent.putExtra(ReminderAlarmService.EXTRA_MATCH_START, matchStart);

        PendingIntent pi = PendingIntent.getService(this, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        final AlarmManager am = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);

        am.set(AlarmManager.RTC_WAKEUP, alarmTime, pi);
    }

    private void notifyDebug() {
        final Resources res = getResources();
        String contentTitle = "Debug Notification";

        String contentText;

        long currentTime = TimeUtils.getUTCTime();
        long matchStart = TimeUtils.getUTCTime() + 60000;

        int minutesLeft = (int) (matchStart - currentTime + 59000) / 60000;
        if (minutesLeft < 2 && minutesLeft >= 0) {
            minutesLeft = 1;
        }

        if (minutesLeft < 0) {
            contentText = "debugNotification";
        } else {
            contentText = "debugNotification";
        }

        NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(this).setContentTitle(contentTitle)
                .setContentText(contentText).setColor(res.getColor(R.color.theme_primary))
                .setTicker(contentTitle + " is about to start.")
                .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
                .setLights(NOTIFICATION_ARGB_COLOR, NOTIFICATION_LED_ON_MS, NOTIFICATION_LED_OFF_MS)
                .setSmallIcon(R.drawable.ic_notification).setPriority(Notification.PRIORITY_DEFAULT)
                .setAutoCancel(true);

        NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        nm.notify(NOTIFICATION_ID, notifBuilder.build());
    }

    private void notifyMatch(long matchId) {
        if (!PrefUtils.shouldShowMatchReminders(this)) {
            return;
        }

        final ContentResolver cr = getContentResolver();

        Cursor c = cr.query(MatchContract.SeriesEntry.CONTENT_URI, MatchDetailQuery.PROJECTION,
                SESSION_ID_WHERE_CLAUSE, new String[] { String.valueOf(matchId) }, null);

        if (!c.moveToNext()) {
            return;
        }

        Intent baseIntent = new Intent(this, MatchActivity.class);
        baseIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        TaskStackBuilder taskBuilder = TaskStackBuilder.create(this).addNextIntent(baseIntent);

        Intent matchIntent = new Intent(this, MatchDetailActivity.class);
        matchIntent.putExtra(MatchDetailActivity.ARGS_GG_MATCH_ID, matchId);
        taskBuilder.addNextIntent(matchIntent);

        PendingIntent pi = taskBuilder.getPendingIntent(0, PendingIntent.FLAG_CANCEL_CURRENT);

        final Resources res = getResources();
        String contentTitle = c.getString(MatchDetailQuery.TEAM_ONE_NAME) + " vs "
                + c.getString(MatchDetailQuery.TEAM_TWO_NAME);

        String contentText;

        long currentTime = TimeUtils.getUTCTime();
        long matchStart = c.getLong(MatchDetailQuery.DATE_TIME);

        int minutesLeft = (int) (matchStart - currentTime + 59000) / 60000;
        if (minutesLeft < 2 && minutesLeft >= 0) {
            minutesLeft = 1;
        }

        if (minutesLeft < 0) {
            contentText = "is scheduled to start now. (" + c.getString(MatchDetailQuery.TOURNAMENT_NAME) + ")";
        } else {
            contentText = "is scheduled to start in " + minutesLeft + " min. ("
                    + c.getString(MatchDetailQuery.TOURNAMENT_NAME) + ")";
        }

        NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(this).setContentTitle(contentTitle)
                .setContentText(contentText).setColor(res.getColor(R.color.theme_primary))
                .setTicker(contentTitle + " is about to start.")
                .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
                .setLights(NOTIFICATION_ARGB_COLOR, NOTIFICATION_LED_ON_MS, NOTIFICATION_LED_OFF_MS)
                .setSmallIcon(R.drawable.ic_notification).setContentIntent(pi)
                .setPriority(Notification.PRIORITY_DEFAULT).setAutoCancel(true);

        NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        nm.notify(NOTIFICATION_ID, notifBuilder.build());
    }

    private void scheduleAllStarredMatches() {
        final ContentResolver cr = getContentResolver();

        final Cursor c = cr.query(MatchContract.ReminderEntry.CONTENT_URI,
                new String[] { MatchContract.SeriesEntry.TABLE_NAME + "." + MatchContract.ReminderEntry._ID,
                        MatchContract.ReminderEntry.COLUMN_SET_REMINDER,
                        MatchContract.SeriesEntry.COLUMN_DATETIME },
                REMINDER_ID_WHERE_CLAUSE, null, null);

        if (c == null) {
            return;
        }

        while (c.moveToNext()) {
            final long matchId = c.getInt(0);
            final boolean reminderSet = c.getInt(1) > 0;
            final long dateTime = c.getLong(2);

            LOGD(TAG, "getUTCTime: " + TimeUtils.getUTCTime() + " cursorTime: " + dateTime);

            if (reminderSet) {
                scheduleAlarm(matchId, dateTime);
            }
        }
    }

    public interface MatchDetailQuery {
        String[] PROJECTION = { MatchContract.SeriesEntry._ID, MatchContract.SeriesEntry.COLUMN_TEAM_ONE_NAME,
                MatchContract.SeriesEntry.COLUMN_TEAM_TWO_NAME, MatchContract.SeriesEntry.COLUMN_TOURNAMENT_NAME,
                MatchContract.SeriesEntry.COLUMN_DATETIME };

        int TEAM_ONE_NAME = 1;
        int TEAM_TWO_NAME = 2;
        int TOURNAMENT_NAME = 3;
        int DATE_TIME = 4;
    }

    private static String SESSION_ID_WHERE_CLAUSE = MatchContract.SeriesEntry.TABLE_NAME + "."
            + MatchContract.SeriesEntry._ID + " = ? ";
    private static String REMINDER_ID_WHERE_CLAUSE = MatchContract.ReminderEntry.TABLE_NAME + "."
            + MatchContract.ReminderEntry.COLUMN_SET_REMINDER + " != 0";
}