Android Open Source - timesync Time Sync Service






From Project

Back to project page timesync.

License

The source code is released under:

Apache License

If you think the Android project timesync listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package me.tatarka.timesync.lib;
// www .ja  v  a  2  s  .c o  m
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.provider.Settings;

import java.util.Map;
import java.util.Random;

import static me.tatarka.timesync.lib.MathUtil.randomInRange;

public class TimeSyncService extends IntentService {
    private static final String TYPE = "type";
    private static final int TYPE_START = 0;
    private static final int TYPE_STOP = 1;
    private static final int TYPE_SYNC = 2;
    private static final int TYPE_UPDATE = 3;
    private static final int TYPE_SYNC_INEXACT = 4;
    private static final int TYPE_NETWORK_BACK = 5;
    private static final int TYPE_POWER_CHANGED = 6;

    private static final String NAME = "name";
    private static final String POWER_CONNECTED = "power_connected";

    private static final long BASE_RETRY_SPAN = 500;
    private static final long MIN_RETRY_CAP = 5 * TimeSync.Config.SECONDS;

    private TimeSyncPreferences prefs;
    private long seed;
    private boolean powerConnected;

    private Map<String, TimeSync> listeners;

    public TimeSyncService() {
        super(TimeSyncService.class.getName());
    }

    @Override
    public void onCreate() {
        super.onCreate();

        prefs = new TimeSyncPreferences(this);
        seed = findOrCreateSeed(prefs);
        powerConnected = prefs.isPowerConnected();

        listeners = TimeSyncParser.parseListeners(this);
    }

    static void start(Context context) {
        context.startService(getStartIntent(context));
    }

    static void stop(Context context) {
        context.startService(getStopIntent(context));
    }

    static void sync(Context context, String name) {
        context.startService(getSyncIntent(context, name));
    }

    static void syncInexact(Context context, String name) {
        context.startService(getSyncInexactIntent(context, name));
    }

    static void update(Context context, String name) {
        context.startService(getUpdateIntent(context, name));
    }

    static void networkBack(Context context) {
        context.startService(getNetworkBackIntent(context));
    }

    static void powerChanged(Context context, boolean connected) {
        context.startService(getPowerChangedIntent(context, connected));
    }

    static Intent getStartIntent(Context context) {
        Intent intent = new Intent(context, TimeSyncService.class);
        intent.putExtra(TYPE, TYPE_START);
        return intent;
    }

    static Intent getStopIntent(Context context) {
        Intent intent = new Intent(context, TimeSyncService.class);
        intent.putExtra(TYPE, TYPE_STOP);
        return intent;
    }

    static Intent getSyncIntent(Context context, String name) {
        Intent intent = new Intent(context, TimeSyncService.class);
        intent.setData(Uri.parse("timesync://" + name));
        intent.putExtra(TYPE, TYPE_SYNC);
        intent.putExtra(NAME, name);
        return intent;
    }

    static Intent getSyncInexactIntent(Context context, String name) {
        Intent intent = new Intent(context, TimeSyncService.class);
        intent.setData(Uri.parse("timesync://" + name));
        intent.putExtra(TYPE, TYPE_SYNC_INEXACT);
        intent.putExtra(NAME, name);
        return intent;
    }

    static Intent getUpdateIntent(Context context, String name) {
        Intent intent = new Intent(context, TimeSyncService.class);
        intent.putExtra(TYPE, TYPE_UPDATE);
        intent.putExtra(NAME, name);
        return intent;
    }

    static Intent getNetworkBackIntent(Context context) {
        Intent intent = new Intent(context, TimeSyncService.class);
        intent.putExtra(TYPE, TYPE_NETWORK_BACK);
        return intent;
    }

    static Intent getPowerChangedIntent(Context context, boolean connected) {
        Intent intent = new Intent(context, TimeSyncService.class);
        intent.putExtra(TYPE, TYPE_POWER_CHANGED);
        intent.putExtra(POWER_CONNECTED, connected);
        return intent;
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        switch (intent.getIntExtra(TYPE, 0)) {
            case TYPE_START: {
                onHandleStart();
                break;
            }
            case TYPE_STOP: {
                onHandleStop();
                break;
            }
            case TYPE_SYNC: {
                String name = intent.getStringExtra(NAME);
                TimeSync listener = listeners.get(name);
                if (listener != null) {
                    onHandleSync(listener);
                }
                break;
            }
            case TYPE_SYNC_INEXACT: {
                String name = intent.getStringExtra(NAME);
                TimeSync listener = listeners.get(name);
                if (listener != null) {
                    onHandleSyncInexact(listener);
                }
                break;
            }
            case TYPE_UPDATE: {
                String name = intent.getStringExtra(NAME);
                TimeSync listener = listeners.get(name);
                if (listener != null) {
                    onHandleUpdate(listener);
                }
                break;
            }
            case TYPE_NETWORK_BACK: {
                AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
                for (TimeSync listener : listeners.values()) {
                    add(alarmManager, listener);
                }
                break;
            }
            case TYPE_POWER_CHANGED: {
                boolean connected = intent.getBooleanExtra(POWER_CONNECTED, false);
                onHandlePowerChanged(connected);
                // TimeSyncPowerReceiver is a WakefulBroadcastReceiver, so make sure to release the lock.
                TimeSyncPowerReceiver.completeWakefulIntent(intent);
                break;
            }
        }
    }

    private void onHandleStart() {
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        removeAll(alarmManager);
        for (TimeSync listener : listeners.values()) {
            add(alarmManager, listener);
        }
        TimeSyncPowerReceiver.enable(this);
        TimeSyncBootReceiver.enable(this);
    }

    private void onHandleStop() {
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        removeAll(alarmManager);
        TimeSyncNetworkReceiver.disable(this);
        TimeSyncPowerReceiver.disable(this);
        TimeSyncBootReceiver.disable(this);
    }

    private void add(AlarmManager alarmManager, TimeSync listener) {
        if (!listener.config().enabled()) return;

        TimeSync.Config config = listener.config();
        long span = config.every();
        if (span > 0) {
            long time = calculateTime(span, config.range());
            setAlarm(alarmManager, listener.getName(), time);
        }
    }

    private void setAlarm(AlarmManager alarmManager, String name, long time) {
        if (time > 0) {
            int alarmType = powerConnected ? AlarmManager.RTC_WAKEUP : AlarmManager.RTC;
            Intent intent = getSyncIntent(this, name);
            PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
            alarmManager.cancel(pendingIntent);
            alarmManager.set(alarmType, time, pendingIntent);
        }
    }

    private void onHandleSync(TimeSync listener) {
        if (!listener.config().enabled()) return;

        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();

        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

        if (netInfo != null && netInfo.isConnectedOrConnecting()) {
            try {
                listener.onSync(this);
                prefs.setLastFailedTimeSpan(listener.getName(), 0);
                add(alarmManager, listener);
            } catch (Exception e) {
                onHandleFailureSyncError(alarmManager, listener);
            }
        } else {
            onHandleFailureNoNetwork(alarmManager, listener);
        }
    }

    private void onHandleSyncInexact(TimeSync listener) {
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        long range = listener.config().range();
        long time = calculateTime(0, range);
        remove(alarmManager, listener);
        setAlarm(alarmManager, listener.getName(), time);
    }

    private void onHandleUpdate(TimeSync listener) {
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        remove(alarmManager, listener);
        add(alarmManager, listener);
    }

    private void onHandleFailureNoNetwork(AlarmManager alarmManager, TimeSync listener) {
        removeAll(alarmManager);
        TimeSyncNetworkReceiver.enable(this);
    }

    private void onHandleFailureSyncError(AlarmManager alarmManager, TimeSync listener) {
        TimeSync.Config config = listener.config();
        long span = config.every();
        if (span < MIN_RETRY_CAP) span = MIN_RETRY_CAP;
        long lastRetrySpan = prefs.getLastFailedTimeSpan(listener.getName());
        long retrySpan = lastRetrySpan == 0 ? BASE_RETRY_SPAN : lastRetrySpan * 2;
        if (retrySpan > span) retrySpan = span;

        prefs.setLastFailedTimeSpan(listener.getName(), retrySpan);
        long time = calculateTime(retrySpan, config.range());
        setAlarm(alarmManager, listener.getName(), time);
    }

    private void removeAll(AlarmManager alarmManager) {
        for (TimeSync listener : listeners.values()) {
            remove(alarmManager, listener);
        }
    }

    private void remove(AlarmManager alarmManager, TimeSync listener) {
        Intent intent = getSyncIntent(this, listener.getClass().getName());
        PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
        alarmManager.cancel(pendingIntent);
        pendingIntent.cancel();
    }

    private long calculateTime(long timeSpan, long range) {
        long currentTime = System.currentTimeMillis();
        long exactTime = EventCalculator.getNextEvent(currentTime, timeSpan);
        long rangeOffset = randomInRange(seed, 0, range);
        return exactTime + rangeOffset;
    }

    private void onHandlePowerChanged(boolean connected) {
        powerConnected = connected;
        prefs.setPowerConnected(connected);
        // Remove and re-add alarms to take into account the state change.
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        removeAll(alarmManager);
        for (TimeSync listener : listeners.values()) {
            add(alarmManager, listener);
        }
    }

    private long findOrCreateSeed(TimeSyncPreferences prefs) {
        long seed = prefs.getSeed();
        if (seed != 0) return seed;

        // Use Random to evenly distribute values
        seed = new Random(Settings.Secure.ANDROID_ID.hashCode()).nextLong();
        prefs.setSeed(seed);

        return seed;
    }

}




Java Source Code List

me.tatarka.timesync.app.MainActivity.java
me.tatarka.timesync.app.MyApplication.java
me.tatarka.timesync.app.RandomSync.java
me.tatarka.timesync.lib.BooleanFormatException.java
me.tatarka.timesync.lib.EventCalculator.java
me.tatarka.timesync.lib.MathUtil.java
me.tatarka.timesync.lib.ReceiverUtils.java
me.tatarka.timesync.lib.SuperNotCalledException.java
me.tatarka.timesync.lib.TimeSyncBootReceiver.java
me.tatarka.timesync.lib.TimeSyncNetworkReceiver.java
me.tatarka.timesync.lib.TimeSyncParser.java
me.tatarka.timesync.lib.TimeSyncPowerReceiver.java
me.tatarka.timesync.lib.TimeSyncPreferences.java
me.tatarka.timesync.lib.TimeSyncProxy.java
me.tatarka.timesync.lib.TimeSyncService.java
me.tatarka.timesync.lib.TimeSync.java