Office Hours — Today, October 1

Tuesday, September 29

Oct 1
8:20 AM
Mark M.
has entered the room
Mark M.
turned on guest access
8:25 AM
Abhishek K.
has entered the room
Abhishek K.
Hey Murphy
Mark M.
hello Abhishek!
how can I help you today?
Abhishek K.
I'm facing an issue with with CoroutineWOrker
Mark M.
I have not spent much time with that class, but I can try to help!
Abhishek K.
I'm using suspendCancellableCoroutine to stop the coroutine and using cancellableContinuation.resumeWithException when any error happens with onError callback
8:30 AM
Abhishek K.
Now I'm downloading some file from network and whenever some error happens, flow goes to onError. Now when single file is getting downloaded and single WOrkRequest is running, everythign work fine
flow comes to onError and as soon as cancellableContinuation.resumeWithException is called, flow goes to catch block and coroutine returns with Result.failure()
But when I run more than 1 workrequest at the same time in parallel, problem happens. Problem is that for some WorkRequest, after calling cancellableContinuation.resumeWithException , flow takes a whole lot of time to come to catch block
and it happens only when onError is called for all Worker at the same time almost
any lead on this?
Mark M.
sorry, but no -- that is well beyond my limited CoroutineWorker experience
Abhishek K.
Okay.
I have one more problem
its with DocumentFile
Mark M.
OK, I have more experience with that! :-)
Abhishek K.
I'm using SD card in my product, it asks for root permission of SD card
Mark M.
what do you mean by "asks for root permission of SD card"?
8:35 AM
Abhishek K.
root permission as in, to deal with any folder inside SD card, we need access permission from user, right?
If I give root access permission, i can do anything with any folder inside the root. All folders are covered
got it?
Mark M.
I think you are using "permission" in a different way than I do -- what specific APIs are you using to accomplish this?
Abhishek K.
View paste
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
            flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
                    Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
        }
        startActivityForResult(intent, SettingsFragment.OPEN_DIRECTORY_REQUEST_CODE)
I'm using this to open the document tree
Mark M.
you can get rid of those flags, but otherwise, now I understand what you mean
Abhishek K.
Okay,
So, Now the problem is that
when I have already granted permission
and device is restarted,
var document = DocumentFile.fromTreeUri(application, treeUri)
document.listFile() is null
8:40 AM
Abhishek K.
its happening only when device is restarted
any lead?
Mark M.
are you calling takePersistableUriPermission() after you receive the Uri, in onActivityResult()?
Abhishek K.
no
Mark M.
OK, start there
Abhishek K.
View paste
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == SettingsFragment.OPEN_DIRECTORY_REQUEST_CODE && resultCode == Activity.RESULT_OK) {

            data?.data?.log("FILEPATH_MyLibrary")

            val sdCardTreeUri: Uri = data?.data!!

            myLibraryViewModel.setSDCardTreeUri(sdCardTreeUri)

            

        }
    }
this is onActivityREsult
just storing it
Mark M.
after the val sdCardTreeUri line, call contentResolver.takePersistableUriPermission(sdCardTreeUri)
Abhishek K.
will it solve it?
Mark M.
probably
I cannot rule out the possibility of some additional problem that you are encountering
but, you can only use that Uri in that particular activity, not from another Context or another process
unless you call takePersistableUriPermission()
the blog post that I linked to covers this
Abhishek K.
takePersistableUriPermission(sdCardTreeUri) is aksing for some flags also in addition to uri
Mark M.
yes, that is where you use Intent.FLAG_GRANT_READ_URI_PERMISSION
(and Intent.FLAG_GRANT_WRITE_URI_PERMISSION if you need it)
Abhishek K.
Okay.
Got it.
no lead on the first problem?
Mark M.
no, sorry, I have not used CoroutineWorker that much, let alone for a bunch of parallel work
8:45 AM
Abhishek K.
anywhere I can find any clue regarding that?
Mark M.
¯\_(ツ)_/¯
Abhishek K.
Hehe
Mark M.
Stack Overflow and other public question-and-answer sites, I guess
Abhishek K.
Anyway
Thanks Mark
Mark M.
and, FWIW, all the WorkManager stuff is in a library, so in theory you could debug it
Abhishek K.
View paste
after calling cancellableContinuation.resumeWithException(
                                error?.connectionException ?: Throwable()
                            ) this
View paste
/**
 * Resumes the execution of the corresponding coroutine so that the [exception] is re-thrown right after the
 * last suspension point.
 */
@SinceKotlin("1.3")
@InlineOnly
public inline fun <T> Continuation<T>.resumeWithException(exception: Throwable): Unit =
    resumeWith(Result.failure(exception))
this is where it leads to
View paste
@SinceKotlin("1.3")
public interface Continuation<in T> {
    /**
     * The context of the coroutine that corresponds to this continuation.
     */
    public val context: CoroutineContext

    /**
     * Resumes the execution of the corresponding coroutine passing a successful or failed [result] as the
     * return value of the last suspension point.
     */
    public fun resumeWith(result: Result<T>)
}
resumeWIth is overridden in 2 classes
View paste
package kotlin.coroutines

@kotlin.PublishedApi @kotlin.SinceKotlin internal final expect class SafeContinuation<in T> : kotlin.coroutines.Continuation<T> {
    internal constructor(delegate: kotlin.coroutines.Continuation<T>, initialResult: kotlin.Any?) { /* compiled code */ }

    @kotlin.PublishedApi internal constructor(delegate: kotlin.coroutines.Continuation<T>) { /* compiled code */ }

    public expect open val context: kotlin.coroutines.CoroutineContext /* compiled code */

    @kotlin.PublishedApi internal final expect fun getOrThrow(): kotlin.Any? { /* compiled code */ }

    public open expect fun resumeWith(result: kotlin.Result<T>): kotlin.Unit { /* compiled code */ }
}
and
View paste (10 more lines)
private final class SequenceBuilderIterator<T> public constructor() : kotlin.sequences.SequenceScope<T>, kotlin.collections.Iterator<T>, kotlin.coroutines.Continuation<kotlin.Unit> {
    public open val context: kotlin.coroutines.CoroutineContext /* compiled code */

    private final var nextIterator: kotlin.collections.Iterator<T>? /* compiled code */

    public final var nextStep: kotlin.coroutines.Continuation<kotlin.Unit>? /* compiled code */

    private final var nextValue: T? /* compiled code */

    private final var state: kotlin.sequences.State /* = kotlin.Int */ /* compiled code */

    private final fun exceptionalState(): kotlin.Throwable { /* compiled code */ }

    public open operator fun hasNext(): kotlin.Boolean { /* compiled code */ }

...
I dont think how can I debug
thos
this*
Mark M.
again, ¯\_(ツ)_/¯
Abhishek K.
Okay
Thanks anyway
Mark M.
this is the sort of thing where if I had the problem in front of me, I might have more ideas
8:50 AM
Mark M.
but I just don't know enough about this particular portion of WorkManager to really comment "off the cuff"
Abhishek K.
lol
Okay
Thanks for the solution of the second problem.
Mark M.
you're welcome!
Abhishek K.
has left the room
Abhishek K.
has entered the room
9:10 AM
Abhishek K.
has left the room
9:25 AM
Mark M.
turned off guest access

Tuesday, September 29

 

Office Hours

People in this transcript

  • Abhishek Kumar
  • Mark Murphy