pl.zajecia.cw3.MainService.java Source code

Java tutorial

Introduction

Here is the source code for pl.zajecia.cw3.MainService.java

Source

/*
 * 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));
        }
    }

}