Notes: 18. Challenge - Services
The student materials have been reviewed and are updated as of SEPTEMBER 2022.
It’s time to practice what you’ve learned about Services! :] In this challenge, you have to do one thing - implement the Synchronization feature using a one-off service.
Here’s a hint: Instead of using a regular Android Service, or the IntentService, use the JobIntentService, to support the new background restrictions. Also, the clear local storage function is already prepared for you, in FileUtils.
That’s it, now pause the video, and solve the challenge, then once you’re done, unpause the video, and compare the two solutions! :] Good luck!
Just like before, start by creating a new class called SynchronizeImagesService, and add the following code to the class:
class SynchronizeImagesService : JobIntentService() {
private val remoteApi by lazy { App.remoteApi }
companion object {
private const val JOB_ID = 15
fun startWork(context: Context, intent: Intent) {
enqueueWork(context, SynchronizeImagesService::class.java, JOB_ID, intent)
}
}
}
This should be familiar! You’re extending the JobIntentService, adding the remoteApi, as you’ll need to fetch the image list from the server, and expanding the class with the companion object, to be able to enqueue work from outside the class.
Now head over to the AndroidManifest.xml file, and declare the service:
<service
android:name=".service.SynchronizeImagesService"
android:permission="android.permission.BIND_JOB_SERVICE" />
You have to declare the service, and add the BIND_JOB_SERVICE permission to it, for the JobScheduler to be able to use it. Now go back to the Service class, and add the next code snippet:
class SynchronizeImagesService : JobIntentService() {
private val remoteApi by lazy { App.remoteApi }
companion object {
private const val JOB_ID = 15
fun startWork(context: Context, intent: Intent) {
enqueueWork(context, SynchronizeImagesService::class.java, JOB_ID, intent)
}
}
override fun onHandleWork(intent: Intent) {
clearStorage()
fetchImages()
}
...
}
You’ll clear the storage and fetch images within the onHandleWork() function. Finally, add the code to fetch the iamges, and clear the storage:
class SynchronizeImagesService : JobIntentService() {
...
private fun fetchImages() {
GlobalScope.launch {
val result = remoteApi.getImages()
if (result is Success) {
val imagesArray = result.data.map { it.imagePath }.toTypedArray()
FileUtils.queueImagesForDownload(applicationContext, imagesArray)
}
}
}
private fun clearStorage() {
FileUtils.clearLocalStorage(applicationContext)
}
}
This code is the same as what’s happening in the Workers you previously used, so it shouldn’t need much explaining. But nonetheless, you’re fetching the image list from the server, and queueing work in the DownloadManager. You also used the FileUtils to clear the storage beforehand.
To launch this service, head over to the SettingsFragment, and replace the current code with the following:
private fun synchronizeImages() {
SynchronizeImagesService.startWork(requireContext(), Intent())
}
Instead of using the WorkManager, you’ll start the service, and that’s it! :] Run the project, and check that everything works like before!