Skip navigation

Android Blogs

13 Posts authored by: Darryn Campbell

This is the second in a series of blog posts looking at the considerations around adopting a GMS deployment in the enterprise.  Each post features a tl;dr along with recommendations.  For other posts in this series please see the links below:


Google are open about the type of data they collect on Android, why they collect that data and how that data is used.  The actual details of the privacy policy are available from and is written to be understandable. Note that there are a number of international versions of this policy that you may be directed to, for example the US and UK policies but the differences are lingual and regional rather than affecting the actual policy wording, for example the US “cell towers” are changed to UK “mobile towers”.   Google also have a “terms of service” and both policies are Google-wide meaning they are written to cover any method for accessing Google’s services e.g. Chromebook, desktop search or Chrome on iOS therefore not all the policy information is immediately applicable to Android.


Collected information includes but is not limited to: Hardware model, Android version, device UUID, mobile network, search queries, telephone logs, IP addresses, device crash information and system activity.


As Google states, “this data will be used to improve Google’s products and services for everyone” but frequently we find our enterprise customers err on the cautious side and would rather disable Google’s data acquisition entirely.  Techniques for disabling data gathering are discussed later but the extent of the privacy policy and TOS are not unique to Google; as more enterprises embrace public cloud and hybrid cloud models in their infrastructure the bigger picture of information sharing should be considered in light of the general trend toward being more accepting of cloud computing.


Executive Summary (TL;DR)

  • It is possible to prevent devices from communicating back to Google’s servers and the most reliable way to achieve this is through network configuration. Options do exist on Android devices and within Android applications to disable analytics but many of these options require manual intervention to disable.
  • The extent of the privacy policy and terms of service are not unique to Android or Google and many enterprises are embracing hybrid or public cloud models which have similar policies.
  • There is not just one type of analytics.  The device OS itself sends analytics, system applications (e.g. Chrome or Maps) send their own analytics and Firebase analytics (owned by Google) is a hugely popular analytics engine used by 3rd party applications.  To truly prevent any analytics going through Google’s servers you will need to address all of these vectors.


Google analytics

In order to use Google services, a user or device administrator are required to agree to Google’s privacy policy and terms of service.


This section discusses some of the ways you can prevent your data being shared with Google and there are two broad techniques to achieve this:

  1. Stop the device from reporting analytics to Google by preventing network access.
  2. Turn off analytics via the device and application settings


Note that you can click ‘Don’t add this account now’ during the set-up wizard rather than agree to Google’s terms of service.  Clicking ‘Don’t add this account now’ does not prevent your device from communicating back to Google as you still implicitly agree to the privacy policy through just using Google services. By not adding a Google account to the device, any information being gathered cannot be associated with a unique user but you will lose any functionality that depends on that account e.g. GSuite, Gmail, Drive, reset protection and many others.


Let us dive into each of these approaches to prevent data being shared with Google:


1) Stop the device from reporting analytics by preventing network access

The simplest, most obvious way to avoid Android devices ‘phoning home’ to Google is to prevent them from having external network access.  This makes sense for a large number of enterprise customers whose devices are deployed within the 4 walls and only have access to the company network; it is not required to give users internet access on the device to perform their job so the network administrator can deny external access.


By preventing devices from reaching the wider internet you will experience a degradation of features but will still have more features than a non-GMS device.  An oft used example to illustrate this is the location APIs: a GMS device with external internet connection is able to take full advantage of location services e.g. to create a Geofence around a particular location. If that same GMS device is prevented from accessing the external internet it can still use location services for actions that do not require internet access, for example determining the current activity of the device user (running, walking, driving).  On a non-GMS device, the location services are not available at all and the developer has to depend solely on the earlier location manager APIs whose use Google no longer recommends where alternatives exist.


If you wish to be more controlled over which addresses to block to prevent Android from ‘phoning home’ there is no authoritative list and the most reliable way is to prevent your device from accessing any of the IP addresses under Google’s ASN, 15169.  ASN 15169 consists of a long list of IP v4 and v6 addresses but external tools exist that can make the job easier for network administrators e.g. using you could create an IP list as and download that list by adding &api=1 to the end of the URL.  These external tools come without any endorsement from Zebra but just be aware that they do exist.


In terms of ports, again there is no authoritative list of all ports an Android device will use to connect to Google servers, the best information available only exists for the Firebase Cloud Message (FCM) service, which states ports: 5228, 5229 and 5230 are used by that tool.  Interestingly the FCM documentation also advises opening up all IP blocks listed under Google’s ASN in order to just support cloud messaging.


Looking at this the other way, the opposite is also true: if you wish to take full advantage of the google services such as enhanced location, application updates via the Play Store or Gmail then it is required to accept outgoing connections to all IP addresses contained in ASN 15169 as well as open ports 5228, 5229 and 5230 if you wish to take advantage of FCM.


2) Turn off analytics via the device & app settings

If preventing your device from having internet access to Google’s servers is not an option for you, perhaps because you require some of the added services that GMS offers then you may wish to disable data collection on the device by modifying the appropriate settings.  There is not a single master switch for turning off all analytics data and there are several classes of application which will be sending data:

  1. The Android system sends information back to Google such as battery level, app usage, app crash statistics and network connectivity.
  2. Google developed system applications pre-installed on Android such as the keyboard, Chrome and Maps send their own analytics to Google.
    1. A further distinction can be made for this application analytics data as it may or may not be associated with a Google account.  Consider the maps example, you can use Maps without a Google account and your location data is available to Google, if you then sign into Maps with your Google account that location data can be (optionally) stored as a history associated with your account.
  3. Any Android developer can integrate Firebase analytics (which is owned by Google) into their native Android application, the getting started guide is here.  So, if you have a specific concern about Google then bear in mind that it is a hugely popular application analytics platform for many 3rd party applications.


Analytics sent from the Android system

The Android system analytics can be configured as part of the start-up wizard (SUW) (see screenshot above, “Help improve your Android experience”) and will default to true, i.e. system analytics will be enabled.


You will not see this start-up wizard screen if you provision your device as a managed Android device (i.e. setup as a device owner).  In my tests the diagnostic data option is disabled by default for managed Android devices but since there are many ways to configure managed devices I recommend you test with your particular deployment.


You can manually modify or check the value of this setting at any time by following the instructions at, i.e. go to Settings --> Google --> (Menu) --> Usage & diagnostics and slide to ‘Off’ to disable analytics.  This settings screen also contains information about what diagnostics are being captured and the link to ‘Find out more’ will take you to the answer URL just given.


Analytics sent from Google developed, preinstalled applications

Google have a number of preinstalled applications on GMS devices that they explicitly call out as having additional privacy considerations in their privacy documentation, here.  Note that some of these applications depend on being associated with a Google account in order to have privacy implications (for clarity the Google account required for analytics to be captured is an account in the @gmail.* domain and not a managed Play account).  The list below is not exhaustive or comprehensive and if you plan on using a Google application or service it is recommended to review the privacy documentation for that application; the aim of the table is to explain how to address some of the common privacy concerns.


Note that some of the applications described below expose managed configurations, these require managed devices as well as an EMM that supports them.  You may consider disabling any system application that gives you privacy concerns and this will be covered in a later post, there is also an earlier blog on the subject available which does not provide any recommendations.


ApplicationPrivacy considerations
Google Search

Google searches can be performed in a number of ways, either through the browser (Chrome) at or via the Google app.


Using the browser, the Google page will attempt to acquire your location via the HTML5 location API. The prompt presented to the user can be overridden if you are using a managed Android device since Chrome exposes a managed configuration to specify the default Geolocation settings. Regardless of the Geolocation API setting however, an approximate location can be determined from the device IP, though that ability is not specific to Google.  Much of Google Search’s analytics capabilities are tied to signing in with a Google account i.e. search history and browsing activity.  You can limit the amount of data gathered by not signing in with a Google account and further limit the association of search activity with the device by frequently clearing cookies or browsing in Incognito mode.  Chrome exposes managed configurations for disabling all cookies and forcing sessions to use incognito mode so managed Android devices are able to take advantage of these features.

If you do choose to sign into a Google account you can opt out of Chrome browsing history and activity as part of the account activity controls.


Google Now can also be enabled from the Google Search application after signing into your Google account.

Google Now provides personalized information in the form of cards based on data already known by Google.  Android Marshmallow introduced ‘Now on Tap’ where by pressing the home button a context sensitive search is made based on the text content of the current screen.  Now on Tap represents an additional privacy consideration since it is parsing the foreground app’s text and can be disabled in the settings UI under Settings --> Google --> Search --> Screen search

but at the time of writing cannot be disabled remotely by EMM; if you wish to avoid these privacy implications then it is best to prevent the user from signing in with a Google account.

GmailThe Gmail application itself can be used as a mail client for a variety of mail providers.  Email from providers such as Outlook or Yahoo will not be subject to Google’s scanning (though the degree of scanning from that external provider is outside the scope of this document).  Using a Google account (in the @gmail.* domain) will mean Google will automatically determine ads which may be of interest to you by scanning your email and combining that information with other information associated with your Google account.  You can opt-out of Google scanning your mail for advertising purposes in your account settings however Google will still scan your mail for anti-spam reasons.
YouTubeYouTube can be used both with and without a Google account.  Without a Google account YouTube is still subject to Google’s privacy policy so your watch history could conceivably be shared with Google but all the official documentation implies analytics are only gathered for views associated with Google accounts.  There are a number of controls and limitations you can apply for YouTube from your Google account settings.
HangoutsThe Hangouts application gets the majority of its functionality from being associated with a Google account. Without an account you are limited to SMS communication on WAN devices only.  If the Hangouts application is associated with a Google account the message history will be backed up to Google but this can be turned off in the application settings.
Google Maps

Google Maps will work perfectly well without a Google account as long as your device location settings are turned on, you even get access to traffic, satellite imagery and ‘place’ information.  Google maps gets its location (i.e. the blue dot) from one of the location providers available on the device, I go into this more in a previous blog and in an upcoming post in this series about GMS but briefly, even if location services are not available on the device Google maps will still be able to determine location through GPS or scanning nearby WiFi APs.  If you want to obtain a location which has been determined without accessing Google’s servers then turn off WiFi / Bluetooth scanning and ensure the location mode is set to ‘GPS only’.  Devices without a GPS chip such as the TC51 will need to rely on non-Google solutions such as BLE beacons to determine their position without reliance on Google.


If you do access Google Maps whilst signed into a Google account you get access to a wealth of additional functionality such as location history, saved places, customised flight info, calendar entries and the ability to contribute photos of places, all of which can be customised or deleted from your account settings.

Google Chrome

On launching Google Chrome for the first time you will be asked if you want to share usage statistics and crash reports with Google.

This is specific to Chrome and you can disable it within the application at any time by launching Chrome --> (Menu) --> Settings --> Privacy --> “Usage and crash reports”, as explained here but there is no managed configuration to change this so it must be done manually.

Other privacy features of Chrome include:

  • ‘Safe Browsing’ which can be enabled or disabled via a managed configuration and provides protection against phishing
  • ‘Security incidents’ which allows Chrome to detect unwanted software.
  • ‘Enable network prediction’ allows prefetching and prerendering of web pages and can be controlled by a managed configuration.
  • Managed configuration settings exist to default to ‘Incognito mode’ and reset cookies on each session to force a more private browsing experience on the end user.

Note that Chrome also has its own terms of service and privacy notice.


By associating a Google account with Chrome your browsing history and bookmarks are synced but these can be deleted via your Google account settings.

Google+Google+ is not functional without associating it with a Google account
Google CalendarGoogle Calendar is not functional without associating it with a Google account
Google PlayGoogle Play requires a Google account to function and is covered in a future post in this series on GMS.
Google DriveGoogle Drive is not functional without associating it with a Google account
Google Keyboard

GMS devices ship with an updated Google keyboard compared with AOSP and the GMS keyboard would like to share some anonymized data with Google:

You can disable this on all Android versions, for example on Marshmallow you can update this via the Settings UI here: (Settings --> Languages & Input --> Google Keyboard --> Advanced --> Share usage statistics / Share snippets) and on Nougat the setting is here: (Settings --> Languages & Input --> Virtual keyboard --> Gboard --> Advanced --> Share usage statistics / Share snippits).  In either case, it is not possible to prevent the dialog from displaying to the user the first time.


Zebra’s own Enterprise Keyboard can be used as an alternative input method for the majority of customers and provisioned as the default IME during staging.

Google Photos

Google Photos can be used without a Google account but functionality is limited.  More pertinent to privacy is the exif data associated with the photos you take: when you launch the camera application you will be prompted to ‘Remember photo locations?’ but it is not possible to alter this setting after it is set.  (This is particular to the Camera app settings so may change in the future).

Associating Google Photos with a Google account will enable photos to back up your data to Google’s servers, including exif data.

The only way to prevent backing up once a Google account has been associated is to rely on the user manually selecting the correct options in the presented dialog, see screenshot.


There are a variety of ways to disable the camera entirely so the user is not able to take photos and you can do this via most EMMs and through Zebra’s StageNow tool.

Google DocsGoogle docs are not preinstalled so strictly should not be in this list but if added to a device without a Google account (e.g. deployed via EMM) at the time of writing the application will not launch.
Google KeepGoogle Keep is not preinstalled but if added to a device without a Google account (e.g. deployed via EMM) the application will not run without a Google account.


Analytics from 3rd party applications using Google as their analytics provider

Firebase analytics is a very popular analytics platform from Google for Android and other operating systems.  You will find many 3rd party applications will use Firebase analytics so a logical question would be whether you can disable Firebase analytics using the same setting described earlier which disables Android analytics, i.e. Settings --> Google --> (Menu) --> Usage & diagnostics and slide to ‘Off’.  The answer is ‘no’, there is no way in software to disable a 3rd party application’s analytics unless an option is explicitly exposed by that application; the fallback is to prevent the application from communicating with the Firebase backend, as explained at for Firebase, i.e. disable access to ports 5228, 5229 & 5230.  If the 3rd party application uses an analytics engine other than Firebase then the instructions would differ depending on the provider.



If you wish to prevent the Android OS as well as applications running on your device from providing analytics to Google the most robust way to achieve this is though network configuration, either:

  • By preventing external access entirely or
  • Prohibiting access to Google’s servers via a VPN or firewall.


Settings exist to turn off analytics but there are some difficulties to this approach:

  • Separate settings exist for the device and system applications.  It can be challenging to manage the number of settings and ensure none are missed.
  • Many settings require manual intervention (at the time of writing) therefore making it more time-consuming to stage & provision devices
  • 3rd party applications making use of Firebase analytics may choose to not expose an option to disable analytics, though they must state that analytics are being gathered in that app’s privacy statement

This is the first in a series of blog posts looking at the considerations around adopting a GMS deployment in the enterprise.  Each post features a summary along with recommendations.  For other posts in this series please see the links below:


The Google Play Store can be used to install and manage the applications on your Android device.  For unmanaged devices it coexists alongside other techniques for application management including Zebra's value-added MX layer, which may be used standalone or as part of your EMM / MDM solution. For managed devices we see the Play Store taking a more central role as the app distribution and installation paradigm, with concepts such as the Play Store for Work integrating more tightly with EMM solutions.


As the Play Store gains traction in the enterprise a common question is how to prevent unattended updates? For applications deployed via the Play Store, how can my Enterprise ensure it is on a known baseline or how can I avoid my validated and tested device configuration from changing unpredictably in the field.  There is of course an argument to be made for allowing unattended updates however for the sake of brevity, this document assumes a desire to prevent automatic updates.  Application deployments which do not rely on the Play Store are outside the scope of this document but the advice here will be equally applicable to both managed and unmanaged devices.


This information is true at the time of writing (November 2017), but as Google continues to focus on enterprise use cases additional recommendations may be made in the future. Some of the techniques described here are proprietary to Zebra hardware but the general principles will be the same throughout the Android ecosystem.


Executive Summary

  • Disabling the Play Store entirely is a reliable way of ensuring no user or system applications get updated in the field.  The down side is that this approach lacks the ability to control individual applications as it is an all-or-nothing solution. StageNow barcodes are attached to this document to enable and disable the Play Store.
  • Play Store automatic updates can be reliably turned off via a Play Store setting however it requires manual interaction to adjust two settings.  Firstly, the automatic updates themselves must be disabled from the play store and secondly, the Play Store must be blocked from presenting notifications which prompt the end user to install available updates manually.
  • Whilst it is possible to prevent a specific application from being updated by disabling the app, the obvious side effect is that the app is no longer available to the end user.


Types of update

There are multiple types of update that an Android device is subject to:

  • User applications are those apps which are installed on the device after it is received from the factory.
  • System applications can mean different things in different contexts, technically Zebra services and apps like DataWedge or StageNow are installed as System apps but since they are not installed via the Play Store, they can be considered distinct from the System apps provided by Google such as Maps, Chrome, Gmail etc.
  • Play Services ( are available via the Play Store ( but are not considered a user or system application per se.  Play Services underpin the majority of GMS functionality such as user authentication, location services, user accounts and more and are subject to different update restrictions.  Play Services are not covered in detail in this blog apart from the effect of disabling the Play Store.
  • Device updates are updates to the entire OS which also includes security patches.  Device updates are outside of the scope of this document.


Techniques to prevent an application from automatically updating

  The following table shows the different techniques which can be used to prevent Play Store applications from automatically updating:


Disable the application you do not wish to update.There are multiple ways to disable applications, some of which effect whether the application will be automatically updated and these techniques are discussed in the next section.  Both the MX AppManager and MX AccessManager can be used on Zebra devices to disable applications with differing levels of control.
Disable the Play Store

Disabling the Play Store can be achieved via the MX AppManager and will prevent all automatic user and system application updates.  This is an all-or-nothing solution and applications cannot be selectively updated; to update any Play Store application it is necessary to first re-enable the Store.



This technique will work equally well on managed and unmanaged Android devices.



Since Google Play Services relies on the Play Store to update, disabling the Play Store will also prevent Google Play Services from updating.

Change the Play Store setting for automatic updates (Global setting).


This applies to both user and system applications.


Note that Google reserve the right in their Terms of Service to override this setting to fix critical security vulnerabilities.

The global Play Store setting is (Play Store) --> (Menu) --> Settings --> Auto-update apps

Applications will only automatically update if configured to do so however this must currently be configured manually since there is no Staging or EMM API to adjust this setting.


If you disable automatic updates, an additional UI component in the Play Store suggests end users turn it back on:

The user is also nagged through a notification from the Play Store to perform the update manually:

The user can then perform the update directly from the notification.  There is no setting to specifically prevent this notification from being shown, it is therefore necessary to block all notifications from the Play Store app to prevent a manual update initiated by the end user.

Change the Play Store setting for automatic updates (application specific setting).


This applies to both user and system applications.

The application specific setting is (Play Store) --> My Apps --> (Select App) --> (Menu) --> Auto-update check

In common with the global setting, if updates are available the end user is presented with a notification prompting them to manually update the application.  An additional confirmation dialog is shown when the user updates an application manually that is configured to not allow auto-updates.  This confirmation dialog is unique to this scenario and is not shown if automatic updates are disabled globally:


Techniques for disabling applications

There are numerous techniques for disabling user or system applications, summarised in the table below:



Package manager shell:

adb shell pm disable <app name>
Disabling an application via the Package Manager shell command is only available on rooted devices and therefore will not be discussed in this blog.

Manually disable the app from the app info screen by pressing the ‘DISABLE’ button

The disable button will only appear for system apps so this technique is not applicable for user applications.


Applications disabled in this manner will NOT automatically update regardless of whether the Play Store is configured for automatic updates.
MX ApplicationManager.  Via the AppManager’s “Action” command an application can be enabled or disabled,

Will work for both System and User applications but is only supported on Zebra devices.

MX is accessible through an SDK or via Zebra’s StageNow tool.

The Play Store itself can be disabled via this technique.


Applications disabled with the AppManager will NOT automatically update regardless of whether the Play Store is configured to auto-update applications.  If the end user has access to the Play Store application, they are given the option to manually ‘Enable’ the app from the Play Store UI:

Enabling an application previously disabled by the AppManager undoes the effects of AppManager; the application reappears in the launcher and is once again subject to automatic updates.


This technique will also prevent the end user from using the application.
MX AccessManager.  The AccessManager’s whitelist functionality will only enable those user applications which have been whitelisted, with all other user applications being disabled.

Will only work for user applications, not system applications meaning this technique cannot be used to disable the Play Store.


Applications disabled with the AccessManager will NOT automatically update regardless of whether the Play Store is configured to auto-update applications.  If the end user has access to the Play Store application, they are given the option to manually ‘Enable’ the app from the Play Store UI:

Enabling an application previously disabled by the AccessManager does not undo the effect of AccessManager whitelisting and the app will not appear in the launcher, in contrast to the AppManager technique described previously.


An application enabled in this manner will now appear in the list of pending updates in the Play Store however it will not be automatically updated and attempting a manual update will lead to a generic error:

To avoid confusion, tools like Zebra's Enterprise Home Screen can be used to prevent the user from accessing the Play Store, if appropriate.


This technique will also prevent the end user from using the application.

On Managed Android devices in Device Owner (DO) mode several system applications may be disabled by default (e.g. Google Photos, Google Maps etc.)

Whether or not these system apps are disabled will depend on your method of provisioning as it can be configured.  Your EMM is able to re-enable system apps by calling a client-side API.


Exactly which system applications are disabled will depend on how the Operating System was built and may be customized by the OEM but the Play Store and Play Services will always remain enabled.


System applications disabled in this manner will not appear to the user or show as installed in the Play Store app so are not be subject to automatic updates.

On managed Android devices running API level 24 or higher, the EMM or DO can suspend packages via the setPackagesSuspended API

Suspended packages will still be shown to the user but will be grayed out and attempting to click on the icon will present the user with a DO branded message box indicating that the operation is not allowed.


Both system apps and user apps can be suspended however suspension has no effect on whether or not the application is updated. If the Play Store is configured for automatic updates then suspended apps will be updated alongside their non-suspended counterparts.


Recommended approaches to prevent applications from automatically updating


RecommendationConditions / Implications
Disable the Play Store ( via the MX AppManager

Will prevent all user and system apps from updating but it is not possible to selectively specify which apps are subject to updates, it is an all-or-nothing solution.  There is a distinction and often a confusion between the Play Store and the Play Services, disabling the former can be achieved without negatively impacting the functionality of the OS or system apps, in stark contrast to the latter.


StageNow barcode to disable the Play Store


StageNow barcode to enable the Play Store


The two barcodes above (also available as attachments to this document) can be used to enable or disable the Play Store with Stage Now.


Note that disabling the Play Store will also prevent Google Play Services from updating.

Disable application updates from the Play Store [(Play Store) --> (Menu) --> Settings --> Auto-update apps]


Block notifications from the Play Store.


Prevent end users from accessing the Play Store to change the setting

Requires additional provisioning steps to:

  1. Configure the Play store setting, since it cannot be a changed via EMM
  2. Block notifications from the Play Store to avoid the user being prompted to perform a manual update.

At the time of writing, both of these steps can only be performed manually.


There are numerous ways to prevent users from accessing the Play Store e.g. Zebra’s Enterprise Home Screen (EHS).  This leaves the Play Store itself available if required e.g. for remote installation of applications on managed android devices or allowing critical updates to be pushed by Google.

The MX AccessManager can be used to prevent updates to applications which will not be used by your end user.

This could save on bandwidth as non-essential apps would not be updated.


Of all the techniques discussed to disable applications, the MX AccessManager provides the most complete solution as it cannot be circumvented from the Play Store and is easily configurable from StageNow or supported EMMs.

Zebra offers a multitude of locationing solutions for a huge range of customers and use cases. Technologies such as Real time locatating system (RTLS) which includes Dart UWB and WhereNet, both of which use dedicated hardware tags and sensors alongside technology based on existing standards to provide high accuracy for high value assets.  Although it is available worldwide, in North America you will have seen this technology prominently featured as it is used in the NFL .  Zebra also offers the recently launched Smartlens targeting retail use cases and using a variety of technologies including RFID and Wi-Fi feeding data into an analytics engine to provide complete retail insight.  RFID itself can of course be used to determine an asset’s location and Zebra have a wide variety of printers and readers for this purpose.


All these technologies are great and can of course be supplemented by technologies ubiquitous in consumer deployments such as Bluetooth Low Energy (BLE) beacons and GPS, indeed providing visibility into your entire organization workflow is a key pillar in Zebra’s corporate objectives so expect to see additional innovation and harmonization in this area in the future.


With such a huge scope it is not possible to cover everything in detail in a single blog.  This blog is aimed solely at developers wishing to use the location technologies available on Zebra android devices and provides some of the special considerations to take when targeting enterprise hardware. Technologies like GPS, Wi-Fi, BLE and cellular based location are the fundamental building blocks on which many location-aware applications are built so it is important to understand what is available and any dependencies.


Android APIs


Critical to understanding Android’s location APIs is appreciating that there are two entirely separate but related APIs available for use in your application:


The Platform location API (android.location and Locationmanager) is available on all Android devices offered by Zebra, both AOSP (Android Open Source Project) and GMS (Google Mobility Services).  These are coloured blue in the diagram below.


The Google Play services location APIs ( are Google’s recommended way to determine device location but since they are part of Google Play services, they will only run on GMS devices.  These are coloured red in the diagram below.


Another set of APIs which depend on Google Play services are known as the Awareness APIs, these are partly cloud-based APIs which also only run on GMS devices and are also coloured red in the diagram below.


This blog goes into more detail on how to access each of these APIs and their dependencies but the diagram below shows the rough architecture and the options available to a user application.


Blog on Location APIs available on GMS and AOSP devicesDiagrams.png

Location Manager & Providers


The Location Manager class can be used to determine the device location on both AOSP and GMS devices.  The manager depends on underlying ‘Providers’ and the code has named constants for GPS, Network and Passive providers:

  • The GPS provider gives the location based on the device’s GPS hardware.
  • The Network provider gives the location determined from both the device’s cellular connection through tower triangulation and nearby Wi-Fi access points as provided by Google’s own data acquisition & heuristics which can be used to associate Mac addresses to physical location.
  • The Passive provider will determine the location as best it can based on location generated by other providers, it is designed for power considerate applications e.g. those running in the background.


Location updates can be requested from any of the pre-defined providers at specified intervals or as a single request but there is no ‘onChanged()’ callback provided for location.  The application is responsible for determining which provider is the best one to use and Google have a page in their documentation detailing some strategies but at its simplest an application would likely register with all providers and use the location with the best reported accuracy.


Location Manager also offers a basic type of GeoLocation.  You can specify a circular geofence (called a proximity alert (, double, float, long, ) around a location and will be notified when a user enters or exits that location


There are obviously some dependencies when using Location Manager:

  • The GPS provider is only available on devices with a GPS chip and to applications which have the ACCESS_FINE_LOCATION permission granted.
  • The Network provider requires either the ACCESS_FINE_LOCATION or ACCESS_COURSE_LOCATION permission and can only provide cell-tower based locationing on devices with a cell connection.  For the Network provider to be able to issue Wi-Fi based locationing the device settings need to allow for Wi-Fi scanning or have Wi-Fi enabled and the device needs to have an external internet connection to be able to communicate with Google’s backend.
  • The Passive provider depends on another application on the device having previously requested location updates and requires the application to have the ACCESS_FINE_LOCATION permission.


Remember from Android Marshmallow onwards the user is empowered at any time to remove your application permissions including ACCESS_COURSE_LOCATION and ACCESS_FINE_LOCATION so ensure you take steps to avoid that.  In addition, the device itself also needs to have the location setting enabled with the appropriate mode, as explained later in this blog.


Custom Provider


Android also offers the ability to define a custom provider, this works similarly to the GPS or Network providers but rather than the data being fed by some underlying hardware it is instead fed from whatever source your application chooses to define. In order for your custom provider to initiate correctly you need to select the ‘mock location app’ from the Android developer settings (Android M and higher) or ensure ‘allow mock location’ is checked (Lollipop), both of which can be found under the developer settings.


You can define the name of the custom provider to be whichever Android String you like with the exception of “gps”, “network” and “passive” which are the predefined constants for the built-in providers.  Setting your custom provider to any of these names will replace the built-in provider and is the technology underlying various apps in the play store which offer to mock your location either to cheat at gaming or cheat on your significant other (judging by the reviews).  Enterprise use cases are somewhat less illicit, perhaps being used to demonstrate a GPS navigation program or test a delivery routing application with a series of pre-defined inputs, indeed Android Studio will give a linting error if you try to use the ACCESS_MOCK_LOCATION permission in a release build manifest.


For purely testing purposes, it is likely the majority of use cases can be addressed by the use of an emulator to playback a series of GPS coordinates to a running application and Google has a short guide to doing this.  Since it is not possible to emulate Zebra devices it may be necessary to use a custom provider in order to test an application on real hardware that depends on GPS navigation.  In my experience, I have found it is always a good idea to reset the device after you have finished using any custom provider.



The Fused Provider & Location Services


The Google Play services location APIs  ( will nearly always provide a superior experience to the Location Manager APIs discussed in the previous section, giving a location faster and to a greater level of accuracy when tested on the same device.  Because the services location APIs depend on Google Play services, they are only available on GMS devices and require location services to be enabled which is typically done as part of the start-up wizard when the device is first initialised (see later section).


Keeping with the provider nomenclature, the GMS based location APIs provide a ‘Fused’ location provider but this offers a different interface than the GPS or Network providers requiring you to first connect to and manage the lifecycle of the GoogleApiClient running on the device.  You are still limited to requesting updates at a specified frequency but with the fused provider you have more options how you receive the location callbacks e.g. PendingIntent or LocationListener.


Perhaps unsurprisingly, the fused provider automatically fuses all location sources together for you returning its best guess as to the device location.  Recall how with the Location Manager the developer had to determine the best location source from GPS or Network depending on accuracy, age and a number of other factors; this burden is taken away from the developer using the fused provider.  It is not possible to influence the fused provider with the Location Manager custom provider described previously but the fused provider does offer a setMockLocation method (, android.location.Location)) which performs a similar purpose.


Geofencing, Activity Recognition & Reverse Geocoding


Geofencing offered by the GMS-based APIs is slightly more powerful than that found in the Location Manager.  You can now register to receive callbacks whenever a user is loitering in a region and therefore supports an expanded set of use cases for example a package delivery taking longer than expected.


The Activity Recognition API provides Android’s best guess what the user is doing, either: In a vehicle, on a bicycle, on foot, running, being still, tilting the device or walking (The full list is here).  In my experience, this is very accurate and perhaps most powerfully all calculations are done on-device meaning if the device does not have a network or cloud connection you can still take advantage of this API to determine user activity.


The Android Geocoder API is also only available on GMS devices with location services although it does not depend on the GoogleApiClient like Geofencing and Activity Recognition.  The Geocoder class offers both geocoding and reverse geocoding meaning it will return a lat / long based on an address and vice-versa.  In my experience the API provides very accurate results and it has clear benefits to package delivery use cases.


Google Awareness API


The Google Awareness APIs are part of play services and are designed as a “unified sensing platform” enabling actions to be triggered when various criteria are met or to provide an overall snapshot of the user’s current environment. The overlap with location comes from how the API defines the user environment and which criteria can be used to trigger context aware actions.


Since the Awareness API depends on a Google backend you will need to have an API_KEY included in your application which, depending on the intensity you plan on using the API, might be a paid service to Google.  Additional keys are required to make use of the Places and Beacons features.


The following information about the user’s environment is made available through the awareness API:

PositionThis will return the same values as the fused location provider from location services and it has the same requirements: The device needs to have the appropriate settings enabled and the application needs to have the required permission to retrieve device location.  Since the Awareness API is not designed primarily with location retrieval in mind, applications wishing to retrieve periodic location updates should instead use the previously described location services API.
ActivityThis is equivalent to the Activity Recognition function of location services and when run on the same device, will return the exact same values.  Also like the equivalent function in location services, this API will work in a disconnected environment, depending on device accelerometers to determine what the device is doing which can be powerful in many enterprise use cases for example detecting theft if a warehouse-based device is ‘in a car’.
Nearby PlacesThis is unique to the Awareness API providing a list of physical locations nearby using Google’s vast repository of map data and as such requires an external internet connection.  In my experience, the places highlighted range from business to community areas which would prove useful in delivery use cases however since the data is backed by Google, your experience may vary elsewhere in the world, particularly as much of the data will be crowd sourced.
BeaconsThe Awareness Beacon API is designed to be used exclusively with the Google Beacon Platform which is good if you are planning on using Google’s platform but if you plan on using a third-party beacon system then I do not see any integration options.
WeatherNo equivalent elsewhere in the location APIs.
Headphones StateNo equivalent elsewhere in the location APIs. Since this is only for pluggable headphones the Enterprise use case is somewhat limited as the majority of Enterprises who deploy headphones are using Bluetooth.


Hardware & Software dependencies


Any locationing technology has a number of hardware dependencies: as previously mentioned GPS requires a GPS chip, network based location requires either a Wi-Fi or WAN device, location based on BLE will require Bluetooth Low Energy on the device compatible and Android Lollipop for the best performance.  The following table attempts to give an overview of the hardware available on Zebra’s current crop of Android devices (as well as immediately dating this blog!)


DeviceGPSWAN CapableBluetoothGMS Variant AvailableNotes
MC18NoNoYesNoDesigned purely as a personal shopping device
MC36YesYesYesNoDevice is KitKat only which has early support for BLE.
MC40 & MC40-HCNoNoYesNoDesigned to work within the 4 walls.
TC51NoNoYesYesDesigned to work within the 4 walls.
TC70NoNoYesYesDesigned to work within the 4 walls.
TC70XNoNoYesYesDesigned to work within the 4 walls.
TC8000NoNoYesYesDesigned primarily as a warehouse device.


Location Settings & Permissions


Device settings


There are a surprising number of device settings associated with location, each of which will need to be configured as part of your staging process to ensure applications requiring location behave as expected.


Setting NameDescriptionScreenshot
Location On / OffThe most fundamental setting for Android location under Settings --> Location. Must be enabled for any location API to function.Screenshot (Jun 7, 2017 9_06_53 AM).png
Location ModeAlso found under Settings --> Location the options are ‘High accuracy’, ‘Battery saving’ or ‘Device only’ and the UI is self-explanatory.  You will not be given any options if your device lacks a GPS chip.Screenshot (09_11am, Jun 07, 2017).png
Wi-Fi scanning (M & higher) / Scanning always available (KK / LP)This setting allows your device to take advantage of the crowd-sourced AP location available as part of Google’s location service even when your device’s main Wi-Fi is turned off.  If your device’s Wi-Fi is turned on the device will scan for nearby APs regardless of this setting.  If his setting is turned off and the device Wi-Fi is also turned off then no Wi-Fi based location will be available (the device will still have access to cellular, BLE and GPS location, depending on settings).  This option moved between Lollipop and Marshmallow, previously under Wi-Fi --> Advanced it is now under Location --> Scanning (or just search settings for ‘Scanning’)

Screenshot (09_16am, Jun 07, 2017).png

Wi-Fi scanning on a KK device

Bluetooth scanningThis setting is only available on Marshmallow devices or higher and is designed to allow Android to take advantage of BLE beacons to improve the location accuracy of the fused provider (and anything that depends on the fused provider such as Geofencing).  This does not impact an application’s ability to scan for BLE devices using the BluetoothLeScanner API or use of the Awareness API.

Screenshot (Jun 7, 2017 9_09_09 AM).png

Wi-Fi and Bluetooth scanning on an M device

Google’s Location service On / Off (GMS Only)

GMS devices require the user to agree to use “Google’s location service” which is the technology underpinning the “fused provider and location services”, covered earlier.  There is no check box in the Settings UI, the agreement must happen either as part of the set-up wizard or after setting up the device if participation was declined during setup (image 1).  The user will be prompted to agree to the terms of the location service when they turn Location On if they have not already done so (image 2).  The Location Services SettingsAPI method can be used as an alternative way to agree to the terms of the location service and image 3 shows the dialog given after a request for high accuracy and BLE on a device without location services accepted.  Note the 3rd line item agreeing to the terms of the service.



Image 1: Sign up as part of the set-up wizard



Image 2: Sign up when enabling location



Image 3: Sign up after being prompted by the SettingsApi

GPS XtraGPX Xtra will only be available on devices whose WAN stack & hardware supports it.  It is a Qualcomm specific feature for the GPS implementation on specific devices (including some Zebra devices) and allows GPS information to be accessed from an eXTended Receiver Assistance (Xtra) server using an Intentet connection, enhancing the operation of standalone GPS.Screenshot (09_12am, Jun 07, 2017).png


In addition to location based Android settings, there are a number of other device settings which are not specific to location but will nonetheless have an effect on it.



Setting NameDescriptionScreenshot
Wi-Fi On / Off

Turns the device Wi-Fi on or off and will take priority over Wi-Fi scanning; when on, Wi-Fi scanning will always be on.


Many location techniques can depend on external data for example the Network provider may need to communicate with Google’s servers to retrieve a location based on nearby Wi-Fi APs.

Bluetooth On / OffBluetooth is required by any application wishing to use BLE beacons via the BluetoothLeScanner API or the Awareness API (discussed earlier)Screenshot_20170607-100117.png
Mobile Data On / OffSimilar to Wi-Fi, many location techniques can depend on external data for example the Network provider may need to communicate with Google’s servers to retrieve a location based on nearby Wi-Fi APs. Having mobile data on enables Wi-Fi (Network) based location even when the device is not connected to Wi-Fi.Screenshot (10_04am, Jun 07, 2017).png



Application permissions


Any application making use of location will need to request one or more permissions:


If the application is using the location manager or location services to determine the position of the device it will need to request one of the following:


<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COURSE_LOCATION" />


In addition, applications should also request the following feature if they are targeting Lollipop or higher:


<uses-feature android:name="android.hardware.location.gps" />


More information on the above settings can be found in the Android developer docs.  Note that from Android Marshmallow onwards, considerations should be taken around runtime permissions where an application should request permission from the user via a dialog unless special steps are taken for Enterprise applications.


Activity recognition, either through the Location Services or via the Awareness API will require the following permission:


<uses-permission android:name=" " />


Applications making use of the Awareness API (which is backed by Google’s cloud services) will need to include an API key as well as separate keys for places and beacons. This is detailed in the Android developer docs for the awareness API.


Any application wishing to make use of mocked locations will need the following permission:


<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />


As previously mentioned, if this MOCK_LOCATION permission is included in a Manifest.xml used for a release build, Android Studio will give a linting error to indicate this permission is designed for testing or debugging only.


Indoor Versus Outdoor


Many of the Android APIs discussed thus far are focused on outdoor use cases, when moving indoors there are a number of additional challenges:

  • No GPS is available (at risk of stating the obvious)
  • The device may not have a network connection or the connection may be unreliable
  • The resolution required for many indoor use cases requires precise location e.g. the customer is by the apples or my lost device is in aisle 3, shelf 2.
  • Maps of indoors locations may not exist and therefore require site surveys to create, a manually intensive effort.
    • The required maps may update very frequently as store layouts change.
  • Battery life of Bluetooth Low Energy (BLE) beacons is finite, adding to maintenance costs.
  • BLE beacon locations are fixed and require expensive effort to move the physical beacons and their virtual location in the corresponding cloud solution.


Although indoor locationing has many challenges, it is also an area of intense innovation right now by both established companies (including Zebra) and start-ups:

  • Solutions available on the market can provide automated indoor mapping without the need for expensive site surveys, this might be done by some deep learning analysis of how signals scatter within the building or by drone.
  • The established concept of BLE is being challenged by various companies, generating virtual beacons or marrying BLE with some bespoke proprietary technology to enhance location.
  • For some time now Google (& Apple) have used the concept of ‘find my device’ where although a precise location cannot be known, a rough location can be given and the device then be further located by making it ring.
  • As mentioned in the introduction, Zebra have a number of indoor locationing solutions based on Wi-Fi and RFID designed to meet a variety of customer needs.


This is a rapidly changing field and no single solution will suit every customer and use-case, one of the primary reasons Zebra produces so many different hardware form factors with different device capabilities is to provide as much choice as possible.  As we move forward, although our devices all support Bluetooth we will see increased support for Lollipop which is the first Android version where Google considered their BLE implementation to be mature and so BLE becomes usable for more of our customers and partners.


Bluetooth Low Energy


The primary go-to technology for indoor locationing is Bluetooth Low Energy (BLE).  Google have a fully functional BLE API but a device detecting nearby beacons is only a part of the overall solution, there needs to be a server-side component to associate those beacons with a physical location and in most cases perform some dynamic action.  The customer does not care that they are stood by the apples (they have eyes to see that), they are more concerned that because they have not purchased apples in 2 weeks they are eligible for a special 10% off coupon.


I mentioned Google’s Beacon platform when discussing the Awareness API but there are many other similar platforms that exist from other companies.  At the time of writing, Zebra does not recommend any specific beacon platform and our Bluetooth hardware is compliant with Bluetooth standards so will support any platform of the customer’s choosing.


Enterprise Considerations for Non-GMS devices


Many enterprises choose to opt for Non-GMS devices for a variety of reasons but doing so limits your NETWORK_PROVIDER to providing cellular only based locations.  One option for non-GMS devices is to use the Google Geolocation REST API which takes a series of Wi-Fi access points and returns a best guess of the device lat / long.  By scanning for nearby APs using the WifiManager and then passing the found APs to the REST API you get a fairly good approximation of the network provider functionality offered by GMS devices.  This technique does of course involve passing data through Google’s servers and acquiring an API key which depending on usage may be a paid service to Google. Your application will also need to request the ACCESS_WIFI_STATE permission.


Sample Application


It seems to be a theme whenever I write a blog, there is always a sample application to go along with it and this blog is no exception.


The application is available on github at, is released under an MIT license and whilst documentation is scarce the UI is hopefully self-explanatory.  I have tested on a Nexus 6P N, TC51 M GMS and TC55 KK GMS. My colleagues have also tested on a TC75 KK as well as their personal phones.


sample app.png


The application offers the following functionality:

  • Whether or not Location is enabled (via the setting) and whether or not the location services are available (accepted in the start-up wizard)
  • The status of the various providers on the device available through LocationManager and LocationServices.
  • The lat / long positions returned by the Network and GPS providers
  • The lat / long position returned by the fused provider
  • The ability to scan for nearby Wi-Fi APs and use Google’s Maps API to resolve those APs to a lat / long
  • Buttons to exercise the location services SettingsApi to ensure device settings are correct (& prompt the user to automatically correct them)
  • Output from activity recognition
  • Ability to declare a geofence with both the location manager and location services APIs
  • Output from reverse-geocoding from the various returned lat / long coordinates
  • Exercise the Awareness API’s snapshot functionality (fences are not implemented)
  • The ability to initiate a custom provider which will use the location manager API to send mocked data to the selected provider name.  Requires the developer option to be set to use mock locations as explained earlier in this blog.  The custom provider lat / long is reported towards the top of the UI.


I am being very trusting and including my application Awareness API keys in the manifest of the application for ease of use; they are not associated with a paid account so if the number of requests exceeds some amount (2500?) a day then you may see the Awareness functionality fail.

DataWedge is a hugely popular way to access Zebra device hardware providing a ‘zero-code’ way to simply and easily acquire barcode data, use SimulScan capabilities or use the in-built card reader, where supported. DataWedge is often used in preference to Zebra’s native SDKs for Java and Xamarin (EMDK) because it offers a simpler interface that ‘just works’ but this ease of use comes at a cost of losing more fine-grained control of the hardware.  The DataWedge Intent API attempts to redress this by enabling user applications to control, modify and query the current DataWedge configuration and operation.


What is DataWedge?

For a more comprehensive explanation of DataWedge please refer to the documentation available on Zebra’s techdocs site.  For the purposes of this blog the salient points are:

  • DataWedge is a service running on all Zebra Android devices which controls the device scanner and provides access to other value-adds such as SimulScan and the ‘Data Capture Plus (DCP)’ panel.
    • DataWedge as a product has been around for over a decade starting life as a post-install application on Zebra’s WM/CE products – it is not going away!
  • DataWedge is configured with Profiles which encapsulate how it should behave in any given situation – profiles define an input – processing – output pipeline i.e. how to capture data, perform any processing on that data and finally how to output that data to the application.
    • Traditionally profiles are defined using the device UI or using the EMDK but must be created prior to use by the application.
    • Any application can retrieve data from DataWedge regardless of the underlying application technology, we have customers using DataWedge with native applications (Java / Xamarin), hybrid applications (e.g. Cordova) and pure web applications running in Chrome or Enterprise Browser.
    • The DataWedge service listens for and responds to broadcast intents with certain actions – this is what comprises the DataWedge API being discussed here.
    • One method of outputting data to the application is via the ‘Intent’ plugin, this is separate to and distinct from the DataWedge API which also uses Android intents.


The above diagram shows how DataWedge interacts with a calling application via intents


The DataWedge API overview

The DataWedge API was introduced to bridge the gap between the highly configurable native SDKs (EMDK) and the ease of use that the DataWedge service provides.


So far there have been three versions of the API released, starting with DataWedge 6.0, then enhanced in DataWedge 6.2 and most recently made more functional in DataWedge 6.3.  Since each iteration of the API introduced new capabilities and even changed the format required for some of the features it is important to understand which version(s) of DataWedge you are running in your device deployment.  You can determine the DW version from the DataWedge application UI as explained here and 6.3 also exposes an API to programmatically determine the version.


Upgrading DataWedge can only be performed via a full operating system update from Android Lollipop onwards.  Pre-Lollipop, DataWedge can be upgraded via the “Device Runtime Deployment” application provided as part of EMDK.  You should therefore be aware of DataWedge API changes when upgrading your devices and adding new devices to any deployment.


DataWedge 6.0

Provided rudimentary capabilities to switch profiles and initiate / disable scanning.  This was useful if you had pre-defined the profile(s) your application would require and enabled your application to control when to scan e.g. you could have a software button in your application that behaved the same as the device hardware trigger.


DataWedge 6.2

Enabled some basic profile management: your application is now able to delete, clone and rename existing profiles as well as retrieve the currently active profile. This was useful if you were configuring devices via an application and provided an alternative to the DataWedge service UI or EMDK to manage profiles but since you could not create new profiles, the usefulness at the time was limited.


A new format was introduced to the Intent API allowing you to invoke multiple commands from the same intent, i.e. you could clone and rename a profile in a single call.


DataWedge 6.3

Several capabilities were introduced in response to customer feedback including:

  • A version API
  • Receive notifications when the scanner state or profile changes.  Useful if you want to only allow the user to initiate a soft scan when the scanner hardware is ready or if you want to know when the correct profile is in effect.
  • Create profiles and modify the contents of profiles.  Not only does this make profile set-up feasible through the API but it also enables a slew of other use cases such as enabling / disabling decoders at runtime (e.g. only enable EAN13 on a single app screen) or configuring scanner parameters at runtime (e.g. enabling picklist mode under certain conditions)
  • The format of the APIs introduced in 6.0 was updated to allow multiple invocations in the same intent e.g. to enable scanning and then initiate a soft scan with the same call.  Whilst this meant changing the API, the original 6.0 API remains supported for backwards compatibility.


Sample Application

To help illustrate how to call the DataWedge APIs I have created a sample native app on my personal GitHub here:, called ‘DataWedge API Exerciser’.  Note that this application is purely for illustrative purposes and is provided without any kind of support from Zebra.



The API exerciser demonstrates both the DataWedge APIs (6.0, 6.2 and 6.3) as well as the various ways to receive scan data from the Intent output plugin: via StartActivity, SendBroadcast or StartService.  In order to retrieve scan data via intents you will need to configure device to listen for intents with action com.zebra.dwapiexerciser.ACTION, as explained in the ReadMe file.  Note that the test for the 6.3 CreateProfile API will create such a profile automatically.


The user interface of the API exerciser is hopefully fairly self-explanatory (if a bit ugly!); note you may find it useful to have your device connected to adb and monitor DataWedge logcat whilst using the app to observe DataWedge logs:


$ adb logcat -s DWAPI


Remember to enable logging in DataWedge before use.


Things to be aware of / Usage scenarios

Whilst putting together the API exerciser application above I came across a number of scenarios which it is worth bearing in mind.


Note that the following conditions exist at the time of writing (June 2017) and may be addressed in future updates to the DataWedge API


The API changed between 6.0 and 6.3 for some commands

As previously mentioned, the API changed between versions 6.0 and 6.3 for the following commands:


In and of itself this is not a constraint since new devices are fully backwards compatible and the 6.0 APIs will continue to work regardless of the DataWedge version.  The difficulty comes where you want to target the lowest common denominator of your devices so if any of your devices do not support 6.3+, you will need to ensure you target the older APIs - be careful since the documentation will always default to the latest versions so use the documentation links above and refer to the API exerciser app for examples of using each API.


Another complication with this is the format of EnumerateScanners has changed from a String array to a bundle array in 6.3 with the bundle containing amongst other information the scanner ID.  This scanner ID is required in any calls to the 6.3 API ‘SetConfig’, therefore strictly if you want to use the SetConfig API you first need to determine the scanner ID via the 6.3 EnumerateScanners – notice in the DW API exerciser I assume the scanner IDs are contiguous but this is not best programming practise for a production application.


API return values are always via implicit broadcast

Although the Intent output Plugin supports sending intents to the application via StartActivity, StartService or SendBroadcast, returned data from the DataWedge API only supports broadcast intents.  As well as being less flexible and requiring the receiving application to have a broadcast receiver it means that any application on the device can listen to the return values being passed; there should not be any security concerns since the DataWedge API is available for any application to call but it is worth bearing in mind.


Whilst not yet supported on any Zebra devices, Android ‘O’ adds restrictions to how broadcast intents can be received.  The link is here but if that link gets moved, search for ‘Android O broadcast limitations’.  You cannot register for implicit broadcast receivers in your application manifest but must dynamically register and unregister to receive broadcasts at runtime, as follows:


//  onResume
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_RESULT_DATAWEDGE_FROM_6_2);//  DW 6.2
filter.addAction(ACTION_RESULT_NOTIFICATION);      //  DW 6.3 for notifications
registeReceiver(myBroadcastReceiver, filter);

//  onPause


Given this change will be coming in future Android versions it would not make sense to develop new applications which declare broadcast intents in the manifest, in my opinion.


You cannot associate the callback with the caller

You make a query to the DataWedge API by sending a broadcast intent and you get a reply back via a broadcast intent.  Take for example enumerate scanners (6.3), you send an intent with:


Action: com.symbol.datawedge.api.NOTIFICATION_ACTION
Extra: com.symbol.datawedge.api.ENUMERATE_SCANNERS


And you receive a broadcast intent shortly after with:


Action: com.symbol.datawedge.api.RESULT_ACTION
Extra: com.symbol.datawedge.api.RESULT_ENUMERATE_SCANNERS


How do you know that the received intent is associated with your original call?  You do not really know, especially if you are sending the intent from multiple points in your application – indeed since these are broadcast intents, the request may conceivably have originated from outside of your application.


I had this experience when creating the API exerciser - I wanted to have a drop-down list of available scanners, populated in onCreate() and I also wanted to have a button the user could press which would show a toast with the available scanners, but I did not want the toast to show every time onCreate() is called.  You could work around this with some class variable to track the state of the requests but I ended up changing my application logic.  This is not particular to enumerate scanners, anything returned from the DataWedge API will work this way including the active profile, version information etc..


Your broadcast receiver requires a filter on the default category

As stated above, all data returned to the application by the DataWedge API is done via Broadcast intents.


In the 6.0 APIs, it was sufficient to just declare an intent filter for the required action (only enumerate scanners was supported), dynamically register a broadcast receiver and you would receive the broadcast data.


From 6.2 upwards, additional attributes are returned via broadcast e.g. active profile, version info, profiles list etc.  These 6.2 returned broadcasts are configured to have the CATEGORY_DEFAULT category.  This is best practice but is worth noting that if you did not previously add CATEGORY_DEFAULT to your intent filter for 6.0, it will need to be added to work with 6.2.


There are no return values from any commands

There is no feedback when any of these APIs are called, for example when calling SwitchProfile your application has no way of knowing:

  1. That the application has finished switching and the new profile is ready to go
  2. That some error did not occur during the switch.


This is a condition which will likely be addressed in the future.


For debugging purposes, you should use logcat to observe any error messages coming from the DataWedge service:


$ adb logcat -s DWAPI


D/DWAPI  ( 1157): switchToProfile: Profile0 (default)
D/DWAPI  ( 1157): Profile id = 1, current profile id = 15
D/DWAPI  ( 1157): Profile 1 found, loading…
D/DWAPI  ( 1157): Current profile is now ‘Profile 0 (default)’.


Also, be aware that any call to the RestoreConfiguration API will disable logging so you will need to re-enable it via the DataWedge application UI (unfortunately there is no programmatic way to enable logging at this time)


Compounding the lack of return values, not all errors are reported via logcat under the DWAPI tag.  For example (and I’m unsure how prevalent this is) if you try to configure a profile to be associated with an application which is already associated with a different profile it fails with the following logcat output:


E/APIConfigurationManager: ApplicationAssociation: Package and Activity already associated to a different profile


So perhaps the -DWAPI tag will not give you the full picture if you see something not behaving as you would expect during development.


The ActiveProfile does not update immediately on application launch

The way the DataWedge service works is to continually monitor the foreground application and when it detects a change to the foreground app, it activates the appropriate profile.  For the API-exerciser application, when we switch to the app, DataWedge will detect the switch and activate the ‘DW API Exerciser Profile’ (if that is what you have called it).  Unfortunately it takes some finite amount of time for DataWedge to detect that the foreground application has changed and consequently if you invoke the GetActiveProfile API during onResume() you will probably be given stale information i.e. the profile which was in effect before the application was resumed.  The speed with which DataWedge detects the change has been improved starting in Android Marshmallow but you may still see stale information if you immediately retrieve the active profile in onResume().


I workaround this in the API exerciser application by retrieving the active profile some point after the application comes to the foreground, this workaround would be unacceptable in a production app since it relies on an arbitrary timeout – your application logic would need to be designed around retrieving the active profile just prior to it being required or re-checking if the active profile is unexpectedly reported as the launcher or default profile.


SetConfig can only configure one plugin at a time

The SetConfig API is incredibly useful, enabling you to modify any existing profile at runtime and allowing a slew of additional use cases.  For example, you can modify the active profile to only enable certain decoders at some points during your application workflow to prevent mis-scans. Before this API existed, you could have only achieved the same effect by having two separate profiles and switching between the two.


The nested structure of the configuration takes a bit to get your head around, unsurprising given that there are literally hundreds of parameters associated with each profile.


One thing to be aware of though is it is only possible to configure one plugin at a time, so if you want to configure two plugins it will require two calls to SetConfig.  I encountered this scenario in the API-Exerciser where I wanted to configure both the barcode input plugin and the intent output plugin – not difficult to do but given the complex structure of the profile bundle it was not entirely obvious at first how to do it.


SetConfig for the Barcode input plugin requires you to specify which scanner you are targeting

This is alluded to in the documentation for SetConfig but I did not appreciate the significance until I tried to change some barcode decoder properties for myself.  If you are using the DataWedge application UI and want to configure the barcode input plugin you go into the profile, select the options you want to change (e.g. EAN8 disabled) and then you are done, you have configured the settings for the selected scanner (by default, ‘auto’).


With the SetConfig API you need to specify the Intent Extra “current-device-id” to explicitly state which scanner you are configuring the settings for and since Zebra devices will usually have at least 3 scanners available (Camera, Imager and Bluetooth) and the default scanner being device specific you will need to ensure this is set correctly.  The current-device-id is obtained from a call to EnumerateScanners (6.3) so your application logic would first have to call EnumerateScanners and either prompt the user or search for a substring (e.g. Imager) in the returned scanner names. You cannot specify ‘auto’ or leave the setting blank to just apply the settings to the selected scanner, you must specify the ID but if you do leave it blank then it seems to default to 0.


What is the point of CreateProfile?

The SetConfig API has a CONFIG_MODE parameter which can be set to ‘Create_If_Not_Exist’, this will create the specified profile if it does not already exist (hence the name).  The only reason to create a profile via the CreateProfile API is if you want to create a profile without configuring any of its settings, this might be useful if you want to separate the logic between creating profiles and configuring those profiles but it is worth being aware of the potential duplication here.


Switching back to the current application’s associated profile will fail

Consider the following sequence of events:

  • Profile exists on device named ‘DW API Exerciser Profile’
  • ‘DW API Exerciser Profile’ is associated with the application ‘DataWedge API Exerciser’
  • That application is in the foreground so the ‘DW API Exerciser Profile’ is in effect.
  • Call SwitchToProfile to switch to ‘Profile0 (default)’.
    • This succeeds and ‘Profile0 (default)’ is now in effect
  • Call SwitchToProfile to switch back to ‘DW API Exerciser Profile’
    • This fails.
    • Error message in logcat is: “swithToProfile failed, ‘DW API Exerciser Profile’ is associated.”

I would classify this as a bug – the application the profile is associated with is the application trying to switch to it(!).  For the current release, it is required to work around this either by closing / relaunching the application or by using SetConfig to remove the application association from the profile.


Changes operate globally

DataWedge is a global service and any application on the device can interact with it to configure any profile.  It is obviously very flexible that any application is able to configure DataWedge however it goes without saying that care would need to be taken if multiple applications are trying to modify the same set of profiles.


There are no immediate plans to lock down the profile model or add some authentication mechanism on top of it since feedback from customers has been that the current architecture is a good trade-off between functionality and integration risk.


Moving forward as we give applications more power with what they can do using the DataWedge API, integration may become riskier.  For example, any application invoking the RestoreConfig API which completely resets DataWedge will need to play nicely with other applications on the device who may suddenly see their profiles being unexpectedly removed.


Next Steps

Zebra continues to improve and evolve its DataWedge APIs as these APIs are a response to customer requests who like the ease of use of DataWedge but would like to have more control over what applications can do with it at runtime.  I would expect many of the conditions listed above to disappear over time.


We are always interested in receiving feedback about the DataWedge APIs and what else we should expose moving forward.  To give feedback either speak with your Zebra representative or leave a comment on this blog post and I will ensure the DataWedge engineering team get to see it.

Devices with Google Mobility Services (GMS) are becoming increasingly popular in the Enterprise space, these are devices which have Google’s proprietary suite of applications and services built in and can provide your enterprise deployment with a powerful foundation on which to build your line of business applications and workflow.  Exactly why an enterprise would choose GMS over non-GMS (also called the Android Open Source Project, AOSP) is outside the scope of this blog: you might wish to deploy “managed” Android devices, you may be swayed by the additional protection offered by Play Protect or your applications might simply require Google Maps and enhanced location precision but whatever your reasons, the prerequisite assumption is you have chosen a deployment incorporating GMS devices.


Although GMS incorporates an ever expanding range of features, some of the most popular features are listed below:

  • Google Play Services APIs including:
    • Firebase Cloud Messaging
    • Fused Location API
    • Geocoding API
    • Google Maps API
    • Google Cast API
  • Google Play Store
  • Google Play Protect
  • Google Chrome (& safe browsing)
  • Gmail
  • Voice recognition


Having chosen GMS devices, many customers find they wish to selectively block certain functionality and applications; this blog aims to inform the administrator exactly how functionality can be selectively disabled and the implications of doing so.


Why disable GMS features at all?


GMS features as an overall suite are extremely powerful, so much so that arguably a consumer smartphone is not fit for purpose without them.  As we see Google increasingly concentrate on the Enterprise market, more and more enterprise functionality will make its way into play services: for example the managed play store or support for managing purpose-built devices.


You may wish to selectively disable GMS features to:

  • Prevent automatic application updates from the Play Store
  • Prevent the user from accessing specific applications e.g. the News app
  • Control whether your devices location is visible to Google e.g. by disabling the fused location API
  • Prevent some ‘Share’ options being displayed to the user e.g. prevent sharing to Drive to avoid the user copying off sensitive data
  • Prevent access to Google+ as it is not relevant to the employee’s work.

And many other use cases


How to disable GMS features


There are 3 steps to disabling GMS features:

  1. Determine which packages represent the features you wish to disable
  2. Disable these packages using the MX App Manager; as with any Zebra ‘manager’ this can be called by stage now during device configuration or at runtime through our EMDK API.
  3. Restart the device


Determining which packages to disable


Unfortunately there is not a public reference on which Android packages are included in GMS devices and the functionality of each, there will therefore unfortunately be some degree of trial and error to determine which packages require disabling. To add to this, the packages which comprise a GMS build vary from desert to desert so you may need separate configurations for each desert if your deployment contains different android versions.


To aid in the ‘trial and error’ I have put together an application which lists all the system apps installed on your Zebra device and allows you to disable or enable them: , there is also the ability to define your own set of applications / package names and for more information see the readme:


disable system apps application.png


To determine which packages are installed on your device you can run the following command with your device connected to adb:


adb shell "pm list packages -f"


You can of course combine this with grep for a more concise output:


adb shell "pm list packages -f | grep"


You will get an output something like this (obtained from my TC51 GMS):




I will attach the full output from my TC51 to the bottom of this blog.  The function of many of these packages will be self-explanatory, for example:

  • disables the Google+ application and the ability to Share to Google+
  • disables the fused location provider available through the Location Services API


And some may be less obvious, for example:

  • disables the ability to web search for a highlighted word outside of Chrome


Disable these packages using the MX App Manager


The MX app manager can be used to disable specific packages using the following profile:


<characteristic type="Profile">
  <parm name="ProfileName" value="ApplicationManager"/>
  <parm name="ModifiedDate" value="2017-01-25 08:07:34"/>
  <parm name="TargetSystemVersion" value="6.0"/>
  <characteristic type="AppMgr" version="4.4">
    <parm name="emdk_name" value="AppManager"/>
    <parm name="Action" value="DisableApplication"/>
    <parm name="Package" value=""/>


As mentioned earlier, you can initiate this profile as part of your device configuration (via StageNow) or at runtime using the EMDK.  If you are using the test application at then this functionality is part of that application.


Here is a before and after of disabling all GMS applications on my TC51 Marshmallow device:


All GMS packages enabled:


gms 1.pnggms 2.pnggms 3.pnggms 4.png


All GMS packages disabled:


aosp 1.pngaosp 2.png


There are 6 different types of applications installed on my device:

  • Applications which are part of GMS, these have disappeared between the screenshots above and include Chrome, Maps, Gmail etc.
  • Applications which are part of the standard Android AOSP continue to be present, e.g. File Browser, Gallery and Settings
  • Applications which are pre-loaded by Zebra as part of the Zebra BSP and provide value adds to Zebra users e.g. the Bluetooth pairing utility, StageNow.  These remain unaffected.
  • Applications I have developed myself and side-loaded to the device, with the common coffee cup icon remain unaffected.
  • Applications downloaded from the Google Play store, e.g. ZXing (Barcode Scanner): These remain on the device despite the play store itself being disabled but are no longer subject to being automatically updated.
  • Applications available from Zebra which have been post-loaded onto the device, e.g. Enterprise Browser remain unaffected.


Applications which rely on GMS services such as the fused location provider no longer report a fused position, as evidenced from this screenshot of my location API exerciser, with GMS services enabled (left) and GMS services disabled (right).


location gms.pnglocation aosp.png

Note: I have redacted some of the location precision for privacy.


Restart the device

Notice how Google Duo is available in the screenshot illustrating all the GMS packages being enabled, this is curious behaviour since Duo does not appear after a device restart on TC51.  Similarly, I have observed other strange behaviour immediately after enabling some packages e.g. the photos application failed to fully start.  For these reasons, I advise rebooting your device after making any changes to the enabled or disabled packages.


Other considerations

  • Enterprise Browser on Marshmallow will continue to work even after “” has been disabled.  I am surprised by this since EB depends on the system webview but this behaviour may change as the OS is updated to Nougat and ‘O’ where the webview is provided by the Chrome APK.
  • As far as I know the list of applications which are part of GMS for each OS flavour is proprietary information to Google so whilst it can be fairly straight forward to determine through trial and error, I cannot go into extensive detail in this blog.  If you require more detailed information on which GMS applications are on each OS flavour, work with your sales engineer who may be able to help.
  • Android’s Device Policy Manager API contains several methods related to enabling system apps.  This is complementary but separate from the enabling and disabling system apps discussed in this blog and is concerned with system apps disabled whilst provisioning an Android managed device.

With the introduction of doze mode in Android M we have seen a number of enterprise use cases where customers want to ensure their application continues to run even though the device wants to enter a power saving mode.  It is assumed the reader is familiar with doze mode, at least at a high level.

From a consumer point of view, getting maximum battery life out of a device is frequently an ever-present consideration, so much so that a slew of snake oil “task manager” and “task killer” applications formerly gained popularity to prevent background apps but in recent Android releases Google has taken a more aggressive approach to what apps can do in the background.

Enterprise applications are written primarily to enhance user efficiency; battery consumption will always be a consideration but may be secondary or tertiary to application responsiveness or performance.

The goal of this blog is to explain your options as an application developer to give you the most control over your device’s power management and what you can do to ensure your application is always available to your users.


There are two fundamental reasons people might not want the device to enter a power saving mode:

  • The application should be available to respond to network requests, for example a push message.  Often Firebase Cloud Messaging (FCM) is not a suitable option for customers because the device is behind a firewall or does not have GMS services installed.
  • The application needs to do work continually and it is not acceptable for the Android OS to kill the application’s background services.


Before diving into the detail, it is necessary to understand the concepts around Android power management:


Wake Locks

Wake locks are an Android concept designed to allow an application to indicate that it wants to have the device stay on, for example the YouTube application would take a FULL_WAKE_LOCK to prevent the screen turning off whilst the user is watching a video.  A wake lock can control the status of the CPU, Screen and hardware Keyboard backlight but all but one type of wake lock can be cancelled by the end user simply by pressing the power key.  Since only PARTIAL_WAKE_LOCKs persist when the user presses the power key the remainder of this blog will be concerned exclusively with those, where the CPU continues running but the screen and hardware keyboard backlight is allowed to turn off.

Android documentation is available for the wake lock definition as well as methods to acquire and release wake locks.


Any application requiring a wake lock must request the android permission:


<uses-permission android:name="android.permission.WAKE_LOCK" />


You can detect any wake locks being held by applications on your device through adb:


adb shell dumpsys power


The following screenshot shows a single wake lock is on the device, it is a partial wake lock and has been given the tag ‘WakeLockExampleAppTag1’ by the application which created it:

Wake lock acquired.png

Partial wake locks will be released either when the application which created it calls release(), or the lock was only acquired for a specified time.  Note that wake locks will be automatically released when the device enters doze mode unless battery optimization is disabled for the application which acquired the lock (see later)


Whilst this blog is concerned primarily with Android Marshmallow, you may notice that earlier Zebra devices’ WiFi service gains its own partial wake lock, even when the WiFi policy is set to not "keep WiFi awake when the device is sleeping".  You can see any wake lock using the technique described above and should bear this in mind if wondering why your device is not sleeping when expected on earlier devices e.g. MC40.


WiFi Locks

WiFi locks allow an application to keep the WLAN radio awake when the user has not used the device in a while, they are frequently used in conjunction with wake locks since any application doing work in the background would likely need WLAN connectivity (e.g. downloading a large file)


Android documentation for the WifiLock is here and the documentation on how to acquire a WiFi lock is here.


As stated in the official docs, WifiLocks cannot override the user-level “Wifi-Enabled” setting, nor Airplane Mode.  For Zebra devices, we can extend this to WifiLocks not being able to override the Wi-Fi Enable / Disable setting of the WiFi CSP


Some other special considerations for Zebra devices:

  • Out of the box, Zebra devices come pre-loaded with the AppGallery client.  AppGallery will be holding its own WifiLock lock and since the radio is only allowed to turn off when no WifiLocks are held, the radio will not turn off by default (until the device enters doze mode).  AppGallery’s lock is defined as follows:
    • WifiLock{Pushy type=1 binder=android.os.BinderProxy@...}
  • You can disable AppGallery in a number of ways:
    • Using the MX AccessManager whitelist feature
    • Using the MX ApplicationManager to disable the application
    • Using Enterprise Home Screen’s <app_disabled> preference
    • Disabling the application manually under Settings --> Apps --> AppGallery --> App info

Note that the current package name is com.rhomobile.appgallery but that may change in the future.

  • Zebra devices also have an additional “Sleep Policy” parameter as part of the MX Wifi Manager
    • You can set the sleep policy via the Settings UI: Settings --> Wi-Fi --> (Menu) Advanced --> “Keep Wi-Fi on during sleep”.  The values are:
      • Always (the WiFi radio will not turn off when the device sleeps)
      • ‘Only when plugged in’ (the WiFi radio will not turn off provided the device is connected to power)
      • Never (the WiFi radio will be allowed to turn off when the device sleeps)
    • The sleep policy does not hold a separate WiFi lock, it is configuring the WiFi policy and is reflected in the mSleepPolicy value.
    • The default value of the sleep policy will vary from device to device.  As a general rule, devices running Marshmallow or earlier will have this value set to 'Never' and devices running Nougat or later will set this value to 'Always' but there will be exceptions (notably the TC8000 which defaults to 'Always'). 
    • The device will only turn WiFi off during standby if there are no WiFi locks and it is allowed to do so according to the WiFi sleep policy
  • When the device receives a network request over WiFi, the device obviously needs to do some processing to handle the message.  Although this requires hardware support from the WiFi stack and processor, recent Zebra devices will be able to wake the processor to perform the required packet handling.  If more than simple processing is required when packets are received it may be prudent to also acquire a wake lock for the duration of that processing.  This is true of all Android M or later devices.


You can detect any wifi locks being held by applications on your device through adb:


adb shell dumpsys wifi


The following screenshot shows a single wifi lock is on the device (in blue) and is given the tag ‘WifiLockExampleAppTag1’ by the application which created it.  Highlighted in green is the mSleepPolicy variable which can be used to determine the WiFi sleep policy, here 0 is ‘Never’ keep WiFi on during sleep but a value of 2 would indicate ‘Always’ keep WiFi on during sleep.:


wifi lock.png


Device Configuration

Will Wi-Fi turn off when the device first sleeps?

Will Wi-Fi turn off when the device enters doze mode? *

No WiFi Locks held by any applications

Sleep policy set to ‘Always’ keep wi-fi on.

No, the WiFi radio will remain on when the device sleepsYes, the WiFi radio will remain off in doze mode.

At least 1 application holds a WiFi lock

Sleep policy set to ‘Always’ keep wi-fi on.
No, the WiFi radio will remain on when the device sleepsYes, the WiFi radio will be turned off when the device enters doze mode.

No Wi-Fi locks held by any applications

Sleep policy set to ‘Never’ keep wi-fi on
Yes, the WiFi radio will turn off when the device sleepsYes, the WiFi radio will remain off in doze mode.

At least 1 application holds a WiFi lock

Sleep policy set to ‘Never’ keep wi-fi on.
No, the WiFi radio will remain on when the device sleepsYes, the WiFi radio will be turned off when the device enters doze mode.


* Note that both wake locks and the “Sleep Policy” will be ignored when the device is in doze mode unless battery optimization is disabled for the application which acquired the lock (see later)


Battery Optimization / Doze Mode

Diving into Google’s documentation for doze mode and app standby, any developer wishing to circumvent doze mode is quickly drawn to application whitelisting.

The terminology can get confusing at times so:



  • Application is not whitelisted
  • Application is optimized
  • Battery is optimized
  • Default state for all applications other than some Google system apps


Not Optimized:

  • Application is whitelisted
  • Application is not optimized
  • Application may drain your device battery more quickly
  • Battery optimizations are being ignored


You can whitelist your application in a few different ways but all require user or manual intervention:

1. By requesting the permission


<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />


And sending an intent with the following action:




Doing so will present the following warning dialog to the user:


ignore battery optimizations.png


If the user presses 'YES' then the application will be whitelisted, else if the user presses ‘NO’ there will be no change.


Note that requesting this permission and sending this intent is likely to have your application removed from the Google PlayStore, per the following warning in Android Studio, “Use of REQUEST_IGNORE_BATTERY_OPTIMIZATIONS violates the Play Store Content Policy regarding acceptable use cases, as described in …”.  This is particularly problematic for customers planning to distribute their enterprise applications through Google’s managed play store.


2. By sending an intent with the following action




Doing so is just a shortcut to Settings --> (menu) Battery optimization where the user can choose to manually whitelist your application by selecting ‘All apps’, finding the application and choosing the appropriate option from the dialog


optimize or dont optimize.png


This is of course error prone and the user could select the incorrect option.  There is an API to read the whitelist state of an application so one option might be to nag the user until they accept.


Since this is accessing the standard Android settings UI then considerations around whether or not the user is allowed access to device settings should also be taken into account.  For example, preventing access to the Settings UI with the MX AccessManager would prevent the user from being able to whitelist the application.


Note that in my testing it is not a good idea to mix the two techniques, I often found the UI displaying optimized applications did not get updated after I performed step 1 even though the app itself was whitelisted.


3. Using ADB during provisioning you can manually edit the whitelist, though obviously your device must first have developer options enabled:


Add your application to the whitelist as follows:


adb shell dumpsys deviceidle whitelist +com.yourcompany.yourapp


And remove your application from the whitelist with the following command:


adb shell dumpsys deviceidle whitelist -com.yourcompany.yourapp


4. This is a feature Zebra may choose to automate in the future


Querying the current whitelist state

Within your application you can query the isIgnoringBatteryOptimizations() method within the PowerManager API to determine whether or not your application is currently whitelisted.   If the API returns true then your application is currently on the whitelist.


The code is called as follows and demonstrates asking the user to whitelist the application if it is not already whitelisted:

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
  if (!pm.isIgnoringBatteryOptimizations(getPackageName())) {
    //  Prompt the user to disable battery optimization
    Intent intent = new Intent();


Service Stickiness

An Android service lifecycle introduces the concept of service stickiness, i.e. a service which should remain running should return START_STICKY or START_REDELIVER_INTENT from its onStartCommand().  These were introduced way back in API level 5 and were designed primarily for where the Android OS would kill a service because it was consuming too much memory, later restarting that service.


START_STICKY does not circumvent doze mode or keep any kind of locks, the overlap with use cases being described in this blog comes when considering long running background services. If the application wants to perform a long running background task then it is generally a good idea to return START_STICKY or START_REDELIVER_INTENT from the onStartCommand(); for an IntentService then call setIntentRedelivery(true) in the constructor to achieve the same effect.


Although by following the advice on locks and whitelisting in this blog can prevent your device sleeping, it cannot avoid Android stopping your service for other reasons (e.g. memory pressure) so this case should always be considered.


Additional documentation is available for START_STICKY, START_REDELIVER_INTENT and START_NOT_STICKY within Android Service docs, setIntentRedelivery() is documented under Android IntentService.


Putting it all together

  • This blog has discussed a number of variables:
    • Android wake locks
    • Android wifi locks
    • Application whitelisting and Doze mode (battery optimization)
  • This blog has also considered a couple of use cases:
    • An application wants to listen for incoming network requests and do some work when it gets a request
    • An application wants to perform a long running background service regardless of whether the device wants to sleep.

I have written a test application to test some of the concepts described here:  Whilst not officially supported by Zebra, The UI should be self-explanatory enough to perform the following operations:

test application.png


  • On launch, if the application is not whitelisted, ask the user if they want to whitelist it
  • A background service is used to test whether the CPU is active or not:
    • Send an HTTP POST to the specified address on that background service
      • Configure that HTTP post address
    • Emit a beep in that background service
  • A web server within the device is used to test whether the WiFi is alive or not and the device is able to respond to an HTTP GET request from a desktop computer.
    • Initialise that background server on port 8080.
  • Acquire or release a wake lock
  • Acquire or release a wifi lock
  • Show the battery optimization settings UI.  As stated earlier, I have found this technique sometimes unreliable when mixed with the automatic whitelisting request on launch.


Table of behaviour

Note: For brevity, the following terms should also be considered synonymous for this table:

  • Acquiring a WiFi lock and setting the sleep policy to ‘Always’ keep wi-fi on.
  • Not acquiring a WiFi lock and setting the sleep policy to ‘Never’ keep wi-fi on.

Testing was performed on a GMS TC51 running Android Marshmallow but should be consistent across all Zebra Android M and later devices.



Application processing can continue?

Application can respond to network requests

Wake lock: Not acquired

Wifi lock: Not acquired

Application whitelisted: No


Application will stop processing a few seconds after the screen turns off.


Application will stop responding to network requests after a few seconds

Wake lock: Acquired

Wifi lock: Not acquired

Application whitelisted: No

Until doze.

Application will continue processing until doze mode kicks in but will not have WLAN access


Application will stop responding to network requests after a few seconds

Wake lock: Not acquired

Wifi lock: Acquired

Application whitelisted: No


Application will stop processing a few seconds after the screen turns off.

Until doze.

Application will respond to network requests until deep doze mode kicks in at which time the application will stop responding to network requests.

Wake lock: Acquired

Wifi lock: Acquired

Application whitelisted: No

Until doze.

Application will continue processing until deep doze mode kicks on.

Until doze.

Application will respond to network requests until deep doze mode kicks in at which time the application will stop responding to network requests.

Wake lock: Not acquired

Wifi lock: Not acquired

Application whitelisted: Yes


Application will stop processing a few seconds after the screen turns off.


Application will stop responding to network requests after a few seconds

Wake lock: Acquired

Wifi lock: Not acquired

Application whitelisted: Yes


Application will continue processing indefinitely but will not have WLAN access


Application will stop responding to network requests after a few seconds

Wake lock: Not acquired

Wifi lock: Acquired

Application whitelisted: Yes


Application will stop processing a few seconds after the screen turns off.


Application will continue responding to network requests indefinitely.

Wake lock: Acquired

Wifi lock: Acquired

Application whitelisted: Yes


Application will continue processing indefinitely.


Application will continue responding to network requests indefinitely.


Upcoming changes with Android ‘O’

Android ‘O’ is introducing a number of limitations to what applications and services can do when running in the background including background services, implicit broadcasts and device location.

Most notably for this blog, Android Services will not typically be permitted to run when their owning application is in the background.  There are exceptions to this, in particular a Service will be allowed to run temporarily to service a high-priority Firebase Cloud Messaging (FCM) message, to handle a PendingIntent addressing the service or if the service was started in response to a broadcast but after several minutes the service will be stopped by the Android system.  At this early stage, it does not appear possible to circumvent these restrictions for running in the background; work arounds provided by Android are to use a foreground service, FCM or the Job Scheduler API to execute at some point in the future, meaning applications wishing to remain running in the background will likely need to use a foreground service.  Since the service is being stopped in a similar manner to calling stopSelf() then returning START_STICKY from the onStartCommand() will not help to keep the service alive in the background.


Android background service limitations are fully documented by Android here and the background location limits are documented here.

The conclusions presented earlier in this blog do not take account of Android ‘O’ changes since ‘O’ is still in developer preview and the behaviour is subject to change.

As ever, Zebra will evaluate how this impacts our customers as we release device OS builds of 'O' and add additional capabilities for enterprises where appropriate.

Using Alarms whilst in Doze Mode

This document has so far focused on the ability of an application to do work and respond to network requests whilst the device is in doze mode, an additional limitation of doze mode is that the standard AlarmManager alarms (including setExact() and setWindow()) are deferred to the next maintenance window, i.e. you cannot rely on the alarms firing at the exact required time.  To be clear, disabling battery optimizations for your application will NOT circumvent the alarm restrictions present when the device is in doze mode.


You have a number of options:

  1. Make use of the new APIs introduced in MarshMallow, setAndAllowWhileIdle and setExactAndAllowWhileIdle. These alarms will fire at the desired time even whilst the device is in doze mode but should be used sparingly to avoid excessive battery drain.  The primary restriction of these alarms is the system will throttle how often they are allowed to fire so you may not be able to trigger more than 1 alarm every 9 minutes (or 15 minutes, both values can be found in the documentation).
  2. If you want an alarm to reliably fire more frequently than every 9 minutes with the device in doze mode then you cannot use the methods detailed in 1, above.  It is recommended that the application wanting to trigger frequent alarms not use the alarm API under these circumstances but instead take a wake lock and manage a timer internally in its own thread.
  3. Use the setAlarmClock API which will wake the system from doze mode shortly before the alarm fires.  The down side of this API for many developers will be that Android displays information about the alarm to the user, typically as a small alarm clock icon in the status bar.

      clock icon.png

For more information, please see the official Google documentation for Doze mode.



Final Thoughts

Whilst Zebra will continue to support and advocate enterprise use cases which depend on the device remaining awake, any application wishing to keep the device awake will face an uphill battle since the industry as a whole, including iOS, are continuing to extend the device battery life by restricting background capabilities of applications. Where possible it is recommended to consider alternatives to keeping the device awake, for example:

  • Holding a WiFi lock only in your application, then responding to a network message pushed to the device in order to perform work at a specified time.
  • Use Firebase Cloud Messaging (FCM) to wake the device up to perform work at a specified time.

Updated July 2017

Enterprise Browser 1.7 released July 2017 and available here has a number of built-in features available to help you lock down your device, I have updated this blog at the bottom to explain these.



Any deployment of enterprise devices requires some control over which features of the device the user is able to access.

In general, you want to restrict an enterprise user in the following ways:

  • Only allow a specific set of named applications to be run.
  • Prevent installation or uninstallation of applications
  • Prevent access to device settings or prevent changing existing settings e.g. wireless

There may be additional considerations for your enterprise deployment:

  • The device may be designed for direct customer interaction (for example a check-in kiosk or audio tour guide)
  • You may have a variety of Android versions in your deployment and the solution needs to run across all target devices.
  • You may or may not be using a third-party Enterprise Mobility Manager (EMM) to facilitate device provisioning.

Existing solutions

There are a number of solutions to lock down your device, all of which are supported on Zebra devices. This blog will contrast these solutions to enable you to choose the solution that best fits with your deployment:

Android logo.png

Android’s APIs and workflows aimed at “Single-Purposes Devices” or “corporate-owned, single use (COSU)” devices.

Android has a set of supported APIs and modalities introduced in 5.0 which receive updates with each new Android release.  These features can be considered enterprise ready from 6.0 onwards.

Enterprise Home Screen (EHS).

An application provided free of charge by Zebra; this is a replacement home screen for your device and provides extensive configuration to restrict what the end user is able to do on the device.
mx logo.png

Mobility eXtensions (MX).

Available on all Zebra devices, MX provides an extensive feature set which includes the ability to control which applications on the device can be run or installed as well as locking down access to device settings.


Clearly there will be some overlap between these offerings.  The differences are summarized in the below table:



Android logo.pngehs-logo.pngmx logo.png
Restrict applications runningYes, via lock task modeYes, by only displaying enabled applicationsYes, by application whitelisting in the AccessManager
Restrict application installationNo, can still install via adb or programmatically through DPC but user ability is restricted as they cannot escape the current appNot explicitely.  Can disable USB to prevent sideloading.  Can prevent access to Play store and web to prevent download.Yes, by application whitelisting
Restrict access to device settings.Yes, via lock task mode.Yes, via a configuration settingYes, via the AccessManager
Restrict access to settings via the notification shade.Yes, via lock task mode.Not on all devices, recommendation is to use MX UiManager insteadYes, via the UiManager
Kiosk mode support (prevent back, home and recent buttons)Yes, via lock task mode.Yes, via a configuration settingNo
GMS / Non-GMS?Both GMS and non-GMSBoth GMS and non-GMSBoth GMS and non-GMS
Zebra / Non-Zebra?No restrictionZebra devcies onlyZebra devcies only
Earliest Android version supported6.0 for Enterprise use casesEarly releases of EHS supported JellyBean and upFeatures supported depend on installed framework version(s).  See matrix.
Enhancements in later Android releasesEvery version from 5.0 to present (O)  includes enterprise enhancementsLatest release (at time of writing) supports KK and upAdditional features are continually being added.
Staging (getting the functionality on device)Device needs to be configured to have a device owner and associated policy controller.  Achieved through NFC bump or QR codeEHS is just an APK. Can be installed via EMM, MX (AppManager), ADB sideload or manually via ‘unknown sources’MX is pre-installed on all recent Zebra mobile computers.  Older devices required installation via APK.
Provisioning / Integration with EMM (MDM)Integrates with all major EMMs.Can be achieved automatically with code, StageNow or EMMs that support Zebra’s MX.Zebra has a number of EMM partners who support MX and the additional functionality MX provides. See Zebra’s device management partner page.
Security of solutionCan only escape lock task mode via an API call in the app that initiated the mode.  Password to escape user mode is encryptedWhitelisted packages can be associated with a signature to ensure a ‘bad app’ could not spoof the package name.
Additional benefitsRecommended way forward by Google so benefits from Google support, development and partner ecosystem.Flexible solution, can be used in conjunction with other lock down offerings e.g. to enhance lockTask mode by disabling USB.Supported on all Zebra devices going back to JellyBean.  Provides a consistent experience without the need for special considerations on each device.
DrawbacksOnly supports Android 6.0+, though applications are still compatible with earlier versions of Android Locked to Zebra hardware. Does not support widgetsLocked to Zebra hardware, alternatives need to be found if the customer solution contains a mixutre of Zebra and non-Zebra devices.
API accessThe DevicePolicyAdmin APIs provide management capabilities to device administrator applications (typically provided by the EMM)NoneComplete API access is provided in Java and C# via the Profile Manager class.
When best to useNew deployments exclusively targeting Marshmallow or greater.Whenever you need a light weight, set and forget solution with a shallow learning curve.  When you have an exclusively Zebra deployment or need to support Zebra devices going back to JellyBean in a consistent manner.



Android’s APIs aimed at “Single-Purposes Devices”

Although Zebra devices have a wide variety of features, for the purposes of Android enterprise they fall under the category of “Single-Purpose Devices” or “corporate-owned, single-use (COSU)” since compared with a consumer smart phone, Zebra devices are generally designed with a task specific purpose in mind.


It is highly recommended to read Android’s developer guide for setting up single-purpose devices and the differences between app pinning and lock task mode:


First, some prerequisites:

  • The device in question must be configured to have a device owner (DO).  Device owners are a type of device policy controller (DPC) as explained here:
    • Zebra devices running Marshmallow and up will run in device owner mode.
    • Typically you would NFC bump or scan a QR code to specify a device owner but for testing purposes (including the screenshots & videos in this blog) you can also configure an emulator with an adb command:

adb shell dpm set-device-owner "com.afwsamples.testdpc/.DeviceAdminReceiver"


Screen pinning vs. Lock task mode:


The Android developer guide does go into more detail but essentially, app pinning targets consumer use cases such as handing a device to a friend to show them a YouTube video without allowing them to see your messages.  Lock task mode targets enterprise use cases, is manageable through the DPC and provides a stronger form of device lock down.


The concept of white listing applications is integral to lock task mode as only white listed applications can be shown in and control this mode.  White listing is accomplished through an API in the Device Policy Manager which in a real deployment would be controlled through an EMM cloud based interface.


Benefits of lock task mode

  • User cannot exit out of your application because the home and ‘recents’ buttons are hidden.
  • If there are multiple whitelisted applications, you can switch between them using either the back button or Intents (where one whitelisted application would be acting as an ‘app chooser’)
  • The status and menu bar are made invisible and inaccessible, this prevents the user from changing device settings.
  • Screen lock and sleep functions are potentially disabled.  You may see documentation stating that screen lock and sleep functions are disabled during lock task mode but this depends on how the device owner is managing the device and is configurable from the DevicePolicyManager APIs.  It is important to note Google’s documentation for Lock task mode may concentrate on kiosk use cases rather than handheld mobile computers as the use case is more familiar to a wider audience.


How to enter lock task mode

To demonstrate lock task mode our set up is as follows:


An app that will stand in for the user facing application.  Since the application can call startLockTask() and stopLockTask() our test application exposes those as buttons on the interface:



Base case: Screen pinning

Even running on an Android Marshmallow device, calling startLockTask() does not automatically enter lock task mode.  The application must first be added to the lock task list, controlled by the DPC to whitelist the application.  If an application is not whitelisted then calling startLockTask() will just result in application pinning.

Invoking lock task mode from an application

If an application is whitelisted by the DPC, calling the startLockTask() API will cause the device to enter lock task mode.  From this mode, the user cannot leave the displayed application.

Note: the ‘Screen pinned’ toasts do not come from the test application, the Android framework is providing misleading information

Entering lock task from the DPC.

Calling startLockTask() from the DPC will cause the device to enter lock task mode.  From this mode, you can also enter additional whitelisted applications by sending an intent (for the video, this is done via adb, in a real app you would call startActivity()) resulting in a stack of whitelisted applications.  Pressing back will cause the stack to unwind and the original (DPC) application to show. Finally, calling stopLockTask() from an application that did not initiate lock task mode will result in a security error; if you call start / stop lockTask in that order from the launched app the stack will again unwind and the DPC app be shown.

Checking the state of lock task mode.

There are a couple of APIs which can be used to determine lock task mode.  Firstly the DevicePolicyManager has an API to determine whether your application is whitelisted but that must be called from the DPC. The activity also has access to getLockTaskModeState() which returns whether or not the application is currently locked or pinned

The lockTaskMode attribute in the Application Manifest

Although the documentation for lockTaskMode will list ‘normal’, ‘never’, ‘always’ and ‘if_whitelisted’; note that ‘never’ and ‘always’ are only available to system apps and privileged apps so a typical end user application will only be able to choose between ‘normal’ and ‘if_whitelisted’.

The examples listed so far have shown the effect of ‘normal’ which is also the default behaviour.  If you specify ‘if_whitelisted’ then the application will launch straight into lock task mode.  The video demonstrates an application configured with ‘if_whitelisted’ being launched twice, the first time is it not white-listed and the second time it is white-listed.



Mobility eXtensions

Mobile eXtensions (MX) are Zebra’s layer of additional functionality added on top of Android to provide an enterprise-class experience for our customers.  MX has a wide variety of features designed to facilitate device staging and configuration as well as some application management and data capture capabilities; these features are exposed as ‘Profiles’ and can be accessed in a variety of ways:

  • Through code, supported in both the EMDK for Android and EMDK for Xamarin
  • Through StageNow, Zebra’s own staging tool which offers integration with several major EMMs.
  • Through a supported EMM agent.  Several of our EMM partners support MX to enhance their ability to manage Zebra devices.


For the purposes of this blog we are only concerned with profile access only through code or through StageNow since these offer the greatest flexibility in how we control profiles.  The examples shown here will use EMDK for Android since it is easier to demonstrate the techniques available but in practice a typical user would most likely be applying these profiles through StageNow.



The MX lockdown application, available on GitHub can be used to quickly test the various profiles described here.  A video is also available at which shows the application running on a Zebra TC51 device



Profiles to lock down your device

The MX profiles offer multiple, often overlapping ways to lock down your device.  The most restrictive (in terms of a user’s ability to circumvent the lock down) is through the Access Manager with other profiles offering less restrictive but more fine grained options to give the most possible control. You may wish to use some of the less restrictive options in conjunction with Enterprise Home Screen to provide a fully locked down solution.


The table below summarizes the lock-down functionality available from the different MX profiles, it is important to note that the profiles themselves are far more functional but I have just pulled out the relevant bits related to locking down your device.


Profile & FunctionalityDescription

Access Manager

  • Application whitelisting
  • Prevent installation of non-whitelisted apps
  • Prevent running of non-whitelisted apps
  • Secure which apps can run through use of app signatures
  • Prevent ability of non-whitelisted apps to invoke other profiles (AKA submit XML)
  • Prevent access to system settings

This offers device administrators the most control but confusingly shares some terminology with Android’s lock task mode.  Whitelisting in this context also means specifying which applications can and cannot be run on the device but the Access Manager defines this list through the Add Package Name(s) parameter.  Whitelisting applications has no bearing on how applications are launched in contrast with LockTask mode where the user was prevented from exiting back to the launcher, AppManager will however only allow whitelisted apps to be run from the launcher with non-whitelisted apps displaying an error through a Toast.


The ability to restrict whether a whitelisted application can or cannot make changes to the system (through profiles, AKA ‘Allow XML’) offers greater control and fidelity.


No special mode is required to use the Access Manager (unlike lock task mode which requires a Device Owner configured on the device) and whitelisting applications via Package signatures, not just the package ID, avoids security concerns on unmanaged devices.


Finally, the parameter to prevent access to system settings provides the most comprehensive way to lock down access to device settings on Zebra device short of hiding the settings icon through EHS.

UI Manager

  • Prevent access to the notification shade
  • Prevent settings access from the notification shade
  • Prevent access to the tiles which enable / disable wireless etc.
  • Prevent Clipboard access

The UI manager offers the most control over which areas of the notification shade are displayed to the user.  The following diagram shows the three different areas (blue, red & green) which can be prevented from being shown to the user allowing for example the user to adjust the screen brightness without giving them access to WAN settings, a common use case where employees are working outdoors.

ui manager.png

Clipboard access can also be disabled via the UI manager to accommodate use cases where users need to run multiple applications but you do not want them to be able to copy data between apps, for example between a company app and a web browser.

Application Manager

  • Disable applications from running
  • Prevent access to application info settings via the Settings UI

Beyond disabling specific system applications with known package names, you can also disable certain system services.  In the MXLockDown application I use this to disable access to which disables the Google assist function present on GMS devices. This is just an example and you can see all packages installed on your Android device by running the following command:

adb shell pm list packages

Or see full information about each package by adding the -f flag

adb shell pm list packages -f

Obviously disabling system packages may have unintended side effects but it is nonetheless a useful tool to have in your arsenal and can be used to restrict which applications the user can “share” content with.


Disabling the settings application entirely can be done through the application manager with the package "".  This is a very heavy handed approach however and can lead to side effects such as common actions not working and providing no feedback to the user as to why (e.g. long pressing an application and dragging onto 'App Info') or presenting confusing warnings to the user (e.g. long pressing an application notification gives a 'System UI stopped' warning).

Settings Manager

  • Prevent access to application settings via the Settings UI

To completely lock down access to settings it is recommended to use the Access Manager.

The Settings Manager only prevents the user from navigating to the ‘Apps’ menu (Settings --> Apps) but the user can still access sub menus directly, for example pressing and holding an application and then dragging over the ‘App Info’ option at the top of the screen will still display that application’s information.


Taking this a step further, it is possible to lock down the ‘App info’ screen with the Application Manager’s AccessToAppInfo parameter but again, this can be circumvented by accessing the sub menus directly.  You can access an application’s notification settings directly by pressing and holding on any notification from that app (Android 6.0+) and then pressing the icon (Android 6.0).

App Info.png

Android 7.0 changed this interface so you now click on ‘More Settings’, but the principle is the same.


MX Version support

Over time, additional features have been added to MX so whilst Zebra does not break backwards compatibility, newer MX features will only be available on newer devices.

For a full list of which profiles are available on which devices consult the compatibility table.  You will need to be able to decipher which version of OSX and MX you are running and instructions for that are here.


In general, the major features discussed above will be available on JellyBean devices and up, meaning MX is an ideal solution for any deployment containing a mixture of JellyBean, KitKat, Lollipop or Marshmallow devices where you want a consistent approach to how you lock down your devices.


Enterprise Home Screen

Enterprise Home Screen (EHS) is a free application offered by Zebra to replace your device’s default launcher application with an Enterprise-first alternative.

EHS resources including setup and configuration guidance can be found on techdocs and the application itself downloaded from the support page.


There is a lot of overlap between the EHS settings, Android’s lock task mode and MX capabilities.  The following table lists the available EHS configuration and how it maps or overlaps with the other lock-down options:


EHS SettingComparable settings in Android and MX





Kiosk mode is directly comparable with LockTask mode, in both cases the Home and recent options are disabled and the user is locked out of the rest of the OS.

Differences include:

  • EHS Kiosk mode is designed to run a single application whereas LockTask mode can use multiple applications, therefore the back key is disabled only in EHS’s kiosk mode.
  • Since EHS does not offer a programmatic interface there is no way for a running application to enable or disable Kiosk mode (as you can with Android’s stopLockTask() API).
EHS allows you to choose the specific activity of an application to be invoked when the app starts whereas LockTask mode is limited to the launch activity as defined in the application manifest.



This setting allows you to specify which applications can be run on the device.  There are obvious comparisons with the MX ApplicationManager to disable applications, MX AccessManager to whitelist only certain apps or LockTask mode’s ability to only whitelist certain apps to run.

The difference with EHS’s setting is the applications are just being hidden on the launcher so the user is not able to select them, applications can still be started by an Intent even if they are not listed under <applications>. Another difference is in the use of wildcards to specify the package name: no equivalent exists for this in MX or LockTask whitelists but this is by design since the use cases are different.


This functionality is specific to EHS as it is a specific use case for a launcher app.


This functionality is specific to EHS as it is a value add of that product.


This functionality is specific to EHS, it is a value add unrelated to locking down access to the OS.


This functionality is specific to EHS, it is a value add unrelated to locking down access to the OS.


This functionality is specific to EHS, it is a value add unrelated to locking down access to the OS.


This functionality is specific to EHS, it is a value add unrelated to locking down access to the OS.


This functionality is specific to EHS, it is a value add unrelated to locking down access to the OS.


You would expect native applications wishing to control the screen orientation to specify a screenOrientation property in their manifest.









There is no equivalent feature in MX or the Android APIs to launch a set of applications at predefined intervals after application reboot.  The closest feature is probably an application’s ability to listen for a BOOT_COMPLETED broadcast intent and on receiving that, start an application or service in their broadcast receiver.


There is overlap with Kiosk mode, as previously stated EHS Kiosk mode can only lock the user to a single application whereas the auto_launch settings will allow the user to toggle between apps quickly without going back to the launcher. Auto_launch will not lock the user out of the launcher like the EHS kiosk_mode does.


This functionality is specific to EHS, it is a value add unrelated to locking down access to the OS.


Counter-intuitively this setting only affects Enterprise Home Screen itself and does not have any effect on apps other than EHS



On JellyBean and KitKat devices this prevents the settings icon being displayed in the Android Status bar, locking down the ability to adjust settings such as Wifi from the pull down.  In Android L the notification drop down as reworked and the official EHS documentation recommends using the MX UI Manager to block access to ‘quick settings’ also known as the ‘tiles’ you see when swiping down twice.

LockTask Mode also prevents the user accessing the notification pull down, duplicating this capability.



Similar to disable_status_bar_settings_icon, since the notification pull down received an overhaul in Android between KitKat and Lollipop this setting only works with pre-L devices.  EHS documentation for L and above recommends the MX UI Manager to prevent the user pulling down the notification shade.

LockTask Mode also prevents the user accessing the notification pull down, duplicating this capability.


This functionality is specific to EHS, it is a value add unrelated to locking down access to the OS.


This functionality is specific to EHS, it is a value add unrelated to locking down access to the OS.


This functionality is specific to EHS, it is a value add unrelated to locking down access to the OS.



The MX Settings Manager has a parameter which can be set to disable access to the airplane mode selector in the settings UI, quick settings and power key menu.

In LockTask mode there is no way for a user to access the settings UI or pull down the notification shade so the lack of a specific setting is a moot point.


The Android DevicePolicyManager has an API to disable the Keyguard, this API is available to the device owner of a managed device.  No equivalent exists in MX.


The Android DevicePolicyManager has an API to disable features of the keyguard, including the camera.  No equivalent exists in MX.


The Android DevicePolicyManager has an API to disable features of the keyguard.  No equivalent exists in MX.


The MX USB Manager offers a setting to disable USB adb mode.  No equivalent exists in Android enterprise APIs unless the device is rooted.



System_settings_restricted is directly comparable with the MX AccessManager parameter to specify “Reduced Access” to system settings.

No equivalent exists in Android enterprise APIs but the user would typically not be able to access the system settings at all in LockTask mode.



Prevents the application being displayed in both admin and user mode, with some special considerations for settings and search.  There are obvious comparisons with the MX ApplicationManager to disable applications, MX AccessManager to whitelist only certain apps or LockTask mode’s ability to only whitelist certain apps to run.

Disabling an application in this list truly prevents the app from being run, even via Intent which maps closer to WhiteListing and the MX ApplicationManager than the previously described <applications><application> section.


This is the opposite of the <apps_disabled> setting.  The implementation is a bit more confusing than the single whitelist + special lock mode as seen in both LockTask Mode and MX AccessManager but the end result is the same, you can explicitly enable or disable specific applications.  Unlike MX AccessManager where you can provide an app signature or package name, EHS only supports the package name.


This functionality is specific to EHS, it is a value add unrelated to locking down access to the OS.


This functionality is specific to EHS, it is a value add unrelated to locking down access to the OS.
Secure ModeThis functionality is specific to EHS and provides an extra layer of security to prevent tampering with the EHS configuration file.  This is only required in EHS because it is a post-loaded application configured via an XML file so there are no equivalents in MX or the Android enterprise APIs.


Overlap with MX

It is worth calling out the <disable_status_bar_settings_icon> and <disable_status_bar_pulldown> settings which explicitly recommend to use MX as an alternative on L+ devices. There is also an additional section in the EHS help detailing how MX can be used to enhance EHS (e.g. to prevent screenshots); this illustrates how EHS is designed to work well in conjunction with MX where required.


Enterprise Browser

Enterprise Browser (EB) 1.7, released July 2017 incorporates a number of features to prevent users exiting your EB application.  These lock-down features are only useful for developers targeting Enterprise Browser who do not expect their end users to exit from EB and take the form of a kiosk mode locking the end user into Enterprise Browser.


There is not a single setting for kiosk_mode_enabled, like there is with Enterprise Home Screen, instead you need to configure the individual settings, as explained below.  Remember if you completely prevent the application from being exited you can potentially make it hard to develop for, you might consider enabling DebugButtons during development if this is the case.  Also be careful, if you use a tool like EHS to launch EB on boot and you have not included any ability to exit from EB you may find yourself requiring a factory reset to exit the application.

Configuration SettingDescription
SetHomeKeyDisableMakes the home key completely ineffective

Probably more accurately described as disabling the notification pull-down, this has the same effect of disabling the notification shade using the MX UI manager.  The end user is still able to see the status bar by swiping at the top of the screen revealing battery and signal levels but they are prevented from:

  • Interacting with notifications including accessing the application AppInfo setting on 6.0+ (as explained under MX Settings Manager, above)
  • Accessing the quick settings (tile) UI to directly disable settings such as WiFi and Bluetooth

Pressing the back key will still navigate back to the previous page in your application just as it does with any mobile web browser e.g. Chrome but with this setting enabled it is not possible to exit Enterprise Browser by pressing the back key. You may notice some visual aberration as EB pauses and then quickly resumes after you press the key but the functionality of your EB application will remain unaffected.


It is not currently possible to prevent the user from going back to the previous page within EB by pressing this button so you should design your application workflow with this in mind.

Note the spelling error in ‘Buton’, for EB 1.7 you need to spell it this way but for subsequent versions the team will fix this whilst retaining backwards compatibility.


Prevents the user from adjusting the device volume.  Obviously on Android, the volume key provides access to the ringer, alarm and notification volume so the user can circumvent lots of functionality by adjusting the volume levels on the staged values.

SetRecentAppDisableThis setting enables or disables the recent applications button.  Similar to the back key, you may see some visual aberration as EB pauses and then quickly resumes after you press the key but the functionality of your EB application will remain unaffected.  During this visual aberration, the other recent applications are visible (though you cannot interact with them) so you may wish to avoid this by clearing the recent apps list using the MX App Manager



These settings are not new in Enterprise Browser 1.7 but are worth including in this list.  You can specify an exit password which must be entered when EB is quit through the EB quit API or debug button.  Note that the exit password is not required if EB is quit via the menu or recents key.  If you are configuring your application with some of these described kiosk settings it is conceivable you also have some kind of admin menu in your app which enables an authorized user to quit EB for maintenance purposes, in that case it may also prudent to specify an exit password


Enterprise Browser overlap with other solutions

It is entirely possible to lock your end user to Enterprise Browser by using a combination of other solutions, for example Enterprise Home Screen’s kiosk mode can be configured to only show Enterprise Browser MX can be used to prevent users from accessing device notifications.  The primary advantage of the Enterprise Browser lock down features is that you can do everything entirely within EB, not having to worry about deploying EHS, some MX solution or whether or not your device is a managed Android device.


Overall Conclusion

Controlling what the end user is able to do on your device remains a fundamental use case for enterprise Android deployments and is an area where functionality is continually being added.  With Google focussing on this market from Android 6.0 onwards it is likely this area will continue to improve and converge but there will always be the need for Zebra to offer customized capabilities on our devices.  Where we do offer customized functionality, Zebra will endeavour to work well with alternative solutions so administrators can pick and choose the desired aspects from each (hopefully that can already be seen above where Android APIs, MX and EHS can all be used together).


Native Android applications can be developed for Zebra mobile Android devices such as the TC51, TC55, TC8000 etc. in a number of ways.  The primary API for accessing device hardware (e.g. scanner) and Zebra value-adds (known as ‘MX’) is the EMDK.The EMDK is being continually being updated to support new devices and features (download link).  One drawback of these continual EMDK updates is that support for older devices can be dropped from newer releases, for example at the time of writing EMDK 6.0 is the latest version but can only support devices as far back as KitKat with Jellybean devices requiring development with EMDK 5.0 or below.


The Problem

A developer targeting a deployment with a mixture of old and new devices will not want to develop separate applications for each device OS.Before discussing an EMDK-based solution it is worth noting that all Zebra devices ship with a zero-code data capture solution known as DataWedge.  Using DataWedge as your data capture agent and delivering barcode data etc. via Android intents may be sufficient for some applications and negates the problems with a lack of EMDK support for older devices.  DataWedge may not be appropriate for your application however if you require fine grained control of the capture hardware or require access to the MX profile layer.The remainder of this guide assumes that your application requires the EMDK and needs to run across a range of devices from Jellybean to Marshmallow and beyond.  This guide supplements the official EMDK documentation and guides for creating enterprise applications, e.g. Creating a project & Creating a profile.


Android Product Flavours

Android build variants provides a solution to the problem as follows:


Define the product flavours

In the app build.gradle file define product flavours as follows:

android {
productFlavors {
  emdk6 {
  targetSdkVersion 23
  minSdkVersion 19 // EMDK 6.0 supports as far back as KitKat (19)
  versionCode 30000 + android.defaultConfig.versionCode
  versionNameSuffix "-emdk6"
  emdk5 {
  // Not compatible with Marshmallow devices
  minSdkVersion 16
  targetSdkVersion 16 // Though EMDK 5 actually supported up to Lollipop, we are only using it for JB deployments
  maxSdkVersion 22 // Note: Google would still allow installation on 23+ devices (
  versionCode 75000 + android.defaultConfig.versionCode
  versionNameSuffix "-emdk5"


And sync your gradle project.You can now observe that your Build Variants pane in Android Studio (Build > Select Build Variant) contains entries for each of the defined flavours:



EMDK Installation

You will need to obtain the appropriate EMDK libraries, which in the case of this worked example are EMDK 5.0 and EMDK 6.0.  Although the EMDK is currently delivered as a series of EMDK add-ons, you can extract the jar file from the add-on and use the jar directly in your project as a provided library and this is required by the next step.  I personally find it easier to copy the jar files into my project to avoid installation dependencies.  You may find it easier to extract the jar file from the EMDK Mac distribution as this is provided as a zip file.

Copying Jar files.png


Referencing the Jar from Gradle

We will be specifying a runtime dependency for our EMDK library similar to what is done in the official documentation when creating an application to run on non-Zebra devices, as explained here.Gradle enables you to specify dependencies as {flavour}Compile, as explained in the gradle docs.  The simplest setup that works for us will be to specify the application dependencies as follows, using Provided instead of Compile:

dependencies {
// NOTE: This gradle depends on the EMDK Jars associated with EMDK 5 & 6 being in the following directories
  emdk5Provided fileTree(include: ['com.symbol.emdk.jar'], dir: 'lib\\emdk5.0')
  emdk6Provided fileTree(include: ['com.symbol.emdk.jar'], dir: 'lib\\emdk6.0')
  compile fileTree(exclude: ['com.symbol.emdk.jar'], dir: 'libs')
  compile ''

It is also possible to specify separate dependencies for Debug and Release (e.g. emdk5DebugProvided) but in this case that is not required.  Note that the above setup does depend on you having previously copied the EMDK lib jars to your project’s ‘lib’ folder.


Choosing a build variant

In general, you should choose the API level that matches your deployment target, just as you do when selecting an Android targetSdkVersion.  There is nothing technically wrong with running an API 22 application on a Marshmallow (23) device, you just won’t get access to Marshmallow features.Our example setup has two build flavours, emdk 5 and emdk6.  This was done to enable us to support JellyBean, KitKat, Lollipop and Marshmallow.  There is an overlap of supported variants with EMDK 5 supporting JB, KK and L and EMDK 6 supporting KK, L and M.  When building for JB we must choose the emdk 5 build flavour, when building for M we must choose the emdk 6 build flavour.


Using Source Sets to define the assets to use

Application interaction with MX Profiles is achieved through the EMDK Profile manager  and visually through a plugin to the Android Studio IDE (EMDK > Profile Manager)


Profiles are defined as XML and stored under <Your app>\src\main\assets\EMDKConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--This is an auto generated document. 
Changes to this document may cause incorrect behavior.-->
  <characteristic type="ProfileInfo">
  <parm name="created_wizard_version" value="6.0.4"/>
  <characteristic type="Profile">
  <parm name="ProfileName" value="HelloProfile"/>
  <parm name="ModifiedDate" value="2017-01-16 10:00:18"/>
  <parm name="TargetSystemVersion" value="4.2"/>
  <characteristic type="Wi-Fi" version="2.7">
  <parm name="emdk_name" value="DisableWifi"/>
  <characteristic type="System">
  <parm name="WiFiAction" value="disable"/>
  <parm name="UseRegulatory" value="0"/>
  <parm name="UseAdvancedOptions" value="0"/>


The version of MX resident on the device will have a number of capabilities with additional capabilities being added in each MX release.  Newer capabilities will not be available to older devices.  A full compatibility table is available from this link but for the purposes of this document we will assume that the desired profiles could differ between Jellybean, KitKat, Lollipop and Marshmallow devices.  In practice since each release of EMDK supports multiple Android dessert letters you would not have separate XML files for each Android letter.Android uses the concept of Source Sets to define which source files are used for each of the product flavours.  Whilst this principle can apply to java files, manifest files, aidl, jni etc we are most interested for this purpose in specifying different assets for each of the product flavours.Modified from the Android docs:

  • Open the Project pane and select the Project view from the drop-down menu at the top of the pane.

  • Navigate to MyProject/app/src/.

  • Right-click the src directory and select New > Folder > Assets Folder.  Note: You may need to untick the setting ‘compact empty middle packages’

  • From the drop-down menu next to Target Source Set, select emdk6

  • Click Finish

  • Add the required EMDKConfig.xml file to the newly created folder under <Your application>\app\src\emdk6\assets


The EMDKConfig.xml under the emdk6\assets folder will be used whenever a build of that flavour is created.  Repeat these steps for emdk5.  Note A complication here is that the EMDK Profile Manager from Android Studio (EMDK > Profile Manager) will always look for the EMDKConfig.xml file under \main\assets\, care should be taken to ensure the correct EMDKConfig.xml file is located in the appropriate <product flavour>\assets folder prior to building (by manually copying or editing the file).  Similarly, to edit the existing application profiles using the Profile Manager GUI, manually copy the EMDKConfig.xml file to \main\assets\ prior to launching the GUI.


Worked Example

There is a worked example available from which shows the principles discussed in this blog.  Note that as explained earlier, it is necessary to copy the appropriate EMDK jar files into the project ‘lib’ directory.  The example shows a simple PowerManager profile that will turn the screen off when invoked, by selecting the appropriate build variant the same application can run on both JB and M devicesWorked Example.png



Power Manager example on M device



Power Manager example after turning screen off (ha ha)

This document details the developer impact of moving to Zebra devices running Android Marshmallow (API level 23).


Audience for this document

Zebra’s new TC51 and TC75x devices ship with Android Marshmallow installed.  Any developer targeting those devices must be mindful of Marshmallow considerations. Of Zebra’s existing portfolio of Android devices (ET1, MC40, TC55, ET50/55, TC70/75, MC67), there are currently no plans for a Marshmallow upgrade. But for deployments featuring or with the potential to feature a mixture of devices, companies should be familiar with Marshmallow changes.



The release of Android ‘M’ (Marshmallow, API level 23) introduced a slew of new features from Google, most notably a new ‘Runtime Permissions’ model, plus power-saving optimizations for idle devices and applications. Google published an overview of these changes on its developer portal, This document does not replace recommendations from Google, but is designed to supplement those recommendations for enterprise use-cases.


Dynamic runtime permission model

Android Marshmallow introduces a new permission model whereby users are asked at runtime to grant access to restricted features and hardware such as contacts and cameras.


Consumer device impact

The new permission model is explained in detail in Google’s official documentation, and Android will utilize this permission model for any application targeting API level 23 or higher. The new permission model necessitates an application change since the user will not be prompted automatically to grant permissions. The application must prompt the user and handle the response appropriately, which means being tolerant of only a subset of required permissions being granted by the user or justifying why certain permissions are required. Applications targeting API level 22 and below will still use the ‘old’ permission model, whereby all required permissions are accepted by the user during installation.  Regardless of the target SDK API level, the user is empowered on Marshmallow devices and above to revoke any application’s specific permissions, which necessitates very defensive programming on the part of the application developer as an application cannot rely on any permissions being granted.


Enterprise impact

Expecting device users to grant permissions at runtime is unacceptable to many enterprise customers. At best, users could accidentally deny a permission (e.g. using gloved hands trying to interact with the ‘grant permission’ dialog’s small buttons) or require additional training to allow permissions. Such denial could lead to an inability of a user to perform a required task or at worst, a re-provisioning of the device.


The new permission model is separate from the security features offered as part of Zebra’s Mobility eXtensions (MX). For example, the MX Camera manager ( introduced in MX4.3 can be used to deny access to the device camera through StageNow, MDM or EMDK:


<characteristic type="CameraMgr" version="4.3">
parm name="UseAllCameras" value="2"/> <!-- 2 is deny all cameras -->


The MX security features will always take precedence over runtime permissions. In the example, even an application requesting access to the camera will not be able to use the hardware if it has been disabled through MX, and doing so will cause an exception to be raised to the calling application.


Developers targeting Zebra Marshmallow devices have two options:

1. Continue to target API level 22 or lower with your application.

Applications targeting API level 22 will not use the new permission model and so will function identically to KitKat or Lollipop devices. You will not have access to Android APIs introduced in Marshmallow, but this may be the quickest option for many developers. The user’s ability to revoke specific permissions from the application is controlled via the settings menu (Settings --> Apps --> (Application in question) --> Permissions). The Settings manager parameter ‘AccessAppsSection’ ( can be used to ensure the user does not have access to the apps settings section and therefore will not be able to manually revoke permissions.

2. Update your application to API level 23 or higher

If you wish to take advantage of Android Marshmallow features in your application, you will need to re-compile your application to target API level 23 or higher. Applications installed via the AppManager will have their required permissions silently granted and will therefore not present the user with a dialog asking to grant permissions. Calls to checkSelfPermission() ( ) will return PackageManager.PERMISSION_GRANTED for any permission that is defined in the application’s manifest with a <uses-permission /> tag. The AppManager is used by StageNow, EMDK and potentially MDMs with official Zebra device clients to silently install applications where required (


Applications that have had their permissions silently granted still can have those permissions revoked by the user through the App permissions UI, but as previously explained, the ‘AccessAppsSection’ parameter can be used to prevent the user from accessing that UI. Revoked permissions will return PackageManager.PERMISSION_DENIED from checkSelfPermission().    


A revoked app permission



Applications not installed via AppManager, for example those installed through the Android Debug Bridge (adb) or during debugging in Android Studio will not have their permissions automatically granted. Zebra recommends granting these permissions manually during development through the standard Android dialog presented by using the requestPermissions ([], int) ) method call.


In summary, the lifecycle of an enterprise application targeting API level 23 or higher should appear similar to a consumer application:

checkSelfPermission() should be called for the required permission, if this does not return PERMISSION_GRANTED, then requestPermissions() should be called. Doing so will facilitate easier debugging, but applications should be deployed through the AppManager to avoid the user seeing the dialog at any time.


During deployment, the device should be configured to ensure that the user cannot revoke permissions on previously installed applications (using the SettingManager’s AccessAppsSection parameter). However, the best practice is still to  call checkSelfPermission() to ensure the permission has been granted. If the lifecycle includes a call to requestPermissions(), the application can be debugged, installed through adb prior to deployment, and be tolerant of misconfigured devices on which the user has managed to revoke the permissions.



Doze mode and App standby

Doze mode and App Standby are related features introduced by Google on Android Marshmallow 6.0 and higher, and are designed to extend battery life by managing how apps behave when under battery power. Google’s own overview is comprehensive (, with the key points being:

        • All applications are affected regardless of their target API level
        • Doze mode & App standby only affects GMS devices.  AOSP devices are unaffected by any changes for Doze mode and App standby.
        • Doze mode affects an entire device with the device entering doze mode after a period of time with the screen off as long as the device remains stationary.


Enterprise impact

By and large, the improvements in Android Marshmallow to improve a device’s battery life are very positive. Zebra devices are designed with industry-leading battery capacities and address the need for a device to work through the user’s whole shift. The primary cause of battery drain on any device (consumer or enterprise) will frequently be post-loaded applications. With this in mind, it is best to work with the changes introduced by Google rather than against them wherever possible. Zebra does not currently plan to offer ways for developers to circumvent Android Doze mode or App Standby beyond what is publicly available through Google’s APIs.


Push messages

If the enterprise is running Google services (GMS), Google’s recommendation to use Firebase cloud messaging (FCM), the successor to Google cloud messaging (GCM) should be followed whenever possible , in particular the use of high-priority GCM messages.

Enterprise developers targeting non-GMS devices (such as those without Maps, Locationing and Google’s other value-add services) will not have access to FCM (previously GCM). Although Zebra does not offer an alternative GCM technology, others are available from third parties such as Pushy (, PubNub ( or Firebase (, though the 2016 acquisition of Firebase by Google works against advising its long-term use on non-GMS devices. More discussion on this topic is available as a developer blog (

Although Doze mode and App standby apply only to GMS devices, any deployment with a mixture of GMS or non-GMS devices will need to be cognisant of the impacts.



Pushy ( WILL be adversely affected by both Doze mode and App standby on GMS devices. Any application leveraging pushy or any other MQTT-based messaging client will not receive push messages while the device is in Doze mode; messages will be delayed until the next “maintenance window”. Applications leveraging any non-GMS-based push technology, including Pushy, must be whitelisted on GMS devices in order to receive push messages during Doze mode and App standby. This falls under Google’s acceptable use cases for whitelisting since GMS is not available on AOSP devices. Please see the subsequent section on Whitelisting applications.  Alternatively, different push solutions can be used in deployments that cover both GMS and AOSP devices though in most cases that is likely to be a sub-optimal solution.


Interaction with Mobile eXtensions

Zebra offers numerous value-adds branded as ‘Mobility eXtensions’ (MX) that allow additional levels of secure access and configuration on Zebra devices through StageNow, EMDK and approved MDMs.


Power Manager ( exposes the ability to put the device to sleep. Instructing the device to go to sleep through the Power Manager will expedite the device entering Doze mode.


DevAdmin ( exposes the ability to change the screen-lock timeout interval. The screen-lock interval is distinct from the display-screen timeout, with the former timer only starting after the screen has turned off. Since Doze mode is concerned only with whether  the screen is on or off, the screen-lock interval has no effect on Doze mode or App standby.


DisplayManager ( configures the display-screen timeout, which is the time between the last user activity and the device screen turning off. The device screen being off is a prerequisite of the device entering Doze mode.


Cellular Manager (  settings include various options concerning the use of background data over a cellular connection. Doze mode will take priority over any of the cellular manager options. For example, if background data is set to ‘enabled’ in the cellular manager but the device is in Doze mode, an application will not be able to use the cellular connection for sync work outside of the OS-defined maintenance windows.


WifiSleepPolicy ( controls whether the Wi-Fi radio will remain enabled when the device is sleeping. This does not override Doze mode; applications will lose network connectivity during Doze mode regardless of this setting.


Whitelisting applications

Google’s developer docs ( describe a technique for whitelisting applications that makes the apps partially exempt from the limitations of Doze mode and App Standby. It is important to note that the exemption covers only network activity and the holding of partial wake locks (for example the ability to perform processing with the screen off) and that whitelisting does not allow the application to trigger alarms outside of the OS defined maintenance windows.

For Play store applications, Google has applied restrictions limiting the use cases of applications that can request whitelisting (, but the only way for a developer of consumer applications to whitelist an app is to prompt the user to do so through the battery optimization UI (Settings --> Battery --> Battery Optimization).

Enterprise developers may wish to whitelist their applications without interaction from the user, but there are no current plans for Zebra to expose this feature during staging. An application can be whitelisted using an adb command:

adb shell dumpsys deviceidle whitelist +com.yourcompany.yourapp

An application can be removed from the whitelist with the following command:

adb shell dumpsys deviceidle whitelist -com.yourcompany.yourapp


Zatar client

Zebra’s Internet of Things Cloud service, known as Zatar (, offers a client for Android devices. The Zatar solution is built on  ARM’s mBed client, which uses Lightweight M2M on CoAP as the protocol for ‘things’ (in this case our Android device) to communicate with the managing server. As Zebra recommended earlier for Pushy, if you wish to run the Zatar client (or any Android client using an SDK from either mBed or Zatar) it is required to whitelist your application in order for it to run successfully during Doze mode. The Zatar Android application will be incommunicado during Doze mode or App Standby unless explicitly whitelisted.


Android ‘N’ changes

Though the changes introduced by Google in Android Nougat are by definition outside the scope of this document, it is worth noting that Doze mode has received several enhancements in Android N. The newer version of Doze mode has two phases of system activity restrictions, and the requirement for a device to be stationary to enter Doze mode has been removed. Since this is an area Google is continuing to enhance, Zebra recommends following Google’s best practises for application development for Doze mode wherever possible to help ensure future-proofing.


Android for the Enterprise

Google’s drive toward Android adoption in the Enterprise, formally known as “Android for Work” but now simply incorporated under the Android umbrella, is a suite of solutions from Google to help manage devices  and applications, augment overall security, and support an increasing number of enterprise-focused use cases. These include BYOD scenarios, Kiosk mode and others. Google started including such functionality in Android L, and with each new desert flavour has added new features, this is true of Marshmallow and will continue to be true for Android Nougat and beyond.


Although the specifics of what Android for the Enterprise means for your organization is outside the scope of this document, administrators are free to leverage Google tools to either replace or complement Zebra’s tools, which share some of the same functionality. For example, Zebra’s Enterprise Home Screen shares functionality with Android task locking. It is important to note that Zebra devices do not currently support multiple user profiles on the same device, so enterprise workflows that depend on this (e.g. COPE) will be unavailable, limiting administrators to COSU use cases (


For more information on Android in the Enterprise, please refer to Google’s landing page ( or Zebra’s future literature on integrating Android enterprise features with your solution.


New Copy / Paste and sharing features

The Android copy / paste experience has gone through a re-design between Android L and M.



Copy / paste experience on Android L

Copy / paste experience on Android M


On KitKat devices, the copy / paste and sharing experience can be fully controlled by the UI Manager Clipboard feature. Disabling the ClipBoard through the UI Manager will entirely prevent user access to the copy / paste / share menu.

On Lollipop devices, the behavior differs depending on the type of text being selected. A user long-pressing on a text field marked as textIsSelectable ( (for example a phone number in the contacts app) will not be able to access the clipboard. A user long-pressing in a more complex renderer (e.g. the Webview or mail client) will be shown the copy / paste / share toolbar. And though the copy and paste buttons are non-functional, the user is still able to share and ‘web search’ for any highlighted term.

On Android Marshmallow devices, the look and feel of copy / paste has changed to a floating toolbar with some additional functionality for language translation and integration with Google Now for GMS devices. No new functions have been added to MX to restrict these features.

Administrators wishing to restrict access to these additional toolbar features can make use of the MX AppManager to prevent the specific Google packages from providing this functionality. For example, disabling will remove the  ‘Search’ and ‘Assist’ options but has the side effect of blocking all Google Now integration on the device.


Access to hardware identifiers

As described in Google’s official changelist for Android M ( ), calls to get the Wi-Fi ( ) or Bluetooth MAC address ( ) will return the hardcoded value “02:00:00:00:00:00” to protect device security. This is true when running on all Android devices with API level 23 or above, regardless of the target SDK of the application.

Zebra has no plans to allow application developers to circumvent this restriction since a negligible proportion of applications would be impacted by this change.

Developers requiring a way to uniquely identify devices may consider using the ANDROID_ID ( or implementing a software solution, the latter protecting against future Android changes in this area.

One possible reason developers could require the Bluetooth MAC address would be if they are targeting a ‘scan-and-pair’ use case with the Zebra RS507 or RS6000 scanners and creating their own pairing app; these peripherals connect as a BT slave by scanning a barcode presented on the mobile device screen. Zebra already recommends using the built-in application ‘Bluetooth pairing utility’ to achieve this rather than trying to develop this capability within your own application. In the case of the RS6000, it is further recommended that tap-and-pair be the preferred method of connection, where possible.



Prior to Android M, whether  NFC was enabled out of the box would have depended on the specific Zebra device you were deploying. It was therefore a best practice during device staging to specify whether you wanted NFC on or off.  This can be configured in the Wireless Usage portion of StageNow or with the MX Wireless manager ( ).

Starting in Android M, Google has mandated that NFC-capable devices ship with NFC enabled. Though strictly mandated only for GMS devices, Zebra will take a common approach to NFC on both our GMS and non-GMS device variants wherever NFC hardware is present.

However, it remains a best practice to avoid reliance on the availability of NFC in your application, even though an NFC-capable device will have it enabled out of the box. Zebra recommends that you should continue to specify the desired NFC state during staging and check that the NFC adapter is enabled prior to use:

NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);

NfcAdapter adapter = manager.getDefaultAdapter();

if (adapter != null && adapter.isEnabled()) {

  // adapter exists and is enabled.



Adoptable storage

Starting with Android M, Google has introduced “adoptable storage,” whereby external storage devices can be ‘adopted’ and behave like internal storage to store applications, application data and media. This opens up a slew of enhanced use cases for the enterprise. For example:

        • Without having to separately encrypt the SD card:
          • Secure offline access to video tutorials for field mobility workers
          • Secure offline access to large product databases or additional application content


Adoptable storage is not suitable if you have a class 2, 4 or 6 card, or plan to swap your card between devices, since swapping necessitates re-formatting the card therefore loss of data.


Please note that there are a number of overlaps between adoptable storage and the Encrypt Manager (, discussed in the Encryption section.


Several consumer manufacturers do not currently support adoptable storage on their Marshmallow devices, citing potential confusion. But this feature is fully supported on Zebra Marshmallow devices.


To enable adoptable storage on your device, go to Settings, Storage & USB, Portable Storage (Volume), More Options, Settings, Format as internal.



UI to format SD card as adoptable storage


Once the storage is formatted, you are given the option to migrate data to the new storage, potentially freeing up space on the original internal storage. Unfortunately, there is currently no way to adopt an installed SD card as part of your provisioning process through StageNow or EMDK.

Adopted storage will be encrypted and formatted to appear identical to internal storage but as a result is not transferrable to another device. Although the use of adopted storage obviously depends on the presence of an SD card in the mobile device, both Zebra Android M launch devices (the TC51 and TC75x) have this feature.


It is always a best practice when developing applications to not hardcode file paths. Adoptable storage makes this particularly important because applications can be moved between internal and external storage, causing paths to change dynamically. Zebra therefore recommends that developers avoid hard-coded file paths and the storage of fully qualified file paths that were previously built into code. For a full list of APIs to use when building file paths, please refer to the Google development documentation for this feature (



Starting with Android M, Google has made full disk encryption mandatory on all new devices. As a Google partner, all Zebra devices running Android M will ship with full disk encryption enabled.

The typical developer targeting an Android M device will see very few differences, though applications implementing cryptography may be impacted by the move from OpenSSL to BoringSSL ( ) or the change to the default Javax cypto cipher provider (


Interaction between full disk encryption and Encrypt Manager

If the application makes use of the MX Encrypt Manager (, there are additional considerations:

        • There is an overlap between the Encrypt Manager’s full storage card encryption functionality ( and adoptable storage. Adopted storage cards will not require encrypting separately since they are encrypted by default during adoption. SD cards that are used as portable storage, (i.e. not adopted) are still subject to separate encryption by the Encrypt Manager
          • Attempting to encrypt an adopted SD card with the Encrypt manager will result in an error, “Cannot Encrypt SD : Mount SD to Encrypt”
        • Encrypt Manager’s folder encryption mode allows any number of Encrypted File Systems (EFSs) to be created, but isrestricted to non-encrypted storage only. Since internal storage is encrypted, it is only possible to create EFSs on non-adopted SD cards that are not themselves encrypted by the Encryption Manager.
        • Calls to retrieve the SD card encryption state through Encryption Manager will return true only if the SD card was encrypted through the Encryption Manager. If an SD card is encrypted by the Android OS during adoption, then SDCardOperation will return 0 (false).


Interaction between full disk encryption and Power Manager

The MX Power Manager ( gives applications and administrators the ability to update the device and to perform several different types of reset. The EMDK documentation goes into detail, but in summary the types of reset are shown in the table below. Please note that adopted storage cards will be made “unadopted” during a full device wipe, factory reset or enterprise reset.


Reset action



Normal reboot; same as holding the power key on your phone and choosing reboot.

Full Device Wipe

Wipes everything from the device including all types of storage cards (emulated, physical and adopted), the /data partition and the /enterprise partition. GMS devices will display the setup wizard after reset.

Confusingly, the message ‘Performing Factory Reset’ might appear prior to shutting down your device; this is due to a naming inconsistency between the Power Manager and the Android OS that will be addressed in the future.

Factory Reset

Wipes the /data and /enterprise partitions. Since emulated storage cards are stored on the /data partition in Zebra Android M devices, a Factory reset also will erase the emulated storage card along with any adopted storage card, but will not erase physical storage cards.

Confusingly, the message ‘Performing Data Reset’ might appear prior to shutting down.

Enterprise Reset

Retains all data on the /enterprise partition, allowing configuration to be retained using the Persist Manager, ( DataWedge (, or any other application whose configuration relies on the /enterprise partition. The /data partition is wiped during an Enterprise reset, and since emulated storage cards are stored in the /data partition on Zebra Android M devices, these internal storage cards also will be erased along with any adopted storage card. External storage cards are not affected.


Another feature of the MX Power Manager is the ability to perform Operating System updates.

To perform an OS Update through the power manager on Android Lollipop or below, the associated zip file must be placed in a location that is unencrypted. With Android M and full disk encryption, this limits the locations from which the can be read. At the time of writing, there were no OSUpdate packages available for Marshmallow devices. When such an update becomes available, please consult the Power Manager documentation ( for details on how to perform an OS Update programmatically on a Marshmallow device.


To perform an OS update without relying on the EMDK or MX Power manager (i.e. manually) you can no longer just copy the update zip file to the emulated storage card as the bootloader will not be able to read the encrypted storage. You have two options:

        • Select the option to load the update from adb. Then, assuming you have all the correct device drivers and Android tools installed, use the adb sideload <>
        • Download the OS update zip file to an unencrypted, unadopted (portable) physical SD card inserted to the device and apply the update through the boot loader.

This technique also applies when flashing a new OS to your device, and is explained in the device quick start guide.


In addition to the manual method described above, performing OSUpdates via EMM or using StageNow's OSUpdate service has the option of using a fixed location to apply the update from, /data/tmp/public.


Interaction between the Power Manager and Google's Device Protection Features

"Device protection" is a security feature available on GMS devices that are associated with a Google account and have a screen lock enabled (e.g. PIN), it was introduced in Lollipop MR1 and is intended primarily to reduce the value of stolen devices by preventing the use of a device unless authorized by the known user.


Device protection is enabled automatically if a Google account & screen lock are added to the device during the set-up wizard but will not be enabled if only one or the other is applied.  After running the set-up wizard, device protection can be applied by assigning both a Google account and screen lock to the device.

   Device protection 1.png

Set-up wizard confirming device protection

With device protection enabled, Android's device manager can be used to remotely locate, lock and reset the device.  Whilst intended primarily for consumer devices there are obviously applications to enterprises looking for a free way to achieve wipe functionality with unmanaged deployments.  Android's device manager can also assign a screen lock to a previously unprotected device as long as that device had a Google account (therefore causing device protection to be enabled).


There are different types of reset for protected devices:


        • Untrusted factory resets mandate that the user re-enter the Google account and password previously associated with the device during a reset.  This ensures that the person resetting the device owns it and will help block stolen devices.  If multiple Google accounts were previously associated with the device then the credentials from any account are sufficient.
          • Examples of untrusted factory resets are resets from the Android device manager as well as any of the reset types invoked from the MX Power manager, as described above: Full Device Wipe, Factory Reset and Enterprise Reset.
            • This means that a protected device cannot be disassociated from a Google account through the Power Manager
          • The factory and enterprise reset packages available from Zebra support are also examples of untrusted resets.  If you need to clear Google's device protection features on your device and do not have access to the associated Google account then your device will need to be returned to Zebra for repair, in which case contact Zebra support.
          • Signing in with a Google account not previously associated with the device will result in an error and you will be asked to try again:

   Device protection 3.png

Error toast given for using an incorrect Google account


        • Trusted factory resets do not mandate the user re-enter any previously associated Google account information
          • Examples of trusted factory resets are those invoked from the device settings UI --> Backup & reset e.g. 'Enterprise Data Reset'.
          • During a trusted factory reset the set-up wizard will give you the option of enabling or disabling device protection (by specifying a Google account and screen lock).  Choosing not to apply either of these will result in the device no longer being protected:

   Device protection 2.png

Set-up wizard warning that you are not protecting the device.



New notification shade  and quick settings menu

Every iteration of Android has made either major or incremental updates to the pulldown notification shade and associated options. Android M introduces incremental updates to the major changes that were brought in for Lollipop and several options are available to Zebra developers to lock down access to this notification shade.


For Lollipop devices, Zebra introduced changes to the UI Manager related to the notification pull down that can be programmatically accessed through StageNow or the EMDK:


   L sections.png

   m sections.png

Configurable sections of notification pull-down on Android L

Very similar configurable sections of notification pull-down on Android M


Notification Pull Down (

When disabled it is not possible to drag the notification pull down at all. This section is colored blue in the diagrams above.

Notification (Icon) Settings (

When disabled, the gear icon is not shown in the notification pull down, highlighted in red in the diagrams above.

(Notification) Quick Settings (

When disabled, the ‘quick settings’ used to modify Wi-Fi, Airplane mode, location etc., are not shown to the user. This section is colored green in the diagrams above. Note that the quick settings option does not include the brightness control.

Similar functionality also is exposed through the Enterprise Home Screen application configuration parameter disable_statusbar_pulldown (which introduced support for Android M in version 2.5)


User account icon

On consumer versions of Android, the user icon shown in the top right-hand corner of the notification shade provides quick access to the different user accounts configured on the device. User accounts were officially added to consumer phones starting with Android 5.0 (Lollipop) but also were accessible on consumer Android back in 4.2. The focus of user accounts was on consumer use cases, such as sharing a tablet with multiple family members or a guest mode for a friend to borrow the device.

Android device “users” should not be confused with Enterprise Android profiles, and “users” are not available on Zebra Lollipop or KitKat devices. User accounts continue to be unavailable on Zebra Android devices running Marshmallow, and for this reason you will not see the account icon on your Zebra Marshmallow device. Multi-user mode cannot be enabled on Zebra devices without using unsupported tools or mechanisms, and there are no plans to implement multiple user accounts for Android Marshmallow at this time.


System UI tuner

Long-pressing on the Settings gear in Android M will unlock the ‘System UI Tuner,’ which presents an additional settings menu. This allows greater configuration of the Notification UI, such as configuring which Quick Settings icons are shown and modifying the UI that appears when the volume buttons are pressed.

There are two approaches to locking down this functionality:

        1. Disable the ability to long-press on the Settings gear in the first place by hiding it using the UI Manager’s Notification (Icon) Settings feature (
        2. A less elegant approach would be to restrict access to the device settings entirely using Enterprise Home Screen or MX AccessManager ( Note that it is not possible to specifically control the visibility of the “System UI Tuner” option.


Long press on notifications

On Marshmallow, if the user long-presses on an application notification they are presented with an information button . Clicking the information button will by default give access to the ‘App notifications,’ offering options to block or prioritize the notification.

Long-pressing on an application notification to bring up additional information has been present in Android since KitKat, and the MX AppManager introduced a property to “disable access to application info for all applications,” ( which locks down this and other related features. Unfortunately, this parameter of AppManager is not supported beyond KitKat. A related MX feature is the Settings Manager parameter ‘AccessAppsSection’ ( While this blocks ‘Apps’ access from the Settings UI and prevents the user from escaping the ‘App notification’ screen, long-pressing a notification will still bring up the ‘App notifications’ settings.

The only way to reliably block access to the ‘App notifications’ settings screen with MX is by using the Access Manager’s ‘system settings access’ parameter ( to prevent access to all but a small subset of settings.  You can disable the package using the Application Manager but doing so will give an ambiguous error to the user if they long press on the notification icon, "System UI has stopped" as opposed to the more informative error you get when using the recommended access manager, "OSX Admin has disabled app notifications".


   Device Notifications.png

App notification settings


Interaction with built-in and post-install applications

There are four types of applications that can run on your Zebra Marshmallow device:


1.    Applications from Google such as the Web browser, calculator, etc. These will have their Android Marshmallow variants present out of the box as you would expect, and the choice of applications will differ between the GMS and non-GMS device variants. For example, Google Maps will be available only on GMS devices.


2.    Applications from Zebra that are pre-installed from the factory. These include DataWedge, AppGallery, and depending on the specific device, perhaps an MDM agent or printing utility.

Less visible than the application updates will be an updated version of Zebra’s Mobility etensions Management Framework (MXMF) and OSX, Zebra’s eXtensions to the Android OS (completely unrelated to Apple’s OSX). You can find out your device’s versions of MXMF and OSX by going to Settings à About Phone/Device à SW components. Developers can access MX through EMDK and see which features are available for which MX configuration in the MX compatibility matrix (


3.    Applications from Zebra that are post-loaded onto the device. These applications are downloaded from Zebra’s support portal, and might require a license. These include Enterprise Browser and Enterprise Home Screen. The important differentiation here is that a user of a post-loaded application will need to ensure the version in use supports the version of Android being targeted. For example, Enterprise Home Screen (EHS) 2.5 is the most recent release at the time of writing and supports a single Marshmallow device, the TC51 ( Please note that in order to ensure maximum reliability and compatibility, these post-loaded applications are supported per device and not per Android version. For example, EHS 2.4 supported the WT6000 running Lollipop, but not the TC75 running Lollipop, which requires at least EHS 2.5 or later. Post-loaded applications will be updated to support new devices as close to that device’s launch date as possible.

Post-installed applications are treated as separate products and may document specific considerations for Android M development. For example, Enterprise Browser might choose to expose new features that are supported only on Android M, but such features are outside the scope of this document. Please consult individual product documentation for more information.


4.    Applications built by customers and partners: These are the applications that will be written by the likely audience of this technical note. Applications making programmatic use of enterprise value-add hardware such as the barcode scanner, notification beeper or payment capabilities will depend on Zebra’s EMDK, which is certified only for a specific list of devices for each release. For example, EMDK for Android 6.0  currently supports a single Marshmallow device (, the TC51. User applications targeting Marshmallow must utilize an EMDK variant that also supports Marshmallow. EMDK for Xamarin developers will have a similar experience, requiring at least EMDK for Xamarin 2.2, thefirst version with Marshmallow support (

Developers also need to take care that the features they include in their application are supported by the versions of OSX, MX and EMDK they are targeting as defined in the compatibility matrix ( The versions of MX and OSX on the device can be seen at Settings à About Phone à SW Components


If you are a developer, then you have no doubt heard of Progressive Web Apps (PWA).  If you are a hybrid or web developer, then you may be considering developing your next application as a PWA.  There are already some great resources online explaining exactly what PWAs are and how to get started writing your own so I won’t cover any of that here; the top results you’ll find will be Google’s overview , Google’s getting started guide and another good getting started blog from a Google engineer, all dating back to late 2015 just after Google announced the methodology at their IO conference.


So, after a year in the wild you would expect the technology to have matured a bit.  In this blog I will look at PWAs from an enterprise perspective and see if they a sensible choice for an enterprise application.


What is a Progressive Web App (PWA)?

The important point about PWAs is that they are not a single technology, PWA is an umbrella term to describe a development methodology that encompasses numerous characteristics.  From Google’s own definition these characteristics are:


Progressive, Responsive, Connectivity independent, App-like, Fresh, Safe, Discoverable, Re-engageable, Installable, Linkable.


At first glance the focus on consumer use cases is evident.  Consumer applications are concerned with the discoverability of their applications in app stores [Discoverable], are seeking their users to engage frequently with their apps to maximize add revenue [Re-engageable] and are seeking to overcome the installation barrier where most users are dissuaded from installing an application in the first place as it involves multiple steps (visit app store, click install, wait for download, open etc) [Installable].


There is substantial overlap however between enterprise use cases and progressive web apps: As we see tablets proliferate in the enterprise space then [Responsive] apps increase in importance; keeping the application fully server-based avoids the need to coordinate application updates across remote devices [Fresh] and being [Connectivity Independent] might finally deliver on the promises made but never quite realised by Application Cache in HTML5


Are Progressive Web Apps a good fit for Enterprise Development?

As mentioned in the previous section there are clear benefits for enterprise applications to use a subset of Progressive Web app functionality.


Let us assume the following use cases when developing an enterprise progressive web app:


  • We want to make use of service workers and cache so our application is available offline or during poor connectivity
  • We want to use the Web manifest to remove the browser UI and brand our application with the appropriate theme colour, splash screen & icons.
  • We do not want to rely on the end user installing the PWA themselves after being prompted by a mysterious Google heuristic.
  • The connection to our server will be over HTTPS in line with best practice, PWA mandating use of HTTPS is therefore not a problem.
  • We want our application to make use of push notifications


Critically here the enterprise requirement to not allow users to install progressive web apps themselves goes against the fundamental tenets of PWAs.  A primary use case of progressive web apps is that the end user will visit a mobile web site and then add that site to their device home screen, either after receiving a prompt or manually doing so through the browser menu. Adding the PWA to the home screen through any other technique is not supported by Google and further, we cannot prevent Google offering the installation popup to the user so long as our application meets the requirements of a PWA (i.e. it runs over HTTPS, has a service worker and has an application manifest).


Note: Although manually adding an application to the home screen is not officially supported, see the end of this blog for a discussion of how that might be achieved.


In conclusion

Progressive web applications are not suitable for Enterprise Development because they put the role of application management solely in the hands of the end user, bypassing any IT management solution.  By disallowing user-centric application management we also lose the branding benefits of being installable (icons on the home screen and a custom splash screen) so a manifest is also no longer required.


Being an umbrella term however we can choose to leverage those aspects of Progressive web applications which offer potential value to the Enterprise:

  • Service workers
  • Push notifications
  • Server-based application logic


Are Progressive Web Apps supported on Enterprise Devices?

As mentioned in the previous section, an end to end PWA solution is not applicable for Enterprise applications but we will leverage the best of what PWAs have to offer for our Enterprise use cases, specifically:


  • Service Workers:   Bringing together previous functionality offered by ‘Web workers’ and ‘Application Cache’, Service workers seek to make an app function in a partially connected environment.


  • Push notifications:  Making use of service workers’ background processing, push notifications offer a platform agnostic notification mechanism independent of Google / Firebase cloud messaging.


  • HTTPS and server-based application logic:  Fundamental to the idea of a ‘web app’ is to ensure the latest version of your application is available on your device in a secure fashion.


Support for service workers and push notifications are delivered through Chromium and are therefore dependant on the webview being used.


A Chromium Blog from late 2014 states that Service Workers were introduced in Chromium version 40 however as with any software development I suspect the true level of support has been enhanced over time.  This blog is a good resource to track Service Worker status across the different versions of Chromium.


Which webview is in use can become confusing so please see below:


Chrome for Android: GMS devices will have Chrome for Android pre-installed as part of Google services along with other Google value adds such as the Play Store, location services etc. Chrome for Android ( can be updated via the play store and is built on the Chromium open source project.  There are a number of variants present in the play store supporting different versions of Chromium e.g. Chrome Canary & Chrome Beta.  Importantly, you will not find Chrome for Android on non-GMS devices or be able to install it in a supported manner.


Android Browser: This will be used as the rendering engine for natively built applications that expose a webview to the user, for example Enterprise Browser and by default with Ionic, Cordova and PhoneGap.  The Android Browser also has a browser UI which will be the only browser present by default on non-GMS devices.  For enterprise GMS devices, it is conceivable that you would have two browsers: Chrome for Android and the Android Browser.  Prior to Android 5.0 (Lollipop) the Android Browser version was not independently updatable and required the whole Android OS to be updated. From Android 5.0 onwards the Android Browser is updatable through the Google Play Store under “Android System WebView” so a more recent Chromium version can be supported.  Android Browser tends to lag slightly behind Chrome for Android in terms of the version of Chromium supported.


Crosswalk: This popular third party browser view is also built on Chromium so will support service workers and push notifications. Crosswalk is popular amongst Enterprise developers as it provides a consistent and known webview instead of having to worry about which versions of Android Browser or Chrome are present on the device.  Developers of Cordova based applications may choose to use Crosswalk and there are tentative plans to add Crosswalk support to Enterprise Browser in a future version.


Opera: A third party browser built on Chromium.  Opera does not ship by default on any Zebra device but is an option for app development as it claims support for progressive web applications.  Opera could be a replacement for Chrome for Android with one possible use case being the application needs to run on a non-GMS device and the customer has side-loaded Opera onto devices as the default browser.


Is it supported on my device?

The best way to check if Service Workers or the Push API are supported on your target devices is to use the website ‘’:


ServiceWorkers / Cache:


Push API:


Bearing in mind you are interested in either ‘Android Browser’ or ‘Chrome for Android’, depending on how you are targeting your application.


One limitation of the site is it only shows results for the latest version of Chromium supported by the browser.  For example you might have a non-GMS Lollipop device whose ‘Android Browser’ is not up to date with the latest ‘Android System WebView’.  In this instance, it is helpful to use which will tell you the version of Chromium being run.


Code solutions to check for the presence of the JavaScript features would be to test as follows:


if ('serviceWorker' in navigator) {  console.log(‘service workers supported’);}
if ('PushManager' in window) { console.log(‘push messaging supported’);} 


Accessing Enterprise APIs

If you are writing an application to run on Enterprise devices then it is very likely you need to make use of enterprise hardware such as the barcode scanner, Bluetooth payment solution or NFC.

There are a number of ways to achieve this through a web app (though technically if you are using hardware APIs this could be classified as a hybrid application).


Enterprise Browser (EB)

Enterprise Browser is the Zebra recommended solution for developing web-based or hybrid applications.  As previously mentioned the webview in which your EB application is running is based on the Android Browser and therefore on Lollipop devices or above you should expect to be able to make use of service workers but not push notifications.  This is because at the time of writing Push Messaging is not supported in the Android Browser.


As well as many other features Enterprise Browser includes an “eb” JavaScript namespace offering JavaScript APIs for barcode scanning, NFC and much more.


Note that there are tentative plans for Enterprise Browser to more thoroughly flesh out which PWA features are supported on which devices in their documentation and samples.



DataWedge is a powerful service running on every Zebra device which offers a zero-code method to integrate with the device hardware.  To use DataWedge you define ‘profiles’ which describe how to control the hardware when specified applications come to the foreground, for example you can enable the barcode scanner when your application is launched.  Data would be returned to the application in the form of keystrokes, so scanning a barcode with the cursor in a text box would result in the text box being populated with the decoded data.


One advantage of DataWedge is it is able to run with any application being in the foreground, including Chrome for Android.  Since Chrome for Android supports the push API (unlike the ‘Android Browser’ at the time of writing) it would be possible to write a web application running in Chrome and utilising both push notifications and barcode scanning.


When defining the application to be associated with the Datawedge profile you would choose  The Chrome activity to choose is less obvious, if you were developing a true Progressive Web Application then the activity would look something like but for a web-app just running in a Chrome tab it might be safest to specify * for the activity.


To view a list of current running activities you can run

$adb shell dumpsys activity


Custom proxy activity

Though a bit more work, it would be possible to interface with the device hardware by writing a custom android application which would act as a proxy between the web application and the native APIs.

The proxy application would expose some custom defined URI scheme which could then be invoked from the browser, similar to how clicking a <a href=”tel:xxxx”>dial</a> link will bring up the Android phone dialer.  Rather than dial a number however the proxy application could use native APIs such as the EMDK for Android to perform any action e.g. integrate with a Bluetooth payment peripheral.


Note however that this communication would only be one way, the options for returning data back to the calling web-app are limited and would require some ingenuity.


The linked stack overflow question is relevant to this scenario.



An Aside: Provisioning a PWA home screen icon

As mentioned earlier the only officially supported techniques for adding a PWA icon to the device home screen are initiated by the device user, either the user selects the relevant menu item from the browser menu or they give a positive response to a popup presented to them by Chrome after some Google heuristic determines they have been interacting with the web app sufficiently.


It would be nice if it were possible to have greater control over whether or not those icons are placed on the home screen and ideally provision a device so the Progressive Web Apps are already present without the user having to interact with the application at all.


It is possible to create a shortcut on the home screen using the undocumented INSTALL_SHORTCUT action but whilst creating a shortcut to a URL is straight forward, the intent to launch a progressive web app is more complicated (containing the application icon amongst other details).  The intent which we need to store in this shortcut and defines the PWA is undocumented but we can find out the details of shortcuts on the home screen using the technique detailed here.


Unfortunately, my attempts to reconstitute the Intent required to launch the PWA were unsuccessful. Invoking the intent directly from adb produced an unresolvable permission error and attempting to insert the Intent into a shortcut proved troublesome.


After a few hours of trying I did not pursue this avenue any further given the completely unsupported nature of adding shortcuts to the home screen on Android.  Your typical developer would not want to rely on this functionality continuing to work moving forward, further, there are currently no plans by Zebra to offer shortcut installation as part of their MX suite or Enterprise Home Screen.

Update - April 2017


This blog received a major overhaul in April 2017 to transition away from the previously used 3rd party plugins and demonstrate the use of the recent DataWedge 6.2 APIs.


DataWedge Intent Interface

DataWedge is a value-add of all Zebra Technologies devices (formally Symbol and Motorola Solutions) that allows barcode capture and configuration without the need to write any code.  This application will demonstrate how to use Android intents to add DataWedge scanning functionality to your application


Quick Start - Getting this Demo running


>git clone
>cd DataWedgeCordova
>cordova platform add android
Plug in Zebra device
Follow instructions under "Configuring Datawedge" (below)
>cordova run android
Scan a barcode


Getting Started

This section walks through the steps to create a new Cordova application that utilises DataWedge for scanning.


Create a cordova application that will run on Android

cordova create DataWedgeCordova com.zebra.datawedgecordova DataWedgeCordova
cordova platform android


We will use a 3rd party plugin to handle sending and receiving Intents to the DataWedge service.  Any plugin capable of sending or receiving generic intents and interpreting the extra bundle into JSON should work:


cordova plugin add 



Note that a previous version of this blog used different 3rd party plugins which have since been deprecated.  I wrote my own generic plugin to handle intents and released it under MIT to aid customers who wish to integrate DataWedge and Cordova but this should not be considered supported software by Zebra Technologies


Configuring Datawedge

DataWedge can be configured to send intents whenever it scans barcodes.  More detailed help is available at the official documentation but for the purposes of this demo I will include the pertinent steps.  There are more sophisticated ways to configure DataWedge but this section will cover the basics.


  • Create a new DataWedge profile (Applications --> DataWedge --> Menu --> New Profile).  This will be the profile that will be active when our Cordova application is in the foreground.  Give it a name e.g. DataWedgeCordova and click into it to configure.
  • The next step requires our Cordova application to have previously run on the device so if you have not already done so, `cordova run android`
  • Back in DataWedge configuration associate the Cordova application with our DW profile


  • Scroll down to the Intent Output section of DW configuration and enable intents to start our activity:
    • Intent Action: com.zebra.datawedgecordova.ACTION
    • Intent Category: leave blank
    • Intent delivery: Broadcast intent




Add Code to the Cordova application

Now to hook up our logic to listen for and send intents.


Listening for intents

Since we configured DataWedge to send barcode data to our application via an implicit broadcast intent we can use the 3rd party plugin to register a broadcast receiver:

  filterActions: [
  filterCategories: [
   function(intent) {
   //  Broadcast received
   console.log('Received Intent: ' + JSON.stringify(intent.extras));
   if (intent.extras["com.symbol.datawedge.data_string"] != null)
   document.getElementById('broadcastData').innerHTML = "Scan: " + intent.extras["com.symbol.datawedge.data_string"];



And in index.html


<div class="event" id="broadcastData"></div>


Sending intents

DataWedge supports an intent based API documented here. The API is somewhat limited but supports initiating the scanner via software (simulating a trigger press), disabling the scanner entirely and various DataWedge profile operations.  We'll be adding features to our application to simulate a trigger press and disable / enable the scanner through that Intent interface:


To simulate a trigger press:

  action: 'com.symbol.datawedge.api.ACTION_SOFTSCANTRIGGER', 
  extras: {
   'com.symbol.datawedge.api.EXTRA_PARAMETER': 'TOGGLE_SCANNING'
   function() {}, 
   function() {}


To disable the scanner:

  action: 'com.symbol.datawedge.api.ACTION_SCANNERINPUTPLUGIN', 
  extras: {
   'com.symbol.datawedge.api.EXTRA_PARAMETER': 'DISABLE_PLUGIN'
   function() {}, 
   function() {}


And hook up our logic to the UI:


document.getElementById("scanButton").addEventListener("click", startSoftTrigger);
document.getElementById("disableScanningButton").addEventListener("click", disableEnableScanning);


Now deploy & launch your app.  You are able to scan barcodes and exercise the functionality:





DataWedge versions

As DataWedge continues to evolve its capabilities continue to be enhanced. At the time of writing there are two different API levels for DataWedge, 6.2 and pre-6.2, as documented here. Future updates will continue to enhance datawedge but the same principles should apply to any updated intent API, that it can be accessed through 3rd party Cordova plugins.



This technique for adding scanning capabilities to a Cordova application represents the most generic possible solution.  We appreciate your developer feedback:

  • Would you prefer a dedicated Cordova plugin for Javascript?
  • Would you like to access EMDK profile functionality through Cordova?
  • Would you rather a dedicated Javascript interface as opposed to relying on third party plugins?
  • Are you interested in JavaScript development outside of Cordova e.g. ReactNative or NativeScript for your Enterprise application


Please feel free to raise github issues on the repository or post comments to this blog.



Jet Brains and Google recently announced a security update for IntelliJ-based IDEs to patch RPC vulnerabilities with the built-in web server.  Android Studio is based on IntelliJ so the advice from Google is to update your version of Android Studio.


There’s a good press release on the topic here:


The latest release of EMDK for Android is 4.0 which states support for Android Studio 1.0.1. Obviously this version is reasonably old and most developers will already be using a more recent version of Android Studio, either 1.5.x, 2.0.x or 2.1.x.


Android Studio 1.x


Developers who wish to continue on the 1.x line will need to upgrade to Android Studio 1.5.2.  Google have released instructions on how to do this here:, the official documented update process will cause you to lose EMDK integration from the Android Studio IDE.


Android Studio 2.1.x


Google actually “highly recommend” moving to Android Studio 2.1.1 and any developer wishing to do so can use the internal Android Studio update mechanism.  However during an automatic update you may see one of the following dialogs:



Therefore updating Android Studio using the built in update mechanism will cause you to lose EMDK integration.


Long story short… Re-Integrating EMDK with Android Studio


So, even if you are upgrading to Android Studio 1.5.2 or 2.1.1 you will lose EMDK integration with Android Studio and your ability to easily create applications for Zebra devices.


In order to Re-integrate EMDK 4.0 with your IDE please perform the following steps which apply equally to both Windows and Mac:

  1. Uninstall your existing EMDK for Android (it’s fine to leave EMDK for Xamarin installed if you are using both)
  2. Ensure Android Studio is closed
  3. Re-install EMDK for Android
  4. You may find that after upgrading, your EMDK based project fails to build with Gradle errors saying that the EMDK SDK cannot be found, if this is the case then please follow the steps documented at which describes selecting the Compile Sdk version.


Yes, the software equivalent of "turn it off and on again"!

The problem

Many of our Zebra mobile computers are shipped without Google Mobile Services (GMS) installed and these are referred to as “Android Open Source Platform” or AOSP devices. There are very good reasons to choose AOSP over GMS devices but customers doing so lose out on a wealth of Google provided services, most notably Maps, Location and push messaging.


Push Messaging is the ability to send messages to mobile devices and have them near instantly received.  It is almost exclusively implemented by Google Cloud Messaging (GCM) on Android and unfortunately for customers with AOSP Android devices this means that most push implementations will not work for them.  For example Pushlets, Azure push, Amazon notification system, PhoneGap push and many others are all built on top of GCM.


This blog is concerned exclusively with comparing like-for-like alternatives for GCM downstream messaging.  Other synchronization solutions exist that work on AOSP like FireBase which will synchronize your data against a server or PubNub whose publish / subscribe model is ideally suited for device to device communication.  If you are writing a new application from scratch then your requirements will determine the correct messaging solution to use.


The customer’s choice for an alternative to GCM on AOSP devices is very limited:

  1. RhoConnect Push
  3. Building a custom solution from third party components, most commonly MQTT with some combination of RabbitMQ or Mosquito.


RhoConnect Push is only officially supported for applications built with the Rho framework so will not be an option for most deployments.


Building a custom solution, whilst good in theory is a large barrier to adoption and prohibitive to many customers.


Enter, a third party push solution that runs well on both AOSP & GMS devices and provides a realistic alternative to GMS in the majority of deployments



The architecture for Pushy and GCM is nearly identical, as shown in the following diagram:


push workflow.png


  1. The Android device requests a unique device ID from the push service
  2. Once registered, the push service issues a unique ID to the device
  3. After receiving the ID, the device will send this ID to the application server
  4. The device ID should be stored for later use.
  5. Whenever a push notification is required, the application server sends a message to the push service along with the device ID and application API key.
  6. The push service delivers the message to the specified device.


What is


  • A replacement for GCM downstream messaging
  • A way to send a simple message from a server to a specific device
  • A way to receive the push message on the device and act accordingly
  • A hosted solution exposing a REST API
  • A very similar user experience to GCM or APNS (Apple Push Notification Service)


What is not

  • Free, there is a small monthly cost associated with each active device
  • A replacement for GCM’s upstream messaging or XMPP connection servers.  If you need upstream messaging then you may wish to consider the previously mentioned PubNub




If you just want to experiment with a working sample you can download the sample app from the Google Play store or build the app from the source in github.

Once the application is running it will give you the device ID it received from the Pushy service (in this case 044fe97a779ba202ae54a9):




Send a test push message. As long as you have signed up for a account, the easiest way to do this is via the website, just enter the device ID and hit ‘SEND TEST PUSH’.  In a real deployment you will call a REST API from your application server similar to GCM downstream messaging.


Getting Started


First of all you need to create an account on the website, you can sign up for a developer trial for free which allows you to test deployments for up to 100 devices.  Once signed up you can create applications by going to the ‘Account’ tab, notice how you are given a unique API key for each application.

The Pushy website offers a great getting started guide here, it is organized into two workflows:

  1. Customers starting out with a new application
  2. Customers with an existing GCM implementation


Integrate the Pushy SDK


The Pushy SDK is available as a jar file and whilst it only exposes a small number of APIs to configure the server it nevertheless exposes enough to enable core push functionality. Copy the jar file to your Android project’s libs/ folder and ensure it is built into the application


Full instructions can be found on the Pushy website:

For Gradle, ensure the following is present in your build.gradle:


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])

Register Devices

The first client-side step in any push solution is for the device to register with the push server, in this case the Pushy push server.  This is handled by the Pushy API through a synchronous call:


// Acquire a unique registration ID for this device
String registrationId = Pushy.register(getApplicationContext());


Once you have a registration ID it needs to be sent to the application’s backend server.  Obviously since transferring the registration ID will involve a network call it is required to perform registration in a background thread.  The combination of device ID and application API key are used when sending push messages to uniquely address a specific application on a specific device

Again, the online Pushy documentation gives an example of device registration


Start listening and manifest changes

Having successfully registered the device, instruct the device to start listening to Push messages via the client API:




It is recommended to have this in the onCreate method of your main launcher activity.


Pushy requires additional manifest permissions, as follows:


<!-- Pushy Permissions - Added in v1.0.0 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<!-- Pushy Permissions - Added in v1.0.1 (optional) -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


As well as requiring changes to the manifest to register the receiver class, which will receive the push message.


All manifest changes as well as the API to start listening are thoroughly documented on the website with full source code.


Receiving messages


The class which will receive the push message needs to extend an Android BroadcastReceiver and is the class you registered in the previous section.  This class’ onReceive() method will be invoked regardless of whether your application is in the foreground or background:


package com.pushytest.testapp;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class PushReceiver extends BroadcastReceiver
    public void onReceive(Context context, Intent intent)
       Toast.makeText(context, “Received Push: “ + intent.getStringExtra("message"), Toast.LENGTH_LONG).show;


This is a much simplified version of the example given in the documentation for a broadcast receiver

Implementing / Updating the Backend


As previously mentioned, Pushy acts as the push service to ensure messages sent to devices are received successfully and as far as network conditions allow, quickly.

It remains necessary to implement application logic on the server to:

  • Have devices notify the application server of their device IDs and persist these IDs.
  • Associate device IDs with users, or some other user friendly way of identifying devices
  • Interface with the pushy service to send the required downstream messages.


Pushy has a number of sample code implementations that can be incorporated into existing application servers in PHP, Java and .NET.  Since Pushy exposes a REST API the call itself is just an HTTP post, for testing purposes anything that will send an HTTP POST can be used, personally I like the Chrome Postman extension


The raw HTTP Post is as follows:


POST /push?api_key=<YOUR_API_KEY>
Content-Type: application/json
Connection: close
Content-Length: 82

{"registration_ids":["a6345d0278adc55d3474f5"], "data":{"message":"Hello World!"}}

Integration with GCM

One of the main benefits of Pushy for many customers will be the ability to quickly update an existing GCM solution to leverage Pushy as the transport medium.  Pushy documentation stresses this ease of transition as each stage of implementation in thee guide is accompanied by a corresponding ‘GCM Migration’ section.

Register Devices



String registrationId = GoogleCloudMessaging.getInstance(context).register(SENDER_ID);


Replace with


String registrationId = Pushy.register(getApplicationContext());


Start listening and manifest changes









Receiving messages


Update the existing GCM broadcast receiver as follows:

  • Avoid checking the intent action for
  • Link the receiver class to the AndroidManifest.xml declaration

Sending a message from the application server


Replace with<YOUR_API_KEY>


Staging your device

In terms of delivering a Pushy enabled application to your device there are no special steps, the Pushy API is built into your Android APK so can be deployed by any MDM solution, manually loaded, delivered via the Play Store or AppGallery etc.

On the client Pushy leverages MQTT to listen for incoming push connections, it is therefore necessary to ensure port 1883 is opened and the application is able to communicate with the backend Pushy service Since communication is over HTTPS port 443 needs to also be open.


On Premises deployments

Whilst available as a hosted solution, Pushy does support on-premises deployments.  Customers interested in on-premises deployments are encouraged to contact Pushy support directly.

Filter Blog

By date:
By tag: