package com.nbs.client.assassins.services; import java.util.UUID; import com.googlecode.androidannotations.annotations.EService; import com.nbs.client.assassins.R; import com.nbs.client.assassins.controllers.MainActivity_; import com.nbs.client.assassins.models.App; import com.nbs.client.assassins.models.Match; import com.nbs.client.assassins.models.Repository; import com.nbs.client.assassins.utils.Bus; import android.app.AlarmManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.os.IBinder; import android.support.v4.app.NotificationCompat; import android.text.format.Time; import android.util.Log; @EService public class NotificationService extends Service { private static final String TAG = "NotificationService"; private static final long ONE_MINUTE = 60*1000; public static final String SET_MATCH_REMINDER_ALARMS = "com.nbs.client.assassins.SET_MATCH_REMINDER_ALARMS"; public static final String CANCEL_MATCH_ALARMS = "com.nbs.client.assassins.CANCEL_MATCH_ALARMS"; public static final String WAIT_FOR_MATCH_START = "com.nbs.client.assassins.WAIT_FOR_MATCH_START"; private IntentFilter intentFilter; private BroadcastReceiver intentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if(intent != null) { String type = intent.getAction(); if(type.equals(PushNotifications.PLAYER_JOINED_MATCH)) { String msg = intent.getStringExtra("player") + " joined match " + intent.getStringExtra("match") +"."; NotificationService.postNotification(context, UUID.randomUUID().hashCode(), R.drawable.crosshairs, "Hunted", msg, new Bundle()); } else if(type.equals(PushNotifications.MATCH_START)) { String msg = "The match has started."; NotificationService.postNotification(context, UUID.randomUUID().hashCode(), R.drawable.crosshairs, "Hunted", msg, new Bundle()); } else if(type.equals(PushNotifications.MATCH_END)) { String winner = intent.getStringExtra("winner"); Repository model = App.getRepo(); if(winner != null && winner.equals(model.getUser().getUsername())) { winner = "you"; } String msg = "The hunt is over. " + winner + " won."; NotificationService.postNotification(context, UUID.randomUUID().hashCode(), R.drawable.crosshairs, "Hunted", msg, new Bundle()); } else if(type.equals(PushNotifications.PLAYER_ELIMINATED)) { String msg = intent.getStringExtra("player") + " eliminated."; NotificationService.postNotification(context, UUID.randomUUID().hashCode(), R.drawable.crosshairs, "Hunted", msg, new Bundle()); } /* else if(type.equals(PushNotifications.INVITE)) { NotificationService.postNotification(context, UUID.randomUUID().hashCode(), R.drawable.crosshairs, TAG, PushNotifications.INVITE, new Bundle()); } else if(type.equals(PushNotifications.ACHIEVEMENT)) { NotificationService.postNotification(context, UUID.randomUUID().hashCode(), R.drawable.crosshairs, TAG, PushNotifications.ACHIEVEMENT, new Bundle()); }*/ } } }; @Override public void onCreate() { Log.d(TAG, "onCreate"); intentFilter = new IntentFilter(); intentFilter.addAction(PushNotifications.PLAYER_JOINED_MATCH); intentFilter.addAction(PushNotifications.MATCH_START); intentFilter.addAction(PushNotifications.MATCH_END); intentFilter.addAction(PushNotifications.PLAYER_ELIMINATED); intentFilter.addAction(PushNotifications.INVITE); intentFilter.addAction(PushNotifications.ACHIEVEMENT); Bus.register(this, intentReceiver, intentFilter); } private void cancelMatchReminderAlarms(Context context) { AlarmManager alarmMngr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); alarmMngr.cancel(prepareNotificationServicePendingIntent(context, PushNotifications.MATCH_COUNTDOWN)); alarmMngr.cancel(prepareLocationServicePendingIntent(context, PushNotifications.MATCH_COUNTDOWN)); } private static PendingIntent prepareLocationServicePendingIntent(Context context, String action) { Intent matchReminderIntent = new Intent(context, LocationService_.class) .setAction(action); return PendingIntent.getService(context, 0, matchReminderIntent, PendingIntent.FLAG_UPDATE_CURRENT); } private static PendingIntent prepareNotificationServicePendingIntent(Context context, String action) { Intent matchStartingIntent = new Intent(context, NotificationService_.class) .setAction(action); return PendingIntent.getService(context, 0, matchStartingIntent, PendingIntent.FLAG_UPDATE_CURRENT); } public static void setMatchReminderAlarms(Context context, Long matchStartTimeUTC) { if(matchStartTimeUTC != null && matchStartTimeUTC > 0) { Time t = new Time(); t.set(matchStartTimeUTC); Log.d(TAG, "setMatchReminderAlarms(context, "+t.toString()+")"); long postNotifReminderTime = matchStartTimeUTC-ONE_MINUTE; AlarmManager alarmMngr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); //if the match has already begun, it will fire immediately alarmMngr.set(AlarmManager.RTC_WAKEUP, postNotifReminderTime, prepareLocationServicePendingIntent(context, PushNotifications.MATCH_COUNTDOWN)); alarmMngr.set(AlarmManager.RTC_WAKEUP, postNotifReminderTime, prepareNotificationServicePendingIntent(context, PushNotifications.MATCH_COUNTDOWN)); alarmMngr.set(AlarmManager.RTC_WAKEUP, matchStartTimeUTC, prepareNotificationServicePendingIntent(context, PushNotifications.MATCH_START)); Log.d(TAG, "registered alarm"); } } public static void postNotification(Context c, int id, int res, String title, String message, Bundle extras) { try { //the intent to launch when the notification is touched Intent notificationIntent = new Intent(c, MainActivity_.class); //TODO why does this not start the app on notification pressed? if(extras != null) notificationIntent.putExtras(extras); NotificationCompat.Builder builder = new NotificationCompat.Builder(c) .setSmallIcon(res) .setContentTitle(title) .setContentText(message) .setAutoCancel(true) .setContentIntent(PendingIntent .getActivity(c, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT)); // Add as notification NotificationManager manager = (NotificationManager) c.getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(id, builder.build()); } catch (IllegalArgumentException e) { Log.v(TAG, e.getMessage()); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand("+intent+")"); String action = intent != null ? intent.getAction() : null; Repository model = App.getRepo(); if(action != null) { if(action.equals(PushNotifications.MATCH_START)) { Bus.post(this, PushNotifications.MATCH_START); } else if(action.equals(PushNotifications.MATCH_COUNTDOWN)) { postNotification(this, UUID.randomUUID().hashCode(), R.drawable.crosshairs, "Hunted", "A match is about to begin.", intent.getExtras()); } //Match starts at specific time else if(action.equals(NotificationService.SET_MATCH_REMINDER_ALARMS)) { for (Match m : model.getPendingMatches()) { setMatchReminderAlarms(this, m.startTime); } } //Manually started match else if(action.equals(NotificationService.WAIT_FOR_MATCH_START)) { postNotification(this, UUID.randomUUID().hashCode(), R.drawable.crosshairs, "Hunted", "Waiting for match to begin...", intent.getExtras()); } else if(action.equals(NotificationService.CANCEL_MATCH_ALARMS)) { cancelMatchReminderAlarms(this); } //TODO: handle other notifications through onStartService rather than // calling the static postNotification method } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.d(TAG, "onDestroy"); Bus.unregister(this, intentReceiver); } @Override public IBinder onBind(Intent intent) { return null; } }