Skip navigation
All Places > Applications Prototype Lab > Blog > Author: mdeaton-esristaff


The Applications Prototype Lab was asked to create an app that would collect and record cellular signal strength at various locations around the new Jack and Laura Dangermond Preserve. Two of us did just that: my colleague Al Pascual wrote the iOS version, and I wrote the Android version.


Though we used very different approaches—some of them dictated by the differences between the two mobile platforms—the app performs the same basic function on each operating system. It very simply gathers the device's location and the strength of its cellular connection at specified time and space intervals, and saves those observations to a feature service layer hosted on ArcGIS Online.


Once the app was done, we realized that it could be adapted to collect more than just cell signal strength; it can save just about anything a mobile device is capable of detecting. So we’re making the source available to those interested in modifying it.


Note: it’s built to save results to a feature layer hosted on Unless you want to modify it to save to a different back-end storage mechanism, you’ll need to create and publish your own hosted feature layer in your ArcGIS Online organization.

Preparation: Create a hosted feature layer to hold the results

You'll need a hosted feature layer to hold the collected data. We’ve provided an empty template database to hold location, cell signal strength, and a few device details.

  1. Download the template file geodatabase here:
  2. Follow the instructions to publish it here:


iOS: how to use it

1. Requirements

- Fork and then clone the repo. Don't know how? Get started here.

- Build and run the project to create a single app containing all of the samples.

2. Settings

Go to device settings, find the app CellSignal in the list to change the feature service layer you've created and hosted. The User ID and password settings are for using the service services.

3. Features

The app needs to be running on the foreground to work, will measure the cell coverage and will send that information to your feature service or, when offline, store it in the device until, connection to the feature service is being restored. The user does not need to interact with the app, only needs to make sure the app is running on the foreground.

The chart will show a historical view of the measurements. The scale is from 0 to 4, depending on the cell bars received. A custom map can show the intended extent as well as a simple rendering of the data.

To change how we capture the cell service information, please refer to this function.

private func getSignalStrengthiOS11() -> Int {
   let application = UIApplication.shared
   if let statusBarView = application.value(forKey: "statusBar") as? UIView {

   for subbiew in statusBarView.subviews {

   if isiPhoneX() {

      return getSignalStrengthiPhoneX()

    } else {
      if subbiew.classForKeyedArchiver.debugDescription ==
            "Optional(UIStatusBarForegroundView)" {
     for subbiew2 in subbiew.subviews {

         if subbiew2.classForKeyedArchiver.debugDescription ==
               "Optional(UIStatusBarSignalStrengthItemView)" {

          let bars = subbiew2.value(forKey: "signalStrengthBars") as! Int
          return bars

return 0 //NO SERVICE

4. Source code

For more information and for the source code, see the GitHub repository here:


Android: how to use it

1. Requirements

  • Android Studio 3+
  • An Android device running Android 18 or above (JellyBean 4.3) and having GPS hardware

2. Installing and sideloading

This app will run on devices that are running Android 4.3 (the last version of "Jelly Bean") or above. It will only run on Google versions of Android--not on proprietary versions of Android, such as the Amazon Kindle Fire devices. If you're running Android 4.3 or later on a device that has the Google Play Store app, you should be able to run this. (Oh, you'll need a functional cell plan as well.)


One way to run the app is to build and run the source code in Android Studio and deploy it to a device connected to the development computer.


If you don’t want to build it, you can download the precompiled .apk available in the GitHub releases section; you'll need to install this app through an alternative process called "sideloading".


3. Settings

Tap the Feature Service URL item and enter the address of the feature service layer you've created and hosted. There are two settings affecting the logging frequency. You can set a distance between readings in meters and you can set a time between readings in seconds. Readings will be taken no more often than the combination of these settings. For example, a setting of ten meters and ten seconds means that the next reading won't be taken until the user has moved at least ten meters and at least ten seconds have passed. If you want to only limit readings by distance, you can set the seconds to zero. Please don't set both time and distance to zero.


The User ID and password settings are for using secured services. If you are using your own ArcGIS Enterprise Portal (not, and you want to log to a secured service, you'll need to enable enter your own portal's token generator URL into the Token Generator Service URL setting.


Start logging by tapping the switch control at the top of the settings page. You should see a fan-shaped icon (a little like the wifi icon) in the notification bar. That tells you that the app is logging readings in the background.


It will continue logging until you tap the switch control again to turn logging off. The notification item also displays the number of unsychronized local records. As the app gathers new readings, it will update a chart on the main activity showing the last fifteen signal strength readings.


You can turn the screen off or use other apps during logging, since it runs as a background service. An easy way to get back to the settings screen is to pull down the notification bar and tap the logger notification item. Features are logged to a local database, and then sent to the feature service when the internet is available.



4. Synchronization

There are three events that cause a synchronization:

  • There is a setting for the synchronization interval; the app will sync whenever that many minutes have passed;
  • When internet connectivity has been lost and then restored;
  • When the logging switch is turned off

5. Source code

For more information and for the source code, see the GitHub repository here:

I built this app to show some of the capabilities of the recently released ArcGIS Quartz Runtime 100.2.1 SDK for Android—specifically its 3D capabilities. The 3D and runtime teams have put in a lot of work to make 3D data and analyses run smoothly on the latest mobile devices.


What does it do?

Esri’s I3S specification covers three kinds of scene layers: 3D Objects, Integrated Meshes, and Point Clouds. Currently, 3D Objects and Integrated Meshes can be displayed in the Quartz runtime. The web scene this app loads by default shows examples of both those layer types.

The app uses a web scene ID to load a list of scene layers, background layers, and slides (3D bookmarks). You’ll find that web scene’s ID in the identifiers.xml source code file. If you want to open a different web scene than the default one, use the Open button in the toolbar to enter your credentials. It will then find out which web scenes your account owns and let you open one of those instead. Note that it will only show the web scenes you have created—not all the web scenes that others have created and made available to you.

The Bookmarks button will show a list of slides in the web scene; tapping one will take you to the slide location. The Layers button shows a checkbox list of all scene layers defined in the web scene.


Standard navigation

First, get familiar with panning, zooming, rotating, and tilting the display. The SDK uses the device’s GPU to accelerate graphics computation and make navigation smoother. You can find more information on supported out-of-the-box gestures and touches here:

This app’s tools can all be found under the rightmost toolbar icon; tap it and you will see a pop-up menu. Standard Navigation will disable any currently chosen tool and return the view to its standard, out-of-the-box navigation gestures as documented in the link above.


Measure tool

This tool is straightforward to use; activate it and tap a location. It calculates a distance and heading from your observation point in space to the location you tapped on the ground. The location and bearing are simple Pythagorean and trigonometric calculations; the point here was not about the calculations, but about using 3D graphics and symbols to display the results.


Line of Sight

Line of Sight and Viewshed are two new onscreen visibility analysis tools; there is detailed information on what that means here:

Line of Sight is simple to implement; just set a start point and an end point, and add the analysis overlay to the scene. Updating the analysis is no more difficult than updating the end point location.



The Viewshed analysis does some extra work beyond what the SDK provides. First, each analysis is limited to a 120° arc; each tap invokes three analyses for complete 360° coverage. I also wanted a put the user right in the middle of the analysis, as if they’re standing on the ground—and that’s what the zoom floating action button does.Once the camera moves down into the scene, the floating action button becomes a return button, which will take the camera back to its original point in space. There’s also a slider in the lower left of the screen which lets you interactively change the viewshed distance. You can use it to explore different visibility scenarios in different scenes; you might want to use a smaller value for dense urban areas or a much larger value for unimpeded rural landscapes.


I wanted to make the analysis experience more interactive by letting you watch the analysis move as you drag your finger around the screen. This can be an interesting exercise, but it uses the same gesture that’s normally used to pan the view. You may reach a point where you want to pan the view without having to go back into standard navigation mode first. If you long-press—tap and hold a finger down without moving it for a second or so—you should see a four-arrows icon show up underneath the compass. That means the view is now in pan mode, and the display will pan (instead of re-running the viewshed) until you lift your finger.


Sensor Navigation mode

Once I was in the shoes of an observer in the middle of a viewshed, I thought it would be fun if I could tilt and rotate the device itself to move the view—kind of like a physical viewport into a virtual scene. And that’s what Sensor Navigation mode does. It listens to the device’s gyroscopic sensors to know when you’ve moved the device, and it moves the scene accordingly. The downside with this mode is that it can request so much scene data that the device, network connection, or scene service may not be able to keep up.


Pivot lock

If you see a building or other feature of special interest, you can use Pivot Lock to focus on that location and rotate around it. Activate the tool, then tap or drag a point, and the view will begin to rotate around it. Return to standard navigation by tapping the floating action button. You can stop the rotation by tapping anywhere on the display; then you can tap or drag a new point to start again. This tool uses the SDK’s OrbitCameraController to provide this functionality without a lot of custom code.


Technical notes

All the tools extend the class. When one is selected, it’s just one line of code to set the new touch listener on the Scene View and let it take over responsibility for all touch gestures until a new tool is chosen.

While the manifest requires OpenGL ES 3.0 or above, that’s not a strict requirement of the runtime SDK (although that could possibly become a requirement in a future release). This will run on devices using OpenGL ES 2, but those devices are generally older and don’t have the GPU, memory, or processor power to run 3D apps smoothly anyway.

I did use a couple of open-source libraries that are licensed under the Apache 2.0 license.


The source code for this app is available in a public Github repo; find it at

Feel free to clone or fork the repo and use it as you like. Also, I’ll probably be making a one-time major update for the next release of the Esri SDK, as that release will probably make obsolete much of the custom web scene parsing code in the app.

What is it?

This ArcGIS Pro Add-in is a rebuild of an old Flex web application of mine; its intent is to answer the question “How far can I drive on a dollar worth of fuel?”. Notice the word “fuel”, because even passenger vehicles don’t run on just gasoline anymore; there are hybrids, diesels and electric vehicles out there. Fuel economy data for this application is taken from the United States Environmental Protection Agency, where you can also find information on their data and methodologies.


How to use it

Make sure you have ArcGIS Pro 1.4 or 1.4.1 installed.

  • Download the add-in file here (for ArcGIS Pro 1.4 or 1.4.1) or here (for ArcGIS Pro 2.0).
  • Double-click the add-in file to install it.
  • Start ArcGIS Pro; make sure to insert or open a map.
  • Click the “Miles Per Dollar” button on the Add-In pane.
  • Choose one to five vehicles and add them to the list.

The user interface makes you choose a year, make, model, and type, in that order.

The user interface makes you choose a year, make, model, and type, in that order.

  • Click “Start Analysis”, then click a point on the active map
  • Results are placed on the map as graphics

They’re ordered from highest to lowest efficiency (longest to shortest driving distance).

Results are ordered from highest to lowest efficiency

  • Click “Save Results” to save the analysis graphics to a feature class

All data about the vehicles and results are saved as attributes in the feature class.

All data about the vehicles and results are saved as attributes in the feature class


Technical details

First, here’s an important step you’ll probably need to take before you can use the Visual Studio project for ArcGIS Pro 1.4. My Pro 1.4.1 development machine has ArcGIS Pro installed on the E: drive, so the assemblies referenced in the project all have paths on that drive. You will probably need to run the “Pro Fix References” tool in Visual Studio before you can compile the project. My Pro 2.0 development machine has everything installed on C: and you’ll likely be fine using that version of the code.

Pro fix references tool


This is an SDK project, implemented as an add-in button and DockPane. Here are some of the patterns and techniques it uses.


  • MVVM control enabling/disabling based on state

I tried to guide the user as much as possible, hiding or disabling buttons and dropdowns that aren’t meant to be used at a given time. This is a standard MVVM tactic; you can see it in use in the ComboBox items in VehiclesPane.xaml; check out the {Binding} statements for the ComboBox IsEnabled properties; you’ll find the referenced properties and ValueConverters in VehiclesPaneViewModel.cs. The buttons are mostly bound to ICommand (delegate command) items defined in VehiclesPaneViewModel.cs; note the use of Boolean methods to enable or disable the buttons (CanAddSelectedVehicle(), CanStartSAAnalysis(), etc.).

  • Using a REST geoprocessing service

ArcGIS Pro documentation calls for creating and using a local *.ags file and using it to run geoprocessing services. In this case, I didn’t want to have to distribute such a file with the add-in, so I opted to make the HTTP calls directly from the .NET code. For simplicity, I made my GP service publicly shared, so I didn’t have to worry about getting authorization tokens first.


One complication I found is that not all geoprocessing parameters have .NET objects that can be populated and then serialized for HTTP execution. You’ll see some inline JSON string construction in the PerformAnalysis() method.

sStartLocParam = "{\"geometryType\":\"esriGeometryPoint\",\"features\":
   [{\"geometry\":" + sStartGeom + "}]}";

Application state is mostly represented in model-level properties and classes. The Start Analysis button isn’t enabled until there’s at least one vehicle in the SelectedVehicles list; Save Results isn’t enabled until there’s at least one analysis result in the Results list. That all worked fine off the bat, but I found that values for the Vehicle and Result classes weren’t showing up in text boxes and tooltips. Eventually, I discovered that these classes needed extra plumbing to make them notify the binding mechanisms when their values changed; changing their base type from object to PropertyChangedBase did the trick.

  • Programmatically invoking a custom MapTool on the user’s behalf

I wanted a simple, guided workflow: choose one or more vehicles, navigate to an area of interest, and then click a start location to run the analysis. After much searching, though, I found only one way to get a mouse click location on a map: through a MapTool.  These tools usually live as buttons on ArcGIS Pro’s toolbar—you mouse over, click it, and then click the map to do what needs doing. This kind of implementation would be awkward for the user, I thought: select some vehicles, then somehow know to go back to the toolbar to click a button up top to kick off the analysis? Instead, I opted not to provide a MapTool button, but rather to search for the undisplayed MapTool and invoke it from the Start Analysis button on the DockPane. You can find this logic in VehiclesPaneViewModel.cs in the StartSAAnalysis() method.

  • About the analysis service

The service that computes the drive areas is, basically, a Network Analyst service area operation. It uses an optimized hierarchy of street data for the United States only (since that’s the area for which we have gas price information). The add-in converts fuel economy and fuel price data to meters and sends those distances to the service as parameters. Once the service generates the drive area polygons, it also generates bounding circles around them; while I don’t currently use those circles, I may do so in the future.

Drive distance model

Next Steps

This idea could be extended. It might be useful to apply a color ramp to the saved feature class automatically, rather than letting ArcGIS Pro apply a random, single-color symbology.

I’ve considered extruding the polygons in 3D space as a more graphical way of viewing and comparing the results with each other. The REST geoprocessing service also returns minimum-bounding circles, which are currently ignored, but could also provide some 2D or 3D context for the results.

For purposes of exploring lots of analyses more quickly, I leave the Miles per Dollar analysis MapTool active after an analysis completes. Users of touchscreens, however, might want to pan or zoom once results are available. With the MapTool active, this initiates a new analysis, which probably isn’t what the user wants. An enhancement might check for a touch input device and activate the navigation tool after an analysis is complete.




For ArcGIS Pro 1.4/1.4.1:

For ArcGIS Pro 2.0:

Source code

There are two branches in this repo. “master” is the Visual Studio 2015 project and code for Pro version 1.4x. “Pro_2.0” is the Visual Studio 2017 project and code for Pro version 2.0.

What is it?

This is an add-in for ArcGIS Pro 1.4. It's a dockable pane that shows basic statistics and a histogram for any numeric attribute in your dataset.  It also offers a slider control for selecting and filtering map features on a range of those numeric values.

Add-in panel

Why build this?

Quite some time ago, I built a healthcare-oriented Flex app. It let you choose two to four attributes and set a numeric filtering criterion on each, using the drop-down control.

HealthIndicators Flex app side-by-side maps

Then the Summary Map button would produce a filtered map with the unioned results of those filters—like a logical "AND" operation. This facilitates exploration of your data set, helping you find, for example, places where diabetes rates are above average and also where uninsured rates are below average.


Now that Flex has come and gone, I wanted to take those capabilities—filtering with a specified range, combining filters together, viewing the data's histogram—to a new platform. Sporting an SDK for extensibility, ArcGIS Pro is Esri's premier desktop application, so I settled on an ArcGIS Pro add-in.


Pro histogram chart

Some searching indicated that all this desired functionality is already available in different places in ArcGIS Pro. A Histogram chart shows the mean and median and a histogram of how the data is distributed throughout its range. There are some pretty neat features here that mirror chart selections on the map and vice-versa. If you create ranges for one or more attributes, you can use the resulting range slider bars to define, apply, and combine filter criteria.


But I wanted all this functionality all together in one place, available with a minimal number of mouse-clicks and dialogs; so I built an add-in to offer it in an ArcGIS Pro DockPane.


To use it

If you want to try it out, here's how:

  1. Make sure you have ArcGIS Pro 1.4 or 1.4.1 installed.
  2. Download the add-in file here.
  3. Double-click the add-in file to install it.
  4. Start ArcGIS Pro and open a project that has a map and a layer with numeric attributes. Or you can download a sample project here.
  5. Click the "Query Helper" button in the add-ins tab.
  6. Select a map, layer, and field; use the track bar control to choose a range of values in that attribute.
  7. Click "Add Clause" and then "Apply Query" to filter the features on the map.
  8. You can add more fields and ranges to the SQL and apply them for an additive effect.
  9. You can also edit the SQL where clause in the text box if you want to explore your data more directly; if you enter an invalid SQL clause, the map result will be blank--just click Clear SQL and start again.

Add-in panel and map

Challenges and lessons learned while building it

To get started, I tried using the ArcGIS Pro DockPane template for Visual Studio 2015. That created an empty DockPane and button, but didn't give me the guidance I needed to work with the MVVM pattern built into the template. (You may also want to see this Microsoft document on the MVVM pattern.) So I ended up extending an existing Esri community sample that loads maps and bookmarks into a DockPane.


I ran into a few instructive challenges in the process, mostly involving helper libraries and controls, but also matters of display and output. usage exampleThere are lots of statistics libraries available for .NET. I was looking for something simple, reliable, and free. Some research led me to the package, which I ended up using for statistical computation and creating histogram ranks.

Chart control

Since there's no chart control bundled into .NET, I had to look for one—again, it needed to be freely available. Though documentation is minimal, I went with the WPF Extended Toolkit (available through Visual Studio via the NuGet package system). Discussion of the challenges of using this charting system could fill another blog post or several. I'll just say that Google is your friend here.

Decimal point precision

This add-in needs to work with all sorts of numbers, including floating point values with too many decimal places to display in the available on-screen space. I opted to use StringFormats for limiting displayed decimal places to three (although computations are still done on the original, unrounded values).

XAML design mode

I also needed a way to hide the statistics field and histogram when an attribute field wasn't yet chosen and there was no data to display. I did this with a ValueConverter. The suggested way to declare ValueConverters is as static resources in the XAML file; unfortunately, this led to another problem I still don't have a proper fix for. The resource declarations seem to confuse the visual editor into displaying only an error message. My workaround was to remove the static resource declarations for those rare occasions I wanted to use the design view; then pasting those declarations back in before building the project.

XAML static resources


Next steps

There's still more to be done. Now that I have a basic level of functionality, I want to add the different range-specification options available in the original Health Indicators Flex app: things like top/bottom X% and choosing a given range of percentages.

HealthIndicators range options




Sample data

Source (GitHub)


Filter Blog

By date: By tag: