We always think about which services to use for background image upload with better performance. Earlier we had AlarmManager, JobScheduler, FirebaseJobDispatcher for scheduling the background tasks. But the issues were, JobScheduler available only for API >= 21 and FirebaseJobDispatcher for backward compatibility. So I had to understand which method to use when.
But when I came across WorkManager library as part of the Android Jetpack component set. Moving forward, WorkManager replaces JobScheduler as Google’s recommended way to enqueue background tasks that are guaranteed to execute, I started liking it. I talked about what WorkManager is and why I should start considering WorkManager for scheduling tasks in Android applications.
- Handles compatibility with different OS versions.
- Follows system health best practices.
- Supports asynchronous one-off and periodic tasks.
- Supports chained tasks with input/output.
- Lets you set constraints on when the task runs.
- Guarantees task execution, even if the app or device restarts.
Implementing WorkManager in Android is easy.
Let get started with uploading an image in the background.
First we add the following dependencies in build.gradle
file
dependencies {
def work_version = "2.3.4"
implementation "androidx.work:work runtime-ktx:$work_version"
//----- AWS dependencies
implementation 'com.amazonaws:aws-android-sdk-core:2.4.2'
implementation 'com.amazonaws:aws-android-sdk-cognito:2.4.2'
implementation 'com.amazonaws:aws-android-sdk-s3:2.4.2'
implementation 'com.amazonaws:aws-android-sdk-ddb:2.4.2'
implementation 'com.github.bumptech.glide:glide:4.8.0'
}
First of all We will create the UploadWorker class by extending the Worker class, and override its doWork() method for background processing. When doWork() method is called by WorkManager, then it calls user defined method uploadImage(). I have used to AWS S3 service to upload image on Cloud.
class UploadWorker(appContext: Context, workerParams: WorkerParameters) : Worker(appContext, workerParams) {
override fun doWork(): Result {
// Upload the images.
uploadImages()
// Indicate whether the work finished successfully with the Result
return Result.success()
}
private fun uploadImages() {
try {
// Upload images from camera and gallery url.
var uploadImageURI = "/storage/emulated/0/Pictures/15062020155500.jpg";
if (!TextUtils.isEmpty(uploadImageURI)) {
val file = File(uploadImageURI)
var transferUtility = AWSUtil.getTransferUtility(applicationContext)
var observer: TransferObserver = transferUtility.upload("Bucket-Name", file.name, file)
observer.setTransferListener(mUploadListener)
}
} catch (exeption: Exception) {
exeption.printStackTrace()
}
}
var mUploadListener = object : TransferListener {
override fun onError(id: Int, e: Exception) {
Log.e("ImageUpload", "Error during upload: " + id, e)
}
override fun onProgressChanged(id: Int, bytesCurrent: Long, bytesTotal: Long) {
Log.d("ImageUpload", String.format("onProgressChanged: %d, total: %d, current: %d", id, bytesTotal, bytesCurrent))
}
override fun onStateChanged(id: Int, newState: TransferState) {
if (newState == TransferState.COMPLETED) {
// Create uploaded image url
val imageURL: String = AWSConstants.S3_URL + "/" + "imageFilename"
Log.e("URL", "Upload: " + imageURL)
}
}
}
}
In our MainActivity.kt
class, I’ve created a button, when user clicks on the button, then immediately UploadWorker class gets call and upload image.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val uploadWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<UploadWorker>().build()
btnStartUpload.setOnClickListener {
WorkManager.getInstance(this@MainActivity).enqueue(uploadWorkRequest)
}
}
}
That’s it!!.
We are done with all the configurations required to run our application.
Conclusion
Now run the application and see the Logcat for uploaded image url. I hope you get a clear idea about WorkManager.
If you face any issues, you can find complete source code here.
Happy coding!!
Can we show notification to user, when the workmanager completes the task ? If yes, can you share the sample code ?
How can we do uplaod files to firebase with RxWorker?