All Downloads are FREE. Search and download functionalities are using the official Maven repository.

co.easimart.provider.RemoteArtSource Maven / Gradle / Ivy

package co.easimart.provider;

import android.content.Context;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.PowerManager;
import android.util.Log;

/**
 * A convenience subclass of {@link ArtSource} that's specifically designed for use by
 * art sources that fetch artwork metadata remotely. Sources that publish remote images but who
 * publish {@link Artwork} objects based on local data shouldnt need to use this subclass.
 *
 * 

The only required method is {@link #onTryUpdate(int)}, which replaces the normal * {@link #onUpdate(int)} callback method. * *

This class automatically does the following in {@link #onUpdate(int)}: * *

    *
  • Check that the device is connected to the network. If not, schedule a retry using * the exponential backoff method and retry when the network becomes available.
  • *
  • Acquire a wakelock (held for a maximum of 30 seconds) and release it when * {@link #onTryUpdate(int)} finishes.
  • *
  • Automatically schedule retries using the exponential backoff method when * {@link #onTryUpdate(int)} throws a {@link RetryException}.
  • *
* *

Applications with sources based on {@link RemoteArtSource} must add the following * permissions: * *

 * <uses-permission android:name="android.permission.INTERNET" />
 * <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 * <uses-permission android:name="android.permission.WAKE_LOCK" />
 * 
*/ public abstract class RemoteArtSource extends ArtSource { private static final String TAG = RemoteArtSource.class.getSimpleName(); private static final int FETCH_WAKELOCK_TIMEOUT_MILLIS = 30 * 1000; private static final int INITIAL_RETRY_DELAY_MILLIS = 10 * 1000; private static final String PREF_RETRY_ATTEMPT = "retry_attempt"; private String mName; /** * Remember to call this constructor from an empty constructor! */ public RemoteArtSource(String name) { super(name); mName = name; } /** * Subclasses should implement this method (instead of {@link #onUpdate(int)}) and attempt an * update, throwing a {@link RetryException} in case of a retryable error such as an HTTP * 500-level server error or a read error. */ protected abstract void onTryUpdate(int reason) throws RetryException; /** * Subclasses of {@link RemoteArtSource} should implement {@link #onTryUpdate(int)} * instead of this method. */ @Override protected void onUpdate(int reason) { PowerManager pwm = (PowerManager) getSystemService(POWER_SERVICE); PowerManager.WakeLock lock = pwm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mName); lock.acquire(FETCH_WAKELOCK_TIMEOUT_MILLIS); SharedPreferences sp = getSharedPreferences(); try { NetworkInfo ni = ((ConnectivityManager) getSystemService( Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo(); if (ni == null || !ni.isConnected()) { Log.d(TAG, "No network connection; not attempting to fetch update, id=" + mName); throw new RetryException(); } // In anticipation of update success, reset update attempt // Any alarms will be cleared before onUpdate is called sp.edit().remove(PREF_RETRY_ATTEMPT).apply(); setWantsNetworkAvailable(false); // Attempt an update onTryUpdate(reason); } catch (RetryException e) { Log.w(TAG, "Error fetching, scheduling retry, id=" + mName); // Schedule retry with exponential backoff, starting with INITIAL_RETRY... seconds later int retryAttempt = sp.getInt(PREF_RETRY_ATTEMPT, 0); scheduleUpdate( System.currentTimeMillis() + (INITIAL_RETRY_DELAY_MILLIS << retryAttempt)); sp.edit().putInt(PREF_RETRY_ATTEMPT, retryAttempt + 1).apply(); setWantsNetworkAvailable(true); } finally { if (lock.isHeld()) { lock.release(); } } } @Override protected void onDisabled() { super.onDisabled(); getSharedPreferences().edit().remove(PREF_RETRY_ATTEMPT).commit(); setWantsNetworkAvailable(false); } @Override protected void onNetworkAvailable() { super.onNetworkAvailable(); if (getSharedPreferences().getInt(PREF_RETRY_ATTEMPT, 0) > 0) { // This is a retry; attempt an update. onUpdate(UPDATE_REASON_OTHER); } } /** * An exception indicating that the {@link RemoteArtSource} would like to retry * a failed update attempt. */ public static class RetryException extends Exception { public RetryException() { } public RetryException(Throwable cause) { super(cause); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy