Aws-sdk-android: Cannot Resume Upload - transferState = WAITING_FOR_NETWORK

Created on 2 May 2019  路  10Comments  路  Source: aws-amplify/aws-sdk-android

State your question
I am trying to resume uploads that did not previously upload to S3 (switched device to airplane mode to force 3 failures).

transferState = WAITING_FOR_NETWORK

I have reviewed and made changes based on issue # 618, but I am having no luck. I cannot get the 3 files to upload. See observers from Logcat output:

Screen Shot 2019-05-02 at 5 12 54 PM

Which AWS Services are you utilizing?
S3 - TransferUtility

Provide code snippets (if applicable)
I have stripped out all my code and am just running the following function to try to resume the upload:

`
private fun resumeTransfers () {
val KEY = MY_KEY
val SECRET = MY_SECRET
val credentials = BasicAWSCredentials(KEY, SECRET)

    val s3Client = AmazonS3Client(credentials, Region.getRegion(Regions.US_EAST_1))

    val xx = TransferNetworkLossHandler.getInstance(appContext)
    val transferUtility = TransferUtility.builder()
            .context(appContext)
            .awsConfiguration(AWSMobileClient.getInstance().configuration)
            .s3Client(s3Client)
            .build()


    val observers = transferUtility.getTransfersWithType(TransferType.UPLOAD)
    Log.i(TAG, "Stats observers: " + observers.size)

    transferUtility.resumeAllWithType(TransferType.UPLOAD)

    for (observer in observers) {

        if (TransferState.WAITING.equals(observer.getState()) || TransferState.WAITING_FOR_NETWORK.equals(observer.getState()) || TransferState.IN_PROGRESS.equals(observer.getState())) {

            observer.refresh()
            Log.i(TAG, "For observers: " + observer.toString())

        }
    }
}

`

Environment(please complete the following information):

  • SDK Version: [2.13.2]

Device Information (please complete the following information):

  • Emulator - Nexus 5X API 28 x86 (Android 9, API 28)
Bug Needs Info from Requester S3

All 10 comments

@richgabrielli Sorry for the inconvenience caused. Can you upgrade to 2.13.4? We have fixed a bug around uploads being stuck in the latest version.

Thanks @kvasukib I upgraded to 2.13.4 and the uploads did not resume when running though my function.

Can you try the following?

    val observers =  transferUtility.resumeAllWithType(TransferType.UPLOAD)

    for (observer in observers) {
        if (TransferState.WAITING.equals(observer.getState()) || TransferState.WAITING_FOR_NETWORK.equals(observer.getState()) || TransferState.IN_PROGRESS.equals(observer.getState())) {
            observer.refresh()
            Log.i(TAG, "For observers: " + observer.toString())
        }
    }

Also I would recommend attaching a listener to the observer rather than refreshing and getting the state.

Thanks @kvasukib
I changed the code to
val observers = transferUtility.resumeAllWithType(TransferType.UPLOAD)

Nothing was uploaded. Logcat output was 0 observers:
2019-05-03 06:03:55.020 4630-4630/com.chandlerconcrete.dispatch I/Chandler: Stats observers: 0

When I returned the code to
val observers = transferUtility.getTransfersWithType(TransferType.UPLOAD)

Logcat still showed the 3 observer with the same status:

2019-05-03 06:11:28.775 5000-5000/com.chandlerconcrete.dispatch I/Chandler: Stats observers: 3
2019-05-03 06:11:28.776 5000-5000/com.chandlerconcrete.dispatch I/Chandler: For observers: TransferObserver{id=2, bucket='chandlertickets-userfiles-mobilehub-134943903', key='050219/Virginia/711/242/2737765.pdf', bytesTotal=297946, bytesTransferred=0, transferState=WAITING_FOR_NETWORK, filePath='/data/user/0/com.chandlerconcrete.dispatch/files/2737765.pdf'}
2019-05-03 06:11:28.779 5000-5000/com.chandlerconcrete.dispatch I/Chandler: For observers: TransferObserver{id=3, bucket='chandlertickets-userfiles-mobilehub-134943903', key='050219/Virginia/711/213/2737771.pdf', bytesTotal=297660, bytesTransferred=0, transferState=WAITING_FOR_NETWORK, filePath='/data/user/0/com.chandlerconcrete.dispatch/files/2737771.pdf'}
2019-05-03 06:11:28.781 5000-5000/com.chandlerconcrete.dispatch I/Chandler: For observers: TransferObserver{id=4, bucket='chandlertickets-userfiles-mobilehub-134943903', key='050219/Piedmont/102/80/2737576.pdf', bytesTotal=298203, bytesTransferred=0, transferState=WAITING_FOR_NETWORK, filePath='/data/user/0/com.chandlerconcrete.dispatch/files/2737576.pdf'}

@kvasukib In response to the listener. I am using one when I upload the files in another section of code

val uploadObserver = transferUtility.upload(filePath, file, myObjectMetadata)
uploadObserver.setTransferListener(object : TransferListener {

I have not been able to figure out how to implement a listener when I am not uploading a file. I get a unresolved reference on setTransferListener when I try to do the same.

 val yyz = transferUtility.resumeAllWithType(TransferType.UPLOAD)
 yyz.setTransferListener(object : TransferListener {

Resolved. I may not fully understand how the API is working but, the call to transferUtility.resumeAllWithType(TransferType.UPLOAD) always returned 0 and never uploaded. Should resumeAllWithType work in the way I was thinking?

I was able to step back and implement the listener and do one at a time. Here is the code and it worked flawlessly.

    private fun resumeTransfers() {
        scope.launch {

            val KEY = MY_KEY
            val SECRET = MY_SECRET
            val credentials = BasicAWSCredentials(KEY, SECRET)

            val s3Client = AmazonS3Client(credentials, Region.getRegion(Regions.US_EAST_1))

            val xx = TransferNetworkLossHandler.getInstance(appContext)
            val transferUtility = TransferUtility.builder()
                    .context(appContext)
                    .awsConfiguration(AWSMobileClient.getInstance().configuration)
                    .s3Client(s3Client)
                    .build()

            val observers = transferUtility.getTransfersWithType(TransferType.UPLOAD)

            Log.i(TAG, "Size getTransfersWithType: " + observers.size)

            for (observer in observers) {
                transferUtility.resume(observer.id)
                observer.setTransferListener(object : TransferListener {


                    override fun onStateChanged(id: Int, state: TransferState) {
                        Log.d(TAG, "Listener - onStateChanged: " + state.toString())
                    }


                    override fun onProgressChanged(id: Int, bytesCurrent: Long, bytesTotal: Long) {
                        val percentDonef = bytesCurrent.toFloat() / bytesTotal.toFloat() * 100
                        val percentDone = percentDonef.toInt()
                        Log.i("Chandler", "Listener - onProgressChanged - " + "ID:$id|bytesCurrent: $bytesCurrent|bytesTotal: $bytesTotal|$percentDone%")
                    }

                    override fun onError(id: Int, ex: Exception) {
                        ex.printStackTrace()
                        Log.i("Chandler", "Listener - onError- " + ex.toString())

                    }
                })

                if (TransferState.WAITING.equals(observer.getState()) || TransferState.WAITING_FOR_NETWORK.equals(observer.getState()) || TransferState.IN_PROGRESS.equals(observer.getState())) {

                    observer.refresh()
                    Log.i(TAG, "Details getTransfersWithType: " + observer.toString())

                }
            }
        }
    }

@richgabrielli Thank you for trying out the other method. When I look at resumeAllWithType method, I notice the following:

List<TransferObserver> observers = new ArrayList<TransferObserver>();
        final List<Integer> transferIds = getTransferIdsWithTypeAndStates(type,
                new TransferState[] {TransferState.PAUSED, 
                    TransferState.FAILED, 
                    TransferState.CANCELED});

        for (final Integer transferId : transferIds) {
            observers.add(resume(transferId));
        }

        return observers;

This implementation only resumes the transfers that in PAUSED / FAILED / CANCELED state. If you do not have transfers in this state, then you will get an empty list.

Thanks @kvasukib
With the way I implemented, should it pick up PAUSED, FAILED, CANCELED? Or do I need to account for those conditions?

@richgabrielli With the way you implemented using the getTransfersWithType and manually calling resume method on the observers, it will resume all the transfers regardless of the state.

Thanks for all your help @kvasukib . I appreciate it. I will close this case.

Was this page helpful?
0 / 5 - 0 ratings