Article summary

Discusses the following points:
  • how to download and build an AEM mobile application. 
  • the AEM APIs used in the application.
  • how to open the AEM mobile application in AEM author. 
A special thank you to Bruce Lefebvre, an AEM Computer Scientist for his help to create this development article.  
Digital Marketing Solution(s) Adobe Experience Manager (Adobe CQ)
Developer (beginner - intermediate)
Required Skills
JCR nodes, JavaScript, HTML
Tested On Adobe Experience Manager 6


You can develop an Enterprise PhoneGap mobile application for Adobe Experience Manager (AEM) 6. By creating a mobile AEM application, you can create content-rich cross-platform mobile applications that interact with device features: 

  • Use the AEM authoring environment to create and manage rich content for your applications.
  • Use the PhoneGap (Cordova) APIs to create components with device-native capabilities, exposed through the PhoneGap javascript bridge.
  • Build and manage mobile content into pre-existing native applications through Cordova WebViews integration with Adobe Experience Manager.

This developer article walks you through how to download and build an AEM mobile sample application. The following illustration shows the mobile sample AEM application built in this development article.



For information about the PhoneGap APIs, see PhoneGap Documentation.


Click the following link for more information about building an AEM 6 PhoneGap application

The following illustration shows the project files created in this development article.


When creating a mobile application for AEM, you have access to all of the AEM APIs to add AEM specific functionality to the application. For example, you can use the Tag Manager API to get tags listed in specific AEM pages. 

This development article steps you through how to download and build this AEM 6 mobile application. Perform these steps:

  1. Download the AEM mobile project. 
  2. Deploy and build the AEM mobile project. 
  3. View the project files.
  4. Open the mobile project.

Download and build the AEM mobile project 

The first step is to download and build the AEM mobile project that is located from the following GitHub repository:

Fork the repository to make a copy of it. Download the forked version by using GitHub clone command:


This command downloads the forked repository to your local Github folder. Now you can use Maven to build and deploy the aem-phonegap-kitchen-sink project. 


For more information about setting up Maven, see: Maven in 5 Minutes.

Navigate to your local folder to where the aem-phonegap-kitchen-sink project files are located. Build and deploy the project by using the following Maven command from the project's root:

mvn -PautoInstallPackage clean install

This command places the /apps/brucelefebvre/kitchen-sink folder in your local version of AEM. (See the illustration at the beginning of this article.) 

Understanding the kitchen-sink project files

The main project files for the AEM kitchen-sink mobile application are located under the following path: /apps/brucelefebvre/kitchen-sink/components. This application consists of the following components:

  • Inappbrowser-button
  • menu-list
  • item-listing
  • mp4-video
  • ng-ionic-page
  • ng-library-item
  • phonegap-camera
  • phonegap-connection
  • phonegap-contacts
  • phonegap-location
  • splash-page

Inappbrowser component 

The inappbrowser component opens content to another web site. The following illustration shows this component. 



The following code represents this component located at /apps/brucelefebvre/kitchen-sink/components/ionic-inappbrowser-button. 

<%@ page session="false" %><%
%><%@include file="/libs/foundation/global.jsp"%><%

    String buttonText = properties.get("buttonText", "Click Me");
    String buttonLink = properties.get("buttonLink", "#");

<button onclick="'<%= xssAPI.getValidHref(buttonLink) %>', '_blank');" class="button button-balanced">
	<%= xssAPI.encodeForHTML(buttonText) %>

The menu component displays the list of options in the mobile application, as shown in the  following illustration. 


The following code represents this component located at /apps/brucelefebvre/kitchen-sink/components/ionic-menu-list.

<%@include file="/libs/foundation/global.jsp" %><%
%><%@ page session="false"
	      " %>
<%-- initialize the list --%>
<cq:include script="init.jsp"/>
    <ul class="list">
    String TEMPLATE_PAGE_RESOURCE_TYPE = "brucelefebvre/kitchen-sink/components/ng-ionic-page/ng-template-page";

    List list = (List)request.getAttribute("list");
    Iterator<Page> items = list.getPages();
    if (items != null) {
        while (items.hasNext()) {
            Page carouselPage =;
            ValueMap vm = carouselPage.getProperties();
            // Only include Angular pages
            Resource currentPageContentResource = carouselPage.getContentResource();
            // Skip this page if it is not based on ng-page
            // OR, if this page is an ng-template-page
            if (currentPageContentResource == null || 
                    currentPageContentResource.isResourceType(TEMPLATE_PAGE_RESOURCE_TYPE) || 
                    !currentPageContentResource.isResourceType(FrameworkContentExporterUtils.NG_PAGE_RESOURCE_TYPE)) {

            String title = (carouselPage.getTitle() == null ? "" : carouselPage.getTitle());
%>        <a class="item" ng-click="go('<%= xssAPI.getValidHref(carouselPage.getPath()) %>')">
        	<%= xssAPI.encodeForHTML(title) %>

Library component

The Library component lists tags that belong to child pages. The following code represents this component located at /apps/brucelefebvre/kitchen-sink/components/library-item-listing. 

<%@ page session="false"
%><%@include file="/libs/foundation/global.jsp"%><%
%><%@include file="/apps/geometrixx-outdoors-app/global.jsp"%><%

%><div class="list">
    final String NG_TEMPLATE_PAGE_RESOURCE_TYPE = "brucelefebvre/kitchen-sink/components/ng-ionic-page/ng-template-page";

    boolean hasAChildPage = currentPage.listChildren().hasNext();

    // Don't show any library items if this page is not a leaf
    if (hasAChildPage == false ) {

        Tag[] tags = currentPage.getTags();
        String libraryDataRootPath = FrameworkContentExporterUtils.getTopLevelAppResource(currentPage.getContentResource()).getPath() + "/library-data";

        if (tags.length > 0) {
            // Convert tags array to an array of String paths
            String[] tagsIds = new String[tags.length];
            for (int i = 0; i < tags.length; i++) {
                tagsIds[i] = tags[i].getPath();
            TagManager tagManager = resourceResolver.adaptTo(TagManager.class);
            RangeIterator<Resource> taggedPages = tagManager.find(libraryDataRootPath, tagsIds);

                Resource productPageResource =;
                // Get the product represented by this page
                Product product = getProduct(productPageResource);
                if (product != null) {
                    // Determine the product path
                    Resource productPageTemplateResource = FrameworkContentExporterUtils.getAncestorTemplateResource(productPageResource, NG_TEMPLATE_PAGE_RESOURCE_TYPE);
                    String productSKUPrefix = product.getSKU().substring(0,2);
                    String templatePath = productPageTemplateResource.getPath();
    <a class="item" ng-click="goLibraryItem('<%= request.getContextPath() %><%= xssAPI.getValidHref(templatePath) %>', '<%= xssAPI.getValidHref(productSKUPrefix) %>', '<%= xssAPI.getValidHref(productPageResource.getParent().getName()) %>')">
        <%= xssAPI.encodeForHTML(product.getTitle()) %>

Video component

The Video component displays videos within the mobile application, as shown in the following illustration. 


The video component displays video within the mobile application. The following code represents the video component located at /apps/brucelefebvre/kitchen-sink/components/mp4-video.

<%@page session="false"%><%

//    boolean wcmEditMode = (WCMMode.fromRequest(request) == WCMMode.EDIT);

    // try find referenced asset
    Asset asset = null;
    Resource assetRes = resourceResolver.getResource(properties.get("asset", ""));
    if (assetRes != null) {
        asset = assetRes.adaptTo(Asset.class);
    if (asset != null) {
        // Determine the top level app resource
        Resource topLevelAppResource = FrameworkContentExporterUtils.getTopLevelAppResource(currentPage.adaptTo(Resource.class));

        boolean appExport = Boolean.parseBoolean(slingRequest.getParameter("appExport"));
        String resourcePath = FrameworkContentExporterUtils.getPathToAsset(topLevelAppResource, request.getContextPath() + resource.getPath(), appExport);

        String videoSrcPath = resourcePath + ".original.mp4";
        String videoPosterPath = resourcePath + ".thumb.100.140.png";

    <video controls poster="<%= xssAPI.encodeForHTMLAttr(videoPosterPath) %>">
        <source src="<%= xssAPI.encodeForHTMLAttr(videoSrcPath) %>" type="video/mp4">
        Your device doesn't support this video. 

} else {
    String ddClassName = DropTarget.CSS_CLASS_PREFIX + "video";
    String classicPlaceholder =
            "<div class=\"" + ddClassName +
                    (WCMMode.fromRequest(request) == WCMMode.EDIT ? " cq-video-placeholder" : "")  +
    String placeholder = Placeholder.getDefaultPlaceholder(slingRequest, component, classicPlaceholder, ddClassName);
%><%= xssAPI.filterHTML(placeholder) %><%

Phonegap-camera component 

The phonegap-camera component lets the application take a picture using the device. The following illustration shows this component.



The following code represents the component located at /apps/brucelefebvre/kitchen-sink/components/phonegap-camera.

<%@page session="false"%><%@ include file="/libs/foundation/global.jsp" %><%
%><%@ page import=",
         " %><%

//    boolean wcmEditMode = (WCMMode.fromRequest(request) == WCMMode.EDIT);

    // try find referenced asset
    Asset asset = null;
    Resource assetRes = resourceResolver.getResource(properties.get("asset", ""));
    if (assetRes != null) {
        asset = assetRes.adaptTo(Asset.class);
    if (asset != null) {
        // Determine the top level app resource
        Resource topLevelAppResource = FrameworkContentExporterUtils.getTopLevelAppResource(currentPage.adaptTo(Resource.class));

        boolean appExport = Boolean.parseBoolean(slingRequest.getParameter("appExport"));
        String resourcePath = FrameworkContentExporterUtils.getPathToAsset(topLevelAppResource, request.getContextPath() + resource.getPath(), appExport);

        String videoSrcPath = resourcePath + ".original.mp4";
        String videoPosterPath = resourcePath + ".thumb.100.140.png";

    <video controls poster="<%= xssAPI.encodeForHTMLAttr(videoPosterPath) %>">
        <source src="<%= xssAPI.encodeForHTMLAttr(videoSrcPath) %>" type="video/mp4">
        Your device doesn't support this video. 

} else {
    String ddClassName = DropTarget.CSS_CLASS_PREFIX + "video";
    String classicPlaceholder =
            "<div class=\"" + ddClassName +
                    (WCMMode.fromRequest(request) == WCMMode.EDIT ? " cq-video-placeholder" : "")  +
    String placeholder = Placeholder.getDefaultPlaceholder(slingRequest, component, classicPlaceholder, ddClassName);
%><%= xssAPI.filterHTML(placeholder) %><%

Phonegap-compass component

The phonegap-compass component creates a component on the device, as shown in the following illustration. 


The following code represents this component that is located at /apps/brucelefebvre/kitchen-sink/components/phonegap-compass. 

<%@include file="/libs/foundation/global.jsp" %><%
%><%@ page session="false" %><%
<div ng-controller="CompassCtrl" class="list">
	<label class="item item-input item-stacked-label">
		<span class="input-label">Heading</span>
		<input type="text" placeholder="Locating..." disabled ng-value="magneticHeading">
	<div style="padding:20px;">
		<cq:include script="compass-svg.jsp" />

In this code, notice the following line of code: 

<cq:include script="compass-svg.jsp" />

This includes another JSP file that contains PhoneGap functionality that uses compass functionality. The following code represents the compass-svg.jsp file.

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "">
<svg version="1.1" id="Layer_1" xmlns="" xmlns:xlink="" preserveAspectRatio="xMidYMid meet" x="0px" y="0px" viewBox="-16 0 877 900" enable-background="new 0 0 877 900" xml:space="preserve">
		#ticks {
			font-family: 'MyriadPro-Regular';
			font-size: 28px;
		#cardinal {
			font-family: 'MyriadPro-Regular';
			font-size: 40px;
		.rotatable {
			-webkit-transform-origin: 50% 50%;
			-webkit-transition: all 100ms ease-in-out;
	<font horiz-adv-x="1000">
		<font-face font-family="MyriadPro-Regular" units-per-em="1000" underline-position="-100" underline-thickness="50" />
		<missing-glyph horiz-adv-x="500" d="M0,0l500,0l0,700l-500,0M250,395l-170,255l340,0M280,350l170,255l0,-510M80,50l170,255l170,-255M50,605l170,-255l-170,-255z" />
		<glyph unicode="E" horiz-adv-x="492" d="M425,388l-262,0l0,213l277,0l0,73l-364,0l0,-674l379,0l0,73l-292,0l0,243l262,0z" />
		<glyph unicode="N" horiz-adv-x="658" d="M158,0l0,288C158,400 156,481 151,566l3,1C188,494 233,417 280,342l214,-342l88,0l0,674l-82,0l0,-282C500,287 502,205 510,115l-2,-1C476,183 437,254 387,333l-216,341l-95,0l0,-674z" />
		<glyph unicode="S" horiz-adv-x="493" d="M42,33C78,9 149,-10 214,-10C373,-10 450,80 450,184C450,283 392,338 278,382C185,418 144,449 144,512C144,558 179,613 271,613C332,613 377,593 399,581l24,71C393,669 343,685 274,685C143,685 56,607 56,502C56,407 124,350 234,311C325,276 361,240 361,177C361,109 309,62 220,62C160,62 103,82 64,106z" />
		<glyph unicode="W" horiz-adv-x="846" d="M277,0l96,351C398,438 413,504 425,571l2,0C436,503 450,437 471,351l85,-351l91,0l191,674l-89,0l-89,-340C639,250 620,175 606,101l-2,0C594,172 576,252 557,332l-82,342l-91,0l-90,-340C271,247 250,167 239,100l-2,0C225,165 207,249 187,333l-80,341l-92,0l171,-674z" />
		<glyph unicode="8" horiz-adv-x="513" d="M255,-11C379,-11 476,65 476,178C476,257 426,314 345,346l0,3C425,387 452,446 452,501C452,582 389,661 263,661C149,661 62,591 62,488C62,432 93,376 165,342l1,-3C86,305 37,247 37,165C37,70 119,-11 255,-11M257,53C174,53 124,111 127,177C127,239 168,289 244,311C332,286 387,248 387,169C387,102 336,53 257,53M258,598C337,598 368,544 368,492C368,433 325,393 269,374C194,394 145,429 145,494C145,550 185,598 258,598z" />
		<glyph unicode="5" horiz-adv-x="513" d="M433,650l-311,0l-42,-312C104,341 133,345 170,345C300,345 356,285 357,201C357,114 286,60 203,60C144,60 91,80 64,96l-22,-67C73,9 133,-11 204,-11C345,-11 446,84 446,211C446,293 404,349 353,378C313,402 263,413 213,413C189,413 175,411 160,409l25,167l248,0z" />
		<glyph unicode="4" horiz-adv-x="513" d="M400,0l0,177l91,0l0,69l-91,0l0,404l-95,0l-290,-415l0,-58l302,0l0,-177M104,246l0,2l159,221C281,499 297,527 317,565l3,0C318,531 317,497 317,463l0,-217z" />
		<glyph unicode="9" horiz-adv-x="513" d="M96,-10C117,-11 145,-10 177,-5C247,3 316,33 366,82C430,144 478,244 478,387C478,553 396,661 263,661C130,661 41,553 41,430C41,319 116,231 233,231C298,231 350,257 386,301l3,0C377,224 346,167 303,128C266,93 218,72 167,65C137,62 115,60 96,62M256,594C348,594 389,509 389,398C389,384 386,374 381,366C358,327 312,298 253,298C177,298 128,355 128,436C128,528 181,594 256,594z" />
		<glyph unicode="1" horiz-adv-x="513" d="M236,0l85,0l0,650l-75,0l-142,-76l17,-67l113,61l2,0z" />
		<glyph unicode="7" horiz-adv-x="513" d="M57,650l0,-73l318,0l0,-2l-282,-575l91,0l283,592l0,58z" />
		<glyph unicode="6" horiz-adv-x="513" d="M416,660C400,660 378,659 352,655C270,645 198,612 144,559C80,495 34,394 34,266C34,97 125,-11 264,-11C399,-11 480,99 480,218C480,345 399,428 284,428C212,428 158,394 127,353l-3,0C139,460 212,561 350,584C375,588 398,589 416,588M264,57C172,57 123,136 121,243C121,259 125,272 131,282C155,329 204,362 257,362C338,362 391,306 391,213C391,120 340,57 264,57z" />
		<glyph unicode="3" horiz-adv-x="513" d="M42,33C74,12 138,-11 211,-11C367,-11 448,80 448,184C448,275 383,335 303,351l0,2C383,382 423,439 423,506C423,585 365,661 237,661C167,661 101,636 67,611l23,-64C118,567 168,590 220,590C301,590 334,544 334,492C334,415 253,382 189,382l-49,0l0,-66l49,0C274,316 356,277 357,186C358,132 323,60 210,60C149,60 91,85 66,101z" />
		<glyph unicode="2" horiz-adv-x="513" d="M460,0l0,73l-292,0l0,2l52,48C357,255 444,352 444,472C444,565 385,661 245,661C170,661 106,633 61,595l28,-62C119,558 168,588 227,588C324,588 356,527 356,461C355,363 280,279 114,121l-69,-67l0,-54z" />
		<glyph unicode="0" horiz-adv-x="513" d="M262,661C130,661 36,541 36,323C38,108 124,-11 251,-11C395,-11 477,111 477,332C477,539 399,661 262,661M257,593C348,593 389,488 389,328C389,162 346,57 256,57C176,57 124,153 124,322C124,499 180,593 257,593z" />

	<line id="indicator" opacity="0.8" fill="none" stroke="#808285" stroke-width="4" x1="422" y1="60" x2="422" y2="0" />
	<circle id="center" fill="#A7A9AC" cx="422" cy="445" r="80" />
	<g id="ticks" class="rotatable" style="-webkit-transform:rotate({{heading}}deg);">
			align-ring is here so that we have something larger than all of the other rendered elements, with the same center point. 
			Otherwise as we change the rotation of sub-elements, we throw off the rotation of the #ticks element
		<circle id="align-ring" fill="none" opacity="0.01" stroke="#FFFFFF" cx="422" cy="445" r="440" />
		<g id="allnumbers">
			<g class="rotatable" style="-webkit-transform: rotate({{-heading}}deg);">
				<text id="_x30_deg" class="deg" transform="matrix(1 0 0 1 415.8164 42.1742)">0</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading-330}}deg);">
				<text id="_x33_30deg" class="deg" transform="matrix(0.866 -0.5 0.5 0.866 204.9858 105.338)">330</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading-300}}deg);">
				<text id="_x33_00deg" class="deg" transform="matrix(0.5 -0.866 0.866 0.5 64.6452 259.2997)">300</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading-270}}deg);">
				<text id="_x32_70deg" class="deg" transform="matrix(7.786777e-09 -1 1 7.786777e-09 20.0878 462.8047)">270</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading-240}}deg);">
				<text id="_x32_40deg" class="deg" transform="matrix(-0.5 -0.866 0.866 -0.5 83.2522 661.3232)">240</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading-210}}deg);">
				<text id="_x32_10deg" class="deg" transform="matrix(-0.866 -0.5 0.5 -0.866 237.2134 801.6642)">210</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading-180}}deg);">
				<text id="_x31_80deg" class="deg" transform="matrix(-1 0 0 -1 440.7183 846.2221)">180</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading-150}}deg);">
				<text id="_x31_50deg" class="deg" transform="matrix(-0.866 0.5 -0.5 -0.866 639.2368 783.0573)">150</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading-120}}deg);">
				<text id="_x31_20deg" class="deg" transform="matrix(-0.5 0.866 -0.866 -0.5 779.5779 629.0956)">120</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading-90}}deg);">
				<text id="_x39_0deg" class="deg" transform="matrix(-7.786777e-09 1 -1 -7.786777e-09 824.1357 431.7466)">90</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading-60}}deg);">
				<text id="_x36_0deg" class="deg" transform="matrix(0.5 0.866 -0.866 0.5 764.0488 232.4025)">60</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading-30}}deg);">
				<text id="_x33_0deg" class="deg" transform="matrix(0.866 0.5 -0.5 0.866 612.3403 89.809)">30</text>
			<line fill="none" stroke="#000000" x1="410.021" y1="102.383" x2="409.311" y2="82.047" />
			<line fill="none" stroke="#000000" x1="398.085" y1="103.009" x2="396.665" y2="82.709" />
			<line fill="none" stroke="#000000" x1="386.177" y1="104.05" x2="384.05" y2="83.813" />
			<line fill="none" stroke="#000000" x1="374.314" y1="105.507" x2="371.482" y2="85.356" />
			<line fill="none" stroke="#000000" x1="350.775" y1="109.658" x2="346.544" y2="89.753" />
			<line fill="none" stroke="#000000" x1="339.128" y1="112.346" x2="334.205" y2="92.602" />
			<line fill="none" stroke="#000000" x1="327.583" y1="115.44" x2="321.974" y2="95.879" />
			<line fill="none" stroke="#000000" x1="316.152" y1="118.935" x2="309.864" y2="99.582" />
			<line fill="none" stroke="#000000" x1="293.691" y1="127.11" x2="286.069" y2="108.243" />
			<line fill="none" stroke="#000000" x1="282.689" y1="131.78" x2="274.412" y2="113.19" />
			<line fill="none" stroke="#000000" x1="271.856" y1="136.832" x2="262.935" y2="118.542" />
			<line fill="none" stroke="#000000" x1="261.206" y1="142.258" x2="251.652" y2="124.291" />
			<line fill="none" stroke="#000000" x1="240.506" y1="154.209" x2="229.723" y2="136.952" />
			<line fill="none" stroke="#000000" x1="230.481" y1="160.719" x2="219.102" y2="143.849" />
			<line fill="none" stroke="#000000" x1="220.69" y1="167.575" x2="208.729" y2="151.112" />
			<line fill="none" stroke="#000000" x1="211.144" y1="174.768" x2="198.616" y2="158.733" />
			<line fill="none" stroke="#000000" x1="192.834" y1="190.132" x2="179.218" y2="175.01" />
			<line fill="none" stroke="#000000" x1="184.092" y1="198.284" x2="169.957" y2="183.646" />
			<line fill="none" stroke="#000000" x1="175.64" y1="206.736" x2="161.003" y2="192.601" />
			<line fill="none" stroke="#000000" x1="167.488" y1="215.478" x2="152.366" y2="201.862" />
			<line fill="none" stroke="#000000" x1="152.124" y1="233.788" x2="136.089" y2="221.26" />
			<line fill="none" stroke="#000000" x1="144.931" y1="243.334" x2="128.468" y2="231.373" />
			<line fill="none" stroke="#000000" x1="138.075" y1="253.125" x2="121.205" y2="241.746" />
			<line fill="none" stroke="#000000" x1="131.565" y1="263.15" x2="114.308" y2="252.367" />
			<line fill="none" stroke="#000000" x1="119.614" y1="283.85" x2="101.647" y2="274.296" />
			<line fill="none" stroke="#000000" x1="114.188" y1="294.5" x2="95.898" y2="285.579" />
			<line fill="none" stroke="#000000" x1="109.136" y1="305.333" x2="90.547" y2="297.056" />
			<line fill="none" stroke="#000000" x1="104.466" y1="316.335" x2="85.599" y2="308.712" />
			<line fill="none" stroke="#000000" x1="96.291" y1="338.796" x2="76.938" y2="332.508" />
			<line fill="none" stroke="#000000" x1="92.796" y1="350.227" x2="73.235" y2="344.618" />
			<line fill="none" stroke="#000000" x1="89.702" y1="361.772" x2="69.958" y2="356.849" />
			<line fill="none" stroke="#000000" x1="87.014" y1="373.419" x2="67.109" y2="369.188" />
			<line fill="none" stroke="#000000" x1="82.863" y1="396.958" x2="62.712" y2="394.126" />
			<line fill="none" stroke="#000000" x1="81.406" y1="408.821" x2="61.169" y2="406.694" />
			<line fill="none" stroke="#000000" x1="80.365" y1="420.729" x2="60.065" y2="419.309" />
			<line fill="none" stroke="#000000" x1="79.739" y1="432.665" x2="59.403" y2="431.955" />
			<line fill="none" stroke="#000000" x1="79.739" y1="456.567" x2="59.403" y2="457.277" />
			<line fill="none" stroke="#000000" x1="80.365" y1="468.504" x2="60.065" y2="469.923" />
			<line fill="none" stroke="#000000" x1="81.406" y1="480.411" x2="61.169" y2="482.538" />
			<line fill="none" stroke="#000000" x1="82.863" y1="492.275" x2="62.712" y2="495.107" />
			<line fill="none" stroke="#000000" x1="87.014" y1="515.814" x2="67.109" y2="520.045" />
			<line fill="none" stroke="#000000" x1="89.702" y1="527.46" x2="69.958" y2="532.383" />
			<line fill="none" stroke="#000000" x1="92.796" y1="539.006" x2="73.235" y2="544.615" />
			<line fill="none" stroke="#000000" x1="96.291" y1="550.437" x2="76.938" y2="556.725" />
			<line fill="none" stroke="#000000" x1="104.466" y1="572.897" x2="85.599" y2="580.52" />
			<line fill="none" stroke="#000000" x1="109.136" y1="583.9" x2="90.547" y2="592.177" />
			<line fill="none" stroke="#000000" x1="114.188" y1="594.733" x2="95.898" y2="603.653" />
			<line fill="none" stroke="#000000" x1="119.614" y1="605.383" x2="101.647" y2="614.936" />
			<line fill="none" stroke="#000000" x1="131.565" y1="626.083" x2="114.308" y2="636.866" />
			<line fill="none" stroke="#000000" x1="138.075" y1="636.107" x2="121.205" y2="647.486" />
			<line fill="none" stroke="#000000" x1="144.931" y1="645.899" x2="128.468" y2="657.859" />
			<line fill="none" stroke="#000000" x1="152.124" y1="655.445" x2="136.089" y2="667.973" />
			<line fill="none" stroke="#000000" x1="167.488" y1="673.755" x2="152.366" y2="687.371" />
			<line fill="none" stroke="#000000" x1="175.64" y1="682.496" x2="161.003" y2="696.632" />
			<line fill="none" stroke="#000000" x1="184.092" y1="690.948" x2="169.957" y2="705.586" />
			<line fill="none" stroke="#000000" x1="192.834" y1="699.1" x2="179.218" y2="714.222" />
			<line fill="none" stroke="#000000" x1="211.144" y1="714.464" x2="198.616" y2="730.499" />
			<line fill="none" stroke="#000000" x1="220.69" y1="721.658" x2="208.729" y2="738.12" />
			<line fill="none" stroke="#000000" x1="230.481" y1="728.513" x2="219.102" y2="745.383" />
			<line fill="none" stroke="#000000" x1="240.506" y1="735.023" x2="229.723" y2="752.28" />
			<line fill="none" stroke="#000000" x1="261.206" y1="746.974" x2="251.652" y2="764.941" />
			<line fill="none" stroke="#000000" x1="271.856" y1="752.401" x2="262.935" y2="770.69" />
			<line fill="none" stroke="#000000" x1="282.689" y1="757.453" x2="274.412" y2="776.042" />
			<line fill="none" stroke="#000000" x1="293.691" y1="762.123" x2="286.069" y2="780.99" />
			<line fill="none" stroke="#000000" x1="316.152" y1="770.298" x2="309.864" y2="789.651" />
			<line fill="none" stroke="#000000" x1="327.583" y1="773.793" x2="321.974" y2="793.353" />
			<line fill="none" stroke="#000000" x1="339.128" y1="776.886" x2="334.205" y2="796.631" />
			<line fill="none" stroke="#000000" x1="350.775" y1="779.575" x2="346.544" y2="799.479" />
			<line fill="none" stroke="#000000" x1="374.314" y1="783.726" x2="371.482" y2="803.876" />
			<line fill="none" stroke="#000000" x1="386.177" y1="785.182" x2="384.05" y2="805.42" />
			<line fill="none" stroke="#000000" x1="398.085" y1="786.224" x2="396.665" y2="806.523" />
			<line fill="none" stroke="#000000" x1="410.021" y1="786.85" x2="409.311" y2="807.186" />
			<line fill="none" stroke="#000000" x1="433.923" y1="786.85" x2="434.634" y2="807.186" />
			<line fill="none" stroke="#000000" x1="445.86" y1="786.224" x2="447.279" y2="806.523" />
			<line fill="none" stroke="#000000" x1="457.767" y1="785.182" x2="459.894" y2="805.42" />
			<line fill="none" stroke="#000000" x1="469.631" y1="783.726" x2="472.463" y2="803.876" />
			<line fill="none" stroke="#000000" x1="493.17" y1="779.575" x2="497.401" y2="799.479" />
			<line fill="none" stroke="#000000" x1="504.816" y1="776.886" x2="509.739" y2="796.631" />
			<line fill="none" stroke="#000000" x1="516.362" y1="773.793" x2="521.971" y2="793.353" />
			<line fill="none" stroke="#000000" x1="527.793" y1="770.298" x2="534.081" y2="789.651" />
			<line fill="none" stroke="#000000" x1="550.253" y1="762.123" x2="557.876" y2="780.99" />
			<line fill="none" stroke="#000000" x1="561.256" y1="757.453" x2="569.533" y2="776.042" />
			<line fill="none" stroke="#000000" x1="572.089" y1="752.401" x2="581.009" y2="770.69" />
			<line fill="none" stroke="#000000" x1="582.739" y1="746.974" x2="592.292" y2="764.941" />
			<line fill="none" stroke="#000000" x1="603.439" y1="735.023" x2="614.222" y2="752.28" />
			<line fill="none" stroke="#000000" x1="613.463" y1="728.513" x2="624.842" y2="745.383" />
			<line fill="none" stroke="#000000" x1="623.255" y1="721.658" x2="635.215" y2="738.12" />
			<line fill="none" stroke="#000000" x1="632.801" y1="714.464" x2="645.329" y2="730.499" />
			<line fill="none" stroke="#000000" x1="651.111" y1="699.1" x2="664.727" y2="714.222" />
			<line fill="none" stroke="#000000" x1="659.852" y1="690.948" x2="673.988" y2="705.586" />
			<line fill="none" stroke="#000000" x1="668.304" y1="682.496" x2="682.942" y2="696.632" />
			<line fill="none" stroke="#000000" x1="676.456" y1="673.755" x2="691.578" y2="687.371" />
			<line fill="none" stroke="#000000" x1="691.82" y1="655.445" x2="707.855" y2="667.973" />
			<line fill="none" stroke="#000000" x1="699.014" y1="645.899" x2="715.476" y2="657.859" />
			<line fill="none" stroke="#000000" x1="705.869" y1="636.107" x2="722.739" y2="647.486" />
			<line fill="none" stroke="#000000" x1="712.379" y1="626.083" x2="729.636" y2="636.866" />
			<line fill="none" stroke="#000000" x1="724.331" y1="605.383" x2="742.297" y2="614.936" />
			<line fill="none" stroke="#000000" x1="729.757" y1="594.733" x2="748.046" y2="603.653" />
			<line fill="none" stroke="#000000" x1="734.808" y1="583.9" x2="753.398" y2="592.177" />
			<line fill="none" stroke="#000000" x1="739.479" y1="572.897" x2="758.346" y2="580.52" />
			<line fill="none" stroke="#000000" x1="747.654" y1="550.437" x2="767.007" y2="556.725" />
			<line fill="none" stroke="#000000" x1="751.149" y1="539.006" x2="770.709" y2="544.615" />
			<line fill="none" stroke="#000000" x1="754.242" y1="527.46" x2="773.987" y2="532.383" />
			<line fill="none" stroke="#000000" x1="756.931" y1="515.814" x2="776.835" y2="520.045" />
			<line fill="none" stroke="#000000" x1="761.082" y1="492.275" x2="781.232" y2="495.107" />
			<line fill="none" stroke="#000000" x1="762.538" y1="480.411" x2="782.776" y2="482.538" />
			<line fill="none" stroke="#000000" x1="763.58" y1="468.504" x2="783.879" y2="469.923" />
			<line fill="none" stroke="#000000" x1="764.206" y1="456.567" x2="784.542" y2="457.277" />
			<line fill="none" stroke="#000000" x1="764.206" y1="432.665" x2="784.542" y2="431.955" />
			<line fill="none" stroke="#000000" x1="763.58" y1="420.729" x2="783.879" y2="419.309" />
			<line fill="none" stroke="#000000" x1="762.538" y1="408.821" x2="782.776" y2="406.694" />
			<line fill="none" stroke="#000000" x1="761.082" y1="396.958" x2="781.232" y2="394.126" />
			<line fill="none" stroke="#000000" x1="756.931" y1="373.419" x2="776.835" y2="369.188" />
			<line fill="none" stroke="#000000" x1="754.242" y1="361.772" x2="773.987" y2="356.849" />
			<line fill="none" stroke="#000000" x1="751.149" y1="350.227" x2="770.709" y2="344.618" />
			<line fill="none" stroke="#000000" x1="747.654" y1="338.796" x2="767.007" y2="332.508" />
			<line fill="none" stroke="#000000" x1="739.479" y1="316.335" x2="758.346" y2="308.712" />
			<line fill="none" stroke="#000000" x1="734.808" y1="305.333" x2="753.398" y2="297.056" />
			<line fill="none" stroke="#000000" x1="729.757" y1="294.5" x2="748.046" y2="285.579" />
			<line fill="none" stroke="#000000" x1="724.331" y1="283.85" x2="742.297" y2="274.296" />
			<line fill="none" stroke="#000000" x1="712.379" y1="263.15" x2="729.636" y2="252.367" />
			<line fill="none" stroke="#000000" x1="705.869" y1="253.125" x2="722.739" y2="241.746" />
			<line fill="none" stroke="#000000" x1="699.014" y1="243.334" x2="715.476" y2="231.373" />
			<line fill="none" stroke="#000000" x1="691.82" y1="233.788" x2="707.855" y2="221.26" />
			<line fill="none" stroke="#000000" x1="676.456" y1="215.478" x2="691.578" y2="201.862" />
			<line fill="none" stroke="#000000" x1="668.304" y1="206.736" x2="682.942" y2="192.601" />
			<line fill="none" stroke="#000000" x1="659.852" y1="198.284" x2="673.988" y2="183.646" />
			<line fill="none" stroke="#000000" x1="651.111" y1="190.132" x2="664.727" y2="175.01" />
			<line fill="none" stroke="#000000" x1="632.801" y1="174.768" x2="645.329" y2="158.733" />
			<line fill="none" stroke="#000000" x1="623.255" y1="167.575" x2="635.215" y2="151.112" />
			<line fill="none" stroke="#000000" x1="613.463" y1="160.719" x2="624.842" y2="143.849" />
			<line fill="none" stroke="#000000" x1="603.439" y1="154.209" x2="614.222" y2="136.952" />
			<line fill="none" stroke="#000000" x1="582.739" y1="142.258" x2="592.292" y2="124.291" />
			<line fill="none" stroke="#000000" x1="572.089" y1="136.832" x2="581.009" y2="118.542" />
			<line fill="none" stroke="#000000" x1="561.256" y1="131.78" x2="569.533" y2="113.19" />
			<line fill="none" stroke="#000000" x1="550.253" y1="127.11" x2="557.876" y2="108.243" />
			<line fill="none" stroke="#000000" x1="527.793" y1="118.935" x2="534.081" y2="99.582" />
			<line fill="none" stroke="#000000" x1="516.362" y1="115.44" x2="521.971" y2="95.879" />
			<line fill="none" stroke="#000000" x1="504.816" y1="112.346" x2="509.739" y2="92.602" />
			<line fill="none" stroke="#000000" x1="493.17" y1="109.658" x2="497.401" y2="89.753" />
			<line fill="none" stroke="#000000" x1="469.631" y1="105.507" x2="472.463" y2="85.356" />
			<line fill="none" stroke="#000000" x1="457.767" y1="104.05" x2="459.894" y2="83.813" />
			<line fill="none" stroke="#000000" x1="445.86" y1="103.009" x2="447.279" y2="82.709" />
			<line fill="none" stroke="#000000" x1="433.923" y1="102.383" x2="434.634" y2="82.047" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="422" y1="102.174" x2="422" y2="81.826" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="362.508" y1="107.377" x2="355.441" y2="67.297" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="304.85" y1="122.826" x2="290.931" y2="84.583" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="250.751" y1="148.053" x2="230.403" y2="112.808" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="201.855" y1="182.291" x2="175.695" y2="151.114" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="159.647" y1="224.499" x2="128.47" y2="198.339" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="125.409" y1="273.395" x2="90.164" y2="253.047" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="100.182" y1="327.494" x2="61.939" y2="313.575" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="84.733" y1="385.152" x2="44.654" y2="378.085" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="79.53" y1="445" x2="38.833" y2="445" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="84.733" y1="504.081" x2="44.654" y2="511.148" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="100.182" y1="561.738" x2="61.939" y2="575.658" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="125.409" y1="615.837" x2="90.164" y2="636.186" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="159.647" y1="664.734" x2="128.47" y2="690.894" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="201.855" y1="706.942" x2="175.695" y2="738.118" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="250.751" y1="741.18" x2="230.403" y2="776.425" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="304.85" y1="766.406" x2="290.931" y2="804.65" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="362.508" y1="781.856" x2="355.441" y2="821.935" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="422" y1="787.058" x2="422" y2="827.756" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="481.437" y1="781.856" x2="488.504" y2="821.935" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="539.094" y1="766.406" x2="553.014" y2="804.65" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="593.193" y1="741.18" x2="613.542" y2="776.425" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="642.09" y1="706.942" x2="668.25" y2="738.118" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="684.298" y1="664.734" x2="715.474" y2="690.894" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="718.536" y1="615.837" x2="753.781" y2="636.186" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="743.762" y1="561.738" x2="782.006" y2="575.658" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="759.212" y1="504.081" x2="799.291" y2="511.148" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="764.414" y1="445" x2="805.112" y2="445" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="759.212" y1="385.152" x2="799.291" y2="378.085" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="743.762" y1="327.494" x2="782.006" y2="313.575" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="718.536" y1="273.395" x2="753.781" y2="253.047" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="684.298" y1="224.499" x2="715.474" y2="198.339" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="642.09" y1="182.291" x2="668.25" y2="151.114" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="593.193" y1="148.053" x2="613.542" y2="112.808" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="539.094" y1="122.826" x2="553.014" y2="84.583" />
			<line fill="none" stroke="#000000" stroke-width="2" x1="481.437" y1="107.377" x2="488.504" y2="67.297" />
		<polygon fill="#BE1E2D" points="409.546,78.059 422,56.536 434.398,78.059" />
		<g id="cardinal">
			<g class="rotatable" style="-webkit-transform: rotate({{-heading}}deg);">
				<text transform="matrix(1 0 0 1 410.1284 142.1742)">N</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading+90}}deg);">
				<text transform="matrix(4.489659e-11 -1 1 4.489659e-11 119.5303 459.8446)">W</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading+180}}deg);">
				<text transform="matrix(-1 0 0 -1 430.8467 747.058)">S</text>
			<g class="rotatable" style="-webkit-transform: rotate({{-heading-90}}deg);">
				<text transform="matrix(-4.489659e-11 1 -1 -4.489659e-11 724.4141 435.7599)">E</text>

PhoneGap connection component

The PhoneGap connection component retrieves infomration about thte connection type. The following illustration shows this component. 


The clientlibs folder that is used by the mobile application is also located here:


This clientlibs folder includes the phonegap-connection.js file

The following code represents the phonegap-connection component that is located at the following location. 

<%@include file="/libs/foundation/global.jsp" %><%
%><%@ page session="false" %><%
<div ng-controller="ConnectionCtrl" class="list">
	<label class="item item-input item-stacked-label">
        <span class="input-label">Connection type</span>
		<input type="text" placeholder="Determining..." disabled ng-value="connectionType">

Phonegap-contacts components

The phonegap-contacts component displays the contacts listed in the device. 


The following code represents this component that is located at the following location /apps/brucelefebvre/kitchen-sink/components/phonegap-contacts. 

<%@include file="/libs/foundation/global.jsp" %><%
%><%@ page session="false" %><%

<div ng-controller="ContactsCtrl" class="list">
	<div class="item item-divider">
		Device Contact List
	<div ng-repeat="contact in contacts">
		<a class="item">{{}}</a>

Phonegap-location component 

The phonegap-location component tracks your location on the device as shown in the following illustration. 


The following code represents this component located at the following location /apps/brucelefebvre/kitchen-sink/components/phonegap-location. 

<%@include file="/libs/foundation/global.jsp" %><%
%><%@ page session="false" %><%
<div ng-controller="LocationCtrl" class="list">
	<label class="item item-input item-stacked-label">
		<span class="input-label">Latitude</span>
		<input type="text" placeholder="Locating..." disabled ng-value="latitude">
	<label class="item item-input item-stacked-label">
		<span class="input-label">Longitude</span>
		<input type="text" placeholder="Locating..." disabled ng-value="longitude">

    <div class="list card">
        <div class="item item-image">
            <img ng-src="{{mapImageSrc}}">


Notice the variable named mapImageSrc. This variable is defined in the cleintlibs folder located at: /apps/brucelefebvre/kitchen-sink/components/phonegap-location/clientlibs. Within this clientlibs folder, there is a file named phonegap-location.js. The following code represents this file.

;(function (angular, document, undefined) {

    angular.module('phonegapLocation', ['btford.phonegap.geolocation'])
        .controller('LocationCtrl', ['$scope', 'geolocation', function($scope, geolocation) {
            function geolocationSuccess(position) {
                $scope.latitude = position.coords.latitude;
                $scope.longitude = position.coords.longitude;
                console.log('[phonegapLocation] current device lat: [' + $scope.latitude + '] long: [' + $scope.longitude + ']');

                // Show a static Google Maps image of the device's current location
                $scope.mapImageSrc = '' + $scope.latitude + ',' + $scope.longitude + 
                    '&markers=' + $scope.latitude + ',' + $scope.longitude +

            function geolocationError(error) {
                console.error('Location error. Code: ' + error.code + '\n' +
                    'Message: ' + error.message + '\n');

            geolocation.getCurrentPosition(geolocationSuccess, geolocationError);

}(angular, document));

Splash screen component

The Splash Screen component represents the splash screen for the mobile application. The following code represents this component. 


<%@ page session="false"
         import="" %><%
%><%@include file="/libs/foundation/global.jsp" %><%
    // Prevent wrapping of module .js content
    IncludeOptions opts = IncludeOptions.getOptions(request, true);


There is another JSP named headlibs.jsp that contains the following code.

<%@page session="false"%><%
%><%@include file="/libs/foundation/global.jsp" %><%
%><cq:includeClientLib css="apps.geometrixx-outdoors-app.splash-screen"/>
    body.cq-mobile-phonegap-splash-page {
    	background: none;


Please refer to the Readme that is located in the project directory. 

Open the mobile application in AEM Author

The Kitchen Sink mobile application is accessible from the Apps menu in AEM 6, as shown in the following illustration.  



When you open the Kitchen Sink mobile application, you will see the main page, as shown in this illustration. 


To open the Kitchen Sink application from the AEM author environment, perform these tasks:

1. Click the Apps menu on the left menu in AEM 6.

2. Click the CheckMark icon located above the Kitchen Sink application (this is the Enter Selection Mode option).

3. Click the Kitchen Sink application. 

4. From the new menu that appears, click the Pencil icon (the open button). The Kitchen Sink open and the URL is http://localhost:4502/editor.html/content/phonegap/brucelefebvre/apps/kitchen-sink/en/home.html. 

5. Click the Preview mode button. 

See also

Congratulations, you have just downloaded and built the AEM 6 sample Mobile application. Please refer to the AEM community page for other articles that discuss how to build AEM services/applications.

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License  Twitter™ and Facebook posts are not covered under the terms of Creative Commons.

Legal Notices   |   Online Privacy Policy