Permalink
Browse files

Done S10.03-FirebaseJobDispatcher

  • Loading branch information...
GinaHsu committed Feb 9, 2018
1 parent d6bf25e commit ff2c8e5b9c2ebe3dbdccef748b64e7d9da7ccdf6
@@ -29,6 +29,7 @@ dependencies {
compile 'com.android.support:preference-v7:25.0.1'
// TODO (1) Add the FirebaseJobDispatcher dependency to the project
compile 'com.firebase:firebase-jobdispatcher:0.5.0'
// Instrumentation dependencies use androidTestCompile
// (as opposed to testCompile for local unit tests run in the JVM)
@@ -64,7 +64,14 @@
android:exported="false" />
<!-- TODO (8) Declare SunshineFirebaseJobService as a service in the manifest -->
<!-- This is the Service declaration used in conjunction with FirebaseJobDispatcher -->
<service android:name=".sync.SunshineFirebaseJobService"
android:exported="false">
<!-- TODO (9) Declare an intent filter with the action ACTION_EXECUTE -->
<intent-filter>
<action android:name = "com.firebase.jobdispatcher.ACTION_EXECUTE"/>
</intent-filter>
</service>
</application>
</manifest>
@@ -13,13 +13,79 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.sunshine.sync;
// TODO (2) Make sure you've imported the jobdispatcher.JobService, not job.JobService
import android.content.Context;
import android.os.AsyncTask;
import com.firebase.jobdispatcher.Job;
import com.firebase.jobdispatcher.JobParameters;
import com.firebase.jobdispatcher.JobService;
import com.firebase.jobdispatcher.RetryStrategy;
// TODO (3) Add a class called SunshineFirebaseJobService that extends jobdispatcher.JobService
public class SunshineFirebaseJobService extends JobService {
// TODO (4) Declare an ASyncTask field called mFetchWeatherTask
private AsyncTask<Void, Void, Void> mFetchWeatherTask;
// TODO (5) Override onStartJob and within it, spawn off a separate ASyncTask to sync weather data
/**
* The entry point to your Job. Implementations should offload work to another thread of
* execution as soon as possible.
*
* This is called by the Job Dispatcher to tell us we should start our job. Keep in mind this
* method is running on the application's main thread, so we need to offload work to background thread.
*
* @return whether there is more work remaining
*/
@Override
public boolean onStartJob(final JobParameters jobParameters) {
mFetchWeatherTask = new AsyncTask<Void, Void, Void>(){
@Override
protected Void doInBackground(Void... voids) {
Context context = getApplicationContext();
SunshineSyncTask.syncWeather(context);
return null;
}
// TODO (6) Once the weather data is sync'd, call jobFinished with the appropriate arguments
@Override
protected void onPostExecute(Void aVoid) {
jobFinished(jobParameters, false);
}
};
mFetchWeatherTask.execute();
return true;
}
// TODO (7) Override onStopJob, cancel the ASyncTask if it's not null and return true
/**
* Call when the scheduling engine has decided to interrupt the execution of a running job,
* most likely because the runtime constraints associated with the job are no longer satisfied.
*
* @return whether the job should be retried
* @see Job.Builder#setRetryStrategy(RetryStrategy)
* @see RetryStrategy
*/
@Override
public boolean onStopJob(JobParameters job) {
if(mFetchWeatherTask != null){
mFetchWeatherTask.cancel(true);
}
return true;
}
}
// TODO (4) Declare an ASyncTask field called mFetchWeatherTask
// TODO (5) Override onStartJob and within it, spawn off a separate ASyncTask to sync weather data
// TODO (6) Once the weather data is sync'd, call jobFinished with the appropriate arguments
// TODO (7) Override onStopJob, cancel the ASyncTask if it's not null and return true
@@ -22,16 +22,82 @@
import android.support.annotation.NonNull;
import com.example.android.sunshine.data.WeatherContract;
import com.firebase.jobdispatcher.Constraint;
import com.firebase.jobdispatcher.FirebaseJobDispatcher;
import com.firebase.jobdispatcher.GooglePlayDriver;
import com.firebase.jobdispatcher.Driver;
import com.firebase.jobdispatcher.Job;
import com.firebase.jobdispatcher.Lifetime;
import com.firebase.jobdispatcher.Trigger;
import java.util.concurrent.TimeUnit;
public class SunshineSyncUtils {
// TODO (10) Add constant values to sync Sunshine every 3 - 4 hours
/*
* Interval at which to sync with the weather. Use TimeUnit for convenience
*/
private static final int SYNC_INTERVAL_HOURS = 3;
private static final int SYNC_INTERVAL_SECONDS = (int) TimeUnit.HOURS.toSeconds(SYNC_INTERVAL_HOURS);
private static final int SYNC_FLEXTIME_SECONDS =SYNC_INTERVAL_SECONDS /3;
private static boolean sInitialized;
// TODO (11) Add a sync tag to identify our sync job
private static final String SUNSHINE_SYNC_TAG = "sunshine-sync";
// TODO (12) Create a method to schedule our periodic weather sync
/**
* Schedules a repeating sync of Sunshine's weather data using FirebaseJobDispatcher.
* @param context Context used to create the GooglePlayDriver that powers the
* FirebaseJobDispatcher
*/
static void scheduleFirebaseJobDispatcherSync(@NonNull final Context context){
Driver driver = new GooglePlayDriver(context);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);
Job syncSunshineJob = dispatcher.newJobBuilder()
.setService(SunshineFirebaseJobService.class)
.setTag(SUNSHINE_SYNC_TAG)
/*
* Network constraints on which this Job should run. We choose to run on any
* network, but you can also choose to run only on un-metered networks or when the
* device is charging. It might be a good idea to include a preference for this,
* as some users may not want to download any data on their mobile plan. ($$$)
*/
.setConstraints(Constraint.ON_ANY_NETWORK)
/*
* setLifetime sets how long this job should persist. The options are to keep the
* Job "forever" or to have it die the next time the device boots up.
*/
.setLifetime(Lifetime.UNTIL_NEXT_BOOT)
/*
* We want Sunshine's weather data to stay up to date, so we tell this Job to recur.
*/
.setRecurring(true)
/*
* We want the weather data to be synced every 3 to 4 hours. The first argument for
* Trigger's static executionWindow method is the start of the time frame when the
* sync should be performed. The second argument is the latest point in time at
* which the data should be synced. Please note that this end time is not
* guaranteed, but is more of a guideline for FirebaseJobDispatcher to go off of.
*/
.setTrigger(Trigger.executionWindow(
SYNC_INTERVAL_SECONDS,
SYNC_INTERVAL_SECONDS + SYNC_FLEXTIME_SECONDS))
/*
* If a Job with the tag with provided already exists, this new job will replace
* the old one.
*/
.setReplaceCurrent(true)
/* Once the Job is ready, call the builder's build method to return the Job */
.build();
/* Schedule the Job with the dispatcher */
dispatcher.schedule(syncSunshineJob);
}
/**
* Creates periodic sync tasks and checks to see if an immediate sync is required. If an
@@ -51,6 +117,11 @@ synchronized public static void initialize(@NonNull final Context context) {
sInitialized = true;
// TODO (13) Call the method you created to schedule a periodic weather sync
/*
* This method call triggers Sunshine to create its task to synchronize weather data
* periodically.
*/
scheduleFirebaseJobDispatcherSync(context);
/*
* We need to check to see if our ContentProvider has data to display in our forecast

0 comments on commit ff2c8e5

Please sign in to comment.