Aws-sdk-android: S3 upload hangs up in WAITING_FOR_NETWORK state

Created on 15 Apr 2019  路  3Comments  路  Source: aws-amplify/aws-sdk-android

Bug description
After upgrading the aws-android-sdk-mobile-client from 2.12.6 to 2.13.1 the code which uploaded image to S3 against TransferUtility stopped working. It was hanging up in WAITING_FOR_NETWORK state.

How To Reproduce
No special circumstances took place: wi-fi connection with internet was available.
The s3 file upload was initiated with the following code (which worked on aws-sdk 2.13.0 and 2.12.6)

val s3Client = AmazonS3Client(AWSMobileClient.getInstance(), region((context)))
val observer = TransferUtility.builder().s3Client(s3Client)
        .context(context)
        .awsConfiguration(AWSMobileClient.getInstance().configuration)
        .build()
        .upload(bucketName(context), name, file)
observer.setTransferListener(listener)

The transfer listener was like this

TransferListener {
    override fun onStateChanged(id: Int, state: TransferState?) {
        Log.i(TAG, "Upload state changed to ${state?.name}")
    }
    override fun onError(id: Int, ex: java.lang.Exception) {
        Log.e(TAG, "Failed to upload to S3, job id $jobId", ex)
    }

    override fun onProgressChanged(id: Int, bytesCurrent: Long, bytesTotal: Long) {
        showProgressNotification(bytesCurrent.toInt(), bytesTotal.toInt())
    }
}

When upload started, the app received only one onStateChanged with WAITING_FOR_NETWORK state and no other updates reported to TransferListener. File was not uploaded to S3 bucket.

Affected AWS service(s)
S3

Expected behavior
File should be uploaded with progress updates reported to TransferListener

Environment Information (please complete the following information):

  • AWS Android SDK Version: 2.13.1
  • Devices: Xiaomi Mi5s and Samsung Galaxy J7 (2016)
  • Android Version: 8.0.0 (Xiaomi) / 8.1.0 (Samsung)

Additional context
There was such message in the logs (com.amazonaws.mobileconnectors.s3.transferutility.UploadTask):

2019-04-12 17:04:49.831 9610-16011/com.ehawk.repath.staging E/UploadTask: 
TransferUtilityException: [com.amazonaws.mobileconnectors.s3.transferutility.TransferUtilityException: TransferNetworkLossHandler is not created. Please call `TransferNetworkLossHandler.getInstance(Context)` to instantiate it before retrieving]
2019-04-12 17:05:23.249 9610-16011/com.ehawk.repath.staging I/UploadTask: Network not connected. Setting the state to WAITING_FOR_NETWORK.

After that UploadTask.call() finished and no actual upload happened

Questions:

  1. Is it now mandatory to register TransferNetworkLossHandler for being able to use TransferUtility?
  2. Is there any examples of how that should be done? Is Application.onCreate() a valid point to create/register this?
Awaiting Release Bug S3

Most helpful comment

@kvasukib We did that in our application, e.g. getApplicationContext().startService(new Intent(getApplicationContext(), TransferService.class)), but that crashed when the Application.onCreate() was executed when the app is in background:

Process: com.ehawk.repath.staging, PID: 22366
     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6065)
   java.lang.RuntimeException: Unable to create application com.package.TrackerApplication: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.ehawk.repath.staging/com.amazonaws.mobileconnectors.s3.transferutility.TransferService }: app is in background uid UidRecord{1eb515a u0a344 TRNB idle procs:1 seq(0,0,0)}
     at android.app.ActivityThread.-wrap1(Unknown Source:0)
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1764)
     at android.os.Handler.dispatchMessage(Handler.java:105)
     at android.os.Looper.loop(Looper.java:164)

As a workaround, we replaced the code which started TransferService with this line: registerReceiver(TransferNetworkLossHandler.getInstance(applicationContext), IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))

We suggest to:
1) update the documentation which suggests to do the action which can lead to a crash
2) adapt TransferNetworkLossHandler for API >= 28 where CONNECTIVITY_ACTION is not recommended to use: https://developer.android.com/reference/android/net/ConnectivityManager#CONNECTIVITY_ACTION

All 3 comments

@nchorniy Sorry for the inconvenience caused.

1) Is it now mandatory to register TransferNetworkLossHandler for being able to use TransferUtility?
No, it is not. TransferNetworkLossHandler is designed to be an optional component. I have made the necessary changes to check for TransferNetworkLossHandler optional. See #900 for more details.

2) Is there any examples of how that should be done? Is Application.onCreate() a valid point to create/register this?

getApplicationContext().startService(new Intent(getApplicationContext(), TransferService.class));

TransferService creates and registers a TransferNetworkLossHandler and takes care of app background/foreground transitions. However, if you do not want to start a service, you could create an object of TransferNetworkLossHandler and register it like any other BroadcastReceiver.

@kvasukib We did that in our application, e.g. getApplicationContext().startService(new Intent(getApplicationContext(), TransferService.class)), but that crashed when the Application.onCreate() was executed when the app is in background:

Process: com.ehawk.repath.staging, PID: 22366
     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6065)
   java.lang.RuntimeException: Unable to create application com.package.TrackerApplication: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.ehawk.repath.staging/com.amazonaws.mobileconnectors.s3.transferutility.TransferService }: app is in background uid UidRecord{1eb515a u0a344 TRNB idle procs:1 seq(0,0,0)}
     at android.app.ActivityThread.-wrap1(Unknown Source:0)
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1764)
     at android.os.Handler.dispatchMessage(Handler.java:105)
     at android.os.Looper.loop(Looper.java:164)

As a workaround, we replaced the code which started TransferService with this line: registerReceiver(TransferNetworkLossHandler.getInstance(applicationContext), IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))

We suggest to:
1) update the documentation which suggests to do the action which can lead to a crash
2) adapt TransferNetworkLossHandler for API >= 28 where CONNECTIVITY_ACTION is not recommended to use: https://developer.android.com/reference/android/net/ConnectivityManager#CONNECTIVITY_ACTION

@nchorniy Thank you for the quick response. TransferService is a background service, hence you are hitting the exception on device running Oreo and above when the service is started when the app is in background. So I would recommend registering the TransferNetworkLossHandler as you did.

To Adapt TransferNetworkLossHandler for API >= 28, I will use this GitHub issue to track that request. Thank you for pointing it out.

UPDATE:

I looked into the three alternatives that Android recommends to use instead of CONNECTIVITY_ACTION, however the alternatives are introduced in a later version of Android (22, 23 and 24) whereas AWS SDK for Android supports API Level of 10. So I will continue my search on what alternatives we could use to still support a lower minimum SDK. Also, please feel free to comment on this issue if you find any other alternative.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

PikkaPikkachu picture PikkaPikkachu  路  4Comments

osugikoji picture osugikoji  路  4Comments

logo17 picture logo17  路  3Comments

zgao67 picture zgao67  路  4Comments

mockturtl picture mockturtl  路  4Comments