CurrentTimeTicker.java :  » App » codeswimmer-android-alarm-app » com » codeswimmer » android » apps » alarm » engine » Android Open Source

Android Open Source » App » codeswimmer android alarm app 
codeswimmer android alarm app » com » codeswimmer » android » apps » alarm » engine » CurrentTimeTicker.java
/**
 * CurrentTimeTicker.java
 * 
 * Copyright (c) 2009 codeswimmer
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
 * permit persons to whom the Software is furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the 
 * Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
 * Created on Nov 26, 2009
 */

package com.codeswimmer.android.apps.alarm.engine;

import java.util.Timer;
import java.util.TimerTask;

import android.util.Log;

/**
 * This class is responsible for broadcasting periodic notifications of the current time. Clients must implements the
 * {@link OnCurrentTimeTickListener} interface in order to receive update notifications.
 *
 * @author codeswimmer 
 */
public class CurrentTimeTicker {
    private static final String LOG_TAG = CurrentTimeTicker.class.getName();
    
    /**
     * The name of this timer task.
     */
    private static final String TIMER_NAME = "CurrentTimeTicker"; //$NON-NLS-1$
    
    /**
     * A default notification interval period.
     */
    public static final long DEFAULT_PERIOD = 1000;
    
    /**
     * Only one {@link OnCurrentTimeTickListener} at a time allowed.
     */
    private OnCurrentTimeTickListener listener;

    /**
     * Where we get our periodic updates from. 
     */
    private Timer ticker;
    
    /**
     * <code>true</code> indicates the ticker is currently firing notifications to its listener.
     */
    private boolean running;
    
    /**
     * Creates a new instance
     */
    public CurrentTimeTicker() {
    }

    /**
     * Starts notification of the current time.
     * <p>
     * Note:
     * <ul>
     * <li>
     * If a negative value for <code>period</code> is given, it will automatically be converted into the
     * {@link #DEFAULT_PERIOD} of {@value #DEFAULT_PERIOD}; a WARNING level log statement will be issued if this occurs.
     * </li>
     * <li>
     * If the {@link CurrentTimeTicker} is already running it will be stopped. A new {@link #ticker} will then be
     * created.</li>
     * </ul>
     * 
     * @param listener
     *            The client who will be receiving update notifications. Must be non-<code>null</code>.
     * @param period
     *            How often, in milliseconds, the ticker is triggered.
     * @throws IllegalArgumentException
     *             If <code>listener</code> is <code>null</code>.
     */
    public void start(OnCurrentTimeTickListener listener, long ... period) throws IllegalArgumentException {
        if (listener == null) {
            throw new IllegalArgumentException("listener cannot be null"); //$NON-NLS-1$
        }
        
        this.listener = listener;
        
        // Use the given interval period; if it wasn't provided use the default.
        long interval = period.length > 0 ? period[0] : DEFAULT_PERIOD;
        
        // Ensure we don't end up with a negative value for the interval
        if (interval < 0) {
            Log.w(LOG_TAG, "negative value of period coerced to default"); //$NON-NLS-1$
            interval = DEFAULT_PERIOD;
        }
        
        Log.d(LOG_TAG, String.format("creating timer with interval of %d ms", interval)); //$NON-NLS-1$
        
        // If we're already running, stop the existing ticker before creating a new one.
        if (running) {
            Log.d(LOG_TAG, "ticker is currently running; stopping before creating new one"); //$NON-NLS-1$
            stop();
        }
        
        // We want the timer to run as a daemon
        ticker = new Timer(TIMER_NAME, true);
        ticker.schedule(new TickTimerTask(), 0, interval);
        running = true;
    }
    
    /**
     * Stops notification of the current time.
     */
    public void stop() {
        Log.d(LOG_TAG, String.format("stopping; ticker != null: %s", (ticker != null))); //$NON-NLS-1$
        if (ticker != null) {
            ticker.purge();
            ticker.cancel();
            running = false;
        }
    }
    
    /**
     * If we have a listener, fire notification of the current time. If not, no need in continuing.
     */
    private void fireOnCurrentTimeTick() {
        if (listener != null) {
            listener.onCurrentTimeTick(System.currentTimeMillis());
        }
    }
    
    /**
     * @return The current value of {@link #running}.
     */
    public boolean isRunning() {
        return running;
    }
    
    /**
     * This interface is used for communicating notifications from the {@link CurrentTimeTicker} to its interested 
     * listener. 
     */
    public static interface OnCurrentTimeTickListener {
        /**
         * Notification that the current time has been updated.
         * 
         * @param currentTime
         *            The current date and time as the number of milliseconds since January 1, 1970, midnight GMT.
         */
        public void onCurrentTimeTick(long currentTime);
    }
    
    /**
     * This class receives notifications from the {@link Timer} when the timer has triggered.
     */
    private class TickTimerTask extends TimerTask {
        /** {@inheritDoc} */
        @Override
        public void run() {
            fireOnCurrentTimeTick();
        }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.