Messaging Users with Amazon SNS and Amazon SQS

Messaging Users with Amazon SNS and Amazon SQS using the AWS SDK for iOS and the AWS SDK for Android


Submitted By: Glenn@AWS
AWS Products Used: Amazon SQS, Amazon SNS, Android
Language(s): Java, Objective-C
Created On: December 16, 2011


Version 2 of the AWS Mobile SDK
  • This article and sample apply to Version 1 of the AWS Mobile SDK. If you are building new apps, we recommend you use Version 2. For details, please visit the AWS Mobile SDK page.
  • This content is being maintained for historical reference.

Messaging Users with Amazon SNS and Amazon SQS using the AWS SDK for iOS and the AWS SDK for Android

Overview

This article discusses how mobile applications can use Amazon Web Services to communicate with users via email, short message service (SMS), and other communication channels. The sample code presented here uses Amazon Simple Notification Service and Amazon Simple Queue Service. Amazon Simple Notification Service (Amazon SNS) makes it easy to set up, manage, and send notifications from mobile applications and have these notifications delivered immediately to any users who have chosen to subscribe to them. Amazon SNS provides a highly scalable, flexible, and cost-effective method to implement such notification systems.

Amazon Simple Queue Service (Amazon SQS), also discussed here, offers a reliable, highly scalable, hosted queue for storing messages. The types of messages supported by Amazon SQS include—but aren't limited to—the notification messages sent from Amazon SNS.

Together, Amazon SNS and Amazon SQS enable developers to create applications that can message large numbers of users in multiple formats quickly and easily.

The sample application described here demostrates how mobile applications can message their users through Amazon SNS and Amazon SQS. The sample demonstrates how to use Amazon SNS to create a topic, subscribe users to that topic, and publish notifications to the topic. Subscribers to the topic can receive their notifications via email, SMS, or an Amazon SQS queue. Amazon SQS and Amazon SNS can also be used to create other types of communication systems not shown here.

This article shows sample code for both the iOS and Android platforms. The complete sample code and project files are included in the AWS SDKs for these mobile platforms. Links to the SDKs are available at the end of this article.

To use the AWS SDK for iOS or the AWS SDK for Android, you will need AWS credentials, that is, an Access Key ID and Secret Access Key. If you haven't already signed up for Amazon Web Services (AWS), you will need to do that first to get your credentials. You can sign up for AWS here. After you sign up, you can retrieve your credentials at this page.

Creating Amazon SQS and Amazon SNS Clients

Making requests to Amazon SNS and Amazon SQS requires creating a client for each service. The code below shows how to create clients for both services on both the iOS and Android platforms.

  • iOS

AmazonSNSClient snsClient = [[AmazonSNSClient alloc] initWithAccessKey:ACCESS_KEY_ID withSecretKey:SECRET_KEY];            
AmazonSQSClient sqsClient = [[AmazonSQSClient alloc] initWithAccessKey:ACCESS_KEY_ID withSecretKey:SECRET_KEY];            
  • Android

AWSCredentials credentials = new BasicAWSCredentials( Constants.ACCESS_KEY_ID, Constants.SECRET_KEY );		
AmazonSNSClient snsClient = new AmazonSNSClient( credentials );
AmazonSQSClient sqsClient = new AmazonSQSClient( credentials );

Topic Creation

Amazon SNS uses topics to route notifications from publishers to subscribers. The term publisher refers to an application that sends notifications; the term subscriber refers to an entity, such as a user, that receives notifications. Topics provide a junction point for publishers and subscribers to communicate with each other. Once a topic is created, subscribers can be added to the topic and receive notifications/messages. The DisplayName attribute is added to a topic to allow notifications to be sent via SMS.

  • iOS

SNSCreateTopicRequest *ctr = [[[SNSCreateTopicRequest alloc] initWithName:TOPIC_NAME] autorelease];
SNSCreateTopicResponse *response = [snsClient createTopic:ctr];    

SNSSetTopicAttributesRequest* st = [[[SNSSetTopicAttributesRequest alloc] initWithTopicArn:response.topicArn andAttributeName:@"DisplayName" andAttributeValue:TOPIC_NAME] autorelease];
[snsClient setTopicAttributes:st];        
  • Android

CreateTopicRequest ctr = new CreateTopicRequest( Constants.TOPIC_NAME );
CreateTopicResult result = snsClient.createTopic( ctr );
	        
SetTopicAttributesRequest tar = new SetTopicAttributesRequest( result.getTopicArn(), "DisplayName", "MessageBoard" );
this.snsClient.setTopicAttributes( tar );  

Subscribing to Topics

In order for notifications sent to a topic to be received, you have to subscribe an endpoint to that topic. The endpoint corresponds to a recipient. An endpoint is an email address, SMS number, web server, or Amazon SQS queue. If you are using an Amazon SQS queue, it needs to be configured to receive notification messages from Amazon SNS. Once you subscribe an endpoint to a topic and the subscription is confirmed, the endpoint will receive all messages published to that topic.

  • iOS

SNSSubscribeRequest *sr = [[[SNSSubscribeRequest alloc] initWithTopicArn:topicARN andProtocol:@"email" andEndpoint:emailAddress] autorelease];
[snsClient subscribe:sr];        
  • Android

SubscribeRequest sr = new SubscribeRequest( this.topicARN, "email", email );
this.snsClient.subscribe( sr );

Listing a Topic's Subscribers

Listing the subscribers for a topic provides the endpoint and corresponding protocol for each subscriber who receives notification via that topic. The protocol for an endpoint depends on the type of endpoint. For example, endpoints that are email addresses have a protocol of SMTP.

  • iOS

SNSListSubscriptionsByTopicRequest *ls = [[[SNSListSubscriptionsByTopicRequest alloc] initWithTopicArn:topicARN] autorelease];
SNSListSubscriptionsByTopicResponse *response = [snsClient listSubscriptionsByTopic:ls];
return response.subscriptions;
                    
  • Android

ListSubscriptionsByTopicRequest ls = new ListSubscriptionsByTopicRequest( this.topicARN );
ListSubscriptionsByTopicResult response = this.snsClient.listSubscriptionsByTopic( ls );
return response.getSubscriptions();

Publishing Notifications

Publishers send notifications to topics. Once a new notification is published, Amazon SNS attempts to deliver that notification to every endpoint that is subscribed to the topic.

  • iOS

SNSPublishRequest *pr = [[[SNSPublishRequest alloc] initWithTopicArn:topicARN andMessage:theMessage] autorelease];
[snsClient publish:pr];
  • Android

PublishRequest pr = new PublishRequest( this.topicARN, message );
this.snsClient.publish( pr );	

Unsubscribing from Topics

Unsubscribing removes the endpoint from the topic and stops notifications from being received.

  • iOS

SNSUnsubscribeRequest *unsubscribeRequest = [[[SNSUnsubscribeRequest alloc] initWithSubscriptionArn:subscriptionArn] autorelease];
[snsClient unsubscribe:unsubscribeRequest];
  • Android

UnsubscribeRequest unsubscribeRequest = new UnsubscribeRequest( subscriptionArn );
this.snsClient.unsubscribe( unsubscribeRequest );

Creating a Queue

The first task in using Amazon SQS is to create a queue. Once a queue is created it can be subscribed as an endpoint to an Amazon SNS topic.

  • iOS

SQSCreateQueueRequest *cqr = [[[SQSCreateQueueRequest alloc] initWithQueueName:QUEUE_NAME] autorelease];
SQSCreateQueueResponse *response = [sqsClient createQueue:cqr];

return response.queueUrl
  • Android

CreateQueueRequest cqr = new CreateQueueRequest( Constants.QUEUE_NAME );
CreateQueueResult result = this.sqsClient.createQueue( cqr );
return result.getQueueUrl();

Subscribing a Queue to a Topic

Here's how to subscribe a queue to a topic. However, for the queue to receive messages, you must also add a policy to the queue. See below.

  • iOS

NSString *queueArn = [self createMessageQueue];
		
SNSSubscribeRequest *request = [[[SNSSubscribeRequest alloc] init] autorelease];
request.endpoint = queueArn;
request.protocol = @"sqs";
request.topicArn = topicARN;
		
[snsClient subscribe:request];
  • Android

String queueArn = this.createMessageQueue();
		
SubscribeRequest request = new SubscribeRequest();
request.withEndpoint( queueArn ).withProtocol( "sqs" ).withTopicArn( this.topicARN );
		
this.snsClient.subscribe( request );

Adding a policy to a Queue

In order for a queue to receive messages from a topic, the queue must have a policy object that specifies that the topic has sqs:SendMessage permission for the queue. For further details see the Amazon SNS FAQ. For more information about queue policies see the Amazon SQS documentation. Once the policy object is created it can be attached to the queue as follows:

  • iOS

NSMutableDictionary *attributes = [[[NSMutableDictionary alloc] init] autorelease];
[attributes setValue:[self generateSqsPolicyForTopic:queueArn] forKey:@"Policy"];
        
SQSSetQueueAttributesRequest *request = [[[SQSSetQueueAttributesRequest alloc] initWithQueueUrl:theQueueUrl andAttributes:attributes] autorelease];    
[sqsClient setQueueAttributes:request];
  • Android

HashMap attributes = new HashMap();
attributes.put("Policy", generateSqsPolicyForTopic( queueArn, this.topicARN ) );
this.sqsClient.setQueueAttributes(new SetQueueAttributesRequest( queueUrl, attributes ) );

Receiving Messages from a Queue

Now that a message is in the queue, you can receive it, which requires getting it from the queue. When requesting to get a message from the queue, you can't specify which message to get. Instead, you simply specify the maximum number of messages you want to get (up to 10), and Amazon SQS returns up to that maximum number. Because Amazon SQS is a distributed system and the particular queue we're working with here has very few messages in it, the response to the receive request might be empty. Therefore, you should rerun the sample until you get the message. You should design your own application so that it continues to poll the queue until it gets one or more messages.

  • iOS

SQSReceiveMessageRequest *rmr = [[[SQSReceiveMessageRequest alloc] initWithQueueUrl:queueUrl] autorelease];
rmr.maxNumberOfMessages = [NSNumber numberWithInt:10];
rmr.visibilityTimeout = [NSNumber numberWithInt:30];
        
SQSReceiveMessageResponse *response = [sqsClient receiveMessage:rmr];
  • Android

ReceiveMessageRequest rmr = new ReceiveMessageRequest( this.queueUrl );
rmr.setMaxNumberOfMessages( 10 );
rmr.setVisibilityTimeout( 30 );

ReceiveMessageResult result = this.sqsClient.receiveMessage( rmr );

Delete Messages from a Queue

Amazon SQS doesn't automatically delete a message after returning it to the application. By default, it keeps the message to protect against the case where the receiving application fails or loses its connection. In these cases, a different application—or perhaps a new instance of the same application— might attempt to get the message.

To delete the message, you must send a separate request. You specify which message to delete by providing the receipt handle that Amazon SQS returned when you received the message. You can delete only one message per call. Deleting the message acknowledges that you've successfully received and processed it.

  • iOS

SQSDeleteMessageRequest *request = [[[SQSDeleteMessageRequest alloc] initWithQueueUrl:queueUrl andReceiptHandle:message.receiptHandle] autorelease];
[sqsClient deleteMessage:request];
  • Android

DeleteMessageRequest request = new DeleteMessageRequest( this.queueUrl, message.getReceiptHandle() );
this.sqsClient.deleteMessage( request );

References

A sample app that includes this code is hosted in our samples repositories on GitHub:

For more information about using AWS credentials with mobile applications see the following article:

Want to learn more?

To learn about mobile development best practices, follow our AWS Mobile Development Blog. You can also ask questions or post comments in the Mobile Development Forum about this or any other topic related to mobile development with AWS.