Step #5: Writing Where the User Asked

We now need to start connecting the createDoc request to our RosterReport.

What we get from createDoc is a Uri pointing to… something. It is up to the user where to save the Web page, and that could be anything from a local file to an entry in Google Drive. A ContentResolver has an openOutputStream() method that will work with any Uri returned by createDoc, so we will not need to worry about the location details.

This means that RosterReport needs a function where we can hand it the user-supplied Uri and have it write the report to that location.

To that end, add this function to RosterReport:

  suspend fun generate(content: List<ToDoModel>, doc: Uri) {
    withContext(Dispatchers.IO + appScope.coroutineContext) {
      context.contentResolver.openOutputStream(doc, "rwt")?.writer()?.use { osw ->
        osw.write(template.apply(content))
        osw.flush()
      }
    }
  }

generate() takes a List of models, along with that Uri. In a coroutine set to run on a background thread and managed by our appScope (withContext(Dispatchers.IO + appScope.coroutineContext)), we:

You may get a warning on the openOutputStream() call, complaining about an “inappropriate blocking method call”. That is an IDE bug.

The “rwt” parameter to openOutputStream() represents the “mode”, indicating what we want to do with the stream. The default mode, if you leave off this parameter, is “w”, indicating that you want to overwrite parts of the content. The “t” in “rwt” indicates that we want to truncate the output — whatever we write becomes the complete content. The “r” means we want to be able to read the content. We are not using that capability, but “wt” is not a documented option for the mode, so we settle for “rwt” to get write and truncate capability.


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.