org.jamienicol.episodes.AutoRefreshHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.jamienicol.episodes.AutoRefreshHelper.java

Source

/*
 * Copyright (C) 2014 Jamie Nicol <jamie@thenicols.net>
 *
 * 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 org.jamienicol.episodes;

import android.app.AlarmManager;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v4.net.ConnectivityManagerCompat;
import android.util.Log;
import org.jamienicol.episodes.db.ShowsTable;
import org.jamienicol.episodes.db.ShowsProvider;
import org.jamienicol.episodes.RefreshShowUtil;

public class AutoRefreshHelper implements SharedPreferences.OnSharedPreferenceChangeListener {
    private static final String TAG = AutoRefreshHelper.class.getName();

    private static final String KEY_PREF_AUTO_REFRESH_ENABLED = "pref_auto_refresh_enabled";
    private static final String KEY_PREF_AUTO_REFRESH_PERIOD = "pref_auto_refresh_period";
    private static final String KEY_PREF_AUTO_REFRESH_WIFI_ONLY = "pref_auto_refresh_wifi_only";

    private static final String KEY_LAST_AUTO_REFRESH_TIME = "last_auto_refresh_time";

    private static AutoRefreshHelper instance;

    private final Context context;
    private final SharedPreferences preferences;

    public AutoRefreshHelper(Context context) {
        this.context = context;

        preferences = PreferenceManager.getDefaultSharedPreferences(context);
        preferences.registerOnSharedPreferenceChangeListener(this);
    }

    public static synchronized AutoRefreshHelper getInstance(Context context) {
        if (instance == null) {
            instance = new AutoRefreshHelper(context);
        }
        return instance;
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (key.equals(KEY_PREF_AUTO_REFRESH_ENABLED)) {
            onAutoRefreshEnabledChanged();
        } else if (key.equals(KEY_PREF_AUTO_REFRESH_PERIOD)) {
            onAutoRefreshPeriodChanged();
        } else if (key.equals(KEY_PREF_AUTO_REFRESH_WIFI_ONLY)) {
            onAutoRefreshWifiOnlyChanged();
        }
    }

    private void onAutoRefreshEnabledChanged() {
        rescheduleAlarm();
    }

    private void onAutoRefreshPeriodChanged() {
        rescheduleAlarm();
    }

    private void onAutoRefreshWifiOnlyChanged() {
        rescheduleAlarm();
    }

    private boolean getAutoRefreshEnabled() {
        return preferences.getBoolean(KEY_PREF_AUTO_REFRESH_ENABLED, false);
    }

    private long getAutoRefreshPeriod() {
        final String hours = preferences.getString(KEY_PREF_AUTO_REFRESH_PERIOD, "0");

        // convert hours to milliseconds
        return Long.parseLong(hours) * 60 * 60 * 1000;
    }

    private boolean getAutoRefreshWifiOnly() {
        return preferences.getBoolean(KEY_PREF_AUTO_REFRESH_WIFI_ONLY, false);
    }

    private long getPrevAutoRefreshTime() {
        return preferences.getLong(KEY_LAST_AUTO_REFRESH_TIME, 0);
    }

    private void setPrevAutoRefreshTime(long time) {
        final SharedPreferences.Editor editor = preferences.edit();
        editor.putLong(KEY_LAST_AUTO_REFRESH_TIME, time);
        editor.apply();
    }

    private boolean checkNetwork() {
        final ConnectivityManager connManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        final NetworkInfo net = connManager.getActiveNetworkInfo();

        final boolean connected = net != null && net.isConnected();
        final boolean metered = ConnectivityManagerCompat.isActiveNetworkMetered(connManager);
        final boolean unmeteredOnly = getAutoRefreshWifiOnly();

        final boolean okay = connected && !(metered && unmeteredOnly);

        Log.i(TAG, String.format("connected=%b, metered=%b, unmeteredOnly=%b, checkNetwork() %s.", connected,
                metered, unmeteredOnly, okay ? "passes" : "fails"));

        return okay;
    }

    public void rescheduleAlarm() {
        NetworkStateReceiver.disable(context);

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

        final Intent intent = new Intent(context, AutoRefreshHelper.Service.class);
        final PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);

        if (getAutoRefreshEnabled() && getAutoRefreshPeriod() != 0) {
            final long alarmTime = getPrevAutoRefreshTime() + getAutoRefreshPeriod();

            Log.i(TAG, String.format("Scheduling auto refresh alarm for %d.", alarmTime));

            alarmManager.set(AlarmManager.RTC, alarmTime, pendingIntent);
        } else {
            Log.i(TAG, "Cancelling auto refresh alarm.");

            alarmManager.cancel(pendingIntent);
        }
    }

    public static class Service extends IntentService {
        private static final String TAG = Service.class.getName();

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

        @Override
        protected void onHandleIntent(Intent intent) {
            final AutoRefreshHelper helper = AutoRefreshHelper.getInstance(getApplicationContext());

            if (helper.checkNetwork()) {
                Log.i(TAG, "Refreshing all shows.");

                final ContentResolver contentResolver = getContentResolver();
                final Cursor cursor = getShowsCursor(contentResolver);

                while (cursor.moveToNext()) {
                    final int showIdColumnIndex = cursor.getColumnIndexOrThrow(ShowsTable.COLUMN_ID);
                    final int showId = cursor.getInt(showIdColumnIndex);

                    RefreshShowUtil.refreshShow(showId, contentResolver);
                }

                helper.setPrevAutoRefreshTime(System.currentTimeMillis());
                helper.rescheduleAlarm();

            } else {
                NetworkStateReceiver.enable(this);
            }
        }

        private static Cursor getShowsCursor(ContentResolver contentResolver) {
            final String[] projection = { ShowsTable.COLUMN_ID };

            final Cursor cursor = contentResolver.query(ShowsProvider.CONTENT_URI_SHOWS, projection, null, null,
                    null);

            return cursor;
        }
    }

    public static class BootReceiver extends BroadcastReceiver {
        private static final String TAG = BootReceiver.class.getName();

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
                Log.i(TAG, "Boot received.");

                // ensure that the auto-refresh alarm is scheduled.
                AutoRefreshHelper.getInstance(context.getApplicationContext()).rescheduleAlarm();
            }
        }
    }

    // This receiver is disabled by default in the manifest.
    // It should only be enabled when it needed, and should be
    // disabled again straight afterwards.
    public static class NetworkStateReceiver extends BroadcastReceiver {
        private static final String TAG = NetworkStateReceiver.class.getName();

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i(TAG, "Network state change received.");

            final AutoRefreshHelper helper = AutoRefreshHelper.getInstance(context.getApplicationContext());

            if (helper.checkNetwork()) {
                helper.rescheduleAlarm();
            }
        }

        public static void enable(Context context) {
            final PackageManager packageManager = context.getPackageManager();

            final ComponentName receiver = new ComponentName(context, NetworkStateReceiver.class);

            if (packageManager
                    .getComponentEnabledSetting(receiver) != PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
                Log.i(TAG, "Enabling network state receiver.");
            }

            packageManager.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                    PackageManager.DONT_KILL_APP);
        }

        public static void disable(Context context) {
            final PackageManager packageManager = context.getPackageManager();

            final ComponentName receiver = new ComponentName(context, NetworkStateReceiver.class);

            if (packageManager
                    .getComponentEnabledSetting(receiver) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
                Log.i(TAG, "Disabling network state receiver.");
            }

            packageManager.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                    PackageManager.DONT_KILL_APP);
        }
    }
}