Developer Blog

Mobile on AWS: Tips, tricks and news from the AWS Mobile SDK and Tools team
RSS
  • Yangfan Zhang

    Making Asynchronous Calls with Handler

    • May 8, 2013
    • Yangfan Zhang
    • Android

    There are two ways to make asynchronous calls: AsyncTask, and Handler plus Thread. I briefly introduced how to use AysncTask to make asynchronous calls in the previous post. In this post, I will explain making asynchronous calls with Handler. I will also compare AsyncTask with Handler.

    What is Handler?

    A Handler is associated with a thread that creates the handler. It receives and processes messages and Runnable objects that are sent from a different thread. With Handler, you can run a time-consuming task in a background thread and send messages to the main thread to update the UI. I will use uploading an image to Amazon S3 as an example to explain how to use Handler to make asynchronous calls.

    Defining a Thread Handler

    An Android application has a default thread — the main thread. When a Handler object is created in onCreate(), it's bonded to the main thread. You override the handlerMessage(Message msg) method in order to process messages that are sent to the handler. The Message class consists of a user-defined message code what, two integer value arguments arg1 and arg2, and an arbitrary object obj. Not all fields are set by the sender. Usually, at minimum the message code is set to identify an event.

    In the process of uploading an image to Amazon S3, you are likely to be interested in three events: when the upload starts, when data is transferring, and when the upload finishes. Therefore, three message codes, S3_UPLOAD_START, S3_UPLOAD_PROGRESS, and S3_UPLOAD_FINISH, are used to identify these events, respectively. Based on the message, you can use a switch statement to perform a corresponding operation.

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case S3_UPLOAD_START:
                // Set up a progress dialog when upload starts
                dialog = new ProgressDialog(...);
                dialog.setMessage(getString(R.string.uploading));
                dialog.setCancelable(false);
                dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                dialog.setMax(msg.arg1);
                dialog.show();
                break;
            case S3_UPLOAD_PROGRESS:
                // Update progress
                dialog.setProgress(msg.arg1);
                break;
            case S3_UPLOAD_FINISH:
                // When upload finishes, dismiss progress dialog
                dialog.dismiss();
                break;
            default:
                break;
            }
        }
    }
    

    Running a Task in a Thread

    As a general rule, it's best to not block the main thread in Android. So time-consuming tasks must be run in a background thread. You can extend the Thread class and implement the time-consuming task inside the run() method, which you kick off by calling start(). In order to communicate with the main thread, messages have to be created and sent to the main thread's handler. Handler has a convenient method, obtainMessage(...), to create a message. You can define message code and include additional data, such as number of bytes that are transferred and error string, to the message. You then send this data to the thread handler.

    S3PutObjectThread gets the Uri of an image to be uploaded from its constructor. The upload logic is implemented inside the run() method. You can send an S3_UPLOAD_START message before the upload starts and an S3_UPLOAD_FINISH message when it finishes. A progress listener is attached to the upload request in order to report transfer progress. When the listener is triggered, you compute the total bytes transferred and send an S3_UPLOAD_PROGRESS message with this number to the main thread.

    class S3PutObjectThread extends Thread {
        private Uri selectedImage;
    
        S3PutObjectThread(Uri selectedImage) {
            this.selectedImage = selectedImage;
        }
    
        @Override
        public void run() {
            // Get the file path of the image from selectedImage
            ...
            File imageFile = new File(filePath);
            Message msg;
    
            // Notify the main thread that the upload starts
            msg = handler.obtainMessage(S3_UPLOAD_START);
            handler.sendMessage(msg);
    
            try {
                // Create a S3 bucket if necessary
                ...
                PutObjectRequest por = new PutObjectRequest(bucket, key, imageFile);
                // Attach a progress listener to the request
                por.setProgressListener(new ProgressListener() {
                    int total = 0;
    
                    @Override
                    public void progressChanged(ProgressEvent pe) {
                        total += (int) pe.getBytesTransfered();
                        // Create a message, and set the total bytes transferred to arg1
                        Message msg = handler.obtainMessage(S3_UPLOAD_PROGRESS, total, 0);
                        // Send progress update to the main thread
                        handler.sendMessage(msg);
                    }
                });
    
                // Send the request
                s3Client.putObject(por);
            } catch (Exception e) {
                // Handle exception here.
                ...
            }
    
            // Upload finishes
            msg = handler.obtainMessage(S3_UPLOAD_FINISH);
            handler.sendMessage(msg);
        }
    }
    
    ...
    
    // Create a thread and start it
    new S3PutObjectThread(selectedImage).start();
    

    Comparison Between Handler and AsyncTask

    AsyncTask is a wrapper of Handler and Thread. It allows you to conveniently make asynchronous calls without handling threads and handlers. You only need to focus on the four steps in the execution cycle of AsyncTask: onPreExecute, doInBackground, onProgressUpdate, and onPostExecute. However, convenience comes with a price. Here are some limitations.

    • An AsyncTask instance has to be initiated and executed in the main thread.
    • AsyncTask instances cannot communicate with each other easily.
    • It's not easy to schedule AsyncTask to run at a certain time in the future.
    • The execution order of multiple AsyncTask instances may not be what you think. Since the arrival of Honeycomb (Android 3.0, API level 11), multiple AsyncTask instances are executed sequentially by default. If you want to change this behavior, you can have them executed on THREAD_POOL_EXECUTOR by invoking executeOnExecutor.

    Handler and Thread are the underlying implementation of AsyncTask. They don't have the limitations of AsyncTask and give you more control over what you want to do.

    • The initialization and execution of a Thread are not limited to the main thread. They can be done almost everywhere.
    • Communication between threads won't be a problem with handlers. If you want to send messages to a thread, you can attach a handler to it. There is a handy class HandlerThread that allows you to create a handler for a thread (other than the main thread).
    • Handler has several methods for scheduling messages in the future: sendMessageAtTime, sendMessageDelayed, postMessageAtTime, and postMessageDelay.

    The choice between AsyncTask and Handler may vary, depending on specific requirements, legacy code, or personal taste. I hope that after reading this post you have a better understanding of Handler and that you properly choose which way to make asynchronous calls in the future.

    If you have any questions, please don't hesitate to post at Mobile Development Forum.

    If you like building mobile applications that use cloud services that our customers use on a daily basis, perhaps you would like to join the AWS Mobile SDK and Tools team. We are hiring Software Developers, Web Developers, and Product Managers.

    • May 8, 2013
    • Permalink
    • Comments (0)
  • Yosuke Matsuda

    S3TransferManager for iOS - Part II: Asynchronous Uploads Best Practices

    • May 1, 2013
    • Yosuke Matsuda
    • iOS

    This post demonstrates some best practices for achieving the high performance and avoiding common mistakes when using asynchronous uploads with S3TransferManager.

    Delegate methods may receive different subclasses of AmazonServiceRequest and AmazonServiceResponse

    Because S3TransferManager uses multipart uploads for large data and put object requests for small data, the delegate methods return different subclasses of AmazonServiceRequest and AmazonServiceResponse for each case. For example:

    • request:didSendData:totalBytesWritten:totalBytesExpectedToWrite: returns
      • S3PutObjectRequest for small data
      • S3UploadPartRequest for large data
    • request:didCompleteWithResponse: returns
      • S3PutObjectResponse for small data
      • S3CompleteMultipartUploadResponse for large data.

    When you need to retrieve properties from the subclass, do not indiscriminately cast the AmazonServiceRequest or AmazonServiceResponse object to the subclass.

    -(void)request:(AmazonServiceRequest *)request didSendData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
    {
        // Do not do this!
        S3UploadPartRequest *uploadPartReqeust = (S3UploadPartRequest *)request;
        NSInteger partNumber = uploadPartReqeust.partNumber;
        NSLog(@"Do something with %d", partNumber);
    }
    

    Instead, call respondsToSelector: first to make sure that the request or response can respond to the selector, and then call performSelector::

    -(void)request:(AmazonServiceRequest *)request didSendData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
    {
        if([request respondsToSelector:@selector(partNumber)])
        {
            NSInteger partNumber = [request performSelector:@selector(partNumber)];
            NSLog(@"Do something with %d", partNumber);
        }
    }
    

    Alternatively, you can use isKindOfClass: or isMemberOfClass: as follows:

    -(void)request:(AmazonServiceRequest *)request didSendData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
    {
        if([request isKindOfClass:[S3UploadPartRequest class]])
        {
            S3UploadPartRequest *uploadPartReqeust = (S3UploadPartRequest *)request;
            NSInteger partNumber = uploadPartReqeust.partNumber;
            NSLog(@"Do something with %d", partNumber);
        }
    }
    

    Use requestTag to uniquely identify a request

    Although it is possible to uniquely identify a request with bucket and key names in many situations, it doesn't always guarantee the uniqueness of a request. As mentioned in the previous post, it is often beneficial to use requestTag to uniquely identify request.

    putObjectRequest.requestTag = @"your-unique-tag";
    [self.tm upload:putObjectRequest];
    

    The requestTag property is a free format NSString, so you can pick any naming strategies that make sense for your apps.

    -(void)request:(AmazonServiceRequest *)request didSendData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
    {
        if([request.requestTag isEqualToString:@"your-unique-tag"])
        {
            // Update the progress bar for "your-unique-tag".
        }
    }
    

    Each thread should have its own instance of S3TransferManager

    We recommend that you create an S3TransferManager object for each thread, and do not share that object among multiple threads. It makes your code simpler by eliminating lots of thread controlling logic.

    The operationQueue property of S3TransferManager is static, and is shared among all instances of S3TransferManager objects. This ensures that the maxConcurrentOperationCount is imposed among all instances of S3TransferManager. When updating any properties of operationQueue or calling any methods on it, please keep in mind that other threads may be affected by the changes even though NSOperationQueue itself is thread-safe.

    Delegate of S3TransferManager will be shared

    Whenever you set the delegate to S3TransferManager and do not set the delegate of S3PutObjectRequest, the S3TransferManager's delegate will be used. It is possible that multiple requests share the same delegate.

    Avoid resetting the delegate property of S3TransferManager as much as possible once set because it may affect other requests running on the same S3TransferManager.

    Though it's not encouraged, when you have to use S3TransferManager from multiple classes or threads, consider using the delegate property of S3PubObjectRequest because it is unique to each request, and has minimal side effects on other requests.

    Do not block the main thread

    The AmazonServiceRequestDelegate methods are always called on the main thread. It is safe to update UIs on the delegate methods, but never call blocking methods on them. Take a look at this post for discussion on why you should never block the main thread.

    Best practices for using AmazonServiceRequestDelegate apply

    Because asynchronous S3TransferManager operations use AmazonServiceRequestDelegate, these best practices apply.

    Please let us know if you have any questions.

    Further reading

    • S3TransferManager for iOS - Part I: Asynchronous Uploads

    We are hiring

    If you like building mobile applications that use cloud services that our customers use on a daily basis, perhaps you would like to join the AWS Mobile SDK and Tools team. We are hiring Software Developers, Web Developers, and Product Managers.

    • May 1, 2013
    • Permalink
    • Comments (0)
  • Glenn Dierkes

    Understanding the JARs in the AWS SDK for Android

    • April 23, 2013
    • Glenn Dierkes

    Why all the JARs?

    The AWS SDK for Android contains a number of JARs. Some are specific for development, while others are meant for distribution. This post explains the purpose of each of the JARs, if a JAR has any dependencies, and how to include the right JARs in your Android application.

    Development JARs

    To simplify and aid development, we include JARs that are compiled with full debug symbols. We have two of these types of JARs in the SDK: aws-android-sdk-VERSION-debug.jar and aws-android-sdk-VERSION-ddb-mapper-debug.jar.

    aws-android-sdk-VERSION-debug.jar
    Contains all the classes, including third-party dependencies, necessary for debugging and using any of the SDK's supported services. All code was compiled with the debug option and with all symbols retained. We utilize this JAR in all the samples we provide with the SDK.

    aws-android-sdk-VERSION-ddb-mapper-debug.jar
    Contains all the classes necessary to use the Amazon DynamoDB Object Mapper. Must be used with the aws-android-sdk-VERSION-debug.jar file. The code was compiled with the debug option on with all symbols retained. There are two versions of the DynamoDB Object Mapper, and this JAR contains both. The two mappers are distinguished by distinct package names. The first mapper abstracts the 2011-12-05 version of Amazon DynamoDB and has the package name com.amazonaws.services.dynamodb.datamodeling. The second mapper abstracts the 2012-08-10 version of Amazon DynamoDB and has the package name com.amazonaws.services.dynamodbv2.datamodeling. Note that the 2011-12-05 version of Amazon DynamoDB is deprecated; therefore, we recommend that you use the version two DynamoDB Object Mapper. The DynamoDB Mapper-User Preference sample included with the SDK uses this JAR and utilizes version two of the DynamoDB Object Mapper.

    Distribution JARs

    When you are ready to distribute your application, we provide two options. You can either include a single JAR, or include the core JAR along with the service JARs you use. Each of the JARs below was compiled without the debug option, keeping each JAR as small as possible. To see how you can further reduce the size of your .apk, see this blog post on Using ProGuard with the AWS SDK for Android.

    Single, all-services JAR
    aws-android-sdk-VERSION.jar
    Contains all the classes, including third-party dependencies, for all supported AWS services.

    Core and service JARs
    aws-android-sdk-VERSION-core.jar
    Contains all third-party dependencies and the base platform used to send to and process requests from AWS services. All individual service JARs depend on the classes present in this JAR.

    aws-android-sdk-VERSION-core-no-third-party.jar
    Contains the base platform used to send to and process requests from AWS services but does not contain any of the third-party dependencies. Use of this JAR requires the following third-party dependencies: Streaming API for XML (sjsxp.jar), Jackson Java JSON-processor (jackson-core.jar, jackson-mapper-asl.jar), Apache Commons Codec (commons-codec.jar), and Apache Commons Logging (commons-logging.jar). The supported and verified versions of these libraries are included in the SDK download. If you need to use different versions than those supplied, please understand that we cannot guarantee functionality of the SDK.

    aws-android-sdk-VERSION-autoscaling.jar
    Contains all the classes necessary to use Auto Scaling. Must be used with the aws-android-sdk-VERSION-core.jar file.

    aws-android-sdk-VERSION-cloudwatch.jar
    Contains all the classes necessary to use Amazon CloudWatch. Must be used with the aws-android-sdk-VERSION-core.jar file.

    aws-android-sdk-VERSION-ddb.jar
    Contains all the classes necessary to use Amazon DynamoDB. Must be used with the aws-android-sdk-VERSION-core.jar file. This JAR supports two versions of DynamoDB, 2011-12-05 and 2012-08-10. The two versions of DynamoDB are represented by distinct package names. The 2011-12-05 version is named com.amazonaws.services.dynamodb, and the 2012-08-10 version is named com.amazonaws.services.dynamodbv2. Note that the 2011-12-05 version of DynamoDB is deprecated but included for backward compatibility.

    aws-android-sdk-VERSION-ec2.jar
    Contains all the classes necessary to use Amazon EC2. Must be used with the aws-android-sdk-VERSION-core.jar file.

    aws-android-sdk-VERSION-elb.jar
    Contains all the classes necessary to use Elastic Load Balancing. Must be used with the aws-android-sdk-VERSION-core.jar file.

    aws-android-sdk-VERSION-s3.jar
    Contains all the classes necessary to use Amazon S3. Must be used with the aws-android-sdk-VERSION-core.jar file.

    aws-android-sdk-VERSION-sdb.jar
    Contains all the classes necessary to use Amazon SimpleDB. Must be used with the aws-android-sdk-VERSION-core.jar file.

    aws-android-sdk-VERSION-ses.jar
    Contains all the classes necessary to use Amazon SES. Must be used with the aws-android-sdk-VERSION-core.jar file.

    aws-android-sdk-VERSION-sns.jar
    Contains all the classes necessary to use Amazon SNS. Must be used with the aws-android-sdk-VERSION-core.jar file.

    aws-android-sdk-VERSION-sqs.jar
    Contains all the classes necessary to use Amazon SQS. Must be used with the aws-android-sdk-VERSION-core.jar file.

    aws-android-sdk-VERSION-sts.jar
    Contains all the classes necessary to use AWS Security Token Service (STS). Must be used with the aws-android-sdk-VERSION-core.jar file.

    aws-android-sdk-VERSION-ddb-mapper.jar
    Contains all the classes necessary to use the Amazon DynamoDB Object Mapper. Must be used with aws-android-sdk-VERSION-core.jar and aws-android-sdk-VERSION-ddb.jar files. There are two versions of the Amazon DynamoDB Object Mapper and this JAR contains both. The two mappers are distinguished by distinct package names. The first mapper abstracts the 2011-12-05 version of Amazon DynamoDB and has the package name com.amazonaws.services.dynamodb.datamodeling. The second mapper abstracts the 2012-08-10 version of Amazon DynamoDB and has the package name com.amazonaws.services.dynamodbv2.datamodeling. Note that the 2011-12-05 version of Amazon DynamoDB is deprecated; therefore, we recommend that you use the version two DynamoDB Object Mapper.

    How to Include These JARs in an Application

    The samples included with the SDK for Android are provided as standalone projects set up for you to try out. They all use the aws-android-sdk-VERSION-debug.jar file. All the samples can be imported into Eclipse. Additionally, the AWS Toolkit for Eclipse supports the SDK for Android as noted in this post. By default, the AWS Toolkit for Eclipse uses the aws-android-sdk-VERSION-debug.jar JAR file.

    To use the SDK for Android with an existing application, follow these steps:

    • Create a libs directory within your Android project directory if one does not already exist.
      • Be sure to name the directory libs and NOT lib.
    • Copy either a bundled JAR for all services or the specific JARs for the services you wish to use. You have three options:
      1. Add aws-android-sdk-VERSION-debug.jar. This JAR creates the largest .apk, but allows for full stack traces during development.
      2. Add aws-android-sdk-VERSION.jar. This JAR creates a smaller .apk and a simple bundle when releasing your application.
      3. Add the aws-android-sdk-VERSION-core.jar plus the JARs for the individual services your project will use. This method creates the smallest .apk, but requires a more complicated setup.
        • Note that copying both bundled JARs and service JARs will cause errors.
    • In Eclipse, go to your project, select Properties -> Java Build Path -> Libraries and then click Add JARs. Then select the JARs you added to your libs directory.

    Summary

    We include these JARs in the SDK to help you make the best choice when developing and distributing your application. We hope this helps!

    • April 23, 2013
    • Permalink
    • Comments (0)
  • Glenn Dierkes

    How to Switch from Single to Multiple Frameworks of the AWS SDK for iOS

    • April 22, 2013
    • Glenn Dierkes

    Early versions of the AWS SDK for iOS contained a single framework that contained the classes for all SDK supported services. The SDK now includes multiple frameworks, a base platform framework and individual service frameworks. For more details about the frameworks, see this post.

    Switching an existing project from using the single framework to using multiple frameworks can be done easily with the following steps:

    • Open your existing project in Xcode.
    • Remove the AWSiOSSDK.framework from your project.
      1. Select the AWSiOSSDK.framework file. This file may be in the Frameworks group within your project.
      2. Control or right-click AWSiOSSDK.framework.
      3. In the popup menu that appears, click Delete.
      4. Select the Remove Reference option.
      5. Go to your project's Build Settings and select the Framework Search Paths setting.
      6. Remove those paths that point to the old AWSiOSSDK.framework.
    • Add the appropriate frameworks to your project.
      1. Within the Project Navigator select Frameworks or another group where you wish to place your includes frameworks.
      2. Control or right-click Frameworks.
      3. In the popup menu that appears, click Add Files to "your-project-name"....
      4. Browse to the AWS SDK for iOS directory, select the desired framework, and click Add.
      5. Repeat these steps for each service utilized in your app. Note that you always need to add the AWSRuntime.framework to your project.
    • Updating the imports
      1. Individual service imports can be converted to individual or multiple frameworks as follows:
        #import <AWSiOSSDK/S3/AmazonS3Client.h>
          →  #import <AWSS3/AWSS3.h>
        #import <AWSiOSSDK/SimpleDB/AmazonSimpleDBClient.h>
          →  #import <AWSSimpleDB/AWSSimpleDB.h>
        #import <AWSiOSSDK/SQS/AmazonSQSClient.h>
          →  #import <AWSSQS/AWSSQS.h>
        #import <AWSiOSSDK/SNS/AmazonSNSClient.h>
          →  #import <AWSSNS/AWSSNS.h>
        #import <AWSiOSSDK/CloudWatch/AmazonCloudWatchClient.h>
          →  #import <AWSCloudWatch/AWSCloudWatch.h>
        #import <AWSiOSSDK/EC2/AmazonEC2Client.h>
          →  #import <AWSEC2/AWSEC2.h>
        #import <AWSiOSSDK/SES/AmazonSESClient.h>
          →  #import <AWSSES/AWSSES.h>
        #import <AWSiOSSDK/AutoScaling/AmazonAutoScalingClient.h>
          →  #import <AWSAutoScaling/AWSAutoScaling.h>
        #import <AWSiOSSDK/ElasticLoadBalancing/AmazonElasticLoadBalancingClient.h>
          →  #import <AWSElasticLoadBalancing/AWSElasticLoadBalancing.h>
        #import <AWSiOSSDK/DynamoDB/AmazonDynamoDBClient.h>
          →  #import <AWSDynamoDB/AWSDynamoDB.h>
        #import <AWSiOSSDK/STS/AmazonSecurityTokenServiceClient.h>
          →  #import <AWSSecurityTokenService/AWSSecurityTokenService.h>
      2. General SDK imports, for logging or other utilities can be converted to a single import (#import <AWSRuntime/AWSRuntime.h>). For example:
        #import <AWSiOSSDK/AmazonLogger.h>
          →  #import <AWSRuntime/AWSRuntime.h>
        #import <AWSiOSSDK/AmazonEndpoints.h>
          →  #import <AWSRuntime/AWSRuntime.h>
        #import <AWSiOSSDK/AmazonServiceResponse.h>
          →  #import <AWSRuntime/AWSRuntime.h>

    Summary

    Please let us know if this helped by leaving a comment below.

    If you like building mobile applications that use cloud services our customers use on a daily basis, perhaps you would like to join the AWS Mobile SDK and Tools team. We are hiring Software Developers, Web Developers, and Product Managers.

    • April 22, 2013
    • Permalink
    • Comments (1)
  • Glenn Dierkes

    Understanding the Frameworks of the AWS SDK for iOS

    • April 19, 2013
    • Glenn Dierkes

    Why all the Frameworks?

    The AWS SDK for iOS now includes separate frameworks for each AWS service supported by the SDK. In addition to these service-level frameworks is a runtime framework that contains the base platform the services frameworks utilize. Separating these frameworks allows developers to choose which services to include in their app and more importantly which version. Therefore, as we update the AWS SDK for iOS, you can choose which service framework to update in your application based on the changes offered.

    Description of the Frameworks

    AWSRuntime.framework
    Contains all third-party dependencies and the base platform used to send to and process requests from AWS services. All individual service frameworks depend on this framework.

    AWSAutoScaling.framework
    Contains all the classes necessary to use Auto Scaling. Must be used with the AWSRuntime.framework framework.

    AWSCloudWatch.framework
    Contains all the classes necessary to use Amazon CloudWatch. Must be used with the AWSRuntime.framework framework.

    AWSDynamoDB.framework
    Contains all the classes necessary to use Amazon DynamoDB. Must be used with the AWSRuntime.framework framework. This contains the latest version of the Amazon DynamoDB service, currently version 2012-08-10. If you still wish to use the older version of Amazon DynamoDB, please see the legacy AWSiOSSDK.framework.

    AWSEC2.framework
    Contains all the classes necessary to use Amazon EC2. Must be used with the AWSRuntime.framework framework.

    AWSElasticLoadBalancing.framework
    Contains all the classes necessary to use Elastic Load Balancing. Must be used with the AWSRuntime.framework framework.

    AWSS3.framework
    Contains all the classes necessary to use Amazon S3. Must be used with the AWSRuntime.framework framework.

    AWSSimpleDB.framework
    Contains all the classes necessary to use Amazon SimpleDB. Must be used with the AWSRuntime.framework framework.

    AWSSES.framework
    Contains all the classes necessary to use Amazon SES. Must be used with the AWSRuntime.framework framework.

    AWSSNS.framework
    Contains all the classes necessary to use Amazon SNS. Must be used with the AWSRuntime.framework framework.

    AWSSQS.framework
    Contains all the classes necessary to use Amazon SQS. Must be used with the AWSRuntime.frameworkr framework.

    AWSSecurityTokenService.framework
    Contains all the classes necessary to use AWS Security Token Service (STS). Must be used with the AWSRuntime.framework framework.

    AWSPersistence.framework
    Contains all the classes necessary to use the AWS Persistence Framework for Core Data. Must be used with the AWSRuntime.framework and AWSDynamoDB.framework frameworks.

    Deprecated Framework

    AWSiOSSDK.framework
    This all-in-one framework contains all the classes and dependencies of the entire AWS SDK for iOS. Including this framework in your project provides access to all services. Going forward, we intend to update only the individual frameworks, which will provide you greater control. This framework also supports the older version of the Amazon DynamoDB service, version 2011-12-05. This framework does not include the AWS Persistence Framework for Core Data. If you wish to use the functionality in your app, you will need to migrate to the service-specific frameworks as described above.

    Summary

    These individual frameworks provide a finer level of control as you update your application. Please let us know if this helped by leaving a comment below.

    If you like building mobile applications that use cloud services that our customers use on a daily basis, perhaps you would like to join the AWS Mobile SDK and Tools team. We are hiring Software Developers, Web Developers, and Product Managers.

    • April 19, 2013
    • Permalink
    • Comments (0)
  • Bob Kinney

    New AWS Mobile SDKs Release 1.5.0

    • April 18, 2013
    • Bob Kinney

    We have just released a new version of the AWS Mobile SDKs. The individual SDKs for version 1.5.0 can be downloaded from the following pages:

    • AWS SDK for iOS
    • AWS SDK for Android

    This new version of the SDKs contains updates for Local Secondary Indexes in Amazon DynamoDB, various bug fixes and individual service frameworks on iOS. For full details on the release, please see the release notes for the individual SDKs below:

    • Release notes for the AWS SDK for Android
    • Release notes for the AWS SDK for iOS

    We'll have more posts in the following days that will go in depth to many of the changes in the SDKs.

    Please let us know what you think of this latest version of the AWS Mobile SDKs.

    • April 18, 2013
    • Permalink
    • Comments (0)
  • Bob Kinney

    Logging with the AWS SDK for Android

    • April 5, 2013
    • Bob Kinney
    • Android

    Logging can be an effective way to debug your application or library, capturing information that can help diagnose errors in logic or verify assumptions of data consistency. The AWS SDK for Android includes logging via the Apache Commons logging project. The SDK makes use of this library and its link to [http://developer.android.com/tools/help/logcat.html Android LogCat] to provide logging for internal operations of the SDK. By default, only informational, warning, and error messages will be visible by LogCat, but in this post I'll discuss how you can control the level of logging generated by the SDK.

    Disabling All Logging

    If you want to disable '''all''' logging in the SDK, you simply need to insert the following piece of code in your Android app, perhaps in your initial Activity's onCreate method:

    java.util.logging.Logger.getLogger("com.amazonaws").setLevel(java.util.logging.Level.OFF);
    

    Enabling Request Logging

    Outside of the basic informational and error logging, the SDK can also offer basic request and response logging when talking to AWS services. This logging is useful to debug successful requests that are not producing the desired result, and you may be asked to enable it if you contact AWS support. Enabling this logging requires two steps; first, you need to add the following code to your Android app:

    java.util.logging.Logger.getLogger("com.amazonaws").setLevel(java.util.logging.Level.FINEST);
    

    Make sure you remove this code before exporting your app for use in production as it will effect your app's performance.

    Secondly, you need to execute the following [http://developer.android.com/tools/help/adb.html Adroid Debug Bridge] (ADB) shell command to enable LogCat to display these new log messages:

    adb shell setprop log.tag.com.amazonaws.request DEBUG
    

    You must run this command either with your Android device connected and configured for development or with your AVD running in the emulator. This setting persists only until the emulator/device restarts.

    Enabling HTTP Client Logging

    If you need to debug further down in the internals of the SDK (either at the request of AWS support or for your own interests), you can log the raw HTTP requests and responses via Apache HTTP client logging. To enable this logging, you must first add the following code to your app:

    java.util.logging.Logger.getLogger("org.apache.http").setLevel(java.util.logging.Level.FINEST);
    

    As with request logging, make sure you remove this code before exporting your app for use in production as it will effect your app's performance.

    Secondly, you need to execute the following ADB shell commands to enable LogCat to display these new log messages:

    adb shell setprop log.tag.org.apache.http.headers VERBOSE 
    adb shell setprop log.tag.org.apache.http.wire VERBOSE
    

    You must run these commands either with your Android device connected and configured for development or with your AVD running in the emulator. This setting persists only until the emulator/device restarts.

    As always, if you have any questions, please feel free to leave a comment below or post in our forums.

    If you like building mobile applications that use cloud services that our customers use on a daily basis, perhaps you would like to join the AWS Mobile SDK and Tools team. We are hiring Software Developers, Web Developers, and Product Managers.

    • April 5, 2013
    • Permalink
    • Comments (0)
  • Yangfan Zhang

    TransferManager for Android

    • March 27, 2013
    • Yangfan Zhang
    • Android

    The AWS SDK for Android has a high-level utility—TransferManager—for managing file transfers to Amazon S3. TransferManager is designed to make transfers between your application to Amazon S3 easy and convenient. Meanwhile, the smart logic behind it can provide transfers with better throughput and performance.

    Why TransferManager

    TransferManager can have several advantages over low-level APIs for file transfers.

    • Better performance: It makes extensive use of multipart uploads. When dealing with a large file, it attempts to use multiple threads to upload multiparts of the file at once, so that throughput can be improved significantly.
    • More convenient: It hides the complexity for you. It has several convenient methods that save you from creating request objects before transferring files. Also, it allows you to download or upload a directory recursively.
    • Easy migration: If you are already using low-level APIs, don't worry, as you will find the migration very easy. You can pass request objects to TransferManager just like you pass them to low-level APIs. I will show this to you in an example later.

    How to Use TransferManager

    With TransferManager, it's as simple as the following to upload a file to Amazon S3:

    AWSCredentials credential = new BasicAWSCredentials("access key", "secret key");
    
    // TransferManager manages its own thread pool, so
    // please share it when possible.
    TransferManager manager = new TransferManager(credential);
    
    // Transfer a file to an S3 bucket.
    Upload upload = manager.upload(bucket, key, file);
    

    The upload method is non-blocking and returns immediately with an Upload object. Wait for the upload to complete and get the result of this upload by making the following blocking call.

    UploadResult result = upload.waitForUploadResult();
    

    If you are interested in tracking the transfer progress, track it inside a while loop till the transfer is done, like so:

    while (!upload.isDone()) {
        long transferred = upload.getProgress().getBytesTransfered();
        // publish progress
        ...
        Thread.sleep(200);
    }
    

    Easy Migration

    It might be a great hassle to use TransferManager if you are used to low-level APIs to transfer files. However, you may find the migration more simple and painless after you read the following example. Your code probably looks like this:

    // Put the image data into S3.
    try {
        ...
        // Content type is determined by file extension.
        PutObjectRequest por = new PutObjectRequest(
            Constants.getPictureBucket(), Constants.PICTURE_NAME,
            imageFile);
        // Send the request.
        s3Client.putObject(por);
    } catch (Exception exception) {
        result.setErrorMessage(exception.getMessage());
    }
    

    TransferManager can take a PutObjectRequest object to start the transfer. Any listener set to the object is passed to TransferManager. Therefore, a one-line change is required after TransferManager is initialized:

    TransferManager manager = new TransferManager(s3Client);
    ...
    // Put the image data into S3.
    try {
        ...
        // Content type is determined by file extension.
        PutObjectRequest por = new PutObjectRequest(
            Constants.getPictureBucket(), Constants.PICTURE_NAME,
            imageFile);
        // Send the request.
        manager.upload(por);
    } catch (Exception exception) {
        result.setErrorMessage(exception.getMessage());
    }
    

    Configuration

    Underneath TransferManager is an AmazonS3Client. You can configure its client options such as user agent string, max retry attempts, connection timeout, etc. Please refer to ClientConfiguration for a complete set of configurable options.

    ClientConfiguration s3Config = new ClientConfiguration();
    // Sets the maximum number of allowed open HTTP connections.
    s3Config.setMaxConnections(5);
    // Sets the amount of time to wait (in milliseconds) for data
    // to be transferred over a connection.
    s3Config.setSocketTimeout(30000);
    
    AmazonS3Client s3Client = new AmazonS3Client(credential, s3Config);
    TransferManager manager = new TransferManager(s3Client);
    

    TransferManager itself has two configurable options: minimum part size for upload parts, and threshold in bytes for when to use multipart uploads. They are configurable through TransferManagerConfiguration.

    TransferManagerConfiguration tmConfig = new TransferManagerConfiguration();
    // Sets the minimum part size for upload parts.
    tmConfig.setMinimumUploadPartSize(5 * 1024 * 1024);
    // Sets the size threshold in bytes for when to use multipart uploads.
    tmConfig.setMultipartUploadThreshold(5 * 1024 * 1024);
    
    manager.setConfiguration(tmConfig);
    

    Amazon S3 Multipart Upload requires the minimum part size to be at least 5 MB. Make sure both options are greater or equal to 5 MB when you configure TransferManager.

    After you read this post, I hope you find TransferManager useful. Using TransferManager provides convenience and performance benefits. If you have further questions, please let me know.

    If you like building mobile applications that use cloud services that our customers use on a daily basis, perhaps you would like to join the AWS Mobile SDK and Tools team. We are hiring Software Developers, Web Developers, and Product Managers.

    • March 27, 2013
    • Permalink
    • Comments (1)
  • Yosuke Matsuda

    S3TransferManager for iOS - Part I: Asynchronous Uploads

    • March 20, 2013
    • Yosuke Matsuda
    • iOS

    Transferring files to and from Amazon Simple Storage Service (S3) is one of the most common operations we see for developers using the AWS SDK for iOS. Handling multiple files or larger files can sometimes be difficult, particularly in a way that is asynchronous and allows for accurate progress and retries. To help developers handle these kinds of operations, we added the S3TransferManager class.

    S3TransferManager is an easy-to-use, high level component that is designed to efficiently upload lots of large files to Amazon S3. Underneath, it uses NSOperationQueue to handle multiple uploads efficiently, and automatically choose the right upload mode: multipart uploads for large files, and put requests for small files. Multipart uploads break up large files into multiple parts and individually upload these parts. When a part upload fails, it retries only the part that failed. S3TransferManager also aggregates the AmazonServiceRequestDelegate methods for multiple part uploads. Because of many added benefits, consider using S3TransferManager first, whenever you need to upload data to Amazon S3 before directly using AmazonS3Client to do so.

    Using S3TransferManager

    It is easy to get started with S3TransferManager. Here are the steps to make an asynchronous upload request:

    1. Instantiate an AmazonS3Client object.
    2. Instantiate an S3TransferManager object.
    3. Pass the AmazonS3Client object to the S3TransferManager object.
    4. Create and configure an S3PutObjectRequest object.
    5. Invoke upload: on the S3TransferManager object with the S3PutObjectRequest object.

    Here is a small code snippet to asynchronously upload a file to Amazon S3:

    // Note that this is not the preferred way to create the AmazonS3Client object. Do not ship apps with your credentials in them.
    AmazonS3Client *s3 = [[AmazonS3Client alloc] initWithAccessKey:@"your-access-key"
                                                     withSecretKey:@"your-secret-key"];
    
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"testData"
                                                         ofType:@"txt"];
    self.tm = [S3TransferManager new];
    self.tm.s3 = s3;
    
    S3PutObjectRequest *putObjectRequest = [[S3PutObjectRequest alloc] initWithKey:@"your-key"
                                                                          inBucket:@"your-bucket"];
    putObjectRequest.filename = filePath;
    
    [self.tm upload:putObjectRequest];
    

    Please note that upload: is an asynchronous method and returns immediately. Since it doesn't block the running thread, it is safe to call this method on the main thread.

    S3TransferManager has the following three convenient methods for asynchronously uploading files:

    - (void)uploadData:(NSData *)data bucket:(NSString *)bucket key:(NSString *)key;
    - (void)uploadFile:(NSString *)filename bucket:(NSString *)bucket key:(NSString *)key;
    - (void)uploadStream:(NSInputStream *)stream contentLength:(long)contentLength bucket:(NSString *)bucket key:(NSString *)key;
    

    For instance, you can rewrite the first code snippet using the uploadFile:bucket:key: method:

    // Note that this is not the preferred way to create the AmazonS3Client object. Do not ship apps with your credentials in them.
    s3 = [[AmazonS3Client alloc] initWithAccessKey:@"your-access-key"
                                     withSecretKey:@"your-secret-key"];
    
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"testData"
                                                         ofType:@"txt"];
    
    self.tm = [S3TransferManager new];
    self.tm.s3 = s3;
    
    [self.tm uploadFile:filePath bucket:@"your-bucket" key:@"your-key"];
    

    Configuring S3TransferManager

    You can customize S3TransferManager behaviors. I'm going to highlight three of them.

    Getting responses through AmazonServiceRequestDelegate

    First, your delegate object needs to adopt the AmazonServiceRequestDelegate protocol:

    #import <AWSiOSSDK/S3/AmazonS3Client.h>
    
    @interface YourViewController : UIViewController <AmazonServiceRequestDelegate>
    {
    }
    

    Then pass the delegate object to S3PutObjectRequest:

    putObjectRequest.delegate = self;
    

    Also, you can specify a default delegate by setting it to the S3TransferManager object:

    self.tm.delegate = self;
    

    Whenever the delegate property of the S3PutObjectRequest is not set, S3TransferManager's delegate is used. For the aforementioned convenient methods, which don't take S3PutObjectRequest, S3TransferManager's delegate is always used.

    Now you can receive callbacks through AmazonServiceRequestDelegate:

    -(void)request:(AmazonServiceRequest *)request didReceiveResponse:(NSURLResponse *)response
    {
        NSLog(@"didReceiveResponse called: %@", response);
    }
    
    -(void)request:(AmazonServiceRequest *)request didReceiveData:(NSData *)data
    {
        NSLog(@"didReceiveData called");
    }
    
    -(void)request:(AmazonServiceRequest *)request didSendData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
    {
        NSLog(@"didSendData called: %d - %d / %d", bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
    }
    
    -(void)request:(AmazonServiceRequest *)request didCompleteWithResponse:(AmazonServiceResponse *)response
    {
        NSLog(@"didCompleteWithResponse called: %@", response);
    }
    
    -(void)request:(AmazonServiceRequest *)request didFailWithError:(NSError *)error
    {
        NSLog(@"didFailWithError called: %@", error);
    }
    

    These delegate methods are always called on the main thread so you can update UI elements in these methods. Also, be reminded not to make any synchronous network requests on the main thread.

    The delegate of S3TransferManager is shared among multiple upload requests, so often it is beneficial to tag the request so that you can differentiate each request in the delegate methods.

    putObjectRequest.requestTag = @"your-unique-tag";
    [self.tm upload:putObjectRequest];
    

    For example, if you tag your request like above, you can update a specific progress bar for the request in the delegate method:

    -(void)request:(AmazonServiceRequest *)request didSendData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
    {
        if([request.requestTag isEqualToString:@"your-unique-tag"])
        {
            // Update the progress bar for "your-unique-tag".
        }
    }
    

    Customize AmazonS3Client Properties

    You can customize properties of AmazonS3Client. Look at AmazonAbstractWebServiceClient.h for available properties. Here is an example to update endpoint, maxRetries, and timeout:

    s3.endpoint = [AmazonEndpoints s3Endpoint:US_WEST_2];
    s3.maxRetries = 10;
    s3.timeout = 240;
    
    self.tm = [S3TransferManager new];
    self.tm.s3 = s3;
    

    Note that explicitly setting the endpoint to the region that the bucket is located in will improve performance.

    Customize S3TransferManager Properties

    You can also update the properties of S3TransferManager. Take a look at S3TransferManager.h for all of the available properties. Here is an example to limit the maximum number of concurrent upload operations allowed:

    self.tm = [S3TransferManager new];
    self.tm.s3 = s3;
    self.tm.operationQueue.maxConcurrentOperationCount = 2;
    

    Do not set maxConcurrentOperationCount too high. The default value of maxConcurrentOperationCount is 3, and in our test, setting it above the default may result in unreliable progress feedback on iOS 5 and above.

    Putting everything together, the sample snippet will look like this:

    // Note that this is not the preferred way to create the AmazonS3Client object. Do not ship apps with your credentials in them.
    AmazonS3Client *s3 = [[AmazonS3Client alloc] initWithAccessKey:@"your-access-key"
                                                     withSecretKey:@"your-secret-key"];
    s3.endpoint = [AmazonEndpoints s3Endpoint:US_WEST_2];
    s3.maxRetries = 10;
    s3.timeout = 240;
    
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"testData"
                                                         ofType:@"txt"];
    
    self.tm = [S3TransferManager new];
    self.tm.operationQueue.maxConcurrentOperationCount = 2;
    self.tm.s3 = s3;
    
    S3PutObjectRequest *putObjectRequest = [[S3PutObjectRequest alloc] initWithKey:@"your-key"
                                                                          inBucket:@"your-bucket"];
    putObjectRequest.delegate = self;
    putObjectRequest.requestTag = @"your-unique-tag";
    putObjectRequest.filename = filePath;
    
    [self.tm upload:putObjectRequest];
    

    I hope this post quickly get you started on the new S3TransferManager for iOS. If you have any questions regarding S3TransferManager, please leave a comment below!

    Further reading

    • S3TransferManager for iOS - Part II: Asynchronous Uploads Best Practices

    We are hiring

    If you like building mobile applications that use cloud services that our customers use on a daily basis, perhaps you would like to join the AWS Mobile SDK and Tools team. We are hiring Software Developers, Web Developers, and Product Managers.

    • March 20, 2013
    • Permalink
    • Comments (9)
  • Bob Kinney

    Using the AmazonCredentialsProvider Protocol in the AWS SDK for iOS

    • March 14, 2013
    • Bob Kinney

    As an AWS developer, you should already be aware of how credentials are necessary to make calls to our various services. As a mobile developer, you should also be aware of the dangers of embedding credentials in your application (see our previous post on this). In order to help developers deliver credentials to the service clients, the AWS SDK for iOS contains the AmazonCredentialsProvider protocol. The goal of this protocol is to standardize a method by which service clients in the SDK can consume temporary, refreshable credentials. The SDK contains two reference implementations for this protocol: AmazonStaticCredentialsProvider, which wraps long term credentials, and AmazonSTSCredentialsProvider, which makes a call to AWS Security Token Service (STS) when credentials expire. This protocol could also be used to fetch credentials from a custom Token Vending Machine (as shown in our Locations2 sample), or another credentials source.

    Understanding the Protocol

    The AmazonCredentialsProvider protocol contains two required methods:

    • credentials – Returns the credentials to use for a call to AWS. This is called every time the SDK needs credentials, so implementations should keep this in mind when considering whether to cache credentials or fetch from a remote source every time.
    • refresh – Forces a refresh of the stored/cache credentials. Depending on your implementation, this may or may not be necessary (for instance, the AmazonStaticCredentialsProvider treats this as a no-op).

    The service clients make use of these two methods during the execution of a request like so:

    1. The request is passed to the client for invocation.
    2. The client calls credentials to fetch the current valid credentials. This may require an additional service call to fetch new, valid credentials.
    3. The client uses the retrieved credentials to sign the request and send to AWS.

    From here, the path diverges depending on whether or not the request is running asynchronously via delegates (see our series on asynchronous operation of the SDK for more info).

    For synchronous requests, if the operation fails with an expired or invalid token, the client calls refresh on the provider and then retries the request.

    For asynchronous requests, you need to handle this error in your delegate callbacks, and then refresh the provider and retry the request.

    How the SDK Uses Providers

    Using this provider protocol is the default for all service clients in the SDK. Using either of these existing methods below will create an instance of AmazonStaticCredentialsProvider internally.

    // create the client
    AmazonS3Client *s3 = [AmazonS3Client alloc];
    // initialize with ACCESS and SECRET key
    [s3 initWithAccessKey:ACCESS_KEY withSecretKey:SECRET_KEY];
    // or with AmazonCredentials object
    [s3 initWithCredentials:CREDENTIALS_OBJECT];
    

    If creating your own provider, or using the AmazonSTSCredentialsProvider included in the SDK, you can use the following:

    // create the client
    AmazonS3Client *s3 = [AmazonS3Client alloc];
    // create the Provider (using STS)
    AmazonSecurityTokenServiceClient *sts = 
        [[AmazonSecurityTokenServiceClient alloc] initWithCredentials:CREDENTIALS_OBJECT];
    AmazonSTSCredentialsProvider *provider = 
        [[AmazonSTSCredentialsProvider alloc] initWithClient:sts];
    [s3 initWithCredentialsProvider:provider];
    

    Note: These examples are using static credentials for demonstration, but we strongly recommend that you not embed credentials in your application.

    Caveats

    If you plan to implement your own AmazonCredentialsProvider, be aware of a few things:

    • Providers are retained by the client, so if you are using the same provider instance for multiple clients, you need to be prepared to handle concurrent access.
    • When operating synchronously, the SDK calls refresh when encountering an expired or invalid token, but we recommend that providers refresh internally prior to explicit expiration of temporary credentials to reduce retries of failed requests.

    Future Development

    AWS is committed to improving the development experience for our customers, so we will continue to add new providers to the AWS SDK for iOS where it makes sense. In the interim, please feel free to write your own provider, and if you believe it will be useful to the community, submit a pull request request to our GitHub repository.

    If you like building mobile applications that use cloud services that our customers use on a daily basis, perhaps you would like to join the AWS Mobile SDK and Tools team. We are hiring Software Developers, Web Developers, and Product Managers.

    • March 14, 2013
    • Permalink
    • Comments (0)
  •  Previous
  • 1
  • 2
  • 3
  • Next 

The search query cannot be empty or single character.

Latest Blog Entries

  • Making Asynchronous Calls with Handler
  • S3TransferManager for iOS - Part II: Asynchronous Uploads Best Practices
  • Understanding the JARs in the AWS SDK for Android
  • How to Switch from Single to Multiple Frameworks of the AWS SDK for iOS
  • Understanding the Frameworks of the AWS SDK for iOS
  • New AWS Mobile SDKs Release 1.5.0
  • Logging with the AWS SDK for Android
  • TransferManager for Android
  • S3TransferManager for iOS - Part I: Asynchronous Uploads
  • Using the AmazonCredentialsProvider Protocol in the AWS SDK for iOS

AWS Blogs

  • The AWS Blog
  • Security
  • Amazon SES
  • Java Development
  • Mobile Development
  • Ruby Development

Useful Links

  • AWS SDK for iOS on GitHub
  • AWS SDK for iOS Getting Started Guide
  • AWS SDK for Android on GitHub
  • AWS SDK for Android Getting Started Guide
  • AWS Mobile Development Center
  • AWS Mobile Development Forum

Archive

SDKs

  • AWS SDK for Java
  • AWS SDK for .NET
  • AWS SDK for Ruby
  • AWS SDK for PHP
  • AWS SDK for Python
  • AWS SDK for iOS
  • AWS SDK for Android

©2013, Amazon Web Services, Inc. or its affiliates. All rights reserved.
  • Terms of Use
  • Privacy Policy