AWS Mobile Blog

Deep Linking – Track and Engage Mobile App Users

by Dennis Hills | on | in Amazon Pinpoint, AWS Mobile, Engagement, Mobile Analytics, Mobile Hub | | Comments

You are about to enter the incredibly engaging and often confusing world of mobile deep linking. You’ll learn what deep linking is—the types of links, what deep linking can do, and why you should care—and walk through implementation details with examples.

What is Deep Linking?

Think of a deep link as a URL that takes you to a specific page or product within a website. Deep links are designed to send the mobile user to your app or content within your app, if installed. If not installed, links can launch a website or redirect a user to an app store to install the app.

There are three levels of deep linking: basic, deferred, and contextual. Each type is explained below.

Basic Deep Link

The basic form of deep linking is specifying a custom name for your app as a target for other mobile apps to launch your app and display specific content. This allows you to keep the user within the mobile app experience. If the user already has your app installed, this is cool. If your app isn’t installed, what happens?

The basic deep link works well when the app is installed but fails when it is not installed because the operating system does not know where to redirect.

Deferred Deep Link

A deferred deep link improves on the basic level. It informs the OS to redirect the user to a website or app store to download the app if the app is not installed. The website can display the content on a mobile browser if needed.  Or, if the user downloads and launches the app, the deep linked content is remembered. The user is presented with the intended content, just as if the user had the app installed in the first place.

Here’s an example flow that shows the value of deferred deep linking. The user is presented with three options. After selecting the circle object, the user is directed one of two ways: If APP 2, which is selling the object, is not installed on the user’s mobile device, the user is redirected to the app store. The user downloads and launches APP 2 and is then presented with, and can purchase, the discounted circle object that was originally selected in APP 1 as a promise. The discounted circle object content was deferred for the user until the user installed and launched APP 2. The user can now add the circle to the shopping cart with the applied discount, all within the native mobile app experience.

 

Deferred deep linking has the basic flow of launching an app to specific content but takes it a step further by enhancing the user experience. This helps acquire more users and improves the retention of existing users. It requires a little more effort in the implementation but handles most use cases for mobile user interaction and engagement.

Contextual Deep Link

The final stage is contextual deep linking. Contextual deep linking takes the basic and deferred links to a new level but looks exactly the same to the end user. With contextual, you are just adding valuable metrics (e.g., referrers, coupons, user attributes, and so on) to track every user interaction, from the user clicking the link to making a purchase in the mobile app. Let’s look at this interaction:

 

Contextual deep linking follows the same basic and deferred pattern but enables you to track the activity of your users throughout their mobile journey. In this case, contextual deep linking can carry information such as referrals, the pages within your app they were sent to, the promotional codes they use, the pages they visit within your app, etc. Access to this data can increase user conversion and app retention, all while giving your users a consistent, smooth, single-platform mobile experience.

What Does Deep Linking Do?

When a mobile app is configured for deep linking, it allows users to launch your mobile app directly (if installed on their device) to specific content within the app.  If the app is not installed, the user can be redirected to specific content on a website or directed to download the app in the app store. If the app is installed and launched, the original content is displayed in the mobile app. A deep link can also be set up to route specific content to a mobile browser where it makes sense.

How Does Deep Linking Work?

The app developer creates a unique name for his or her app and configures the app to handle redirection of an incoming link to a page, product, or announcement within the app. Deep links indicate to the OS how to handle these incoming links so that the result is seamless (no visual redirects) and users are taken directly to the intended endpoint. Each platform has a different implementation but the end user flow is the same.

What Does a Deep Link Look Like?

Each mobile platform and OS has its own implementation but they have similar patterns to a URL as explained earlier. The latest deep link integration for both iOS and Android looks like traditional URLs (for example, http://myapp.com/path/to/content). However, previous versions of iOS and Android used a URI like this: myapp.com://path/to/content.

In the implementation, apply deferred deep linking as a URL and use a URI as a fallback. This enables you to handle third-party app flows that only support the URI scheme and users running a previous version of the OS.

Let’s Get Started

First, look at the following chart. It shows platform-specific support for deep linking. It’s important to understand the terms and implementation details for each platform and OS version.

Platform Specific Deep Linking Integration Instructions

For all iOS applications, use the latest Apple universal links for deep links introduced with iOS 9.2. For versions earlier than iOS 9.2, use Custom URI Schemes.

To enable universal links for iOS, Apple requires that your has Associated Domains enabled in the Apple Developer Portal and in your Xcode project. In addition, you’ll need to upload and host a configuration file (apple-app-site-association) at the root of your web server (this could even be a static web hosting enabled S3 bucket).

Get Started by following these steps to integrate universal links into your iOS app:

  1. Enable Associated Domains for your App ID in the Apple Developer Portal.
  2. In your Xcode project, enable Associated Domains under App Target > Capabilities.
  3. In the Domains field, add your website domain appended to applinks: as shown here: applinks:domain.com.
  4. Add a restorationHandler function to your iOS project AppDelegate to handle the incoming links.
  5. Add the Apple apple-app-site-association JSON file (without the .json extension) to the ROOT of your secure web server. Use the domain you provided in step #3 (your website must be served using HTTPS).
  6. Launch the app so that it registers the domain.

Done.

You can test the universal link functionality by sending a link with the URL specified in associated domains to your email or SMS. Selecting the link opens the app. The app’s restorationHandler in the AppDelegate manages the link URL and any attributes.

Universal link caveats:

  • iOS remembers the user’s first choice when opening universal links. If the user taps the top-right breadcrumb to open the link in Safari, all further taps take the user to Safari, and not open within the app. The user can switch back to opening the app (instead of the browser) by choosing Open in the app banner within Safari.
  • Universal links only work for iOS 9 and later. Universal links in early versions of iOS 9 only work on the device; they do not work on the simulator.
  • For users who are running versions of iOS earlier than 9.0, tapping a universal link to your website opens the link in Safari.

For all Android apps as of API 6.0, use Android App Links. For API version 5 and earlier, use Android Chrome Intents.

The easiest way to implement Android App Links is to use App Links Assistant, introduced in Android Studio 2.3. The assistant is a step-by-step wizard for setting up Android App Links. The wizard walks you through the following.

Launch your Android Studio 2.3 project and select Tools > App Links Assistant.

A.   URL Mapping

  1. Select Open URL Mapping Editor button
  2. Select ‘+’ to add a new URL Mapping
  3. Provide a URL
  4. Provide a path
  5. Select OK

B.     Add code to your app’s activities to handle incoming links.

  1. Select the Select Activity button
  2. Highlight the activity
  3. Select Insert Code button

C.     Associate your mobile app and your web site with Digital Asset Links.

  1. Select Open Digital Asset Links File Generator button
  2. Provide your domain
  3. Select Signing config radio button
  4. Select Generate Digital Asset Links file
  5. Upload the assetlinks.json file to the location as shown
  6. Select Link and Verify button

You are done with Android deep linking integration instructions. Congratulations!

Contextual Deep Linking Analytics

Using the contextual deep linking approach, you can track your campaigns and funnels by sending custom events to Amazon Pinpoint. Here’s a high-level overview of how you can track your campaigns by storing each interaction as a custom event using Pinpoint.

  1. Launch the AWS Mobile Hub console.
  2. Create a project.
  3. Choose User Engagement.
  4. Download the iOS Swift project sample app.
  5. Follow the six previous steps to enable universal links for iOS.
  6. In your Xcode project, navigate to the restorationHandler function within your AppDelegate. Add the following snippet of code to send a custom event to Amazon Pinpoint when a universal link is selected. The sample code with hard-coded key/values. You capture these values from the incoming referring linked attributes.

Here’s what the custom event looks like in the Amazon Pinpoint console:

Deep Linking Terminology

Apple Universal Links – The latest version of deep linking for iOS, as of iOS 9.2.

Android App Links – The latest version of deep linking for Android as of version 6.

URI Scheme – The original deep linking format on iOS, before version iOS 9.2. A URI Scheme for deep linking looks something like appname://page/1234, where appname is your unique app name and page/1234 is the page content within the app that is installed on the user’s iOS device.

Android Intent with Chrome – A feature in Android that you use to launch an app directly from a webpage via an Android intent. This feature works in the Chrome for Android browser, version 18 and earlier.

Deferred Deep Links – A deep link that points to content inside a mobile app that is not yet installed. The link brings the user to the download page in the app store. After downloading the app, the user launches the app and is taken directly to the content within the app.

Conclusion

In nearly all categories, mobile app developers can benefit by implementing deep links into their own apps. The implementation process can be a bit involved but once you apply the platform-specific requirements, the benefits far outweigh the additional effort.

Happy linking everyone!

Web and Hybrid Mobile App Solution from AWS Mobile Hub and Ionic

by Dennis Hills | on | in AWS Mobile, Cordova, Hybrid, Ionic, Mobile Hub, Mobile Web | | Comments

AWS Mobile Hub and Ionic, an open source framework for building mobile apps, have teamed up to create an official Ionic starter project that demonstrates an end-to-end solution for hosting and building mobile web and hybrid applications on AWS.

In this blog post, we explain what the project is, describe key areas, highlight additional use cases, and then send you on your way to get started.

What is the official Ionic AWS starter project?

The Ionic team used the new Mobile Hub project export/import feature to build an official Ionic AWS starter project (Ionic blog | GitHub). The project demonstrates how quick and easy it is to deploy an end-to-end Ionic application on AWS using Mobile Hub.

The Ionic starter project is a sample mobile and web “todo task list” app based on a pre-configured AWS Mobile Hub project. After you import this exported Mobile Hub project from Ionic, Mobile Hub provisions the backend services. The Ionic project shows how to securely authenticate users with Amazon Cognito User Pools and receive AWS credentials. At that point, the user can read and write application data to Amazon DynamoDB and store user profile images to Amazon S3.

What is Ionic?

Ionic is an open source framework for building cross-platform hybrid mobile applications using web technologies like HTML, CSS, and JavaScript. Ionic is built on top of AngularJS and Apache Cordova. Ionic apps can be distributed through native app stores by using Apache Cordova API to call JavaScript functions that map to native code or plugins.

What is deployed on AWS?

Let’s look at the backend resources. After importing the exported project from Ionic, Mobile Hub creates a new project, and then enables and provisions the User Sign-in, NoSQL Database, User Data Storage, and App Content Delivery features. The Mobile Hub feature cards are curated common mobile use cases consisting of one or more AWS services. To learn more about these Mobile Hub features, click here.

To get started, download the mobile-hub-project.zip from GitHub and navigate to the Mobile Hub console. Click Import your project and drop the .zip file into the dialog box. Select Import Project. Mobile Hub creates the project and resources.

The purple cards indicate the enabled features, which were auto-generated by the Ionic imported project template.

Let’s explore the enabled backend features of your AWS Ionic Starter Project and see what they do.

User Sign-in: This feature creates an Amazon Cognito User Pool for identity management. The user pool allows your users to authenticate (sign-up and sign-in). After a user authenticates, they are provided a unique identifier by Amazon Cognito. That identity is used to generated temporary, limited-privilege AWS credentials to directly access your resources.. That identity is used when creating, editing, and deleting tasks within the app. Only the task that the authenticated user creates is available to the user. And… no more secret keys!

To view the configuration and a list of your users in the Amazon Cognito console, go to your Mobile Hub project, select resources, and then choose the direct link to your Amazon Cognito User Pools.

NoSQL Database: This creates a single Amazon DynamoDB table called “ionic-mobile-hub-tasks” for storing each task. Here’s what the data looks like (in the Amazon DynamoDB console) after creating a few tasks in the Ionic app. The userId is the Identity given to that user by Amazon Cognito.

To view the table data within the DynamoDB console, go to your Mobile Hub project, select resources, and then choose the direct link to your table under Amazon DynamoDB Tables.

User Data Storage: This created a single Amazon S3 bucket that is used to store files such as photos or other user content. When running the Ionic app on a device, users can click their account settings and change their profile picture, which stores the image in the S3 bucket.

App Content Delivery: This is the core of the Ionic web application. This feature created a single S3 bucket. In the S3 bucket, you’ll see some sample images along with the AWS SDK for JavaScript, aws-config.js, and a default index.html file. In addition, the S3 bucket is configured as a website to demonstrate the ability to host web content directly from your S3 bucket without having a web server. Because an Ionic application can be run either on a device as a native app or as a web app, the app can be hosted on an S3 static website.

Here’s a list of the bucket contents after enabling the App Content Delivery feature within Mobile Hub but before copying the web assets from your Ionic starter project.

In the Ionic starter project instructions, you copy the aws-config.js from here to your project to run the app locally. Instead of running your app locally using “$ionic serve” you just copy the web assets in your myApp/www/ to the root of your S3 bucket. To do this inside your Ionic project, run the following commands, substituting WEBSITE_BUCKET with the S3 content delivery bucket name that was created by the Mobile Hub project import.

npm run build
aws s3 cp --recursive ./www s3://WEBSITE_BUCKET

To learn more about setting up a static website on Amazon S3, see the Amazon S3 Developer Guide.

What have we built today?

The Ionic starter project provides a full end-to-end experience. Once configured, the app is quite diverse and is truly cross-platform. The same code base can be run locally as a web app in a browser, deployed to an iOS or Android device as a hybrid mobile app, or served from an S3 bucket for desktop and mobile browser users. The app showcases the ability to sign in from any device or browser and then sign in on another device: the user’s task list follows the sign-in because the data that is stored in Amazon DynamoDB is associated with that user.

Here’s a look at the interaction with the Ionic todo app from different platforms:

Running the web app locally and interacting in a desktop browser

 

Interacting with the web app served from Amazon S3, using a desktop browser

Ionic starter web app running from an installed app on an iOS device

 

The mobile web app being served from Amazon S3 on a mobile browser

 

Get Started

You’ll find the Ionic + AWS Mobile Hub Starter Project on GitHub. The README walks you through using the starter, installing the necessary CLIs, creating the project, running the app, and deploying the project’s web assets to the S3 bucket.

Additional Resources

AWS What’s New
Ionic Blog
Ionic on AWS

Sign Up and Confirm With Amazon Cognito User Pools Using C#

by Dennis Hills | on | in .NET, AWS Mobile, Cognito, Cognito User Pools | | Comments

This post was authored by Tom Moore & Mike Morain, AWS Solutions Architects.

With Amazon Cognito, you can add user sign-up and sign-in to your mobile and web apps. You can also authenticate users through social identity providers such as Facebook, Twitter, or Amazon; with SAML identity solutions; or by using your own identity system.

Amazon Cognito user pools are for mobile and web app developers who want to handle user registration and sign-in directly in their apps. Previously, you needed to implement your own user directory to create user accounts, store user profiles, and implement password recovery flows to support user registration and sign-in.

This post follows on from the Basics – User Registration and Authentication post, and is intended to function as a companion to that post. The basics post walked through the process of setting up an Amazon Cognito user pool that can be accessed through an MVC 5 web site. This post walks through the process of developing a native Windows application to leverage the same app pool, by adding another app to the user pool for native Windows applications.

PREREQUISITES

 

COMPLETE THE WALKTHROUGH IN THE BASICS TUTORIAL

The previous blog post describes the steps to create your Amazon Cognito user pool and to get basic authentication working. You should complete all the steps in that post and ensure that you can successfully create accounts and authenticate to the user pool. This post assumes that you have access to the user pool created in that post, including the user pool ID and the identity pool ID, and that you are able to create a new client ID for the application to use.

VISUAL STUDIO

This blog post assumes that you are using Microsoft Visual Studio 2015 Community Edition. This edition is available for free from Microsoft at https://www.visualstudio.com/vs/community/.

NEW CLIENT ID

Each client that is authenticating to a user pool in Amazon Cognito requires a unique client ID.
To obtain a new client ID:

• Sign in to the AWS Management Console.
• Choose Amazon Cognito.
• Choose Manage your user pools.
• Choose the user pool you created in the previous post.
• In the lower left, choose Apps.
• In the list of applications, choose Add another App.

Give your application a name, select the following options, choose Create App, and then choose Save Changes.

After the application is created, note the client ID to use later.

PROJECT SETUP

Open Visual Studio 2015 and select the new project option.

From the built in templates, choose Classic Desktop application, and choose a project type of WPF Application. This option creates a blank WPF application to use as a starting point for this tutorial. Give the application a name and a location, and then click OK. Visual Studio now sets up the boilerplate code for your initial project.

After the application is created, run the application to ensure that the boilerplate code compiles correctly on your machine.

INSTALLING DEPENDENCIES

The first step to incorporate Amazon Cognito in your application is installing the necessary SDK components. You can use the built-in NuGet functionality to install these components.

Right-click in the Solution Explorer and then choose Manage NuGet Packages.

From the NuGet window, choose Browse, and in the search box type AWSSDK. The AWS SDK for .NET has many components, so you can install only the portions of the SDK that you need for your application. For this blog post we are working with Amazon Cognito to authenticate your application, so you can install only these components for now. In future posts, we will install additional components to access other AWS resources.

Note: All versions of the components used in this blog post are for version 3.x of the AWS SDK for .NET. Version 2 components are available in the NuGet repository for compatibility with older applications; however these should not be used. The following version numbers are correct as of the writing of this blog post.

Select and install the following NuGet packages:
• AWSSDK.Core (v3.3.7.1)
• AWSSDK.CognitoIdentity (v 3.3.1.1)
• AWSSDK.CognitoIdentityProvider (v3.3.2.3)

BUILDING THE INTERFACE

After you install the required components, you can build the Windows user interface for the application to interact with Amazon Cognito. In Visual Studio, add a second WPF window to act as the sign-up page. Right-click the project, choose Add, and then choose New Item. Choose WPF from the category of templates, and choose Windows (WPF) as the template. Name the new page SignUp.xaml and choose Add.

Open the MainWindow.xaml file and replace the default Grid XAML with the following:

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Column="1" Grid.Row="1">
            <TextBlock>User Name:</TextBlock>
            <TextBox Name="UserNameTextBox" />
            <TextBlock>Password:</TextBlock>
            <PasswordBox Name="PasswordTextBox" />
            <Button Name="LoginButton" Click="LoginButton_Click" Content="Login" />
        </StackPanel>
        <Button Name="SignUpButton" Grid.Column="2" Grid.Row="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Click="SignUpButton_Click" Content="Sign Up" />
    </Grid>

This creates a basic login page with a button to launch a sign-up form. The login code is filled in later. Right-click the file and select View Code.

Open SignUp.xaml and replace the default Grid tag with the following XAML:

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Column="1" Grid.Row="1">
            <TextBlock>User Name:</TextBlock>
            <TextBox Name="UserNameTextBox" />
            <TextBlock>Password:</TextBlock>
            <PasswordBox Name="PasswordTextBox" />
            <TextBlock>Email:</TextBlock>
            <TextBox Name="EmailTextBox" />
            <Button Name="SignUpButton" Click="SignUpButton_Click" Content="Sign Up" />
            <TextBlock>Confirmation Code:</TextBlock>
            <TextBox Name="ConfirmatinTextBox" />
            <Button Name="ConfirmButton" Click="ConfirmButton_Click" Content="Confirm Email" />
        </StackPanel>
    </Grid>

INTEGRATING AMAZON COGNITO

ENABLE APPLICATION CONFIGURATION

Add a reference to the System.Configuration assembly into the project.

Open the App.Config file for the application and add the following code:

  <appSettings>
    <!-- AWS Cognito Identity Settings -->
    <add key="AWSRegion" value="{Your Region}" />
    <add key="CLIENT_ID" value="{Your Cognito Client ID}" />
    <add key="USERPOOL_ID" value="{Your User Pool ID}" />
    <add key="IDENITYPOOL_ID" value="{Your Identity Pool Id}" />
    <add key="IDENITY_PROVIDER" value="{Your Identity Provide}" />
  </appSettings>

Warning: The curly bracket sections must be replaced with the values from the user pool that you set up.

ENABLE NAVIGATION

Right-click MainWindow.xaml and choose View Code. In the code editor, make the following changes to the form code.

Add the following using statements to import the necessary AWS and supporting modules:

using Amazon;
using Amazon.Runtime;
using Amazon.CognitoIdentityProvider;
using Amazon.CognitoIdentityProvider.Model;
using System.Threading.Tasks;
using System.Configuration;

Add the following  items to the class as member variables.

private readonly AmazonCognitoIdentityProviderClient _client = new AmazonCognitoIdentityProviderClient();
private readonly string _clientId = ConfigurationManager.AppSettings["CLIENT_ID"];
private readonly string _poolId = ConfigurationManager.AppSettings["USERPOOL_ID"];

Add the following method to the form to handle opening the registration dialog.

private void SignUpButton_Click(object sender, RoutedEventArgs e)
{
       SignUp signUpDlg = new SignUp(_client);
signUpDlg.ShowDialog();
}

The code provides the ability to launch your sign-up page in the application, which enables you to create new accounts in Amazon Cognito.

IMPLEMENT SIGN-UP

The sign-up page and related code are used to enable a client application to create user accounts within the Amazon Cognito identity provider. This assumes that you want all user accounts to be created from the end-user application. If you do not intend for the application to create users, then you should remove the sign-up page from the application, along with the code to launch the sign-up page.

The process of creating users is performed by Amazon Cognito within your AWS account. All of the rules governing accounts are maintained in the Amazon Cognito user pool configuration. The following code shows basic user creation. You can modify it to suit your business processes; for example, if you require more options for user creation.

Right-click the SignUp.xaml page and choose View Code to edit the sign-up code.

Update the boilerplate code for the SignUp class with the following:

private readonly string _clientId = ConfigurationManager.AppSettings["CLIENT_ID"];
private readonly string _poolId = ConfigurationManager.AppSettings["USERPOOL_ID"];
private AmazonCognitoIdentityProviderClient _client;

public SignUp(AmazonCognitoIdentityProviderClient client)
{
        InitializeComponent();

        _client = client;
}

This enables the application to pass the Amazon Cognito client to the Signup.xaml form, and retrieves the client ID, which is used for the sign-up process.

Add the following code to the SignUp.xaml form.

private async void SignUpButton_Click(object sender, RoutedEventArgs e)
{
     try
     {
         SignUpRequest signUpRequest = new SignUpRequest()
         {
               ClientId = _clientId,
               Password = PasswordTextBox.Password,
               Username = UserNameTextBox.Text
         };
         AttributeType emailAttribute = new AttributeType()
         {
              Name = "email",
              Value = EmailTextBox.Text
         };
         signUpRequest.UserAttributes.Add(emailAttribute);

         var signUpResult = await _client.SignUpAsync(signUpRequest);
     }
     catch (Exception ex)
     {
        string message = ex.Message;
        MessageBox.Show(message, "Sign Up Error");
     }
}

This code implements a handler for the sign-up button. The sign-up button handles the process of Amazon Cognito creating an account from the client. If your user pool requires additional attributes for the user, you include them here along with the email attribute in the preceding example.

After the user is created in Amazon Cognito, a confirmation email is sent to the specified email address, along with a confirmation code. The user uses that confirmation code to complete the sign-up process.

Add the following code to the sign-up form to enable account confirmation and complete the sign up process.

private async void ConfirmButton_Click(object sender, RoutedEventArgs e)
{
     try
     {
          Amazon.CognitoIdentityProvider.Model.ConfirmSignUpRequest confirmRequest = new ConfirmSignUpRequest()
          {
               Username = UserNameTextBox.Text,
               ClientId = _clientId,
               ConfirmationCode = ConfirmationTextBox.Text
          };

          var confirmResult = await _client.ConfirmSignUpAsync(confirmRequest);
     }
     catch (Exception ex)
     {
           string message = ex.Message;
           MessageBox.Show(message, "Sign Up Error");
      }
}

The user receives the confirmation code, types it into the Confirmation text box, and clicks the Confirm button. This completes the registration process.

IMPLEMENT SIGN-IN

The final step is to implement the sign-in process for the mobile application. Right-click the MainWindow.xaml file and choose View Code to edit the code for the main dialog box in the application.

Add the following code to your application:

private async void LoginButton_Click(object sender, RoutedEventArgs e)
{
     bool loggedIn = await CheckPasswordAsync(UserNameTextBox.Text, PasswordTextBox.Password);
}

private async Task<bool> CheckPasswordAsync(string userName, string password)
{
     try
     {
          var authReq = new AdminInitiateAuthRequest()
          {
               UserPoolId = _poolId,
               ClientId = _clientId,
               AuthFlow = AuthFlowType.ADMIN_NO_SRP_AUTH
          };
          authReq.AuthParameters.Add("USERNAME", userName);
          authReq.AuthParameters.Add("PASSWORD", password);

          AdminInitiateAuthResponse authResp = await _client.AdminInitiateAuthAsync(authReq);

          return true;
     }
     catch (Exception ex)
     {
           return false;
     }
}

The preceding code enables the user to sign in with Amazon Cognito.

NEXT STEPS

Completion of this walkthrough enables you to create and authenticate against those accounts within your application. The next steps are to allow the user to interact with other AWS resources within your account. These interactions will be covered in subsequent posts.

WHAT DOES IT COST?

The only service used in this walkthrough is Amazon Cognito. This service is free for the first 50,000 monthly active users. Accessing other AWS resources may incur charges.

CONCLUSIONS

This post extended the previous post by using the user pool you created and enabling a Windows native client to sign up, confirm, and authenticate. After you complete this process, you can extend your application to use other AWS capabilities.

Questions or Comments?

Reach out to us via the AWS Mobile Development Forum.

Export, Import, and Clone AWS Mobile Hub Projects

by Dennis Hills | on | | Comments

This post was authored by Bharath Kumar, Sr. Product Manager, AWS Mobile.

AWS Mobile Hub now supports exporting and importing the configuration of an AWS Mobile Hub project from the Mobile Hub console with a few clicks. You can import previously exported Mobile Hub projects from any AWS account or import your own exported Mobile Hub projects. You can create just the right project and clone it as a backup or as a template for building out other projects. These exported projects can be shared with other teams or even across AWS accounts. Importing a project creates an identical isolated stack of AWS resources that provides an independent consistent development and testing environment.

Developers will find the export/import feature helpful: where multiple developers, working in parallel, need repeatable mobile backend deployments for testing and debugging; in open source sharing contexts; and for getting-started projects, short-cutting tutorial setup, or as a working template to build from.

How Does It Work? For exporting, you create a project, enable features, and configure resources as you normally would. You then select the project card and select export. The export is a zipped YAML file that can be imported into your own account as another project. You can also share the file with another user or account for the user to import.

Importing a project requires you to log in to the Mobile Hub console, choose the Import your project button, and drop the previously exported zipped YAML file into the import modal. On importing a project, Mobile Hub creates a new project and begins creating the resources defined by the imported YAML.

We’ll show you how easy it is to export, import, and clone a Mobile Hub project.

Exporting a project

You can export a project by selecting the export button on your project card. Exporting a project creates a zipped YAML file. The YAML file represents all the configured backend resources and features enabled in your project.

Importing a project

To import a project, select Import your project in the project list page and drag and drop the exported zipped YAML file into the Import project modal. After you select the zipped Mobile Hub project file for importing, the project name is pre-populated according to the name of the zip file. You can change the name of the project and select the region where you want resources to be created.

Importing the zipped YAML file into the AWS Mobile Hub console creates a new project and begins provisioning the backend resources and features defined in the YAML file.

Cloning a project

Cloning a project combines export and import into a single step. You can only clone your own projects. Cloning a project creates a project with the same provisioned backend services and  features as the project you cloned it from.

Limitations of Cloning and Importing Projects

  1. Importing a NoSQL feature requires unique DynamoDB table names.
  2. Any exported project credentials (always encrypted in the export) can only be imported into the same account from where they were exported from.
  3. Existing AWS resources that were added to a project, such as a legacy Cloud Logic API function or Push Notifications, can only be imported into the same AWS account where they were created.

Note about legacy Cloud Logic: Export, import, and cloning are not supported for projects that include the legacy Cloud Logic feature (indicated by a type LEGACY in the Cloud Logic feature as shown below). Legacy Cloud Logic refers to any enabled Cloud Logic features prior to the integration of Amazon API Gateway into Cloud Logic on November 9, 2016.

Supported import and cloning feature reference table:

AWS Mobile Hub Feature Clone Import
CAN A PROJECT CONTAINING THIS FEATURE BE CLONED WITIHIN THE SAME AWS ACCOUNT? CAN A PROJECT CONTAINING THIS FEATURE BE IMPORTED INTO A DIFFERENT AWS ACCOUNT?
User Sign-In  Yes  Yes
No SQL Database  Yes  Yes
Cloud Logic  Yes  Yes, if Cloud Logic API was created by Mobile Hub and not imported.
User Data Storage  Yes  Yes
App Content Delivery  Yes  Yes
Connectors  Yes  No
Push Notifications  Yes  No
User Engagement  Yes  No

To learn more about the AWS Mobile Hub export, import, and clone feature, see the AWS Mobile Hub Developer Guide.

Use C# To Register and Authenticate with Amazon Cognito User Pools

by Dennis Hills | on | in .NET, AWS Mobile, Cognito, Cognito User Pools | | Comments

This post was authored by Tom Moore & Mike Morain, AWS Solutions Architects.

You can use Amazon Cognito to add user sign-up and sign-in to your mobile and web apps. You can also authenticate users through social identity providers such as Facebook, Twitter, or Amazon; with SAML identity solutions; or by using your own identity system.

Amazon Cognito user pools enable you to handle user registration and sign-in directly in your app.Without user pools, you needed to implement your own user directory to create user accounts, store user profiles, and implement password recovery flows to support user registration and sign-in.

This post is intended for developers working in C# who want to integrate backend web applications with Amazon Cognito. It provides an overview of basic authentication integration with user pools. We demonstrate how to do this with C# and the .NET stack, but you can apply these ideas by using our other SDKs too.

PREREQUISITES

IAM User

To integrate with the Amazon Cognito APIs, you must have an AWS user with programmatic access. If you need information on how to get this access, see Creating IAM Users in the AWS Identity and Access Management User Guide. If you already have an account that has access to the credentials, read on.

Deploying ASP.NET on AWS

While there are many tools that leverage the C# .NET platform on AWS, one of the fastest ways to get started is to deploy the application with AWS Elastic Beanstalk. For more information, see the How to Deploy a .NET Sample Application Using AWS Elastic Beanstalk tutorial in the AWS Elastic Beanstalk Developer Guide.

AWS Toolkit for Visual Studio

For this tutorial, we recommend the AWS Toolkit for Visual Studio. It enables you to access and manage AWS resources inside of Visual Studio. It also supports credential management and injection to ease the development workflow. For more information, see Setting Up the Toolkit for Visual Studio in the AWS Toolkit for Visual Studio User Guide. If you’ve already got your development environment set up, feel free to skip ahead.

Note: The AWS Toolkit for Visual Studio is great for storing credentials during the development cycle, but cannot be used for storing credentials in a production application. For more information on how to secure your credentials in a production environment, see Using Credentials in an Application in the AWS SDK for .NET Developer Guide.

Setting up Amazon Cognito

Set up the User Pool

In Amazon Cognito, a user pool represents a set of identities for users of an application. To integrate with Amazon Cognito, you must first set up a user pool where information about your app’s users is stored. Since this is a one-time setup for the purposes of this demo, we demonstrate this using the AWS Management Console. You can also use the AWS CLI or an AWS SDK. For more information, see Using the Console to Create a New User Pool in the Amazon Cognito Developer Guide.

While setting up the user pool, you also define an application that provides programmatic access to each user pool. This is shown next. During app creation, it is important to note the user pool ID and app client ID. You use these later when integrating this user pool and application with the Amazon Cognito identity pool. For more information, see Specifying User Pool App Settings in the Amazon Cognito Developer Guide.

Ensure that the Generate client secret box is cleared. Since you are authenticating with your AWS credentials, no user secret is required.

Figure 1: Don’t generate a client secret, since you are authenticating with credentials

It is also important to select the Enable sign-in API for server-based authentication (ADMIN_NO_SRP_AUTH) box for this integration. For client-side applications, Amazon Cognito uses the Secure Remote Password (SRP) protocol, which allows for secure password entry and transmission from code running on the client device. However, since the C# code for this tutorial runs on a trusted and secured backend server, you don’t need to implement SRP. Selecting this box allows you to use these secure API endpoints from this application.


Figure 2: Enable ADMIN_NO_SRP_AUTH

Overview of C# Configuration and Code

The code snippets in this document were built into a default MVC 5 boilerplate application bootstrapped from the Visual Studio template wizard. Because the purpose of this document is to demonstrate basic integration functionality for Amazon Cognito in C#, the glue code required to integrate with Microsoft’s Open Web Interface for .NET (OWIN)[MS1]  authentication mechanisms are outside the scope of this document, and may be covered in a future blog post.

Web.CONFIG SETUP

The required configuration elements are outlined in the following Web.config excerpt:

<appSettings>
    . . .
    <!-- AWS Cognito Identity Settings -->
    <add key="AWSRegion" value="eu-west-1" />
    <add key="CLIENT_ID" value="XXXXXXXXXXXXXXXXXXXXXXXXXX" />
    <add key="USERPOOL_ID" value="REGION_XXXXXXXXX" />
    <add key="IDENITYPOOL_ID" value="REGION:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX" />
    <add key="IDENITY_PROVIDER" value="cognito-idp.REGION.amazonaws.com/" />
  </appSettings>

Figure 3: Required Web.config settings

The AWSRegion field should contain the standard formatted AWS Region name where the Amazon Cognito setup was performed. The CLIENT_ID is the app client ID from the Amazon Cognito user pool. The USERPOOL_ID and IDENTITYPOOL_ID are the user pool ID and identity pool ID that you set up in the prerequisites section. The IDENTITY_PROVIDER setting should point to the endpoint for the specified region (replace REGION in the preceding snippet with the AWS Region).

User Registration and Confirmation

The first thing to do is instantiate the Amazon Cognito identity provider client, as seen next. You also reference some of the configuration variables for easy access in the functions later on.

. . .
using Amazon.CognitoIdentityProvider;
using Amazon.CognitoIdentityProvider.Model;

    public class CognitoUserStore : IUserStore<CognitoUser>, 
                                    IUserLockoutStore<CognitoUser, string>, 
                                    IUserTwoFactorStore<CognitoUser, string>
    {
        private readonly AmazonCognitoIdentityProviderClient _client = 
            new AmazonCognitoIdentityProviderClient();
        private readonly string _clientId = ConfigurationManager.AppSettings["CLIENT_ID"];
        private readonly string _poolId = ConfigurationManager.AppSettings["USERPOOL_ID"];

        . . . 
    }

Figure 4: Instantiating the AmazonCognitoIdentityProviderClient

Next, create a standard object to store basic user information for a user stored in Amazon Cognito.

public class CognitoUser : IdentityUser
    {
        public string Password { get; set; }
        public UserStatusType Status { get; set; }
    }

Figure 5: Basic user object.

After you create the client object in _client, create a function to call the SignUpAsync, accepting the basic user object. This function then calls the Amazon Cognito API to register the user.

. . .
using Amazon.CognitoIdentityProvider;
using Amazon.CognitoIdentityProvider.Model;

    public class CognitoUserStore : IUserStore<CognitoUser>, 
                                    IUserLockoutStore<CognitoUser, string>, 
                                    IUserTwoFactorStore<CognitoUser, string>
    {
        . . . 

        public Task CreateAsync(CognitoUser user)
        {
            // Register the user using Cognito
            var signUpRequest = new SignUpRequest
            {
                ClientId = ConfigurationManager.AppSettings["CLIENT_ID"],
                Password = user.Password,
                Username = user.Email,

            };

            var emailAttribute = new AttributeType
            {
                Name = "email",
                Value = user.Email
            };
            signUpRequest.UserAttributes.Add(emailAttribute);

            return _client.SignUpAsync(signUpRequest);
        }
    }

Figure 6: Create a user identity with SignUpAsync()

For this tutorial, you confirm the user account manually. User confirmation and email verification will be covered in a future post. To confirm the user manually, sign in to the AWS Management Console and navigate to your user pool for your sample application. After you call the CreateAsync function with a valid user object, you should see the user in your pool. Choose the user ID, and on the detail page, click Confirm user.

Figure 7: Manual confirmation of the user.

USER Authentication

After creating and confirming the user, implement user authentication by creating a function to check the user’s credentials. Call the AdminInitiateAuthAsync function on the AmazonCognitoIdentityProviderClient.

. . .
using Amazon.CognitoIdentityProvider;
using Amazon.CognitoIdentityProvider.Model;

    public class CognitoUserManager : UserManager<CognitoUser>
    {

        private readonly AmazonCognitoIdentityProviderClient _client = 
            new AmazonCognitoIdentityProviderClient();
        private readonly string _clientId = ConfigurationManager.AppSettings["CLIENT_ID"];
        private readonly string _poolId = ConfigurationManager.AppSettings["USERPOOL_ID"];

        public CognitoUserManager(IUserStore<CognitoUser> store)
            : base(store)
        {
        }

	 . . .

        public override Task<bool> CheckPasswordAsync(CognitoUser user, string password)
        {
            return CheckPasswordAsync(user.UserName, password);
        }

        private async Task<bool> CheckPasswordAsync(string userName, string password)
        {
            try
            {
                var authReq = new AdminInitiateAuthRequest
                {
                    UserPoolId = ConfigurationManager.AppSettings["USERPOOL_ID"],
                    ClientId = ConfigurationManager.AppSettings["CLIENT_ID"],
                    AuthFlow = AuthFlowType.ADMIN_NO_SRP_AUTH
                };
                authReq.AuthParameters.Add("USERNAME", userName);
                authReq.AuthParameters.Add("PASSWORD", password);

                AdminInitiateAuthResponse authResp = await _client.AdminInitiateAuthAsync(authReq);

                return true;
            }
            catch
            {
                return false;
            }
        }
    . . .
    }

Figure 9: Authenticating credentials with AdminInitiateAuthAsync()

And that’s it! Your C# application now integrates basic user creation and authentication with the Amazon Cognito platform.

Conclusion

In this post, we went through an overview of basic authentication integration with Amazon Cognito user pools in C#. After setting up the user pool, we walked through code for a basic user sign-up and authorization flow.

Please post your questions and feedback to the .NET Development Forum.

Encrypting an Amazon S3 object on the client side with AWS KMS and the AWS Mobile SDK for Android

by Karthik Saligrama | on | in AWS Mobile, S3 | | Comments

Starting with the AWS Mobile SDK for Android version 2.4.0, you have two options to encrypt client-side objects before sending them to Amazon S3: an AWS Key Management Service (AWS KMS) customer master key (CMK) or a client-side master key.

 

Customer master key

 

When using an AWS KMS customer master key (CMK) for client-side data encryption, you provide only a CMK ID. The AWS Mobile SDK for Android sends a request to AWS KMS for a key to encrypt your data. There is no requirement to provide encryption keys to the Amazon S3 encryption client.

While uploading, the data in the object is encrypted and the cipher blob version of the encryption key that is returned from KMS is stored in the object metadata.

When the client calls Amazon S3 to download the object and its metadata, the client uses the cipher blob key to get the plaintext key to decrypt the entire S3 object.

The following example shows how to set up Amazon S3 client-side encryption with a CMK on an Android device using the AWS Mobile SDK for Android.

 

Initialize KMSEncryptionMaterialsProvider

 

final KMSEncryptionMaterialsProvider materialProvider = new KMSEncryptionMaterialsProvider(<kmsKey>); 
final CryptoConfiguration cryptoConfiguration = new CryptoConfiguration()
                                                      .withAwsKmsRegion(Region
                                                                   .getRegion(Regions.US_EAST_1));
final AmazonS3 s3Client = new AmazonS3EncryptionClient(<credentialProvider>, 
                                            materialProvider, 
                                            cryptoConfiguration);
s3Client.setRegion(Region.getRegion(Regions.US_EAST_1));

Uploading

To upload an object to Amazon S3, use the AmazonS3EncryptionClient you initialized, and then use either PutObjectRequest or TransferUtility.

Using PutObjectRequest
final PutObjectRequest putObjectRequest = new PutObjectRequest(<bucketName>, <key>, <file>);
final PutObjectResult putObjectResult = s3Client.PutObject(putObjectRequest);
Using TransferUtility
final TransferUtility transferUtility = new TransferUtility(s3Client, <context>); 
final TransferObserver transferObserver =  transferUtility
                                                  .upload(<bucketName>, <key>, <file>);

Downloading

To download an object from Amazon S3, use the AmazonS3EncryptionClient you initialized earlier, and then use either GetObjectRequest or TransferUtility.

Using GetObjectRequest
final InputStream inputStream = s3Client.getObject(<bucketName>, <key>).getObjectContent();
Using TransferUtility:
final File tempDownloadFile = temp.newFile();
final TransferObserver observer = transferUtility
                                       .download(<bucketName>, <key>, <tempDownloadFile>);

Client-side master Key

Your client-side master keys and your unencrypted data are never sent to AWS. It is important that you safely manage your encryption keys. If you lose them, you won’t be able to decrypt your data.

If you want to use your own custom master key, use the following code to create a material provider.

final EncryptionMaterials encryptionMaterials = new EncryptionMaterials(<keypair>);
final AmazonS3 s3Client = new AmazonS3EncryptionClient(<credentialProvider>, encryptionMaterials);

As always you can post your questions and feedback to our GitHub repo or to our AWS Forums.

 

Targeted push notifications and campaign management using Amazon Pinpoint and React Native

by Richard Threlkeld | on | in AWS Mobile, Lambda | | Comments

This post was authored by Michael Labieniec, AWS Solutions Architect

Amazon Pinpoint makes it easy to run targeted campaigns to drive user engagement with mobile apps. Using Amazon Pinpoint you can understand user behavior, determine which users to engage with your campaigns, determine which messages to send, schedule the best time to deliver the messages, and then track the results of your campaign. Building cross-platform mobile apps and engaging with users across these platforms can be challenging; it requires you to maintain multiple code bases to take advantage of native features using the AWS Mobile SDK.

React Native enables you to create cross-platform mobile apps while utilizing native features. By building custom native modules, you can interact with the native AWS Mobile SDK generated by AWS Mobile Hub. This means that you maintain a single code base, while customizing the look and feel per platform within React Native. In this example, we will show how to build a native module for the Android platform. The same concepts can be applied to iOS by building a custom module and using the Mobile Hub-generated package.

In this tutorial, you generate a Mobile Hub app that uses an unauthenticated Amazon Cognito identity pool and interacts with API Gateway and AWS Lambda. This app allows you to purchase round trip tickets to your favorite planet. The app generates monetization events using the native AWS Mobile SDK. It then creates custom user attributes for Amazon Pinpoint so you can engage with users based on their planet interest, traveled to destination, and weather preference. To add user authentication along with features such as registration and MFA, consider using the Amazon Cognito User Pools functionality, which you can enable in Mobile Hub.

Requirements

Clone the completed sample app from Github and use the files within this repository as reference when creating your app.

git clone https://github.com/awslabs/aws-pinpoint-sample

Once you have node.js and npm, you can get started by running the following commands from the terminal:

npm install -g react-native-cli
react-native init PinpointSample
cd PinpointSample

NOTE: If you name your project something other than “PinpointSample”, you will need to find/replace the  references in the sample code with your new project name.

Creating the API for your cross-platform app

Go to the AWS Mobile Hub console and click Create new mobile project. In this example for this tutorial, the app name is PinpointSample. Enter the name then click “Create Project”. In the list of features, choose Cloud Logic and then choose Create new API. Give the API a name PinpointSampleApi and a description, leave the defaults, and choose Create API. This API will simply return back whatever you send to it in the request body. You will use this API later in this tutorial to simulate requesting weather information for specific planets.

CREATE_IN_PROGRESS appears while the APIs are being created. When the status is CREATE_COMPLETE, choose “Configure more features”.

image005

Getting a GCM Sender ID and API Key

To send push notifications to Android devices, you need Google Cloud Messaging keys. To create a new Sender ID and API Key, go to https://firebase.google.com.

  • Choose an existing project or create a new project.
  • Click Add (another) app and select Android

Type your package name from the generated React Native app. In this example, it’s com.pinpointsample. Then click Add App. Click Continue and then Finish. Note, you don’t need the google.json file.

Click the menu icon to the right of your new app’s name and then choose Manage Settings. Choose the CLOUD MESSAGING tab. Copy the Sender ID and Legacy Server Key (this is the API Key).

Enabling User Engagement

In the AWS Mobile Hub console, choose User Engagement and then choose Enable engagement and select Android

  • In Sender ID, add the Sender ID from the previous procedure.
  • In API Key, add the Server Key from the previous procedure.

Click Save changes then choose Integrate with your app. Next choose the Android tab, and then choose Download package.

image009

Find the directory where you created your project earlier with the React Native CLI. Inside that directory, extract the amazonaws folder from the Mobile Hub package archive you downloaded from Mobile Hub to android/app/src/main/java/com/amazonaws. Overwrite the existing directory (if it exists).

image010

Creating the React Native Android Module

Open projectname/android/app/build.gradle with a text editor and add the following dependencies. The Google Play library is required to use push notifications. The included badge library places a badge next to your push notifications.

dependencies {
compile fileTree(dir: "libs", include: ["*.jar"])
    compile "com.android.support:appcompat-v7:23.0.1"
    compile 'com.android.support:support-v4:23.1.0'
    compile "com.facebook.react:react-native:+"  // From node_modules
    compile "me.leolin:ShortcutBadger:1.1.4@aar"
    compile 'com.amazonaws:aws-android-sdk-core:2.3.9'
    compile('com.amazonaws:aws-android-sdk-pinpoint:2.3.9')
    compile('com.amazonaws:aws-android-sdk-apigateway-core:2.3.9')
    compile 'com.google.android.gms:play-services-gcm:7.8.0'
    compile 'com.google.code.gson:gson:2.7'
}

Create 3 new files in the android/app/src/main/java/com/pinpointsample package folder. Copy the contents of the files from the corresponding sample app repository files.

  • AWSMobileHubModule.java
  • AWSMobileHubPackage.java
  • AWSPushListenerService.java

Next, update your android/app/src/main/AndroidManifest.xml. Copy the contents from the sample app repository. If you did not use the example package name of com.pinpointsample, be sure to update the package names in the manifest file to your package name.

Note: The package names must match your application package name.

In the android/app/src/main/com/amazonaws/mobile/AWSConfiguration.java file, remove the “final” from all variables. These variables will be updateable from the JavaScript interface.

Note: If you update your Mobile Hub app in the future, you mustoverwrite the com.amazonaws.mobile package folder and will need to perform this step again if you want to be able to configure the variables from javascript.

Finally, modify the MainApplication.java file to load your new package. Add import com.pinpointsample.AWSMobileHubPackage; to the imports section of the class, then update the getPackages() method to include the module:

@Override
    protected List getPackages() {
      return Arrays.asList(
          new MainReactPackage(),
          new AWSMobileHubPackage()
      );
    }

Add your configuration to the constructor method in by copying the contents of the index.android.js from the sample code into your projects index.android.js. The values can be copied from your Mobile Hub generated AWSConfiguration.java file class (where you previously removed the “final” statement).

Finally, create a AWSMobileHub.js file in your projects root directory. this is the main interface that communicates with our native module. Copy the contents from the completed sample app repository file.

Note: the name of the module corresponds directly to the getName property inside the java module code getName() method.

Finally, enable the gradle daemon to speed up builds; run this command from your terminal on your Mac or Linux computer.

touch ~/.gradle/gradle.properties && echo "org.gradle.daemon=true" >> ~/.gradle/gradle.properties

Now, run the app either on a device (push notifications may not work on the Android Emulator). From your root project run the following command:

react-native run-android
adb logcat

image011

The following information is logged to adb logcat:

Note: use the logcat.sh script in the sample app repository to automatically filter your adb logs with ./logcat.sh (on mac/linux) or just “logcat” on windows.

  • AWSMobileClient: AWS Mobile Client is OK – This means the AWS Mobile SDK was initiated
  • EventRecorder: Successful submission of 1 events – These events are being submitted to Pinpoint
  • TargetingClient: EndpointProfile – These are Amazon Pinpoint events

Within the app, when you choose the Request Weather button, you see a request to Amazon API Gateway. This request calls an AWS Lambda function, which simply returns the request. The app echoes the query parameter that was sent; in this case, the weather for the selected planet.

The API Gateway call can be used to send any request to API Gateway by passing in the method, endpoint, request body, and query params (see comments in the sample code). This call uses the Amazon Cognito identity, which in this example is an unauthenticated user. You can instead use a login system with an authenticated role and the SDK manages that for you. This call also sets custom attributes for the Weather Requested attribute so that you can engage with specific users that requested weather for a specific planet by creating a custom user segment within Amazon Pinpoint.

Next, choose Planet Trip, {COST}. The event echoes out in the adb log, which creates a monetization event using the AWS Mobile SDK. This event also updates custom attributes about this user under the Traveled To attribute, which enables you to engage with users who have traveled to this specific planet.

Enabling Campaign Management with Amazon Pinpoint

Next we are going to create user segments for each of the planet attributes users are interested in traveling to. Then we will create a campaign that targets these specific users based on their interests.

Go to the Amazon Pinpoint console and click on your app (if you used “PinpointSample” as the name of your Mobile Hub app, your Pinpoint app should be called “pinpointsample_MobileHub”), choose Segments, and then choose New Segment. Name your segment after a planet that you selected within the app; for example, “Earth People” if, in the app, you purchased a trip to Earth by clicking “Planet Trip”. Choose the + button under Custom Attributes, choose Planet and then choose Earth. This enables you to engage with all users that picked Earth in the app. You can also specify a usage metric; for example, Used within the last 30 days. The user count goes to 1 and shows 100%. This indicates that all current users are interested in this planet.

image013

Next, choose Campaigns, and then choose Create Campaign. Choose the segment that you created in the previous step by selecting Use a previously defined segment. For this example, the segment is called “Earth People”.

image014

The Segment estimate should be 1 total user. If the Segment estimate is 0, give it some time, refresh the app, and refresh the console. Be sure you see the Endpoint updated successfully event in the logcat log. If you are only running the app on the Android Emulator, try running it on a device instead.

Click Next step, choose Message and type a message. For example, in Title, type “Earth is Awesome”, and in Message, type “Travel to Earth now the weather is great!”

image015

Choose Next step.

image016

In the Advanced section, choose Immediate, and then choose Review and Launch. Choose Launch Campaign and return to the app running on your device. If the app is active the alert popup will display with your message. If your app is minimized, your notification appears in the top area of the screen with any other notifications. You can also see the update in the Amazon Pinpoint console. Tapping your notification will open your app. This behavior can be customized when you create the campaign within Amazon Pinpoint.

image017

Next, in the app, choose another planet. If your terminal is open, you should see a Endpoint updated successfully event display. Go back to the Amazon Pinpoint console. Choose Copy to new campaign. Choose Segment, choose Create a New Segment, and then choose Custom.

In “Customer Attributes” choose Planet and then choose the planet name you chose in the previous step. Repeat the preceding steps to send push notifications to this custom segment.

The custom attributes (attribute,value) can be changed in the index.android.js file’s _customAttributes function. The native module takes a simple comma delimited string as its argument for custom attributes, as follows.

  • @param {String} Attribute name i.e. “Interest”
  • @param {String} Attribute values i.e. “Pizza, Sushi”

You should also now see monetization events if you choose the Planet Trip, $200.00 button in the app. The monetization and usage data is populated in the Amazon Pinpoint console in near real time. When you choose the Planet Trip button in the app, the event is sent via Google Play monetization builder in the native AWS Mobile SDK. You can customize the values in index.android.js method via JavaScript. You can also customize and send more parameters by modifying the AWSMobileHubModule.java file to send details like Transaction ID. You simply need to update the generateMonetizationEvent method appropriately.

Questions or Comments?
Reach out to us on the AWS Mobile Development Forum.

Source Code on GitHub
github.com/awslabs/aws-pinpoint-sample

AWS Mobile SDK for iOS version 2.5.0 – Improvements and changes to Swift support

by Karthik Saligrama | on | in AWS Mobile | | Comments

What

Version 2.5.0 of the AWS Mobile SDK for iOS introduces better compatibility for a Swift 3 migration.

This blog walks through improvements and breaking changes with this SDK release that are relevant for Swift developers.

When you open your legacy Swift 2.x project with Xcode 8.0 for the first time, you will be prompted by the Swift Migration Assistant to migrate to Swift 3. The following changes have been made to the AWS Mobile SDK for iOS to better support the migration.

Compatibility Improvements

AWS Mobile SDK for iOS version 2.5.0 now has better support for Auto-Completion, added generics, and improved name translation for AWSTask so that it handles the Xcode 8 Swift Migration Assistant gracefully and predictably.

Here are some examples of the changes that will improve the migration to Swift 3:

  •  Added more generics support for public APIs. For example, in Amazon Cognito Sync, dataset.getAllRecords() now returns an array of type AWSCognitoRecord instead of an array without a type.
  • Improved name translation for AWSTask continueWithSuccessBlock and continueWithBlock. This enables Xcode to distinguish these methods and it avoids returning an ambiguous use of the continue error message. To illustrate, The following is an asynchronous call to list Amazon DynamoDB tables:

Prior to iOS SDK 2.5.0

let dynamoDB = AWSDynamoDB.defaultDynamoDB()

let listTableInput = AWSDynamoDBListTablesInput()

dynamoDB.listTables(listTableInput).continueWithBlock{ (task: AWSTask?) -> AnyObject? in
    if let error = task.error {
       print("Error occurred: \(error)")
       return nil
    }

    let listTablesOutput = task.result as  AWSDynamoDBListTablesOutput
    for tableName in listTablesOutput.tableNames {
        print("\(tableName)")
    }
    return nil
}

After iOS SDK 2.5.0

let dynamoDB = AWSDynamoDB.default()
let listTableInput = AWSDynamoDBListTablesInput()

dynamoDB.listTables(listTableInput!).continueWith{ (task:AWSTask<AWSDynamoDBListTablesOutput>) -> Any? in
	if let error = task.error as? NSError {
		print("Error occurred: \(error)")
		return nil
	}

	let listTablesOutput = task.result

	for tableName in listTablesOutput!.tableNames! {
		print("\(tableName)")
	}

	return nil
}
  • When migrating legacy Swift code to iOS SDK 2.5.0, continue to use Swift 2.3 syntax for AWS region and service naming conventions. For example: use .USEast1 instead of .usEast1, and use SNS instead of sNS. We made the decision to go against standard Swift 3 naming practices to provide consistency across all AWS region values and service enums.

Swift 3 sample code has been updated and added where appropriate in our AWS Mobile SDK for iOS Samples GitHub repository, in our API reference documentation, and in the AWS Mobile SDK for iOS Developer Guide. Support for a Swift 3 sample app on AWS Mobile Hub is coming soon.

Questions or Comments?

Raise an issue on GitHub or reach out to us via the AWS Mobile Development Forum.

Create an Android Mobile App with Pinpoint using Mobile Hub

by Georgie Mathews | on | in AWS Mobile | | Comments

Amazon Pinpoint is a new AWS service that makes it easy to run targeted campaigns to improve user engagement. Amazon Pinpoint helps you understand your users’ behavior so that you can define who to target, what messages to send, and when to deliver them. Amazon Pinpoint tracks how your users interact with your app so you can monitor the impact of your campaigns.

Amazon Pinpoint provides real-time analytics with dashboards for analyzing user engagement, monetization, user demographics, custom events, and funnels so you can understand how users engage with your app. You can analyze and understand your user data by drilling down based on the segments you’ve defined, segmentation attributes, or time.

With Amazon Pinpoint, you can define target segments from various data sources. You can identify segments from app user data collected by Amazon Pinpoint. You can build custom segments from user data collected by other AWS services, such as Amazon S3 and Amazon Redshift. You can also import user segments from third party sources, such as Salesforce via S3.

Once you define your segments, Amazon Pinpoint lets you send targeted notifications with personalized messages to each user in the segment based on custom attributes, such as game level, favorite team, and news preferences. Amazon Pinpoint can send push notifications immediately, at a time you define, or as a recurring campaign. By scheduling campaigns, you can optimize the push notifications to be delivered at a specific time across multiple time zones. Amazon Pinpoint supports rich notifications, so you can send images as part of your push notifications. Amazon Pinpoint also supports silent or data notifications, which allow you to control app behavior and configuration in the background.

Once your campaign is running, Amazon Pinpoint provides metrics to track the impact of your campaign, including the number of notifications received, number of times the app was opened as a result of the notifications, time of app open, push notification opt-out rate, and revenue. You can also export event data reported by your app and run custom analytics using your existing analytics systems.

You can run A/B tests for different messages, track results, and then send the best message to your target segment.

With Amazon Pinpoint there is no minimum fee, no setup cost, and no fixed monthly cost based on your total user pool. You only pay for the number of users you target or collect events from, the messages you send, and events you collect, so you can start small and scale as your application grows.

Now let’s have a look at how you integrate Amazon Pinpoint with your app.

Requirements

Latest version Android Studio: https://developer.android.com/studio/index.html

Step 1 – Mobile Hub

Create a new Mobile Hub project from the AWS Mobile Hub console. In this example, we are naming the project PinpointMobileHub.

MobileHubCreate

Enable Amazon Pinpoint by clicking User Engagement.

Image2

Enable app and campaign analytics by clicking Enable Engagement.

Choose Android and add your API Key and Sender ID.

EnableUserEngagement

To provide your API Key and Sender ID, refer to the next section for information on how to get these credentials from your Google Developer Project using Firebase.

Getting Sender ID and API Key

Go to https://console.firebase.google.com. Create a new Firebase project called PinpointMobileHub.

Go to your project settings by clicking on the gear icon next to your project name, and then click on Project settings.

Click on the CLOUD MESSAGING tab. Copy the Sender ID (also called Project Number) and the API Key.

Back to Mobile Hub

Provide your sender ID and server key (API Key).

SaveCredentials

Click Save changes. Click Integrate with your app
. You will be redirected to the Integrate feature of Mobile Hub. Click the Android tab to download the Android Mobile Hub sample.

The Android sample contains the Amazon Pinpoint SDK, along with a Demo fragment demonstrating how to record analytics events and how to enrich an endpoint profile with custom attributes so that you can target users based on their preferences.

Mobile Hub Android Sample

Unzip the downloaded file PinpointMobileHub-aws-my-sample-app-android.zip.

IntegrationSteps

Open Android Studio.

Click Open an existing Android Studio project, and navigate to the MySampleApp directory.

Android Studio will open the sample project. Now you should be able to run the sample in your device or on the simulator.

You can verify that your credentials are correct by checking the AWSConfiguration file inside the com.amazonaws.mobile package.
 Verify that your project contains a value for the GOOGLE_CLOUD_MESSAGING_SENDER_ID key.

Note: The Mobile Hub sample project uses the Google Cloud Messaging SDK and not the Firebase SDK. If you are using the Firebase SDK in your application, Amazon Pinpoint will still work with your project, however, there are some extra steps you will need to take to make it work correctly. See the section on Firebase integration.

Run the application on a simulator or device, if you are running the application on the simulator you need to make sure that you have logged in to Google Account on the simulator so that Push Notifications will work on the simulator. To add an account, go to Settings -> Accounts -> Add account -> Google, and log in to your account.

Demo App Analytics

On the demo application, navigate to the User Engagement section and tap on Demo App Analytics.
You will see two buttons on the bottom, the left button records a custom event and the right button records a monetization event.

You can add custom attributes and metrics to an event. The sample code is the following:

 

final AnalyticsClient analyticsClient = AWSMobileClient.defaultMobileClient().getPinpointManager().getAnalyticsClient();

final AnalyticsEvent event = analyticsClient.createEvent(“DemoCustomEvent”) // A music app use case might include attributes such as:
// .withAttribute(“Playlist”, “Amazing Songs 2015”)
// .withAttribute(“Artist”, “Various”)

// .withMetric(“Song playtime”, playTime);

.withAttribute(“DemoAttribute1”, “DemoAttributeValue1”) .withAttribute(“DemoAttribute2”, “DemoAttributeValue2”) .withMetric(“DemoMetric1”, Math.random());

analyticsClient.recordEvent(event); analyticsClient.submitEvents();

 

The sample app records a custom event with event type _monetization.purchase.
You can add also custom attributes and metrics to a monetization event. A monetization event must have a price, a product ID, a quantity, and a transaction id. The sample code is the following:

 

final AnalyticsClient analyticsClient = AWSMobileClient.defaultMobileClient().getPinpointManager().getAnalyticsClient();

// This creates a Google Play monetization event. To create an Amazon monetization
// event instead, use AmazonMonetizationEventBuilder.
final AnalyticsEvent event = GooglePlayMonetizationEventBuilder.create(analyticsClient)

.withFormattedItemPrice(“$1.00”)
.withProductId(“DEMO_PRODUCT_ID”) .withQuantity(1.0) .withTransactionId(“DEMO_TRANSACTION_ID”).build();

analyticsClient.recordEvent(event); analyticsClient.submitEvents();

 

Demo user engagement

We will now run through the user engagement and targeting portion of the demo and get a notification sent to the device.

 

Update an endpoint profile

Amazon Pinpoint is able to segment and target users based on an endpoint profile. The endpoint profile contains information about the device, such as model, make, version, etc., as well as custom attributes or metrics.

To demo the targeting feature of the demo application, navigate to the User Engagement section and tap on Demo User Engagement.

On the User Engagement demo, you will see information about your endpoint profile, such as your current locale, platform, and version. You can also set custom attributes on the endpoint profile. The demo is setting a custom attribute named `season` to signify the favorite seasons of a user.

Go ahead and select your favorite seasons, we will use it later to create a segment that targets devices with those preferences. For this example, we will select all four seasons.

The sample code to update your profile with custom attributes is the following:

.defaultMobileClient().getPinpointManager() .getTargetingClient().addAttribute(“seasons”, Arrays.asList(“winter”,”spring”,”summer”,”fall”)

.defaultMobileClient().getPinpointManager()

AWSMobileClient

.getTargetingClient().updateEndpointProfile();

 

Creating a campaign

Go to the Amazon Pinpoint console: https://console.aws.amazon.com/pinpoint/home/

Select the PinpointMobileHub application we created in Mobile Hub. It will be named pinpointmobilehub_MobileHub since we created the app in Mobile Hub.

Click New Campaign.

Image6

Name your campaign My first campaign, keep the campaign type as a Standard campaign, and click Next step.

Image7

Now let’s create a segment to target users that have selected `Fall` as a favorite season. Name this segment `Fall` so that we can reuse it later.

In the section Filter by custom attributes, select fall and click Next step.

Image8

Give a title and body to the notification, then click Next step.

Schedule the campaign to be Immediate so that you get the notification right away.

Review your campaign and click Launch Campaign.

If you have the sample app in the foreground, an alert will show up. If the sample app is in the background, a banner will be displayed with the notification. You can also swipe down to see the notification center.

If your app is in the background and you tap on the notification, you will be able to see notification opens metrics in the Amazon Pinpoint console as a Directly Opened metric. Click on the Campaign analytics button.

At this point you should also be able to head over to Amazon Pinpoint Analytics and see the monetization and usage data populated in the console, it may take some time for the data to update.

Image9

 

SDK Integration

First add the Amazon Pinpoint SDK to your Gradle Build.

 

dependencies {
// … other dependencies go here …

compile(‘com.amazonaws:aws-android-sdk-core:2.3.5’) // add the Amazon Pinpoint SDK dependency
compile(‘com.amazonaws:aws-android-sdk-pinpoint:2.3.5’) }

 

Initializing the SDK

To initialize the SDK you must instantiate an instance of the PinpointManager class:

 

try {
final CognitoCachingCredentialsProvider cognitoCachingCredentialsProvider =

new CognitoCachingCredentialsProvider( context,
”YOUR_IDENTITY_POOL_ID”, Regions.US_EAST_1,

new ClientConfiguration() final PinpointConfiguration config =

);
new PinpointConfiguration(context, “YOUR_APP_ID”,

Regions.US_EAST_1,

cognitoCachingCredentialsProvider); this.pinpointManager = new PinpointManager(config); //Save instance of pinpointManager

}
catch (final AmazonClientException ex) {

Log.e(LOG_TAG, “Unable to initalize Amazon Mobile Analytics. ” + ex.getMessage(), ex); }

Mobile Hub initializes the SDK inside its AWSMobileClient class. You may use that class to manage initialization of AWS SDKs.

 

Instrumenting Session Data

You must instrument session data manually on Android. You must record session start and stop events in order for Analytics to work. A session must be started before an event is recorded, and they should be stopped once the application goes into the background. Mobile Hub has an example inside its Application class utilizing the AbstractApplicationLifeCycleHelper that provides callbacks to detect when your application goes into the background and comes to the foreground.

The following example is taken from Mobile Hub’s example code:

 

@Override

public void onCreate() {
Log.d(LOG_TAG, “Application.onCreate – Initializing application…”); super.onCreate();
initializeApplication();
Log.d(LOG_TAG, “Application.onCreate – Application initialized OK”);

}
private void initializeApplication() {
AWSMobileClient.initializeMobileClientIfNecessary(getApplicationContext());

// The Helper registers itself to receive application lifecycle events when it is constructed. // A reference is kept here in order to pass through the onTrimMemory() call from
// the Application class to properly track when the application enters the background. applicationLifeCycleHelper = new AbstractApplicationLifeCycleHelper(this) {

@Override
protected void applicationEnteredForeground() {
final PinpointManager pinpointManager = AWSMobileClient.defaultMobileClient()

.getPinpointManager();
pinpointManager.getSessionClient().startSession();
// handle any events that should occur when your app has come to the foreground…

}
@Override

protected void applicationEnteredBackground() {
Log.d(LOG_TAG, “Detected application has entered the background.”);
final PinpointManager pinpointManager = AWSMobileClient.defaultMobileClient()

.getPinpointManager();
pinpointManager.getSessionClient().stopSession(); pinpointManager.getAnalyticsClient().submitEvents();
// handle any events that should occur when your app has gone into the background…

} };

// …Put any application-specific initialization logic here…

}

@Override
public void onTrimMemory(final int level) { Log.d(LOG_TAG, “onTrimMemory ” + level); applicationLifeCycleHelper.handleOnTrimMemory(level); super.onTrimMemory(level);

}
Setting up push notification with GCM

The SDK needs to register the device token received from GCM with the endpoint profile.
Implement the GCMTokenUpdateObserver in a class and override the onGCMTokenUpdate method. The following example is taken from Mobile Hub’s example code:

 

@Override

public void onGCMTokenUpdate(final String gcmToken, final boolean didTokenChange) { if (didTokenChange) {

Log.d(LOG_TAG, “GCM Token changed, registering for Campaign push.”);
// Register the Device Token to receive Campaign Push.
final NotificationClient notificationClient = AWSMobileClient.defaultMobileClient()
.getPinpointManager()

.getNotificationClient(); notificationClient.registerGCMDeviceToken(gcmToken);

} }

 

On your class that extends the GcmListenerService add the following code inside the onMessageReceived method:

 

AWSMobileClient.initializeMobileClientIfNecessary(this.getApplicationContext()); final NotificationClient notificationClient = AWSMobileClient.defaultMobileClient()

.getPinpointManager().getNotificationClient(); NotificationClient.CampaignPushResult pushResult =
notificationClient.handleGCMCampaignPush(from, data, this.getClass());

if (!NotificationClient.CampaignPushResult.NOT_HANDLED.equals(pushResult)) {
if (NotificationClient.CampaignPushResult.APP_IN_FOREGROUND.equals(pushResult)) {

// You can handle the notification any way you like if the app is in the foreground.

}

return;

}

 

Add the following declarations to your AndroidManifest.xml. In this example taken from Mobile Hub, we register the PushListernerService to handle messages.

 

<uses-permission android:name=”android.permission.WAKE_LOCK”/> <uses-permission android:name=”com.google.android.c2dm.permission.RECEIVE” /> <permission android:name=”com.amazon.mysampleapp.permission.C2D_MESSAGE”
android:protectionLevel=”signature” />
<uses-permission android:name=”com.amazon.mysampleapp.permission.C2D_MESSAGE” />

<application

<receiver

android:name=”com.google.android.gms.gcm.GcmReceiver” android:exported=”true” android:permission=”com.google.android.c2dm.permission.SEND” > <intent-filter>

<action android:name=”com.google.android.c2dm.intent.RECEIVE” />

<category android:name=”@string/google_cloud_messaging_package” /> </intent-filter>

</receiver>

<!– BEGIN – PUSH NOTIFICATIONS WITH GOOGLE CLOUD MESSAGING (GCM) –>
<service

android:name=”.PushListenerService” android:exported=”false” > <intent-filter>

<action android:name=”com.google.android.c2dm.intent.RECEIVE” /> </intent-filter>

</service>

 

Setting up push notification with Firebase

The SDK needs to register the device token received from FCM with the endpoint profile. Extend the FirebaseInstanceIdService in a class, and override the onTokenRefresh method.

On your class that extends the FirebaseMessagingService, add the following code inside the onMessageReceived method:

 

@Override

public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken(); AWSMobileClient.defaultMobileClient().getPinpointManager()
.getNotificationClient().registerGCMDeviceToken(refreshedToken); }
NotificationClient.CampaignPushResult pushResult = AWSMobileClient.defaultMobileClient().getPinpointManager().

getNotificationClient().handleFCMCampaignPush( remoteMessage.getFrom(), remoteMessage.getData());

if (!NotificationClient.CampaignPushResult.NOT_HANDLED.equals(pushResult)) {
if (NotificationClient.CampaignPushResult.APP_IN_FOREGROUND.equals(pushResult)) {

// You can handle the notification any way you like if the app is in the foreground.
}

return;

}

 

Add the following declarations to your AndroidManifest.xml. You must register this receiver so that we can launch the app when the user taps on the notification.

 

<receiver

android:name=”com.amazonaws.mobileconnectors.pinpoint.targeting.notification.PinpointNotificationReceiver” android:exported=”false” >
<intent-filter>

<action android:name=”com.amazonaws.intent.fcm.NOTIFICATION_OPEN” /> </intent-filter>

</receiver>

 

AWS Mobile App Backend with Hybrid Apps

by Sean Senior | on | | Comments

This post was co-authored by Leo Drakopoulos, AWS Solutions Architect.

Today we would like to tell you about a new solutions brief for building serverless mobile backend solutions on AWS, and a step-by-step walkthrough for implementing this pattern, using the Ionic framework on AWS Answers. Like other solutions on AWS Answers, this one was built by AWS Solutions Architects. This solution incorporates best practices for deploying scalable backend services for mobile applications by leveraging AWS managed services.

The Mobile Backend Services brief provides best practices, architectural guidance, and considerations for using managed services on the AWS Cloud to simplify development of RESTful backend services for mobile apps. The walkthrough shows you how to power hybrid mobile applications built using the Ionic Framework. You can use the walkthrough guide to quickly integrate your hybrid mobile application with mobile backend services hosted on AWS. The reference architecture and walkthrough enable you to deploy your Ionic mobile app without having to manage any backend infrastructure. The same general approach can be applied to any framework built using JavaScript, such as PhoneGap/Cordova, Framework 7, etc. Here’s how it looks:

This mobile app backend design applies to both hybrid and native mobile application use cases, including the following:

  • User sign in and registration
  • Saving and retrieving data from a NoSQL store
  • Calling cloud hosted REST APIs from your hybrid mobile application

To enable these use cases, the solution uses Amazon Cognito User Pools to add sign-up, sign-in, and user management for mobile apps. Amazon API Gateway is used to create custom RESTful APIs. These APIs trigger an AWS Lambda function to perform CRUD operations on an Amazon DynamoDB NoSQL data store.

Here is how it works. An Amazon Cognito User Pool authorizer is associated with a RESTful API hosted in Amazon API Gateway. The authorizer authenticates every API call made from a mobile app by leveraging a JSON Web Token (JWT) passed in the API call headers. Amazon API Gateway is natively integrated with Amazon Cognito User Pools so the validation of the JWT requires no additional effort from the application developer. Amazon API Gateway then invokes an AWS Lambda function that accesses other AWS services, which in this case is Amazon DynamoDB. When AWS Lambda is invoked, it assumes an AWS Identity and Access Management (IAM) role. The IAM role determines the level of access that AWS Lambda has to Amazon DynamoDB.

The cost to run this reference implementation in production varies, depending on the scale of your backend services. Some of the services leveraged by the solution are part of the AWS Free Tier, which enables you to get started at a very low cost point. For more information, see AWS Free Tier at https://aws.amazon.com/free/.

The solution brief for the Mobile App Backend is available online or you can download the .pdf version here. You can get started today by downloading the step-by-step walkthrough guide for the reference implementation using the Ionic framework.