Java tutorial
/* * Copyright (C) 2012 ukasz Wasylkowski * * 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 pl.zajecia.cw3; import java.io.IOException; import java.util.Calendar; import java.util.Random; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.app.WallpaperManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.os.IBinder; import android.support.v4.content.LocalBroadcastManager; /** * MainService class, handling wallpaper changing alarms, settings and broadcasts. */ public class MainService extends Service { /** The Constant TAG. */ @SuppressWarnings("unused") private static final String TAG = "MainService"; //Message for handling settings updates /** The Constant MESSAGE_UPDATE_SETTINGS. */ public static final String MESSAGE_UPDATE_SETTINGS = "MessageUpdateSettings"; //Message to set next alarm. Receiver after //successful wallpaper change /** The Constant MESSAGE_SET_NEXT_ALARM. */ public static final String MESSAGE_SET_NEXT_ALARM = "MessageSetNextAlarm"; /** The Constant INTENT_ALARM. */ private static final String INTENT_ALARM = "pl.zajecia.cw2.Alarm"; // BroadcastReceiver for handling alarm (so changing wallpaper) /** The m alarm broadcast receiver. */ private AlarmBroadcastReceiver mAlarmBroadcastReceiver; /** The m battery change broadcast receiver. */ private BroadcastReceiver mBatteryChangeBroadcastReceiver; // Broadcast receiver for handling local messages // Like updating settings or setting next alarm /** The m local broadcast receiver. */ private BroadcastReceiver mLocalBroadcastReceiver; //settings variables /** The m interval value. */ private int mIntervalValue; /** The m interval type. */ private int mIntervalType; /** The m next image. */ private int mNextImage; /** The m photos. */ private String[] mPhotos; /** The m change during sleep. */ private boolean mChangeDuringSleep; /** The m change on screen on. */ private boolean mChangeOnScreenOn; /** The m disable on battery low. */ private boolean mDisableOnBatteryLow; /** The m alarm broadcast receiver enabled. */ private boolean mAlarmBroadcastReceiverEnabled; /** The m alarm m. */ private AlarmManager mAlarmM; @Override public void onCreate() { loadSettings(); mLocalBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { handleLocalBroadcast(intent); } }; mBatteryChangeBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { handleBatteryChange(intent); } }; IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(MESSAGE_SET_NEXT_ALARM); intentFilter.addAction(MESSAGE_UPDATE_SETTINGS); //mAlarmBroadcastReceiver is implemented in separate file mAlarmBroadcastReceiver = new AlarmBroadcastReceiver(); LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mLocalBroadcastReceiver, intentFilter); mAlarmM = (AlarmManager) getSystemService(Context.ALARM_SERVICE); registerAlarmReceiver(); registerOtherReceivers(); setNextAlarm(); } /** * Registers alarm receiver, handling options * (adding intent filters for SCREEN_ON etc). */ private void registerAlarmReceiver() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(INTENT_ALARM); if (mChangeOnScreenOn) { intentFilter.addAction(Intent.ACTION_SCREEN_ON); } registerReceiver(mAlarmBroadcastReceiver, intentFilter); mAlarmBroadcastReceiverEnabled = true; } /** * Registers other receivers, which receiving doesn't * mean changing wallpaper. */ private void registerOtherReceivers() { if (mDisableOnBatteryLow) { IntentFilter i = new IntentFilter(); i.addAction(Intent.ACTION_BATTERY_LOW); i.addAction(Intent.ACTION_BATTERY_OKAY); registerReceiver(mBatteryChangeBroadcastReceiver, i); } } /** * Unregisters all receivers, for before service destroys itself. */ private void unregisterAllReceivers() { try { unregisterReceiver(mAlarmBroadcastReceiver); mAlarmBroadcastReceiverEnabled = false; if (mDisableOnBatteryLow) { unregisterReceiver(mBatteryChangeBroadcastReceiver); } } catch (IllegalArgumentException e) { // Do nothing, as we probably just tried to unregister // not registered broadcast receiver return; } } /** * Handles local broadcast, like updating settings or setting next alarm. * * @param intent the intent */ private void handleLocalBroadcast(Intent intent) { String action = intent.getAction(); if (action == MESSAGE_SET_NEXT_ALARM) { setNextAlarm(); } else if (action == MESSAGE_UPDATE_SETTINGS) { updateSettings(); } } /** * Handles battery state change broadcast, * like stopping receiver when battery low. * * @param intent the intent */ private void handleBatteryChange(Intent intent) { if (intent.getAction() == Intent.ACTION_BATTERY_LOW) { if (mDisableOnBatteryLow) { unregisterReceiver(mAlarmBroadcastReceiver); } } else if (intent.getAction() == Intent.ACTION_BATTERY_OKAY) { if (!mAlarmBroadcastReceiverEnabled) { registerAlarmReceiver(); } } } /** * Sets the next alarm, based on wakelock options and interval value. */ private void setNextAlarm() { Intent intent = new Intent(INTENT_ALARM); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); int addType; switch (mIntervalType) { case MainActivity.INTERVAL_SECONDS: addType = Calendar.SECOND; break; case MainActivity.INTERVAL_MINUTES: addType = Calendar.MINUTE; break; case MainActivity.INTERVAL_HOURS: addType = Calendar.HOUR; break; case MainActivity.INTERVAL_DAYS: addType = Calendar.DAY_OF_YEAR; break; default: addType = MainActivity.INTERVAL_HOURS; } Calendar time = Calendar.getInstance(); time.setTimeInMillis(System.currentTimeMillis()); time.add(addType, mIntervalValue); if (mChangeDuringSleep) { mAlarmM.set(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pendingIntent); } else { mAlarmM.set(AlarmManager.RTC, time.getTimeInMillis(), pendingIntent); } } /* (non-Javadoc) * @see android.app.Service#onDestroy() */ @Override public void onDestroy() { unregisterAllReceivers(); try { LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mLocalBroadcastReceiver); } catch (IllegalArgumentException e) { //Do nothing, broadcast not registered //Only when no images on the list } super.onDestroy(); } /** * Stops current alarm, for when we stop service * and want to cancel all pending broadcasts. */ private void stopAlarm() { AlarmManager alarmM = (AlarmManager) getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(INTENT_ALARM); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); alarmM.cancel(pendingIntent); } /** * Loads settings from shared preferences * and resets alarm (with new settings). */ private void loadSettings() { SharedPreferences settings = getApplicationContext().getSharedPreferences(MainActivity.PREFERENCES, 0); mPhotos = getSharedPreferences(MainActivity.PREFERENCES, 0).getString(MainActivity.FILE_PATHS, "") .split(";"); if (mPhotos.length < 2) { stopSelf(); } boolean randomOrder = settings.getBoolean("randomOrder", true); if (randomOrder) { mNextImage = -1; } else { mNextImage = 0; } mChangeDuringSleep = settings.getBoolean("changeDuringSleep", false); mChangeOnScreenOn = settings.getBoolean("changeOnScreenOn", true); mDisableOnBatteryLow = settings.getBoolean("changeOnBatteryLow", false); mIntervalValue = settings.getInt("intervalValue", Integer.parseInt(MainActivity.DEFAULT_INTERVAL)); mIntervalType = settings.getInt("intervalType", 1); } /** * Updates classes variables to meet application settings * Should be called when user changes options (like download interval). */ public void updateSettings() { stopAlarm(); unregisterAllReceivers(); loadSettings(); registerAlarmReceiver(); registerOtherReceivers(); setNextAlarm(); } /* (non-Javadoc) * @see android.app.Service#onBind(android.content.Intent) */ @Override public IBinder onBind(Intent intent) { return null; //We don't provide binding } /** * AlarmBroadcastReceiver class, handles receiving INTENT_ALARM broadcast, * thus setting up new wallpaper. */ private class AlarmBroadcastReceiver extends BroadcastReceiver { @SuppressWarnings("unused") private static final String TAG = "AlarmBroadcastReceiverClass"; @Override public void onReceive(Context context, Intent intent) { String[] paths = mPhotos; int nextImage = mNextImage; /* * Handle random/non-random wallpaper change */ if (nextImage == -1) { Random random = new Random(); nextImage = random.nextInt(paths.length); } else { mNextImage = (mNextImage + 1) % paths.length; } String path = paths[nextImage]; WallpaperManager wm = WallpaperManager.getInstance(context); try { wm.setBitmap(BitmapUtils.getCorrectlyOrientedImage(path)); } catch (IOException e) { return; //Couldn't get picture, we should try again } /* * send request for new wallpaper change */ LocalBroadcastManager.getInstance(context) .sendBroadcast(new Intent(MainService.MESSAGE_SET_NEXT_ALARM)); } } }