ClockService.java :  » Clock » 24clock » com » alfray » a24clock » Android Open Source

Android Open Source » Clock » 24clock 
24clock » com » alfray » a24clock » ClockService.java
/*
 * Project: 24ClockWidget
 * Copyright (C) 2009 ralfoide gmail com,
 *
 *  This program 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.
 *
 *  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.alfray.a24clock;

import java.util.Arrays;

import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class ClockService extends Service {

    private static boolean DEBUG = true;
    public static String TAG = "ClockService";

    private static final Object kLock = ClockService.class;
    private static int[] sCachedIds = null;
    private static ClockThread sThread;

    private static final long DELAY_MS = 30 * 1000;

    @Override
    public IBinder onBind(Intent intent) {
        if (DEBUG) Log.d(TAG, "onBind");
        return null;
    }

    public static void start(Context context) {
        ClockThread ct;
        synchronized (kLock) {
            ct = sThread;
        }
        if (ct == null) {
            clearCachedIds();
            Intent i = new Intent(context, ClockService.class);
            context.startService(i);
        } else {
            ct.wakeUp();
        }
    }

    public static void stop() {
        synchronized (kLock) {
            if (sThread != null) {
                sThread.setCompleted();
                sThread = null;
            }
        }
    }

    public static void clearCachedIds() {
        synchronized (kLock) {
            sCachedIds = null;
        }
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);

        if (DEBUG) Log.d(TAG, "onStart, thread=" + ((sThread==null)?"none":sThread.toString()));

        synchronized (kLock) {
            if (sThread == null) {
                sThread = new ClockThread((ClockApp) getApplicationContext());
                sThread.start();
            } else {
                sThread.wakeUp();
            }
        }
    }

    @Override
    public void onDestroy() {
        // ask thread to stop
        stop();
        super.onDestroy();
    }

    private class ClockThread extends BaseThread {

        private ClockApp mApp;
        private AppWidgetManager mAWMan;
        private int mNotHomeDelay = 0;
        private long mLastMinute;

        public ClockThread(ClockApp app) {
            super("ClockThread");
            mApp = app;
            mAWMan = AppWidgetManager.getInstance(mApp);

            mLastMinute = 0;
        }

        @Override
        protected void runIteration() {

            long now = System.currentTimeMillis();

            if (!mApp.isScreenOn()) {
                if (DEBUG) Log.d(TAG, "loop, screen on=>off");
                // stop the thread if the screen is not running
                stopThreadInternal(false /*stopService*/);
                return;
            }

            long waitNext = 0;
            boolean needUpdate = false;

            if (mApp.currentTaskIsHome()) {
                mNotHomeDelay = 0;
                mLastMinute = 0;
                needUpdate = true;
                waitNext = 1000;

            } else {
                // check again in 10 seconds if not in home
                if (mNotHomeDelay < 30) mNotHomeDelay += 5;
                if (DEBUG) Log.d(TAG, "loop, not home, wait " + Integer.toString(mNotHomeDelay));

                // however we still perform an update every minute
                long minute = now / DELAY_MS;
                long nextMinute = DELAY_MS - (now - (minute * DELAY_MS));
                if (mLastMinute == 0) {
                    mLastMinute = minute;
                } else if (mLastMinute != minute) {
                    mLastMinute = minute;
                    needUpdate = true;
                }

                waitNext = mNotHomeDelay * 1000 /*ms*/;
                if (nextMinute < waitNext) {
                    if (DEBUG) Log.d(TAG, "minute wait: " + Long.toString(nextMinute));
                    waitNext = nextMinute;
                }
            }

            // perform an update
            if (needUpdate && mAWMan != null) {
                int[] ids;
                synchronized (kLock) {
                    ids = sCachedIds;
                }
                if (ids == null) {
                    ids = mAWMan.getAppWidgetIds(new ComponentName(mApp, ClockWidgetReceiver.class));
                    if (ids != null) {
                        synchronized (kLock) {
                            sCachedIds = ids;
                        }
                    }
                }
                if (ids != null) {
                    if (ids.length > 0) {
                        // Update remote view
                        mApp.updateRemoteView(mAWMan, ids);
                    }

                    if (DEBUG) Log.d(TAG, String.format("Ids[%d]: %s",
                                    ids.length,
                                    Arrays.toString(ids)));
                }

                if (ids == null || ids.length == 0) {
                    // No widgets to update... stop the thread AND service
                    stopThreadInternal(true /*stopService*/);
                    return;
                }
            }

            if (waitNext > 0) {
                waitNext -= System.currentTimeMillis() - now;
                if (DEBUG) Log.d(TAG, "waitNext: " + Long.toString(waitNext));
                waitFor(waitNext);
            }
        }

        private void stopThreadInternal(boolean stopService) {
            synchronized (kLock) {
                setCompleted();
                sThread = null;
                clearCachedIds();
                if (DEBUG) Log.d(TAG, "stopping update thread");
                if (stopService) {
                    ClockService.this.stopSelf();
                }
                return;
            }
        }

        @Override
        protected void endRun() {
            clearCachedIds();
            super.endRun();
        }
    }
}
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.