Vacay Coupons Mobile Application Demo

Core team

  • [Diego Rodriguez] – Lead Developer, GSM Media Group
  • Paul DeCarlo – Senior Technical Evangelist, Microsoft
  • Hao Luo – Technical Evangelist, Microsoft
  • James Earle – Technical Evangelist, Microsoft

Customer profile

GSM Worldwide Media is a Houston-based company that provides a platform for advertisers to target their market effectively to the most media-receptive audience in “buying mode” across America. Vacay Coupons is a service from the GSM Media Group that allows guests to receive exclusive sales offers and gifts from retailers at port locations across the Caribbean and Alaska. Vacay provides the guest with pertinent information on their phone without Wi-Fi or mobile data usage. Vacay also allows guests to review coupons, discounts, and gifts from stores while in port so that guests never miss an opportunity to bring home the perfect souvenir or memento.

By using the app, customers can opt in to a selection of deals from local retailers as well as receive pertinent information about the port that they are visiting. Are they looking for some interesting history about the island or the current exchange rate? Vacay Coupons helps customers feel confident that they are getting the very best while on shore during their vacation.

Problem statement

Port areas often suffer from limited access to the Internet, which makes it difficult for their retailers to communicate shopping opportunities to potential customers. To solve this problem, retailers are installing beacons on their properties. Beacons are low-cost, low-powered transmitters equipped with Bluetooth Low Energy (BLE) that deliver proximity-based, context-aware messages. A beacon transmits signals, which allows another device to determine its proximity to the broadcaster. In a store, a beacon lets a customer’s app determine that it’s close to a particular aisle or in a particular department.

Retailers who use Vacay can communicate directly with customers by beacons. While the beacon provides access, applications are also employed to ensure retailer and customer success. Vacay provides a solution that communicates bidirectionally to/from customers who run their mobile application by using access points (kiosks) within local shops. Notifications may include information about currency exchange rates, health advisories, or coupons for use at local retailers. Upstream data from these retailers to Vacay’s analytics hub (MixPanel) requires pass-through to a scalable web application. This is hosted alongside an informative site that offers white-labeled services based on the technology used by Vacay to communicate with mobile devices via Bluetooth, Wi-Fi, P2P, and iBeacon.

Vacay also required a mechanism to assist in the development and delivery of their Android application on mobile devices. The Vacay development team is spread across the United States and Mexico, which can cause issues when different teams attempt to sync their daily code changes. It can also be difficult to ultimately distribute builds to testers and stakeholders looking to verify the latest development features. Vacay required a solution that encouraged collaboration while providing stakeholders a way to gauge overall project status with the inclusion of a friction-free method for daily build distribution. Here we introduced the concept of modern DevOps practices that focus on the union of products, process, and people to enable continuous delivery (CD) of value to end users. By incorporating Visual Studio Team Services (product) and applying continuous integration (CI) and continuous delivery (process), Vacay (people) were able to overcome these obstacles and streamline their overall development, testing, and release cycles to provide higher value to end users.

Solution, steps, and delivery

Analyze and improve existing project architecture

Vacay started out with an infrastructure as a service (IaaS) environment that relied on using virtual machines for hosting their web services environment. Through interaction with developers from Microsoft, we were able to reduce costs and maintenance overhead for Vacay by consolidating to a platform as a service (PaaS) environment focused on using the Web Apps feature of Microsoft Azure App Service. The end result retained all the benefits of scalability with the added benefit of an overall lighter-weight deployment.

Following is a diagram of the pre-existing architecture.


Original architecture


This diagram shows two informational web pages (WordPress instances) running on two individual virtual machines running Internet Information Services (IIS). One of these virtual machines also runs a REST API and MVC app to service their proposed mobile application. Development work was done in GitLab running on a third virtual machine.

This architecture satisfied the basic technical needs for Vacay, but was built entirely on the concept of IaaS. This approach can be equated to taking an existing hard drive with a pre-installed operating system, middleware, runtime, data, and application code, and then copying it into a cloud host where it would run in a virtual machine environment. The resulting virtual machine would behave in a manner identical to having a copy of said hard drive installed and running on a physical machine. This means that these virtual machine servers, while scalable, still require maintenance at the operating system, middleware, and runtime layer. In addition, the dollar cost for deploying to the cloud as IaaS is the most expensive method for running custom software in the cloud when compared to PaaS and software as a service (SaaS).

PaaS is not always possible because this requires an analysis and understanding of the underlying technologies being used in the existing environment. Our diagram shows that two WordPress instances were in use, both of which relied on a PHP codebase with an underlying MySQL database. In addition, an API service was exposed in an ASP.NET MVC 5 web application. Web Apps supports a variety of different technologies out of the box including Java, PHP, Node.JS, Python, and .NET. Under the covers, Web Apps serves these technologies through a managed IIS instance on top of Windows Server. These characteristics resolve the operating system, middleware, and runtime layer with Azure Cloud Services providing the network, storage, and physical server. As a result, Web Apps PaaS offerings reduce the responsibilities of the developer to requiring only the data and application code necessary to run their intended application.

Following our analysis of the existing architecture and the knowledge that Web Apps supports Vacay’s PHP and .NET dependencies, we were able to develop a strategy to reduce virtual machine (IaaS) usage by implementing Web Apps (PaaS). This would provide the same core functionality with lower costs while still maintaining the ability to scale to demand.

We created a proposal to shift existing resources into three web apps (PaaS) with development work migrated to a new Git repository on Visual Studio Team Services (SaaS). This reduced us from three virtual machines to three instances of web apps. The Mobile Apps feature of Azure App Service along with Azure Notification Hubs provided enhanced mobile application functionality.

The following diagram shows what the newly proposed architecture looks like.


Current architecture


Moving the WordPress instances off of IIS and into a Web Apps host was resolved by first creating a fresh WordPress instance by using one of Azure’s built-in Web Apps templates for WordPress.


WordPress Template


We then installed the All-in-One WP Migration Plug-in from WordPress.org onto both the existing and new WordPress instances. Using this plug-in, we exported from the existing site and then imported the resulting backup into the freshly deployed WordPress instance. All that was left was pointing the A record of the existing domain name from the IP address of the virtual machine to the IP address of the Web Apps instance. This was accomplished by selecting the Custom Domains tab for the web app within Azure, retrieving the IP address, and modifying the DNS record with Vacay’s registrar.


A Record


Migration of the ASP.NET MVC 5 application was possible by deploying the codebase directly to a new Web Apps instance from within Visual Studio by using the Azure SDK 2.5. To deploy the codebase, right-click the MVC Project and select Publish Web App within Visual Studio.


VS Deploy


VS Publish


It should be noted that other migrations may require configuration of deployment credentials under a newly created Web Apps instance.


Deployment Credentials


After your credentials are configured, Azure will supply an FTP hostname that can be used for transferring your existing codebase. You may also set up continuous deployment to push your code from a service such as Visual Studio Team Services, OneDrive, Git, GitHub, Bitbucket, or Dropbox.


Deployment sources


We were fortunate that the existing MVC 5 codebase pointed to an existing Azure SQL Database. As a result, the database ConnectionStrings were still valid after moving into the PaaS host, and our site was up and running following migration of the codebase.

However, our migration to PaaS did not go completely without issue. On November 8, 2016, the network quota maxed out on the VacayCoupons property.


Outage


We solved this by scaling up the Web Apps instance to an S1 and enabling Autoscale, which can be configured based on a target CPU range or by defining your own scheduling and performance rules.


Autoscale


ConfigScale


After applying Autoscale, Vacay has run smoothly without service interruption since November 2016.

As a result of our engagement, we were able to consolidate two virtual machines running three web applications into two web apps. This resulted in a cost savings and resource savings as maintenance of the operating system, middleware, and runtime is now handled behind the scenes in Azure Cloud Services. Vacay also experienced a need for Autoscale, which was satisfied with just a few clicks in the Azure portal. In addition, we consolidated the existing source control server into a SaaS offering by using Visual Studio Team Services.

In the next section, we discuss additional solutions provided by the migration to Visual Studio Team Services.

Create development and distribution system for the Android mobile application

The original environment was designed for iOS; however, Vacay wanted to create an Android mobile application. Because Vacay has development teams in both the United States and Mexico, and both teams would be working on the new app, Vacay needed a collaborative code repository to integrate app development no matter which team was working on it. The stakeholders also wanted to use the HockeyApp platform to distribute their builds. We were able to solve both issues by using continuous integration with Visual Studio Team Services and continuous deployment with HockeyApp integration in Team Services.

By conducting a lightweight value stream mapping exercise, we were able to assess the existing workflow to build and distribute Vacay iPhone apps.


Vacay iOS


Vacay’s planning, development, and release processes were not fully connected. The development process relied on the stakeholder to deliver requirements directly to development. The development team created builds for eventual distribution by using Apple TestFlight, and decided when to push a build to TestFlight when they finished a list of minimal requirements and fixed internal defects. After a release candidate was pushed to TestFlight, regression testing started if the App Store submission process failed.

The new app platform gave the team an opportunity to improve the development process. Our solution distributes testable Android Package Kit (APK) builds over HockeyApp. Stakeholders could give the development team feedback while the development workflow continued until both groups agreed on a successful build. Continuous integration and deployment provided up-to-minute build availability, which allowed testers and stakeholders to immediately test bleeding edge and known stable builds. Due to differences in marketplace submission times for Android vs iOS, we show a sizable lead time reduction, but our most valuable improvements came from using Team Services to directly tie in all the processes. Stakeholders can now provide work items to developers and receive status updates as work progresses. Work can be unit-tested to assign appropriate quality, passing builds are immediately available to testers, and candidates with tracked improvements are available for marketplace release.


Vacay Droid


We moved the existing Android application codebase into a Visual Studio Team Services project space and configured Git as our version control system (VCS). We replaced the GitLab virtual machine with a comparable VCS; this gave us tools to monitor the project and assign work item status. For example, when code check-ins occur, it was easy to configure and deliver stakeholder notifications. Vacay could monitor work progress as it happened no matter where the development occurred.


Team Services Notifications


We used Vacay’s Java-targeted Android codebase, the Visual Studio Team Services standard workflows, and the Gradle script that produces Android Studio local builds to create an environment to develop a Team Services build process to verify code changes. Because this is part of Team Services, developers can set up gated check-ins so that only code that passes a successful build process can be accepted into the Team Services repository. Instructions for setting up this and other custom configuration rules for continuous integration can be found in the VisualStudio.com documentation.


Vacay Build


The Visual Studio Team Services build process and distribution requires proper Gradle Wrapper build setup. We used the assembleRelease value to produce a zip-aligned and signed APK output. HockeyApp will accept any arbitrary APK in a valid build. Output artifacts can be installed on Android devices configured to accept apps from unknown sources, but you can only install HockeyApp on Android devices if the device is signed with a valid keystore/key (in the project’s .gradle file).

It is interesting to note that the hosted build agent contained all of the prerequisites necessary for proper compilation of our Android Studio project. This included Apache ANT 1.9.7, Apache Maven 3.2.2, and the Android Software Development Kit 25.2.5. The hosted agent not only supports these and other pre-installed packages, but also is available for use free of charge right out of the box in Visual Studio Team Services. Our build only required configuring Team Services to use JDK 8 for successful compilation as shown in Advanced Settings.


Java


The build process includes a step to copy successful build output to HockeyApp. Developers, testers, and stakeholders now have immediate access to the latest builds and can install directly on a compatible Android device.


Vacay Build


We found that the Team Services build log could show the HockeyApp build step as green, while a red ‘X’ appeared next to the build step, indicating that the HockeyApp build step failed but not providing additional information. We increased log verbosity but that didn’t tell us anything else. When we took the produced APK and tried to manually upload it into HockeyApp, we received a message that our APK was unable to be uploaded due to a missing version number in the Android manifest. We resolved this by assigning a version number in the Android manifest as depicted in the following diagram.


Vacay Build


Integrate Azure App Service into the Android mobile application

The Vacay mobile application requires a GSM Proximity Platform SDK provided by GSM Media Group. This SDK allows Vacay to communicate from a kiosk to a mobile application by using Bluetooth, Wi-Fi, P2P, and iBeacon. When an app-enabled device is detected in range of the kiosk or any available proximity point, Azure Notification Hubs contacts the device.

Notification Hubs allows simple user communication and feedback but it requires a platform-specific service provider to communicate with a devices notification API. In the past, Google Cloud Messaging (GCM) was the service provider, but this has been replaced by the Google Firebase project and Firebase Cloud Messaging (FCM). To achieve notifications in an Android application, the device has to be registered with the Google Firebase project. Because FCM is used, the developer is responsible for including their FCM token in the code that manages this registration. Following is a snippet of code from Vacay’s RegistrationIntentService class where this is done.

	@Override
	protected void onHandleIntent(Intent intent) {

		SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
		String resultString = null;
		String regID = null;
		String storedToken = null;

		try {
			String FCM_token = FirebaseInstanceId.getInstance().getToken();
			Log.d(TAG, "FCM Registration Token: " + FCM_token);

			// No registration prior
			if (((regID=sharedPreferences.getString("registrationID", null)) == null)){

				NotificationHub hub = new NotificationHub(NotificationSettings.hubName,
						NotificationSettings.hubListenConnectionString, this);
				Log.d(TAG, "Attempting a new registration with NH using FCM token : " + FCM_token);
				regID = hub.register(FCM_token).getRegistrationId();

				resultString = "New NH Registration Successfully - RegId : " + regID;
				Log.d(TAG, resultString);

				sharedPreferences.edit().putString("registrationID", regID ).apply();
				sharedPreferences.edit().putString("FCMtoken", FCM_token ).apply();
			// Old FCM token on device from previous failed registration
			} else if ((storedToken=sharedPreferences.getString("FCMtoken", "")) != FCM_token) {

				NotificationHub hub = new NotificationHub(NotificationSettings.hubName,
						NotificationSettings.hubListenConnectionString, this);
				Log.d(TAG, "NH Registration refreshing with token : " + FCM_token);
				regID = hub.register(FCM_token).getRegistrationId();

				resultString = "New NH Registration Successfully - RegId : " + regID;
				Log.d(TAG, resultString);

				sharedPreferences.edit().putString("registrationID", regID ).apply();
				sharedPreferences.edit().putString("FCMtoken", FCM_token ).apply();
			// Old registration token exists from successful registration
			} else {
				resultString = "Previously Registered Successfully - RegId : " + regID;
			}
		} catch (Exception e) {
			Log.e(TAG, resultString="Failed to complete registration", e);
		}

		Toast.makeText(getBaseContext(), "Done", Toast.LENGTH_LONG);
		// Notify UI that registration has completed.
		if (SampleActivity.isVisible) {
			SampleActivity.sampleActivity.ToastNotify(resultString);
		}
	}


Notifications can be delivered to users as an on-screen pop-up (Toast), sent to the notification drawer, or displayed on the lock screen depending on the state of the device when sent. Devices that use an Android version lower than Android 5.0 (Lollipop) can’t receive notifications on the lock screen; instead they will be delivered to the notification drawer. The NotificationHandler class is responsible for sending notifications in the application. It makes use of the Android API that is required to send any notification to the user’s screen or notification drawer. Following is the code that handles this action.

	private void sendNotification(String msg) {

		Intent intent = new Intent(context, SampleActivity.class);
		intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

		mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);

		PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);

		Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
		NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
				.setContentTitle("Notification Hub Demo")
				.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
				.setSound(defaultSoundUri)
				.setContentText(msg);

		mBuilder.setContentIntent(contentIntent);
		mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
	}


Following is an example of the Vacay application receiving a Toast notification.


Azure Notification Hub to FCM


Vacay Device Notification


Usage data is captured and stored in a Mobile Apps Easy table. Every time an app starts, the app will insert a row in a database table with a timestamp. Currently, the Easy table integration is using the latest version of the Azure Mobile Apps Android SDK, version 3.1.0.

The following code snippet can be found in the main Activity file of the onStart method.

	mClient = new MobileServiceClient("https://vacaymobile.azurewebsites.net", this);
	EventItem item = new EventItem();
	item.Message = "App Started";
	MobileServiceTable<EventItem> table = mClient.getTable(EventItem.class);
	ListenableFuture future = table.insert(item);
	future.addListener(new Runnable() {
		@Override
		public void run() {
			Toast.makeText(getApplicationContext(), "Inserted to Easy table", Toast.LENGTH_LONG).show();
		}
	}, MoreExecutors.directExecutor());


We chose to use ListenableFuture instead of the sync approach to make our insert call, because ListenableFuture allows us to potentially decentralize the logic of what happens after the insert. This approach enables developers to delegate the responsibility of handling async logic to other parts of the application by passing the future variable to other parts of the application.

Customer example

Vacay Coupons website

GSM Media Group website

Conclusion

With the power and scalability of Azure Cloud Services, Vacay is able to deliver reliable service to end users from all over the world. Pending the results of the lightweight value stream mapping exercise, development teams across countries are using Visual Studio Team Services and HockeyApp distribution to produce native Android applications for mobile devices. With a quick analysis of existing processes, we were able to reduce lead time by a full five days. By applying continuous integration through the use of gated code check-in rules, and continuous delivery by using automated deployment on build completion with HockeyApp, the Vacay development and distribution infrastructure ensures that end users receive a high-quality product in cloud-connected and mobile scenarios.

Keep in mind that these are only a sampling of the benefits that Vacay can take advantage of in their Team Services/HockeyApp environment. HockeyApp can also provide insight into the usage of live or in-beta apps by using built-in crash reporting and metric reporting. Furthermore, Team Services provides the ability to test builds on real mobile devices in the cloud with Visual Studio Mobile Center. Having a Team Services/HockeyApp infrastructure configured and readily available will no doubt prove beneficial to Vacay when they move to develop their iOS application. In addition to support for Windows and Android devices, Mobile Center can provide Mac build environments to produce device testable/signed iOS builds.

Through our engagement with Vacay, we have showcased the ability for Microsoft technologies to serve as a critical component in modern software industries focused on delivering high availability, scalable mobile applications to a global user base.

Additional resources

Vacay Coupons Retail Demo