Front-End Web & Mobile
AWS SDK for Android Transfer Manager to Transfer Utility Migration Guide
With the announcement of the S3 Transfer Utility, we deprecated the S3 Transfer Manager. This post is a guide to help developers currently using the Transfer Manager migrate to the new Transfer Utility. The guide is split into sections based on functionality, and shows how Transfer Manager code will change to work with the Transfer Utility. So lets get started!
Client Construction
The Transfer Utility has a single constructor, which requires an instance of AmazonS3Client (which we recommend setting the region on, prior to passing to the Transfer Utility), and the application context. As with the Transfer Manager, we recommend constructing the Transfer Utility client once, and using a single instance throughout your application. An example is shown below:
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider( context.getApplicationContext(), YOUR_IDENTITY_POOL_ID, Regions.US_EAST_1); AmazonS3Client s3Client = new AmazonS3Client(credentialsProvider); TransferUtility transferUtility = new TransferUtility(s3Client,context.getApplicationContext());
Permissions & Service Declaration
The Transfer Manager only requires the INTERNET permission. However, since the Transfer Utility automatically detects network state and pauses/resumes transfers based on the network state, your app will require the ACCESS_NETWORK_STATE permission as well.
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
The Transfer Utility is now based on an Android service, which must be declared in the AndroidManifest.xml within the Application tag.
<service android:name= "com.amazonaws.mobileconnectors.s3.transferutility.TransferService" android:enabled="true" />
Uploading and Downloading
The Transfer Manager has a plethora of APIs for uploading and downloading. Pausing transfers using the Transfer Manager is not possible with stream based uploads or downloads, or those using client-side encryption. Additionally, when using streams, developers must still specify the content length ahead of time. To create one coherent API, which can always be paused and resumed, the Transfer Utility has one single-file-based method for uploads, and downloads. All requests will need to be converted to the API below:
Uploading:
TransferObserver observer = transferUtility.upload( MY_BUCKET, // The S3 bucket to upload to OBJECT_KEY, // The key for the uploaded object FILE_TO_UPLOAD // The location of the file to be uploaded );
Downloading:
TransferObserver observer = transferUtility.download( MY_BUCKET, // The S3 bucket to download from OBJECT_KEY, // The key for the object to download FILE_TO_UPLOAD // The name of the file to download );
Tracking Transfers
To track transfer progress with the Transfer Manager, developers pass an S3ProgressListener callback to upload or download, which periodically fires the method below.
public void progressChanged(ProgressEvent progressEvent);
The ProgressEvent gives developers an integer code if the state of the transfer had changed, and would tell developers the amount of data transferred since the last progressChanged was fired.
The Transfer Utility returns a TransferObserver object when you call Upload/Download/Resume. You can also query for TransferObservers from anywhere within your app using the following APIs:
public TransferObserver getTransferById(int id) public List<TransferObserver> getTransfersWithType(TransferType type) public List<TransferObserver> getTransfersWithTypeAndState(TransferType type, TransferState state)
You can get the current state and progress from the TransferObserver, or if you are interested in continual updates you can call
public void setTransferListener(TransferListener listener)
on the TransferObserver, and the TransferListener will fire the following callbacks:
public void onStateChanged(int id, TransferState state); public void onProgressChanged(int id, long bytesCurrent, long bytesTotal); public void onError(int id, Exception ex);
So code relating to :
-
progressEvent.getEventCode()
will now be handled by theonStateChange()
function, which now uses an enum to describe the state of the transfer. -
progressEvent.getBytesTransferred()
will need to be updated to use theonProgressChanged()
method. NOTE: bytesCurrent inonProgressChanged()
represents the total number of bytes transferred, while the getBytesTransferred in the ProgressEvent class gives the number of bytes since the last ProgressEvent was fired.
Pausing Transfers
With the Transfer Manager, transfers using APIs involving I/O streams cannot be paused. For transfers that can be paused, developers call pause()
on the Upload or Download object, or pass a callback to upload and download which fires when a transfer is able to be paused. In either case, a PersistableTransfer object is received, which then produces a String via the serialize()
method. This String then has to be written to persistable storage by the developer. Migrating pause functionality to the Transfer Utility is easy, since all transfers can be paused and resumed. Additionally, the Transfer Utility stores all of the metadata about transfers to the local SQLite database, so developers do not need to persist anything. The Transfer Utility automatically pauses transfers when the app loses network connectivity, and will automatically resume them when the app regains connectivity. You can manually pause a single transfer using
public boolean pause(int id)
or pause uploads, downloads, or all transfers with
public void pauseAllWithType(TransferType type)
The transfer id can be retrieved from any TransferObserver instance, which can be queried for as described in the Tracking Transfers sections above. The only other consideration is that pausing will return false and do nothing unless the transfer is in one of the following states:
TransferState.IN_PROGRESS TransferState.RESUMED_WAITING TransferState.WAITING
Resuming Transfers
In Transfer Manager code, to resume an upload you first create a PersistableTransfer with the static deserializeFrom()
method, passing it the String you received from calling serialize()
on an Upload or Download. Then with the PersistableTransfer object, you call resume() from the TransferManager class.
The Transfer Utility handles persisting the transfer metadata, so all you need to do is call
public TransferObserver resume(int id)
where id is the id from a TransferObserver. If you do not have a TransferObserver you can query for one as described in the Tracking Transfers section above. Remember that if a transfer is paused because of a loss of network connectivity, it will automatically be resumed and there is no action you need to take. Transfers that are automatically paused and waiting for network connectivity will have the state TransferState.WAITING_FOR_NETWORK to distinguish them from manually paused transfers.
Copying Transfers
The Transfer Utility does not support a copy()
API, because it is not a commonly used API on mobile. However you can accomplish much of the same functionality using the AmazonS3Client class copyObject()
method shown below.
public CopyObjectResult copyObject(String sourceBucketName, String sourceKey,String destinationBucketName, String destinationKey)
Aborting Transfers Using the Transfer Manager you can abort a transfer by calling
public void abort();
on an Upload or Download object. With the Transfer Utility to abort a transfer you call
public boolean cancel(int id)
on the Transfer Utility class. Canceling a transfer using the Transfer Utility will not remove it from the local SQLite database, and it can still be queried for. To completely remove the transfer from local storage, you must first cancel the transfer (if it is running), and call the delete method shown below. It is an error to delete a running transfer without first canceling it.
public boolean deleteTransferRecord(int id)
For additional help using the Transfer Utility see:
The step by step Getting Started Guide
The Sample on GitHub (including tutorial)
The latest SDK API Reference
This guide is intended to make transitioning from the Transfer Manager to the Transfer Utility as easy and quick as possible. If you have any additional questions or feedback, do not hesitate to contact us: as a comment on this blog, a post on our forums, or as a GitHub issue.