{"id":2068762,"date":"2023-09-14T09:00:14","date_gmt":"2023-09-14T16:00:14","guid":{"rendered":"https:\/\/www.esri.com\/arcgis-blog\/?post_type=blog&#038;p=2068762"},"modified":"2024-04-12T01:15:24","modified_gmt":"2024-04-12T08:15:24","slug":"craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps","status":"publish","type":"blog","link":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps","title":{"rendered":"Craft your own dynamic entity data source for ArcGIS Maps SDKs for Native Apps"},"author":8512,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"closed","template":"","format":"standard","meta":{"_acf_changed":false,"_searchwp_excluded":""},"categories":[738191],"tags":[23451,23321,141132],"industry":[],"product":[761642,769142],"class_list":["post-2068762","blog","type-blog","status-publish","format-standard","hentry","category-developers","tag-arcgis-runtime","tag-real-time-data","tag-stream-service","product-platform","product-sdk-net"],"acf":{"authors":[{"ID":8512,"user_firstname":"Thad","user_lastname":"Tilton","nickname":"Thad Tilton","user_nicename":"ttilton","display_name":"Thad Tilton","user_email":"TTilton@esri.com","user_url":"","user_registered":"2018-11-05 21:12:45","user_description":"I'm a product engineer on the ArcGIS Maps SDKs for Native Apps team, where I help create and maintain developer guides and API reference documentation. I enjoy .NET programming, helping our customers solve problems, and exploring creative ways of using ArcGIS.","user_avatar":"<img alt='' src='https:\/\/secure.gravatar.com\/avatar\/ca357c472fe1cfc0327aad444d36ceff475526bff5e5afe118b7fba02dda2d14?s=96&#038;d=blank&#038;r=g' srcset='https:\/\/secure.gravatar.com\/avatar\/ca357c472fe1cfc0327aad444d36ceff475526bff5e5afe118b7fba02dda2d14?s=192&#038;d=blank&#038;r=g 2x' class='avatar avatar-96 photo' height='96' width='96' loading='lazy' decoding='async'\/>"}],"short_description":"You can create a custom dynamic entity data source to wrap a data feed for use in your ArcGIS Maps SDKs for Native Apps applications.","flexible_content":[{"acf_fc_layout":"content","content":"<p>If you\u2019ve developed an app using ArcGIS Maps SDK for Native Apps, then you\u2019ve probably worked with features and graphics. Have you met their\u00a0<a href=\"https:\/\/developers.arcgis.com\/documentation\/glossary\/geoelement\/\">geoelement\u00a0<\/a>cousin, dynamic entity? As part of the geoelement family, dynamic entities have attributes and geometry. They\u2019re used to represent observations from a data stream to enable some really cool real-time workflows like:<\/p>\n<ul>\n<li>Tracking moving vehicles, such as delivery vehicles, commercial airline traffic, public transit, or emergency responders.<\/li>\n<li>Monitoring information from stationary sensors, like weather stations, traffic sensors, or stream gauges.<\/li>\n<li>Sending and receiving notifications about point-in-time events, such as crime or accidents.<\/li>\n<\/ul>\n"},{"acf_fc_layout":"image","image":{"ID":2068782,"id":2068782,"title":"station-dc-update-flash","filename":"station-dc-update-flash.gif","filesize":2456025,"url":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-dc-update-flash.gif","link":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps\/station-dc-update-flash","alt":"Bike rental stations, read from a data feed, flash when updated.","author":"8512","description":"Dynamic entities representing bicycle rental stations flash when bikes are taken or returned.","caption":"Dynamic entities representing bicycle rental stations flash when bikes are taken or returned.","name":"station-dc-update-flash","status":"inherit","uploaded_to":2068762,"date":"2023-09-07 00:05:06","modified":"2023-09-07 00:06:57","menu_order":0,"mime_type":"image\/gif","type":"image","subtype":"gif","icon":"https:\/\/www.esri.com\/arcgis-blog\/wp-includes\/images\/media\/default.png","width":800,"height":400,"sizes":{"thumbnail":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-dc-update-flash-213x200.gif","thumbnail-width":213,"thumbnail-height":200,"medium":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-dc-update-flash.gif","medium-width":464,"medium-height":232,"medium_large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-dc-update-flash.gif","medium_large-width":768,"medium_large-height":384,"large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-dc-update-flash.gif","large-width":800,"large-height":400,"1536x1536":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-dc-update-flash.gif","1536x1536-width":800,"1536x1536-height":400,"2048x2048":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-dc-update-flash.gif","2048x2048-width":800,"2048x2048-height":400,"card_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-dc-update-flash.gif","card_image-width":800,"card_image-height":400,"wide_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-dc-update-flash.gif","wide_image-width":800,"wide_image-height":400}},"image_position":"center","orientation":"horizontal","hyperlink":""},{"acf_fc_layout":"sidebar","content":"<p>See the developer guide for information about dynamic entities in the Native Maps SDKs:\u00a0<a href=\"https:\/\/developers.arcgis.com\/java\/real-time\/work-with-dynamic-entities\/\">Java<\/a>\u00a0|\u00a0<a href=\"https:\/\/developers.arcgis.com\/kotlin\/real-time\/work-with-dynamic-entities\/\">Kotlin<\/a>\u00a0|\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/real-time\/work-with-dynamic-entities\/\">.NET<\/a>\u00a0|\u00a0<a href=\"https:\/\/developers.arcgis.com\/qt\/real-time\/work-with-dynamic-entities\/\">Qt<\/a>\u00a0|\u00a0<a href=\"https:\/\/developers.arcgis.com\/swift\/real-time\/work-with-dynamic-entities\/\">Swift<\/a>.<\/p>\n","image_reference":false,"layout":"standard","image_reference_figure":"","snippet":"","spotlight_name":"","section_title":"","position":"Right","spotlight_image":false},{"acf_fc_layout":"content","content":"<p><span style=\"font-size: 28; font-weight: bold;\">In this article,<\/span> I\u2019ll give an overview of dynamic entity data sources and step through the process of creating one. I\u2019ll use\u00a0<a href=\"https:\/\/github.com\/ThadT\/bike-rental-stations-maui\">a .NET MAUI example<\/a>\u00a0created using ArcGIS Maps SDK for .NET and C# to highlight these steps. While the code and some of the implementation details differ across Native Maps SDKs, the basic concepts are the same. If you\u2019re new to dynamic entities or want to simply work with them out-of-the-box, you might prefer my previous blog. See\u00a0<a href=\"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/create-real-time-apps-with-arcgis-maps-sdks-for-native-apps\/\">Eight essential real-time techniques with ArcGIS Maps SDKs for Native Apps<\/a> for a more general discussion. However, if you want to craft your own custom dynamic entity data source, read on!<\/p>\n<ul>\n<li><a href=\"#why_custom_datasource\">Why create a custom data source?<\/a><\/li>\n<li><a href=\"#example_bikes\">Example: Bike rental stations<\/a><\/li>\n<li><a href=\"#basic_steps\">Implementation steps<\/a><\/li>\n<li><a href=\"#summary\">Summary<\/a><\/li>\n<\/ul>\n<h3>It&#8217;s about to get real (time)<\/h3>\n<p>When working with dynamic entities, a great deal of work is managed by the dynamic entities API. A <a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.html\"><code>DynamicEntityDataSource<\/code><\/a> provides data (observations) as a data stream, delivering a constant series of updates. Once connected to such a data source, dynamic entities automatically update as new observations come from the stream. This information includes updated locations and attributes. Attributes describe the properties of each entity. For moving things, these may be speed, heading, or altitude. For our bike stations, attributes describe the available bike inventory. A dynamic entity layer from the data source can manage the display of dynamic entities on the map.<\/p>\n<p>The initial release of the dynamic entities API at version 200.1 only supported\u00a0<a href=\"https:\/\/enterprise.arcgis.com\/en\/server\/latest\/publish-services\/windows\/stream-services.htm\">ArcGIS stream services<\/a> as a data source. With the 200.2 release, however, Native Maps SDKs also support custom dynamic entity data sources. This gives you the ability to wrap just about any data feed as a <a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.html\"><code>DynamicEntityDataSource<\/code><\/a> for use in your app.<\/p>\n"},{"acf_fc_layout":"content","content":"<h2 id=\"why_custom_datasource\">Why create a custom data source?<\/h2>\n<p>Perhaps your app can use an existing ArcGIS stream service as a dynamic entity data source. If you have access to <a href=\"https:\/\/www.esri.com\/en-us\/arcgis\/products\/arcgis-geoevent-server\">ArcGIS GeoEvent Server<\/a>\u00a0or\u00a0<a href=\"https:\/\/doc.arcgis.com\/en\/iot\/get-started\/what-is-arcgis-velocity.htm\">ArcGIS Velocity<\/a>\u00a0you can easily create your own. In those cases, you may not benefit much from creating a custom dynamic entity data source. GeoEvent Server and ArcGIS Velocity both allow you to configure a data source using a variety of data feed formats. You can then expose the data as an ArcGIS stream service.\u00a0<a href=\"https:\/\/doc.arcgis.com\/en\/iot\/ingest\/what-is-a-feed-.htm\">Supported feed types<\/a>\u00a0include AWS, Azure, HTTP polling, and many more. If, however, you have a data feed that is not in a standard format or you cannot easily expose your feed with an ArcGIS stream service, a custom data source is a great option.<\/p>\n<h3>From zero to dynamic in five steps<\/h3>\n<p>OK &#8230; creating a custom dynamic entity data source might not be &#8220;simple&#8221;. Of course, the complexity involved depends on the nature of the data feed and your requirements. But, good news! Once you create your data source, it fits into the dynamic entities API to leverage additional functionality. For example, you can display it using a dynamic entities layer, get notifications for data updates, and manage the local data cache. For dynamic entities that move, a dynamic entity layer shows tracks of previous locations and has options for track display.<\/p>\n"},{"acf_fc_layout":"content","content":"<h2 id=\"example_bikes\">Example: Bike rental stations<\/h2>\n<p>I created a .NET MAUI app to illustrate a custom\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.html\"><code>DynamicEntityDataSource<\/code><\/a>. The app shows bike rental stations for a few major cities. These stations are, well, stationary, so you won\u2019t see anything \u201cdynamic\u201d about their locations on the map. Attributes like bike availability, however, are updated frequently, so these values are dynamic. The color of the stations indicates the number of bikes available. Station attributes show the last inventory update time and the change in available bikes (+\/-) since the previous update. The page shows a summary of available bikes for the entire city that updates as observations come in. The user can select favorite stations to quickly see inventory updates for those stations.<\/p>\n<p>When observations come in, corresponding stations flash red to indicate a bike left or blue to indicate a bike returned.<\/p>\n<p>The bike information comes from the\u00a0<a href=\"https:\/\/api.citybik.es\/v2\/\">CityBikes API<\/a>. This is a REST API that sends information in a JSON response. The app uses a timer to periodically request information from the service. It then deserializes the response into classes that represent the stations (point locations and relevant attributes).<\/p>\n<p>&nbsp;<\/p>\n"},{"acf_fc_layout":"image","image":{"ID":2068792,"id":2068792,"title":"bike-app-maui","filename":"bike-app-maui.png","filesize":404598,"url":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-app-maui.png","link":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps\/bike-app-maui","alt":"A multi-platform .NET MAUI app that shows bike availability at rental stations.","author":"8512","description":"","caption":"A multi-platform .NET MAUI app that shows bike availability at rental stations.","name":"bike-app-maui","status":"inherit","uploaded_to":2068762,"date":"2023-09-07 00:22:04","modified":"2023-09-12 17:08:10","menu_order":0,"mime_type":"image\/png","type":"image","subtype":"png","icon":"https:\/\/www.esri.com\/arcgis-blog\/wp-includes\/images\/media\/default.png","width":995,"height":606,"sizes":{"thumbnail":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-app-maui-213x200.png","thumbnail-width":213,"thumbnail-height":200,"medium":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-app-maui.png","medium-width":429,"medium-height":261,"medium_large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-app-maui.png","medium_large-width":768,"medium_large-height":468,"large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-app-maui.png","large-width":995,"large-height":606,"1536x1536":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-app-maui.png","1536x1536-width":995,"1536x1536-height":606,"2048x2048":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-app-maui.png","2048x2048-width":995,"2048x2048-height":606,"card_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-app-maui-763x465.png","card_image-width":763,"card_image-height":465,"wide_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-app-maui.png","wide_image-width":995,"wide_image-height":606}},"image_position":"center","orientation":"horizontal","hyperlink":"https:\/\/github.com\/ThadT\/bike-rental-stations-maui"},{"acf_fc_layout":"content","content":"<p><strong id=\"basic_steps\">To create a custom dynamic entity data source, follow these basic steps.<\/strong><\/p>\n<ol>\n<li><a href=\"#create_data_source_class\">Create a class for your custom data source<\/a> that derives from the ArcGIS Maps SDK <a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.html\"><code>DynamicEntityDataSource<\/code><\/a> base class<\/li>\n<li><a href=\"#connect_data_feed\">Connect to a data feed<\/a><\/li>\n<li><a href=\"#define_metadata\">Define and return metadata about your data source<\/a><\/li>\n<li><a href=\"#read_feed_data\">Implement logic to read data from the feed and add observations<\/a> Full disclosure: this step will likely be composed of several substeps (and cups of coffee)<\/li>\n<li><a href=\"#disconnect\">Clean up when the data source is disconnected<\/a><\/li>\n<\/ol>\n<p><strong>You can then consume your custom dynamic entity data source in your ArcGIS Maps SDK app.<\/strong><\/p>\n<ol>\n<li><a href=\"#create_instance\">Create an instance of your data source<\/a><\/li>\n<li><a href=\"#create_dynamicentitylayer\">Create a new <code>DynamicEntityLayer<\/code> to display the data source<\/a><\/li>\n<li><a href=\"#work_with_events\">Handle data source events to get update notifications<\/a><\/li>\n<\/ol>\n"},{"acf_fc_layout":"content","content":"<h2 id=\"create_data_source_class\">Create a class for your data source<\/h2>\n<p>Start by creating a new class to represent your dynamic entity data source. The class must inherit from the\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.html\"><code>DynamicEntityDataSource<\/code><\/a>\u00a0base class and override a handful of methods. I describe the details of these overrides in a bit. My class (<code>CityBikesDataSource<\/code>) consumes a data feed that shows available bikes for rental stations in some major cities.<\/p>\n<p>My class requests updates for a specified city at a specified interval. It has variables to store the CityBikes URL for the selected city and a timer (<a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.windows.threading.dispatchertimer?view=windowsdesktop-7.0\"><code>IDispatcherTimer<\/code><\/a>) to periodically get updates. I also store the city name and a dictionary of the last observations received. This allows me to evaluate the change in bike inventory between updates. These are all details specific to my implementation and could vary greatly on your data feed and use case.<\/p>\n<details>\n<summary><span style=\"color: purple; font-style: bold;\">\u2295\u00a0Show code &#8230;<\/span><\/summary>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\">  \r\n<span style=\"color: #0000ff;\">internal<\/span> <span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #2b91af;\">CityBikesDataSource<\/span> : DynamicEntityDataSource\r\n{\r\n    <span style=\"color: #008000;\">\/\/ Timer to request updates at a given interval.<\/span>\r\n    <span style=\"color: #0000ff;\">private<\/span> <span style=\"color: #0000ff;\">readonly<\/span> IDispatcherTimer _getBikeUpdatesTimer = Application.Current.Dispatcher.CreateTimer();\r\n    <span style=\"color: #008000;\">\/\/ REST endpoint for a city in the CityBikes API (http:\/\/api.citybik.es\/).<\/span>\r\n    <span style=\"color: #0000ff;\">private<\/span> <span style=\"color: #0000ff;\">readonly<\/span> <span style=\"color: #2b91af;\">string<\/span> _cityBikesUrl;\r\n    <span style=\"color: #008000;\">\/\/ Previous observations for bike stations (to evaluate change).<\/span>\r\n    <span style=\"color: #0000ff;\">private<\/span> <span style=\"color: #0000ff;\">readonly<\/span> Dictionary&lt;<span style=\"color: #2b91af;\">string<\/span>, Dictionary&lt;<span style=\"color: #2b91af;\">string<\/span>, <span style=\"color: #2b91af;\">object<\/span>&gt;&gt; _previousObservations = <span style=\"color: #0000ff;\">new<\/span>();\r\n    <span style=\"color: #008000;\">\/\/ Name of the city.<\/span>\r\n    <span style=\"color: #0000ff;\">private<\/span> <span style=\"color: #0000ff;\">readonly<\/span> <span style=\"color: #2b91af;\">string<\/span> _cityName;\r\n<\/pre>\n<\/div>\n<\/details>\n<p>In the constructor for my class, I accept values for the city name and URL (strings) and an update interval in seconds (int). I store those values in the appropriate variables and then define a function to run when the timer interval expires. The <code>PullBikeUpdates()<\/code> function contains the logic to send a request to the REST endpoint, deserialize the results, and add observations to the data source.<\/p>\n<details>\n<summary><span style=\"color: purple; font-style: bold;\">\u2295\u00a0Show code &#8230;<\/span><\/summary>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\">    <span style=\"color: #0000ff;\">public<\/span> CityBikesDataSource(<span style=\"color: #2b91af;\">string<\/span> cityName, <span style=\"color: #2b91af;\">string<\/span> cityBikesUrl,\r\n        <span style=\"color: #2b91af;\">int<\/span> updateIntervalSeconds)\r\n    {\r\n        <span style=\"color: #008000;\">\/\/ Store the name of the city.<\/span>\r\n        _cityName = cityName;\r\n        <span style=\"color: #008000;\">\/\/ Store the timer interval (how often to request updates from the URL).<\/span>\r\n        _getBikeUpdatesTimer.Interval = TimeSpan.FromSeconds(updateIntervalSeconds);\r\n        <span style=\"color: #008000;\">\/\/ URL for a specific city's bike rental stations.<\/span>\r\n        _cityBikesUrl = cityBikesUrl;\r\n        <span style=\"color: #008000;\">\/\/ Set the function that will run at each timer interval.<\/span>\r\n        _getBikeUpdatesTimer.Tick += (s, e) =&gt; _ = PullBikeUpdates();        \r\n    }\r\n<\/pre>\n<\/div>\n<\/details>\n<p>&nbsp;<\/p>\n"},{"acf_fc_layout":"content","content":"<h2 id=\"connect_data_feed\">Connect to a data feed<\/h2>\n<p>Your custom\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.html\"><code>DynamicEntityDataSource<\/code><\/a>\u00a0must override the\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.OnConnectAsync.html\"><code>OnConnectAsync<\/code><\/a>\u00a0method. This is where you put any logic required to connect to the data feed. For my\u00a0<code>CityBikesDataSource<\/code>\u00a0class, I simply start the timer so updates will start coming in at the specified interval.<\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\">    <span style=\"color: #0000ff;\">protected<\/span> <span style=\"color: #0000ff;\">override<\/span> Task OnConnectAsync(CancellationToken cancellationToken)\r\n    {\r\n        <span style=\"color: #008000;\">\/\/ Start the timer to pull updates periodically.<\/span>\r\n        _getBikesTimer.Start();\r\n        \r\n\r\n        <span style=\"color: #0000ff;\">return<\/span> Task.CompletedTask;\r\n    }\r\n<\/pre>\n<\/div>\n<p>It might be tempting to make a call to\u00a0<code>PullBikeUpdates()<\/code>\u00a0here to get an initial set of observations. Otherwise, the user has to wait until the next timer interval before anything appears on the map, right? Unfortunately, you cannot add observations until the data source is connected (when this override completes). To handle this dilemma, I added a public method to populate the initial set of dynamic entities. I\u2019ve spared you the details here. Refer to the\u00a0<a href=\"https:\/\/github.com\/ThadT\/bike-rental-stations-maui\">bike-rental-stations-maui<\/a>\u00a0project on GitHub if you\u2019re interested.<\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\">    <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">async<\/span> Task GetInitialBikeStations()\r\n    {\r\n        <span style=\"color: #008000;\">\/\/ Exit if the data source is not connected.<\/span>\r\n        <span style=\"color: #0000ff;\">if<\/span> (<span style=\"color: #0000ff;\">this<\/span>.ConnectionStatus != ConnectionStatus.Connected) { <span style=\"color: #0000ff;\">return<\/span>; }\r\n\r\n        <span style=\"color: #008000;\">\/\/ &lt;Logic here to add dynamic entity observations&gt;<\/span>\r\n    }\r\n<\/pre>\n<\/div>\n<p>The consuming code calls this method after the connection is established (I\u2019ll show you that code later).<\/p>\n"},{"acf_fc_layout":"content","content":"<h2 id=\"define_metadata\">Define metadata about your data source<\/h2>\n<p>You need to provide metadata about some important aspects of your data source. Specifically, the schema (fields) to include for observations, a field name that uniquely identifies dynamic entities, and the spatial reference used for their geometry. Notice that geometry is not defined as a field in the schema. Instead, you create points from the latitude and longitude values. You then add an observation and provide the location and attributes. I\u2019ll describe that process later in the article. As of this writing (version 200.2), only point geometry is supported for dynamic entities.<\/p>\n<p>Define data source metadata with a\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSourceInfo.html\"><code>DynamicEntityDataSourceInfo<\/code><\/a>\u00a0object. Return it from an override of the\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.OnLoadAsync.html\"><code>OnLoadAsync()<\/code><\/a>\u00a0method.<\/p>\n<details>\n<summary><span style=\"color: purple; font-style: bold;\">\u2295\u00a0Show code &#8230;<\/span><\/summary>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\">    <span style=\"color: #0000ff;\">protected<\/span> <span style=\"color: #0000ff;\">override<\/span> Task&lt;DynamicEntityDataSourceInfo&gt; OnLoadAsync()\r\n    {\r\n        <span style=\"color: #008000;\">\/\/ When the data source is loaded, create metadata that defines:<\/span>\r\n        <span style=\"color: #008000;\">\/\/ - A schema (fields) for the observations (bike stations)<\/span>\r\n        <span style=\"color: #008000;\">\/\/ - Which field uniquely identifies entities (StationID)<\/span>\r\n        <span style=\"color: #008000;\">\/\/ - The spatial reference for the station locations (WGS84)<\/span>\r\n        <span style=\"color: #2b91af;\">var<\/span> fields = <span style=\"color: #0000ff;\">new<\/span> List&lt;Field&gt;\r\n        {\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Text, <span style=\"color: #a31515;\">\"StationID\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 50),\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Text, <span style=\"color: #a31515;\">\"StationName\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 125),\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Text, <span style=\"color: #a31515;\">\"Address\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 125),\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Text, <span style=\"color: #a31515;\">\"TimeStamp\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 50),\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Float32, <span style=\"color: #a31515;\">\"Longitude\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 0),\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Float32, <span style=\"color: #a31515;\">\"Latitude\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 0),\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Int32, <span style=\"color: #a31515;\">\"BikesAvailable\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 0),\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Int32, <span style=\"color: #a31515;\">\"EBikesAvailable\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 0),\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Int32, <span style=\"color: #a31515;\">\"EmptySlots\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 0),\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Text, <span style=\"color: #a31515;\">\"ObservationID\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 50),\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Int32, <span style=\"color: #a31515;\">\"InventoryChange\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 0),\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Text, <span style=\"color: #a31515;\">\"ImageUrl\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 255),\r\n            <span style=\"color: #0000ff;\">new<\/span> Field(FieldType.Text, <span style=\"color: #a31515;\">\"CityName\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span>, 50)\r\n        };\r\n        <span style=\"color: #2b91af;\">var<\/span> info = <span style=\"color: #0000ff;\">new<\/span> DynamicEntityDataSourceInfo(<span style=\"color: #a31515;\">\"StationID\"<\/span>, fields)\r\n        {\r\n            SpatialReference = SpatialReferences.Wgs84\r\n        };\r\n\r\n        <span style=\"color: #0000ff;\">return<\/span> Task.FromResult(info);\r\n    }\r\n<\/pre>\n<\/div>\n<\/details>\n<p>The values for observations might come directly from the data feed (for example\u00a0<em>StationName<\/em>,\u00a0<em>Address<\/em>, and\u00a0<em>BikesAvailable<\/em>\u00a0attributes). They may also come from values you provide or calculate yourself (for example, the\u00a0<em>InventoryChange<\/em>\u00a0and\u00a0<em>ImageUrl<\/em>).<\/p>\n"},{"acf_fc_layout":"content","content":"<h2 id=\"read_feed_data\">Read data from the feed<\/h2>\n<p>The details for how updates from the data feed are read and processed can vary according to your implementation. I won\u2019t go into detail about specifics for my\u00a0<code>CityBikesDataSource<\/code>\u00a0class. If you\u2019re interested, check out the\u00a0<a href=\"https:\/\/github.com\/ThadT\/bike-rental-stations-maui\/blob\/main\/CityBikesDataSource.cs\">code on GitHub<\/a>.<\/p>\n<p>To start with, I check the connection status before requesting updates to avoid a potential exception. You cannot add observations to your data source if it\u2019s not in a connected state.<\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\">   <span style=\"color: #0000ff;\">if<\/span> (<span style=\"color: #0000ff;\">this<\/span>.ConnectionStatus != ConnectionStatus.Connected) { <span style=\"color: #0000ff;\">return<\/span>; }\r\n<\/pre>\n<\/div>\n<p>When you read from the feed, you\u2019ll create a dictionary of attributes (<a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.collections.generic.dictionary-2?view=net-7.0\"><code>Dictionary&lt;string, object&gt;<\/code><\/a>) and a location (<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.Geometry.MapPoint.html\"><code>MapPoint<\/code><\/a>) for each observation. You then store the observation by calling\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.AddObservation.html\"><code>AddObservation()<\/code><\/a>\u00a0and passing the attributes and location.<\/p>\n<details>\n<summary><span style=\"color: purple; font-style: bold;\">\u2295\u00a0Show code &#8230;<\/span><\/summary>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\">    <span style=\"color: #008000;\">\/\/ --Code here to get a set of updates from the feed\u2014-<\/span>\r\n\r\n    <span style=\"color: #008000;\">\/\/ Process each update.<\/span>\r\n    <span style=\"color: #0000ff;\">foreach<\/span> (<span style=\"color: #2b91af;\">var<\/span> update <span style=\"color: #0000ff;\">in<\/span> bikeUpdates)\r\n    {\r\n         <span style=\"color: #2b91af;\">var<\/span> attributes = <span style=\"color: #0000ff;\">new<\/span> Dictionary&lt;<span style=\"color: #2b91af;\">string<\/span>, <span style=\"color: #2b91af;\">object<\/span>&gt;\r\n         {\r\n              { <span style=\"color: #a31515;\">\"StationID\"<\/span>, update.StationInfo.StationID },\r\n              { <span style=\"color: #a31515;\">\"StationName\"<\/span>, update.StationName },\r\n              { <span style=\"color: #a31515;\">\"Address\"<\/span>, update.StationInfo.Address },\r\n              { <span style=\"color: #a31515;\">\"TimeStamp\"<\/span>, update.TimeStamp },\r\n              { <span style=\"color: #a31515;\">\"Longitude\"<\/span>, update.Longitude },\r\n              { <span style=\"color: #a31515;\">\"Latitude\"<\/span>, update.Latitude },\r\n              { <span style=\"color: #a31515;\">\"BikesAvailable\"<\/span>, update.BikesAvailable },\r\n              { <span style=\"color: #a31515;\">\"EBikesAvailable\"<\/span>, update.StationInfo.EBikesAvailable },\r\n              { <span style=\"color: #a31515;\">\"EmptySlots\"<\/span>, update.EmptySlots },\r\n              { <span style=\"color: #a31515;\">\"ObservationID\"<\/span>, update.ObservationID },\r\n              { <span style=\"color: #a31515;\">\"InventoryChange\"<\/span>, 0 },\r\n              { <span style=\"color: #a31515;\">\"ImageUrl\"<\/span>, <span style=\"color: #a31515;\">\"\"<\/span> },\r\n              { <span style=\"color: #a31515;\">\"CityName\"<\/span>, _cityName }                    \r\n         };\r\n         <span style=\"color: #008000;\">\/\/ Create a MapPoint for the location from the lat\/long values.<\/span>\r\n         <span style=\"color: #2b91af;\">var<\/span> location = <span style=\"color: #0000ff;\">new<\/span> MapPoint(update.Longitude, update.Latitude, SpatialReferences.Wgs84);\r\n\r\n         <span style=\"color: #008000;\">\/\/ Add the observation to the data source.<\/span>\r\n         AddObservation(location, attributes);\r\n    }\r\n<\/pre>\n<\/div>\n<\/details>\n<p>For the bike updates, I discovered I was adding an observation for each bike station on every request. I added observations even when there was no change for a station. This was pretty inefficient since I was adding many more \u201cupdates\u201d than I needed to. I also realized that this made my notification events essentially meaningless. They fired whether a change had occurred in the available bikes for that station or not.<\/p>\n<p>The solution was to use a dictionary to store the previous set of values. I could then compare each station\u2019s previous inventory with the updated values. If the values for available bikes or e-bikes change, I record the inventory change and add the observation. If the values are the same for available bikes, I skip the update. For the consumer of the data source, this means notifications only arrive when a station\u2019s values change.<\/p>\n<details>\n<summary><span style=\"color: purple; font-style: bold;\">\u2295\u00a0Show code &#8230;<\/span><\/summary>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\">    <span style=\"color: #008000;\">\/\/ Check if the update has different values for BikesAvailable or EBikesAvailable.<\/span>\r\n    <span style=\"color: #0000ff;\">if<\/span> ((<span style=\"color: #2b91af;\">int<\/span>)attributes[<span style=\"color: #a31515;\">\"BikesAvailable\"<\/span>] != (<span style=\"color: #2b91af;\">int<\/span>)lastObservation[<span style=\"color: #a31515;\">\"BikesAvailable\"<\/span>] ||\r\n        (<span style=\"color: #2b91af;\">int<\/span>)attributes[<span style=\"color: #a31515;\">\"EBikesAvailable\"<\/span>] != (<span style=\"color: #2b91af;\">int<\/span>)lastObservation[<span style=\"color: #a31515;\">\"EBikesAvailable\"<\/span>])\r\n    {\r\n         <span style=\"color: #008000;\">\/\/ Calculate the change in inventory.<\/span>\r\n         <span style=\"color: #2b91af;\">var<\/span> stationInventoryChange = (<span style=\"color: #2b91af;\">int<\/span>)attributes[<span style=\"color: #a31515;\">\"BikesAvailable\"<\/span>] <span style=\"border: 1px solid #FF0000;\">\u2013<\/span> \r\n                 (<span style=\"color: #2b91af;\">int<\/span>)lastObservation[<span style=\"color: #a31515;\">\"BikesAvailable\"<\/span>];\r\n         attributes[<span style=\"color: #a31515;\">\"InventoryChange\"<\/span>] = stationInventoryChange;\r\n         totalInventoryChange += stationInventoryChange;\r\n\r\n         <span style=\"color: #008000;\">\/\/ Add the update to the data source.<\/span>\r\n         AddObservation(location, attributes);\r\n    }\r\n<\/pre>\n<\/div>\n<\/details>\n<p>&nbsp;<\/p>\n"},{"acf_fc_layout":"content","content":"<h2 id=\"disconnect\">Clean up when the data source is disconnected<\/h2>\n<p>You must override the <a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.OnDisconnectAsync.html\"><code>OnDisconnectAsync<\/code><\/a> method on the data source to handle when the data source is disconnected. The code you add here can vary according to your implementation. For me, I simply need to stop the timer and clear the dictionary of previous observation values.<\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\">    <span style=\"color: #0000ff;\">protected<\/span> <span style=\"color: #0000ff;\">override<\/span> Task OnDisconnectAsync()\r\n    {\r\n        _getBikeUpdatesTimer.Stop();\r\n        _previousObservations.Clear();\r\n\r\n        <span style=\"color: #0000ff;\">return<\/span> Task.CompletedTask;\r\n    }\r\n<\/pre>\n<\/div>\n<p>At this point, you can consume your custom\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.html\"><code>DynamicEntityDataSource<\/code><\/a>\u00a0in your app as you would any other data source.<\/p>\n"},{"acf_fc_layout":"content","content":"<h2 id=\"create_instance\">Create an instance of your data source<\/h2>\n<p>Create a new instance of your dynamic entity data source class and pass in all required arguments. For my\u00a0<code>CityBikesDataSource<\/code>, this is the city name, a URL for the bike stations, and the seconds between updates.<\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\"><span style=\"color: #008000;\">    \/\/ Create an instance of the custom dynamic entity data source.<\/span>\r\n    _cityBikesDataSource = <span style=\"color: #0000ff;\">new<\/span> CityBikesDataSource(cityName, cityBikesUrl, UpdateIntervalSeconds);\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n"},{"acf_fc_layout":"content","content":"<h3>Get an initial set of dynamic entities<\/h3>\n<p>Remember that I couldn\u2019t add logic inside the\u00a0<code>OnConnect()<\/code>\u00a0override to get an initial set of dynamic entities? You might recall that this was because the data set isn\u2019t officially connected until after that method completes. I added a separate public method to get the initial set of data (<code>GetInitialBikeStations<\/code>). I can now call that from the code that consumes the data source. The trick is to make sure the data source is connected before making the call. I can do that by handling the\u00a0<code>ConnectionStatusChanged<\/code>\u00a0event and then making the call once connected.<\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\">    <span style=\"color: #008000;\">\/\/ When the connection is established, request an initial set of data.<\/span>\r\n    _cityBikesDataSource.ConnectionStatusChanged += (s, e) =&gt;\r\n    {\r\n        <span style=\"color: #0000ff;\">if<\/span> (e == ConnectionStatus.Connected)\r\n        {\r\n            _ = _cityBikesDataSource.GetInitialBikeStations();\r\n        }\r\n    };\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n"},{"acf_fc_layout":"content","content":"<h2 id=\"create_dynamicentitylayer\">Display the dynamic entities from your data source<\/h2>\n<p>ArcGIS Maps SDK for\u00a0Native Apps\u00a0provides a layer\u00a0designed to display dynamic entities, called\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.Mapping.DynamicEntityLayer.html\"><code>DynamicEntityLayer<\/code><\/a>. This layer is created from a\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.html\"><code>DynamicEntityDataSource<\/code><\/a>\u00a0and manages the display of all dynamic entities and observations. The layer updates as observations are added, purged, or updated in the data source. You can define the display of dynamic entities in the layer using any of the available renderer types (simple, class breaks, unique value, or dictionary).\u00a0You can also display\u00a0labels\u00a0for dynamic entities to display information for the current observation.<\/p>\n<p>Adding a\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.Mapping.DynamicEntityLayer.html\"><code>DynamicEntityLayer<\/code><\/a>\u00a0to a\u00a0map\u00a0or\u00a0scene\u00a0automatically loads and connects the associated\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.html\"><code>DynamicEntityDataSource<\/code><\/a>.<\/p>\n<p>For bike stations, I created a class breaks renderer to show relative bike availability. Darker green means more bikes and gray means no bikes available.<\/p>\n"},{"acf_fc_layout":"image","image":{"ID":2070242,"id":2070242,"title":"bike-availability-map","filename":"bike-availability-map.png","filesize":441127,"url":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-availability-map.png","link":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps\/bike-availability-map","alt":"Map showing rental bike availability for New York City.","author":"8512","description":"","caption":"Bike availability map for New York City.","name":"bike-availability-map","status":"inherit","uploaded_to":2068762,"date":"2023-09-07 19:59:45","modified":"2023-09-07 20:00:35","menu_order":0,"mime_type":"image\/png","type":"image","subtype":"png","icon":"https:\/\/www.esri.com\/arcgis-blog\/wp-includes\/images\/media\/default.png","width":801,"height":400,"sizes":{"thumbnail":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-availability-map-213x200.png","thumbnail-width":213,"thumbnail-height":200,"medium":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-availability-map.png","medium-width":464,"medium-height":232,"medium_large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-availability-map.png","medium_large-width":768,"medium_large-height":384,"large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-availability-map.png","large-width":801,"large-height":400,"1536x1536":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-availability-map.png","1536x1536-width":801,"1536x1536-height":400,"2048x2048":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-availability-map.png","2048x2048-width":801,"2048x2048-height":400,"card_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-availability-map.png","card_image-width":801,"card_image-height":400,"wide_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-availability-map.png","wide_image-width":801,"wide_image-height":400}},"image_position":"center","orientation":"horizontal","hyperlink":""},{"acf_fc_layout":"content","content":"<h2 id=\"work_with_events\">Handle data source events<\/h2>\n<p>When the data source adds observations, the value of the entity ID field indicates the entity to which the observation applies. This field is defined in the <code>OnLoadAsync()<\/code> override. The data source raises the <code>DynamicEntityReceived<\/code> event when the first observation for a dynamic entity is added. This indicates that a new dynamic entity has appeared in the data. All subsequent observations will raise the <a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.DynamicEntityObservationReceived.html\"><code>DynamicEntityObservationReceived<\/code><\/a> event, indicating that an existing dynamic entity has been updated.<\/p>\n<p>I use the\u00a0<code>DynamicEntityReceived<\/code>\u00a0event to calculate the initial bike availability for the entire city.<\/p>\n<details>\n<summary><span style=\"color: purple; font-style: bold;\">\u2295\u00a0Show code &#8230;<\/span><\/summary>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\">    <span style=\"color: #008000;\">\/\/ Listen for dynamic entities being created, calculate the initial bike inventory.<\/span>\r\n    _cityBikesDataSource.DynamicEntityReceived += (s, e) =&gt;\r\n    {\r\n        <span style=\"color: #2b91af;\">var<\/span> bikeStation = e.DynamicEntity;\r\n        <span style=\"color: #2b91af;\">var<\/span> emptySlots = (<span style=\"color: #2b91af;\">int<\/span>)bikeStation.Attributes[<span style=\"color: #a31515;\">\"EmptySlots\"<\/span>];\r\n        <span style=\"color: #2b91af;\">var<\/span> availableBikes = (<span style=\"color: #2b91af;\">int<\/span>)bikeStation.Attributes[<span style=\"color: #a31515;\">\"BikesAvailable\"<\/span>] +\r\n            (<span style=\"color: #2b91af;\">int<\/span>)bikeStation.Attributes[<span style=\"color: #a31515;\">\"EBikesAvailable\"<\/span>];\r\n\r\n        TotalBikes += emptySlots + availableBikes;\r\n        BikesAvailable += availableBikes;\r\n\r\n        BikesOut = TotalBikes - BikesAvailable;\r\n        PercentBikesAvailable = (<span style=\"color: #2b91af;\">double<\/span>)BikesAvailable \/ TotalBikes;\r\n    };\r\n<\/pre>\n<\/div>\n<\/details>\n<p>I handle the <a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.DynamicEntityObservationReceived.html\"><code>DynamicEntityObservationReceived<\/code><\/a> event to respond to updates to stations. I adjust the total bike inventory for the city and call a function to flash each station that has an update. The station flashes red when a bike leaves and blue when a bike returns.<\/p>\n<details>\n<summary><span style=\"color: purple; font-style: bold;\">\u2295\u00a0Show code &#8230;<\/span><\/summary>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div>\n<pre style=\"background: #FBFBF9; overflow: auto; width: 100%; height: 100%; border: solid purple; border-width: 0em 0em 0em .3em; padding: .1em .1em; margin: 0; line-height: 125%; font-size: smaller;\">    <span style=\"color: #008000;\">\/\/ Listen for new observations; flash the station and update inventory if there's an update.<\/span>\r\n    _cityBikesDataSource.DynamicEntityObservationReceived += <span style=\"color: #0000ff;\">async<\/span> (s, e) =&gt;\r\n    {\r\n        <span style=\"color: #2b91af;\">var<\/span> bikesAdded = (<span style=\"color: #2b91af;\">int<\/span>)e.Observation.Attributes[<span style=\"color: #a31515;\">\"InventoryChange\"<\/span>];\r\n        <span style=\"color: #0000ff;\">if<\/span> (bikesAdded == 0) { <span style=\"color: #0000ff;\">return<\/span>; }\r\n\r\n        UpdateBikeInventory(bikesAdded); <span style=\"color: #008000;\">\/\/ note: this might be negative if more bikes were taken than returned.<\/span>\r\n        <span style=\"color: #0000ff;\">await<\/span> Task.Run(() =&gt; FlashDynamicEntityObservationAsync(e.Observation.Geometry <span style=\"color: #0000ff;\">as<\/span> MapPoint, bikesAdded &gt; 0));\r\n    };\r\n<\/pre>\n<\/div>\n<\/details>\n<p>Changes for a particular entity are available by handling its\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntity.DynamicEntityChanged.html\"><code>DynamicEntityChanged<\/code><\/a> event. This lets you respond to observations received or purged (removed) for the entity and be notified when the entity itself is purged (removed from the data source). I don\u2019t use this event in my app, but a good use case would be to flash the favorite card in the \u201cfavorites\u201d collection view when a favorite station is updated.<\/p>\n"},{"acf_fc_layout":"image","image":{"ID":2070392,"id":2070392,"title":"bike-favorite-list","filename":"bike-favorite-list.png","filesize":39616,"url":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-favorite-list.png","link":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps\/bike-favorite-list","alt":"Available bikes for favorite rental stations.","author":"8512","description":"","caption":"Bike availability for favorite rental stations.","name":"bike-favorite-list","status":"inherit","uploaded_to":2068762,"date":"2023-09-07 21:09:24","modified":"2023-09-07 21:10:19","menu_order":0,"mime_type":"image\/png","type":"image","subtype":"png","icon":"https:\/\/www.esri.com\/arcgis-blog\/wp-includes\/images\/media\/default.png","width":820,"height":430,"sizes":{"thumbnail":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-favorite-list-213x200.png","thumbnail-width":213,"thumbnail-height":200,"medium":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-favorite-list.png","medium-width":464,"medium-height":243,"medium_large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-favorite-list.png","medium_large-width":768,"medium_large-height":403,"large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-favorite-list.png","large-width":820,"large-height":430,"1536x1536":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-favorite-list.png","1536x1536-width":820,"1536x1536-height":430,"2048x2048":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-favorite-list.png","2048x2048-width":820,"2048x2048-height":430,"card_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-favorite-list.png","card_image-width":820,"card_image-height":430,"wide_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/bike-favorite-list.png","wide_image-width":820,"wide_image-height":430}},"image_position":"center","orientation":"horizontal","hyperlink":""},{"acf_fc_layout":"content","content":"<h2>Display consistent updates<\/h2>\n<p>When testing, I noticed observations usually came in as a large group of updates. With an update interval of a few seconds, nothing happens for a few minutes and then a flurry of updates appears at once. That cycle repeated as I watched and waited for updates. For the cities I tested, updates were batched on the server and released every 4-5 minutes.<\/p>\n<p>I wanted to provide a more consistent and smooth display for the updates. I set the interval to four minutes, store those updates, and then use another timer to slowly (consistently) display them in the app. This technique improves the display and the overall user experience at the expense of having the most recent updates. Using this technique, updates are four minutes behind. For me, I thought that was a good trade-off. Check out the <a href=\"https:\/\/github.com\/ThadT\/bike-rental-stations-maui\/blob\/main\/CityBikesDataSource.cs\">CityBikesDataSource code<\/a> to see what that looks like.<\/p>\n<p>&nbsp;<\/p>\n"},{"acf_fc_layout":"image","image":{"ID":2070462,"id":2070462,"title":"station-paris-update-android-crop","filename":"station-paris-update-android-crop.gif","filesize":2923520,"url":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-paris-update-android-crop.gif","link":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps\/station-paris-update-android-crop","alt":"Stations flash when updated.","author":"8512","description":"","caption":"Bike station observations arrive at a consistent interval.","name":"station-paris-update-android-crop","status":"inherit","uploaded_to":2068762,"date":"2023-09-07 21:36:41","modified":"2023-09-07 21:37:41","menu_order":0,"mime_type":"image\/gif","type":"image","subtype":"gif","icon":"https:\/\/www.esri.com\/arcgis-blog\/wp-includes\/images\/media\/default.png","width":396,"height":390,"sizes":{"thumbnail":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-paris-update-android-crop-213x200.gif","thumbnail-width":213,"thumbnail-height":200,"medium":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-paris-update-android-crop.gif","medium-width":265,"medium-height":261,"medium_large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-paris-update-android-crop.gif","medium_large-width":396,"medium_large-height":390,"large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-paris-update-android-crop.gif","large-width":396,"large-height":390,"1536x1536":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-paris-update-android-crop.gif","1536x1536-width":396,"1536x1536-height":390,"2048x2048":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-paris-update-android-crop.gif","2048x2048-width":396,"2048x2048-height":390,"card_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-paris-update-android-crop.gif","card_image-width":396,"card_image-height":390,"wide_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/station-paris-update-android-crop.gif","wide_image-width":396,"wide_image-height":390}},"image_position":"center","orientation":"horizontal","hyperlink":""},{"acf_fc_layout":"content","content":"<h2 id=\"summary\">Summary<\/h2>\n<p>I hope this article helped you understand the process of creating a dynamic entity data source for your ArcGIS Maps SDK for .NET app. By extending the <a href=\"https:\/\/developers.arcgis.com\/net\/api-reference\/api\/netwin\/Esri.ArcGISRuntime\/Esri.ArcGISRuntime.RealTime.DynamicEntityDataSource.html\"><code>DynamicEntityDataSource<\/code><\/a> class, there are only a handful of overrides required to create your own data source. Hopefully, you\u2019ve seen some of the advantages of using a custom data source as part of the existing API. Perhaps most importantly, many of the data management and display details will be handled for you.<\/p>\n<p>With the 200.2 release of ArcGIS Maps SDK for Native Apps, you can wrap just about any data feed as a dynamic entity data source for use in your app. While there are other ways to bring such data into your app, using dynamic entities allows you to offload a lot of work to the API. Once your custom data source is complete, you can plug it into the existing dynamic entities API to get a lot of additional functionality. You can display the data source in a dynamic entities layer, get notifications for data updates, and manage the local data cache. For dynamic entities that move, a dynamic entity layer shows tracks of previous locations and provides options for track display.<\/p>\n"},{"acf_fc_layout":"content","content":"<h2>Try it yourself!<\/h2>\n<ul>\n<li><a href=\"https:\/\/github.com\/ThadT\/bike-rental-stations-maui\">GitHub repo with the code described in this article<\/a><\/li>\n<li>Custom dynamic entity data source Native Maps SDKs sample: <a href=\"https:\/\/developers.arcgis.com\/java\/sample-code\/add-custom-dynamic-entity-data-source\/\">Java<\/a> | <a href=\"https:\/\/developers.arcgis.com\/net\/wpf\/sample-code\/add-custom-dynamic-entity-data-source\/\">.NET<\/a> | <a href=\"https:\/\/developers.arcgis.com\/qt\/cpp\/sample-code\/add-custom-dynamic-entity-data-source\/\">Qt<\/a> | <a href=\"https:\/\/developers.arcgis.com\/swift\/sample-code\/add-custom-dynamic-entity-data-source\/\">Swift<\/a><\/li>\n<li>Add dynamic entity layer\u00a0Native Maps SDKs samples:\u00a0<a href=\"https:\/\/developers.arcgis.com\/java\/sample-code\/add-dynamic-entity-layer\/\">Java<\/a>\u00a0|\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/wpf\/sample-code\/add-dynamic-entity-layer\/\">.NET<\/a>\u00a0|\u00a0<a href=\"https:\/\/developers.arcgis.com\/qt\/cpp\/sample-code\/add-dynamic-entity-layer\/\">Qt<\/a>\u00a0|\u00a0<a href=\"https:\/\/developers.arcgis.com\/swift\/sample-code\/add-dynamic-entity-layer\/\">Swift<\/a><\/li>\n<li>Work with dynamic entities\u00a0(Native Maps SDKs Guide topic):\u00a0<a href=\"https:\/\/developers.arcgis.com\/java\/real-time\/work-with-dynamic-entities\/\">Java<\/a>\u00a0| <a href=\"https:\/\/developers.arcgis.com\/kotlin\/real-time\/work-with-dynamic-entities\/\">Kotlin<\/a> |\u00a0<a href=\"https:\/\/developers.arcgis.com\/net\/real-time\/work-with-dynamic-entities\/\">.NET<\/a>\u00a0|\u00a0<a href=\"https:\/\/developers.arcgis.com\/qt\/real-time\/work-with-dynamic-entities\/\">Qt<\/a>\u00a0|\u00a0<a href=\"https:\/\/developers.arcgis.com\/swift\/real-time\/work-with-dynamic-entities\/\">Swift<\/a><\/li>\n<li>ArcGIS Enterprise <a href=\"https:\/\/enterprise.arcgis.com\/en\/server\/latest\/publish-services\/windows\/stream-services.htm\">Stream services<\/a>\u00a0documentation<\/li>\n<li><a href=\"https:\/\/learn.arcgis.com\/en\/paths\/get-started-with-arcgis-velocity\/\">Get started with ArcGIS Velocity<\/a>: Tutorials, Articles, and Videos<\/li>\n<li>ArcGIS Enterprise <a href=\"https:\/\/enterprise.arcgis.com\/en\/geoevent\/\">GeoEvent Server<\/a>\u00a0documentation<\/li>\n<\/ul>\n"},{"acf_fc_layout":"content","content":"<p><em>Each ArcGIS Maps SDK for Native Apps (<a href=\"https:\/\/developers.arcgis.com\/net\/\" rel=\"nofollow\">.NET<\/a>,\u00a0<a href=\"https:\/\/developers.arcgis.com\/qt\/\" rel=\"nofollow\">Qt<\/a>,\u00a0<a href=\"https:\/\/developers.arcgis.com\/java\/\" rel=\"nofollow\">Java<\/a>,\u00a0<a href=\"https:\/\/developers.arcgis.com\/kotlin\/\" rel=\"nofollow\">Kotlin<\/a>,\u00a0and\u00a0<a href=\"https:\/\/developers.arcgis.com\/swift\/\" rel=\"nofollow\">Swift<\/a>) provides a rich set of guide documentation, API references, tutorials, and samples to help you build great apps. If you&#8217;re new to working with these SDKs, visit the <a href=\"https:\/\/developers.arcgis.com\/documentation\/mapping-apis-and-services\/get-started\/\">ArcGIS Developers site to get started.<\/a>\u00a0<\/em><\/p>\n"}],"related_articles":[{"ID":1845082,"post_author":"8512","post_date":"2023-04-19 10:00:07","post_date_gmt":"2023-04-19 17:00:07","post_content":"","post_title":"Eight essential real-time techniques with ArcGIS Maps SDKs for Native Apps","post_excerpt":"","post_status":"publish","comment_status":"open","ping_status":"closed","post_password":"","post_name":"create-real-time-apps-with-arcgis-maps-sdks-for-native-apps","to_ping":"","pinged":"","post_modified":"2024-04-12 02:39:01","post_modified_gmt":"2024-04-12 09:39:01","post_content_filtered":"","post_parent":0,"guid":"https:\/\/www.esri.com\/arcgis-blog\/?post_type=blog&#038;p=1845082","menu_order":0,"post_type":"blog","post_mime_type":"","comment_count":"0","filter":"raw"},{"ID":809671,"post_author":"24791","post_date":"2020-04-20 07:00:52","post_date_gmt":"2020-04-20 14:00:52","post_content":"","post_title":"Performing near-real-time analysis in ArcGIS Velocity","post_excerpt":"","post_status":"publish","comment_status":"open","ping_status":"closed","post_password":"","post_name":"performing-near-real-time-analysis-in-arcgis-velocity","to_ping":"","pinged":"","post_modified":"2021-01-13 05:01:54","post_modified_gmt":"2021-01-13 13:01:54","post_content_filtered":"","post_parent":0,"guid":"https:\/\/www.esri.com\/arcgis-blog\/?post_type=blog&#038;p=809671","menu_order":0,"post_type":"blog","post_mime_type":"","comment_count":"0","filter":"raw"}],"card_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/custom-datasource-blog-card.png","wide_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/custom-datasource-blog-banner2.png"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Craft your own dynamic entity data source for ArcGIS Maps SDKs for Native Apps<\/title>\n<meta name=\"description\" content=\"ArcGIS Maps SDKs for Native Apps can consume data from a feed and update the location and attributes of dynamic entities in the map.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Craft your own dynamic entity data source for ArcGIS Maps SDKs for Native Apps\" \/>\n<meta property=\"og:description\" content=\"ArcGIS Maps SDKs for Native Apps can consume data from a feed and update the location and attributes of dynamic entities in the map.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps\" \/>\n<meta property=\"og:site_name\" content=\"ArcGIS Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/esrigis\/\" \/>\n<meta property=\"article:modified_time\" content=\"2024-04-12T08:15:24+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:site\" content=\"@ESRI\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps\"},\"author\":{\"name\":\"Thad Tilton\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/68e8fc10434ed22705c26033bc89f131\"},\"headline\":\"Craft your own dynamic entity data source for ArcGIS Maps SDKs for Native Apps\",\"datePublished\":\"2023-09-14T16:00:14+00:00\",\"dateModified\":\"2024-04-12T08:15:24+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps\"},\"wordCount\":14,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#organization\"},\"keywords\":[\"ArcGIS Runtime\",\"real-time data\",\"stream service\"],\"articleSection\":[\"Developers\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps\",\"name\":\"Craft your own dynamic entity data source for ArcGIS Maps SDKs for Native Apps\",\"isPartOf\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#website\"},\"datePublished\":\"2023-09-14T16:00:14+00:00\",\"dateModified\":\"2024-04-12T08:15:24+00:00\",\"description\":\"ArcGIS Maps SDKs for Native Apps can consume data from a feed and update the location and attributes of dynamic entities in the map.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.esri.com\/arcgis-blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Craft your own dynamic entity data source for ArcGIS Maps SDKs for Native Apps\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#website\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/\",\"name\":\"ArcGIS Blog\",\"description\":\"Get insider info from Esri product teams\",\"publisher\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.esri.com\/arcgis-blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#organization\",\"name\":\"Esri\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/04\/Esri.png\",\"contentUrl\":\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/04\/Esri.png\",\"width\":400,\"height\":400,\"caption\":\"Esri\"},\"image\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/esrigis\/\",\"https:\/\/x.com\/ESRI\",\"https:\/\/www.linkedin.com\/company\/5311\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/68e8fc10434ed22705c26033bc89f131\",\"name\":\"Thad Tilton\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/ca357c472fe1cfc0327aad444d36ceff475526bff5e5afe118b7fba02dda2d14?s=96&d=blank&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/ca357c472fe1cfc0327aad444d36ceff475526bff5e5afe118b7fba02dda2d14?s=96&d=blank&r=g\",\"caption\":\"Thad Tilton\"},\"description\":\"I'm a product engineer on the ArcGIS Maps SDKs for Native Apps team, where I help create and maintain developer guides and API reference documentation. I enjoy .NET programming, helping our customers solve problems, and exploring creative ways of using ArcGIS.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/thad-tilton-2ba4a92\/\"],\"url\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Craft your own dynamic entity data source for ArcGIS Maps SDKs for Native Apps","description":"ArcGIS Maps SDKs for Native Apps can consume data from a feed and update the location and attributes of dynamic entities in the map.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps","og_locale":"en_US","og_type":"article","og_title":"Craft your own dynamic entity data source for ArcGIS Maps SDKs for Native Apps","og_description":"ArcGIS Maps SDKs for Native Apps can consume data from a feed and update the location and attributes of dynamic entities in the map.","og_url":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps","og_site_name":"ArcGIS Blog","article_publisher":"https:\/\/www.facebook.com\/esrigis\/","article_modified_time":"2024-04-12T08:15:24+00:00","twitter_card":"summary_large_image","twitter_site":"@ESRI","twitter_misc":{"Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps#article","isPartOf":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps"},"author":{"name":"Thad Tilton","@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/68e8fc10434ed22705c26033bc89f131"},"headline":"Craft your own dynamic entity data source for ArcGIS Maps SDKs for Native Apps","datePublished":"2023-09-14T16:00:14+00:00","dateModified":"2024-04-12T08:15:24+00:00","mainEntityOfPage":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps"},"wordCount":14,"commentCount":0,"publisher":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/#organization"},"keywords":["ArcGIS Runtime","real-time data","stream service"],"articleSection":["Developers"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps","url":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps","name":"Craft your own dynamic entity data source for ArcGIS Maps SDKs for Native Apps","isPartOf":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/#website"},"datePublished":"2023-09-14T16:00:14+00:00","dateModified":"2024-04-12T08:15:24+00:00","description":"ArcGIS Maps SDKs for Native Apps can consume data from a feed and update the location and attributes of dynamic entities in the map.","breadcrumb":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/sdk-net\/developers\/craft-your-own-dynamic-entity-data-source-for-arcgis-maps-sdks-for-native-apps#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.esri.com\/arcgis-blog\/"},{"@type":"ListItem","position":2,"name":"Craft your own dynamic entity data source for ArcGIS Maps SDKs for Native Apps"}]},{"@type":"WebSite","@id":"https:\/\/www.esri.com\/arcgis-blog\/#website","url":"https:\/\/www.esri.com\/arcgis-blog\/","name":"ArcGIS Blog","description":"Get insider info from Esri product teams","publisher":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.esri.com\/arcgis-blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.esri.com\/arcgis-blog\/#organization","name":"Esri","url":"https:\/\/www.esri.com\/arcgis-blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/04\/Esri.png","contentUrl":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/04\/Esri.png","width":400,"height":400,"caption":"Esri"},"image":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/esrigis\/","https:\/\/x.com\/ESRI","https:\/\/www.linkedin.com\/company\/5311\/"]},{"@type":"Person","@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/68e8fc10434ed22705c26033bc89f131","name":"Thad Tilton","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/ca357c472fe1cfc0327aad444d36ceff475526bff5e5afe118b7fba02dda2d14?s=96&d=blank&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ca357c472fe1cfc0327aad444d36ceff475526bff5e5afe118b7fba02dda2d14?s=96&d=blank&r=g","caption":"Thad Tilton"},"description":"I'm a product engineer on the ArcGIS Maps SDKs for Native Apps team, where I help create and maintain developer guides and API reference documentation. I enjoy .NET programming, helping our customers solve problems, and exploring creative ways of using ArcGIS.","sameAs":["https:\/\/www.linkedin.com\/in\/thad-tilton-2ba4a92\/"],"url":""}]}},"text_date":"September 14, 2023","author_name":"Thad Tilton","author_page":false,"custom_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2023\/09\/custom-datasource-blog-banner2.png","primary_product":"ArcGIS Maps SDK for .NET","tag_data":[{"term_id":23451,"name":"ArcGIS Runtime","slug":"arcgis-runtime","term_group":0,"term_taxonomy_id":23451,"taxonomy":"post_tag","description":"","parent":0,"count":91,"filter":"raw"},{"term_id":23321,"name":"real-time data","slug":"real-time-data","term_group":0,"term_taxonomy_id":23321,"taxonomy":"post_tag","description":"","parent":0,"count":13,"filter":"raw"},{"term_id":141132,"name":"stream service","slug":"stream-service","term_group":0,"term_taxonomy_id":141132,"taxonomy":"post_tag","description":"","parent":0,"count":4,"filter":"raw"}],"category_data":[{"term_id":738191,"name":"Developers","slug":"developers","term_group":0,"term_taxonomy_id":738191,"taxonomy":"category","description":"","parent":0,"count":426,"filter":"raw"}],"product_data":[{"term_id":761642,"name":"ArcGIS Location Platform","slug":"platform","term_group":0,"term_taxonomy_id":761642,"taxonomy":"product","description":"","parent":36601,"count":215,"filter":"raw"},{"term_id":769142,"name":"ArcGIS Maps SDK for .NET","slug":"sdk-net","term_group":0,"term_taxonomy_id":769142,"taxonomy":"product","description":"","parent":36601,"count":40,"filter":"raw"}],"primary_product_link":"https:\/\/www.esri.com\/arcgis-blog\/?s=#&products=sdk-net","_links":{"self":[{"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/blog\/2068762","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/users\/8512"}],"replies":[{"embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/comments?post=2068762"}],"version-history":[{"count":0,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/blog\/2068762\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/media?parent=2068762"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/categories?post=2068762"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/tags?post=2068762"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/industry?post=2068762"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/product?post=2068762"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}