Java tutorial
/* * 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"; }