Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to subscribe AWS SNS Topic in React Native (Android)?

I tried with the aws-sdk-react-native module:

https://github.com/awslabs/aws-sdk-react-native

The configuration took some time, but thanks to this links I could i.e. list the topics:

https://github.com/awslabs/aws-sdk-react-native/issues/35

https://github.com/awslabs/aws-sdk-react-native/blob/master/SNS/IntegrationTests/SNSTests.js

The test includes a sample how to subscribe to get emails but not how to get notifications in the app. I don't know how to get the platformEndpoint, the PlatformApplicationArn and the deviceToken.

endPoint = sns.createPlatformEndpoint({
  PlatformApplicationArn: '{APPLICATION_ARN}',
  Token: '{DEVICE_TOKEN}'
})
...
var subscribeRequest= {
  "Protocol":"application",
  "TopicArn":topicARN,
  "Endpoint":endPoint
}
try{
  await AWSSNS.Subscribe(subscribeRequest);
}catch(e){
  console.error(e);
  shouldResolve = false;
  return shouldResolve;
}

Are there any samples for this? I'm also looking for an authentication sample. Would it be easier to use firebase?

Thanks

like image 699
Jan F. Avatar asked Feb 23 '17 08:02

Jan F.


1 Answers

I have used GCM over SNS to send notifications. Here are the steps I went through assuming you already set up GCM and added required libraries from AWS React Native SDK:

First create a SNS app from AWS:

enter image description here

Then you need to create Federated Identity through Cognito service of AWS. This is required for sending your device token from mobile app to AWS SNS app. Choose Manage Federated Identities

enter image description here

Then create your pool, don't forget to check Enable Access to unauthenticated identities enter image description here

When you create the pool you will need to create IAM Roles for unauthenticated and authenticated roles of that pool. AWS will help you create new roles for that but you need to go to IAM Roles menu and attach AmazonSNSFullAccess to created roles, otherwise from the mobile app you won't able to send device token.

enter image description here

After doing these steps you will able send your device token using Amazon's React Native SDK. I have written a helper class for sending token to AWS SNS as suggested here:

class AWSUtility {

  constructor() {
    const region = "us-west-1"; //change it with your region
    const IDENTITY_POOL_ID = "pool id created from Federated Identities"
    AWSCognitoCredentials.initWithOptions({region, identity_pool_id: IDENTITY_POOL_ID});
    AWSSNS.initWithOptions({region});
  }

  addTokenToAWSSNS(token, snsEndpointARN) {
    const applicationArn = "change with SNS application Amazon resource name";
    return Promise.try(() => {
      if (!snsEndpointARN) {
        return this.createPlatformEndpoint(token, applicationArn);
      } else {
        return AWSSNS.GetEndpointAttributes({EndpointArn: snsEndpointARN})
          .then((result) => {
            const {Attributes = {}} = result;
            const {Token, Enabled} = Attributes;
            const updateNeeded = Token !== token || Enabled !== 'true';
            if (updateNeeded) {
              return this.updateEndpoint(token).then(() => result.EndpointArn);
            }
            return snsEndpointARN;
          })
          .catch(() => {
            this.createPlatformEndpoint(token, applicationArn)
          });
      }
    });
  }

  updateEndpoint(snsEndpointARN, token) {
    //AWS is returning error saying that it requires 6 params to update endpoint, if anyone has any idea about it let me know please
    return AWSSNS.SetEndpointAttributes({EndpointArn: snsEndpointARN, Attributes: {Token: token, Enabled: true}});
  }

  createPlatformEndpoint(token, applicationArn) {
    return AWSSNS.CreatePlatformEndpoint({Token: token, PlatformApplicationArn: applicationArn})
      .then(result => result.EndpointArn)
      .catch((error = {}) => {
        console.log(error);
      });
  }
}

export default new AWSUtility();
like image 149
cubbuk Avatar answered Oct 02 '22 17:10

cubbuk