-
Notifications
You must be signed in to change notification settings - Fork 0
Lab 16
Let's use WorkManager
to upload a Note
to a public GitHub repo.
- Work Manager is a library for defining persistent background work; that is work that should be completed across app restarts, configuration changes, or in the background.
- Work Manager supports 3 types of work:
- Immediate
- Persistent
- Deferrable
-
Add an "upload"
Button
toNoteDetailsFragment
- Add a
Button
element tofragment_note_details.xml
- When clicked, this button will eventually start our upload worker
- Add a
-
Create a new package
upload
-
Within the
upload
package, create aWorker
to upload ourNote
toGitHub
- Create a
NoteUploadWorker
class that extendsWorker
- Define a
uploadFileData(context: Context, filename:String, content:String)
method (see hints) - Within
uploadFileData()
, use Volley to upload aNote
as a .txt file toGitHub
- see notes for URL formatting
- Override
doWork()
to useuploadFileData()
to upload yourNote
- Create a
-
Submit work request to
WorkManager
- Within
NoteDetailFragment.uploadNote()
remove the call to start our upload service (if previously completed Lab 15) - Construct a
WorkRequest
forNoteUploadWorker
usingOneTimeWorkRequestBuilder<NoteUploadWorker>().setInputData(NoteUploadWorker.buildInputData(note)).build()
(see hints) - Submit the request to
WorkManager
usingWorkManager.getInstance(requireContext()).enqueue(uploadWorkRequest)
- Within
You should use a URL to any repo to which you can generate an access token.
The path to that repo should then be specified as
https://api.github.com/repos/<username>/<repo>/contents/$filename
ex: https://api.github.com/repos/goobar-dev/workshop-sample-data/contents/$filename
We can pass data to a Worker
using the androidx.work.Data
class. This class functions very similar to a Bundle
.
Within NoteUploadWorker
, create a companion object to help build and parse a Data
object for passing the Note
data.
companion object {
private const val KEY_CONTENT = "key_content"
private const val KEY_FILENAME = "filename"
fun buildInputData(note: Note): Data = workDataOf(
KEY_FILENAME to "uploaded-notes/${note.title}-${System.currentTimeMillis()}.txt",
KEY_CONTENT to encodeNote(note)
)
fun parseInputData(data: Data): NoteUploadConfig {
return NoteUploadConfig(data.getString(KEY_FILENAME)!!, data.getString(KEY_CONTENT)!!)
}
private fun encodeNote(note: Note): String {
val noteContent = note.title + "\n" + note.category + "\n" + note.content
return Base64.encodeToString(noteContent.toByteArray(), android.util.Base64.DEFAULT)
}
}
data class NoteUploadConfig(val filename: String, val content: String)
override fun doWork(): Result {
// inputData is a property on [Worker]
// it provides the input data specified by the work request
val noteUploadConfig = parseInputData(inputData)
uploadFileData(applicationContext, noteUploadConfig.filename, noteUploadConfig.content)
// Indicate whether the work finished successfully with the Result
return Result.success()
}
private fun uploadFileData(context: Context, filename: String, content: String) {
val requestQueue = Volley.newRequestQueue(context)
val body = JSONObject().apply {
put("message", "Upload from app") // commit message of file upload to GitHub
put("content", content)
}
val request = object : JsonObjectRequest(
Method.PUT,
"url to your repo",
body,
{
// handle success
Toast.makeText(context, "Successfully uploaded note", Toast.LENGTH_SHORT).show()
},
{
// handle error
Toast.makeText(context, "Failed to upload note", Toast.LENGTH_SHORT).show()
}
) {
override fun getHeaders(): MutableMap<String, String> {
return mutableMapOf(
"Authorization" to "token <your repo access token>",
"Accept" to "application/vnd.github.v3+json"
)
}
}
requestQueue.add(request)
}
// within NoteDetailsFragment
private fun uploadNote() {
lifecycleScope.launch(Dispatchers.IO) {
val note = requireActivity().studyGuideApplication().database.noteDao().get(args.selectedNoteId)
val uploadWorkRequest: WorkRequest =
OneTimeWorkRequestBuilder<NoteUploadWorker>()
.setInputData(NoteUploadWorker.buildInputData(note))
.build()
WorkManager.getInstance(requireContext()).enqueue(uploadWorkRequest)
}
}