Back to project page volumescheduler.
The source code is released under:
GNU General Public License
If you think the Android project volumescheduler listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright (c) 2014 RuneCasters IT Solutions. *//ww w .j av a2s. c o m * This file is part of VolumeScheduler. * * VolumeScheduler is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VolumeScheduler is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VolumeScheduler. If not, see <http://www.gnu.org/licenses/>. */ package au.com.runecasters.volumescheduler.service; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; import android.media.AudioManager; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.provider.CalendarContract.Events; import android.util.Log; import au.com.runecasters.volumescheduler.model.DatabaseHelper; import au.com.runecasters.volumescheduler.model.SchedulerRule; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Locale; public class VolumeSchedulerService extends Service { public static final String TAG = "Service"; private static final List<String> EVENT_PROJECTION = new ArrayList<String>() {{ add(Events._ID); add(Events.CALENDAR_ID); add(Events.TITLE); add(Events.EVENT_LOCATION); add(Events.DESCRIPTION); add(Events.AVAILABILITY); add(Events.DTSTART); add(Events.DTEND); }}; private AudioManager mAudioManager; private AlarmManager mAlarmManager; private PendingIntent mPendingIntent; private List<SchedulerRule> mRuleList; private HandlerThread mHandlerThread; private Handler mHandler; private Runnable mRunTriggersRunnable = new Runnable() { @Override public void run() { runTriggers(); } }; private SharedPreferences mSharedPrefs; private long mCurrentRule; private int mCurrentRulePriority; private boolean mIgnorePriority; private int mNormVolRingtone; private int mNormVolNotification; private int mNormVolMedia; private int mNormVolAlarm; private int mNormRingerMode; public VolumeSchedulerService() { } @Override public void onCreate() { super.onCreate(); createBackgroundThread(); updateTriggers(this); mIgnorePriority = false; mSharedPrefs = getSharedPreferences("VolumeScheduler", MODE_PRIVATE); mCurrentRule = mSharedPrefs.getLong("currentRule", -1); mCurrentRulePriority = mSharedPrefs.getInt("currentRulePriority", -1); mNormVolRingtone = mSharedPrefs.getInt("normVolRingtone", -1); mNormVolNotification = mSharedPrefs.getInt("normVolNotification", -1); mNormVolMedia = mSharedPrefs.getInt("normVolMedia", -1); mNormVolAlarm = mSharedPrefs.getInt("normVolAlarm", -1); mNormRingerMode = mSharedPrefs.getInt("normRingerMode", -1); mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE); } @Override public void onDestroy() { super.onDestroy(); mHandlerThread.quit(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null) { String intentAction = intent.getAction(); if(intentAction.equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED) || intentAction.equals(VolumeSchedulerReceiver.START_TRIGGERS)) { if (mAlarmManager == null && mPendingIntent == null) { setTriggers(this); } } else if (intentAction.equals(VolumeSchedulerReceiver.STOP_TRIGGERS)) { removeTriggers(); } else if (intentAction.equals(VolumeSchedulerReceiver.RUN_TRIGGERS)) { mHandler.post(mRunTriggersRunnable); } else if (intentAction.equals(VolumeSchedulerReceiver.UPDATE_TRIGGERS)) { updateTriggers(this); } } return START_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } private void createBackgroundThread() { mHandlerThread = new HandlerThread("VolumeSchedulerBGThread"); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); } public void setTriggers(Context context) { Intent alarmIntent = new Intent(context, VolumeSchedulerReceiver.class); alarmIntent.setAction(VolumeSchedulerReceiver.RUN_TRIGGERS); mPendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT); mAlarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); mAlarmManager.set(AlarmManager.RTC, Calendar.getInstance().getTimeInMillis(), mPendingIntent); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.MILLISECOND, 0); calendar.set(Calendar.SECOND, 0); mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 60000, mPendingIntent); Log.i(TAG, "Service started"); } public void removeTriggers() { if (mAlarmManager != null && mPendingIntent != null) { mAlarmManager.cancel(mPendingIntent); mAlarmManager = null; mPendingIntent = null; } Log.i(TAG, "Service stopped"); deactivateRule(); stopSelf(); } public void updateTriggers(Context context) { DatabaseHelper dbHelper = DatabaseHelper.getInstance(context); mRuleList = dbHelper.getRules(); mIgnorePriority = true; Log.i(TAG, "Trigger rules updated from database"); } public void runTriggers() { // Log.v(TAG, "Running triggers"); int listLength = mRuleList.size(); boolean activeRuleStillExists = false; long oldCurrentRule = mCurrentRule; for (int priority = 1; priority <= listLength; priority++) { if (priority <= mCurrentRulePriority || mCurrentRulePriority < 0 || mIgnorePriority) { SchedulerRule rule = mRuleList.get(priority-1); if (rule.getRuleID() == mCurrentRule) activeRuleStillExists = true; int ruleType = rule.getRuleType(); if (ruleType == SchedulerRule.CALENDAR_RULE) { runCalendarEventTrigger(rule, priority); } else if (ruleType == SchedulerRule.TIME_RULE) { runTimeDayRuleTrigger(rule, priority); } } } if (!activeRuleStillExists && mCurrentRule == oldCurrentRule && mCurrentRule >= 0) deactivateRule(); mIgnorePriority = false; } private void runCalendarEventTrigger(SchedulerRule rule, int priority) { // Log.v(TAG, "Running CalendarEventTrigger on rule " + rule); Cursor eventCursor = getContentResolver().query(Events.CONTENT_URI, EVENT_PROJECTION.toArray(new String[EVENT_PROJECTION.size()]), Events.CALENDAR_ID + " = " + rule.getCalendarID(), null, null); boolean triggered = false; long currentTime = System.currentTimeMillis(); while (eventCursor.moveToNext()) { long startTime = eventCursor.getLong(EVENT_PROJECTION.indexOf(Events.DTSTART)); long endTime = eventCursor.getLong(EVENT_PROJECTION.indexOf(Events.DTEND)); String eventTitle = eventCursor.getString(EVENT_PROJECTION.indexOf(Events.TITLE)); String eventLoc = eventCursor.getString(EVENT_PROJECTION.indexOf(Events.EVENT_LOCATION)); String eventDesc = eventCursor.getString(EVENT_PROJECTION.indexOf(Events.DESCRIPTION)); // Because Google apparently stores empty strings as null instead of "" in their events table eventTitle = eventTitle == null ? "" : eventTitle.toUpperCase(Locale.US); eventLoc = eventLoc == null ? "" : eventLoc.toUpperCase(Locale.US); eventDesc = eventDesc == null ? "" : eventDesc.toUpperCase(Locale.US); int eventAvail = eventCursor.getInt(EVENT_PROJECTION.indexOf(Events.AVAILABILITY)); if (currentTime >= startTime && currentTime < endTime && (eventTitle.contains(rule.getSearchTitle().toUpperCase(Locale.US)) && eventLoc.contains(rule.getSearchLocation().toUpperCase(Locale.US)) && eventDesc.contains(rule.getSearchDesc().toUpperCase(Locale.US)) && (rule.getAvailability() < 0 || eventAvail == rule.getAvailability()))) { triggered = true; if (rule.getRuleID() != mCurrentRule || mIgnorePriority) { // Log.v(TAG, "Calendar Rule \"" + rule + "\" Activated"); activateRule(rule, priority); } mIgnorePriority = false; } } if (!triggered && rule.getRuleID() == mCurrentRule) { // Log.v(TAG, "Calendar Rule \"" + rule + "\" Deactivated"); deactivateRule(); } eventCursor.close(); } private void runTimeDayRuleTrigger(SchedulerRule rule, int priority) { // Log.v(TAG, "Running TimeDayRuleTrigger on rule " + rule); Calendar currentTime = Calendar.getInstance(); if (rule.getDaysOfWeek()[currentTime.get(Calendar.DAY_OF_WEEK) - 1]) { int[] startTime = rule.getStartTime(); int[] endTime = rule.getEndTime(); int currentMinuteOfDay = currentTime.get(Calendar.HOUR_OF_DAY) * 60 + currentTime.get(Calendar.MINUTE); int startMinuteOfDay = startTime[0] * 60 + startTime[1]; int endMinuteOfDay = endTime[0] * 60 + endTime[1]; // Check for overnight rule - times straddling midnight boolean overnightRule = endMinuteOfDay < startMinuteOfDay; if ((startMinuteOfDay <= currentMinuteOfDay && endMinuteOfDay > currentMinuteOfDay) || (overnightRule && !(startMinuteOfDay > currentMinuteOfDay && endMinuteOfDay <= currentMinuteOfDay)) || startMinuteOfDay == endMinuteOfDay) { if (rule.getRuleID() != mCurrentRule || mIgnorePriority) { // Log.v(TAG, "Time/Day Rule \"" + rule + "\" Activated"); activateRule(rule, priority); } mIgnorePriority = false; } else { if (rule.getRuleID() == mCurrentRule) { // Log.v(TAG, "Time/Day Rule \"" + rule + "\" Deactivated"); deactivateRule(); } } } } private void activateRule(SchedulerRule rule, int priority) { deactivateRule(); // Deactivate any current rule SharedPreferences.Editor sharedPrefsEditor = mSharedPrefs.edit(); if (rule.changingRingtone() && mNormVolNotification < 0) { mNormVolRingtone = mAudioManager.getStreamVolume(AudioManager.STREAM_RING); sharedPrefsEditor.putInt("normVolRingtone", mNormVolRingtone); } if (rule.changingNotification() && mNormVolNotification < 0) { mNormVolNotification = mAudioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION); sharedPrefsEditor.putInt("normVolNotification", mNormVolNotification); } if (rule.changingMedia() && mNormVolMedia < 0) { mNormVolMedia = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); sharedPrefsEditor.putInt("normVolMedia", mNormVolMedia); } if (rule.changingAlarm() && mNormVolAlarm < 0) { mNormVolAlarm = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM); sharedPrefsEditor.putInt("normVolAlarm", mNormVolAlarm); } if (rule.isVibrate() && mNormRingerMode < 0) { mNormRingerMode = mAudioManager.getRingerMode(); sharedPrefsEditor.putInt("normRingerMode", mNormRingerMode); } mCurrentRule = rule.getRuleID(); mCurrentRulePriority = priority; sharedPrefsEditor.putLong("currentRule", mCurrentRule); sharedPrefsEditor.putInt("currentRulePriority", mCurrentRulePriority); sharedPrefsEditor.commit(); if (rule.getVolRingtone() == 0 && rule.getVolNotification() == 0) { int vibrateSetting = rule.isVibrate() ? AudioManager.RINGER_MODE_VIBRATE : AudioManager.RINGER_MODE_SILENT; mAudioManager.setRingerMode(vibrateSetting); } else { if (rule.changingRingtone()) { mAudioManager.setStreamVolume(AudioManager.STREAM_RING, rule.getVolRingtone(), 0); } if (rule.changingNotification()) { mAudioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, rule.getVolNotification(), 0); } } if (rule.changingMedia()) { mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, rule.getVolMedia(), 0); } if (rule.changingAlarm()) { mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, rule.getVolAlarm(), 0); } } private void deactivateRule() { SharedPreferences.Editor sharedPrefsEditor = mSharedPrefs.edit(); mCurrentRule = -1; mCurrentRulePriority = -1; sharedPrefsEditor.remove("currentRule"); sharedPrefsEditor.remove("currentRulePriority"); if (mNormRingerMode >= 0) { mAudioManager.setRingerMode(mNormRingerMode); mNormRingerMode = -1; sharedPrefsEditor.remove("normVolRingtone"); } if (mNormVolRingtone >= 0) { mAudioManager.setStreamVolume(AudioManager.STREAM_RING, mNormVolRingtone, 0); mNormVolRingtone = -1; sharedPrefsEditor.remove("normRingerMode"); } if (mNormVolNotification >= 0) { mAudioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, mNormVolNotification, 0); mNormVolNotification = -1; sharedPrefsEditor.remove("normVolNotification"); } if (mNormVolMedia >= 0) { mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mNormVolMedia, 0); mNormVolMedia = -1; sharedPrefsEditor.remove("normVolMedia"); } if (mNormVolAlarm >= 0) { mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, mNormVolAlarm, 0); mNormVolAlarm = -1; sharedPrefsEditor.remove("normVolAlarm"); } sharedPrefsEditor.commit(); // Log.v(TAG, "All rules deactivated"); } private void changeVolume(int stream, int newVol) { // Because Android doesn't seem to always respect setStreamVolume while (mAudioManager.getStreamVolume(stream) != newVol) { mAudioManager.setStreamVolume(stream, newVol, 0); } } public static class VolumeSchedulerReceiver extends BroadcastReceiver { public static final String START_TRIGGERS = "au.com.runecasters.volumescheduler.service.START_TRIGGERS"; public static final String STOP_TRIGGERS = "au.com.runecasters.volumescheduler.service.STOP_TRIGGERS"; public static final String RUN_TRIGGERS = "au.com.runecasters.volumescheduler.service.RUN_TRIGGERS"; public static final String UPDATE_TRIGGERS = "au.com.runecasters.volumescheduler.service.UPDATE_TRIGGERS"; @Override public void onReceive(Context context, Intent intent) { intent.setClass(context, VolumeSchedulerService.class); context.startService(intent); } } }