package de.tum.in.tumcampusapp.services; import android.app.AlarmManager; import android.app.IntentService; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.media.AudioManager; import android.os.Build; import android.provider.Settings; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Locale; import de.tum.in.tumcampusapp.auxiliary.Const; import de.tum.in.tumcampusapp.auxiliary.Utils; import de.tum.in.tumcampusapp.managers.CalendarManager; /** * Service used to silence the mobile during lectures */ public class SilenceService extends IntentService { /** * Interval in milliseconds to check for current lectures */ private static final int CHECK_INTERVAL = 60000 * 15; // 15 Minutes private static final int CHECK_DELAY = 10000; // 10 Seconds after Calendar changed private static final String SILENCE_SERVICE = "SilenceService"; /** * default init (run intent in new thread) */ public SilenceService() { super(SILENCE_SERVICE); } private static long getWaitDuration(String timeToEventString) { long timeToEvent = Long.MAX_VALUE; try { timeToEvent = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH).parse(timeToEventString).getTime(); } catch (ParseException e) { Utils.log(e, ""); } return Math.min(CHECK_INTERVAL, timeToEvent - System.currentTimeMillis() + CHECK_DELAY); } @Override public void onCreate() { super.onCreate(); Utils.log("SilenceService has started"); } @Override public void onDestroy() { super.onDestroy(); Utils.log("SilenceService has stopped"); } @Override protected void onHandleIntent(Intent intent) { //Abort, if the settings changed if (!Utils.getSettingBool(this, Const.SILENCE_SERVICE, false)) { // Don't schedule a new run, since the service is disabled return; } AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE); Intent newIntent = new Intent(this, SilenceService.class); PendingIntent pendingIntent = PendingIntent.getService(this, 0, newIntent, PendingIntent.FLAG_UPDATE_CURRENT); long startTime = System.currentTimeMillis(); long waitDuration = CHECK_INTERVAL; Utils.log("SilenceService enabled, checking for lectures …"); CalendarManager calendarManager = new CalendarManager(this); if (!calendarManager.hasLectures()) { Utils.logv("No lectures available"); alarmManager.set(AlarmManager.RTC, startTime + waitDuration, pendingIntent); return; } AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); Cursor cursor = calendarManager.getCurrentFromDb(); Utils.log("Current lectures: " + cursor.getCount()); if (cursor.getCount() == 0 || isDoNotDisturbMode()) { if (Utils.getInternalSettingBool(this, Const.SILENCE_ON, false) && !isDoNotDisturbMode()) { // default: old state Utils.log("set ringer mode to old state"); am.setRingerMode(Integer.parseInt( Utils.getSetting(this, Const.SILENCE_OLD_STATE, Integer.toString(AudioManager.RINGER_MODE_NORMAL)))); Utils.setInternalSetting(this, Const.SILENCE_ON, false); Cursor cursor2 = calendarManager.getNextCalendarItem(); if (cursor.getCount() != 0) { //Check if we have a "next" item in the database and update the refresh interval until then. Otherwise use default interval. // refresh when next event has started waitDuration = getWaitDuration(cursor2.getString(1)); } cursor2.close(); } } else { // remember old state if just activated ; in doubt dont change if (!Utils.getInternalSettingBool(this, Const.SILENCE_ON, true)) { Utils.setSetting(this, Const.SILENCE_OLD_STATE, am.getRingerMode()); } // if current lecture(s) found, silence the mobile Utils.setInternalSetting(this, Const.SILENCE_ON, true); // Set into silent mode String mode = Utils.getSetting(this, "silent_mode_set_to", "0"); if ("0".equals(mode)) { Utils.log("set ringer mode: vibration"); am.setRingerMode(AudioManager.RINGER_MODE_VIBRATE); } else { Utils.log("set ringer mode: silent"); am.setRingerMode(AudioManager.RINGER_MODE_SILENT); } // refresh when event has ended cursor.moveToFirst(); waitDuration = getWaitDuration(cursor.getString(3)); } cursor.close(); alarmManager.set(AlarmManager.RTC, startTime + waitDuration, pendingIntent); } /** * We can't and won't change the ringermodes, if the device is in DoNotDisturb mode. DnD requires * explicit user interaction, so we are out of the game until DnD is off again */ private boolean isDoNotDisturbMode() { // see https://stackoverflow.com/questions/31387137/android-detect-do-not-disturb-status //Settings.System.getInt(getContentResolver(), Settings.System.DO_NOT_DISTURB, 1); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { android.app.NotificationManager nm = (android.app.NotificationManager) getSystemService(NOTIFICATION_SERVICE); return (nm.getCurrentInterruptionFilter() != android.app.NotificationManager.INTERRUPTION_FILTER_ALL); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { try { int mode = Settings.Global.getInt(getContentResolver(), "zen_mode"); return mode != 0; } catch (Settings.SettingNotFoundException e) { return false; } } return false; } }