Custom location and movement on Xamarin Remoted iOS Simulator for Windows
This article is more than two years old. Some details may have changed, so check the current documentation before applying them.
When I was building a Xamarin PoC at the client, I was disappointed to notice that there wasn’t any way of simulating the user’s location on the Remoted iOS Simulator for Windows. Not to mention simulating a walk or bike ride around an area other then the standard rides around Apple’s headquarters.
Setting a custom location
I did notice that setting a custom location was possible on the iOS simulator on OSX.

Unfortunately, this does not exist on the remoted simulator. However, soon I discovered that when I’d open up the same simulator on iOS and Windows, changing the location on my Mac would also change the position on my Remoted Simulator on Windows. In order to do this, you need to start a particular iOS simulator on Windows, let’s say iPhone 6 - iOS 10.2. Once it is booted up, go to your Mac, cmd+space and type “Simulator”. Then in the Menu bar go to ‘Hardware’, ‘Device’ and select the same simulator as the one that is running on your Windows machine. If everything goes well, you should get an error message saying something like the device is already booted.

Close the error message and in your Menu bar go to ‘Debug’, ‘Location’ and select ‘Custom Location…’. Enter any coordinates in the window, click ‘OK’ and you should see the position on your simulator on Windows update as well. The easiest way to check this is by opening the Maps app in your simulator on Windows, or in your own app ofcourse :-).
Now, take another step and move forward…
That already helped me a lot! Now I didn’t need to mock all my data around Cupertino anymore. But what if I want to simulate a walk or bike ride around Brussels for example, instead of being at one fixed location? Simple! Just do whatever I just described and change your location every 2 seconds… :-) This idea may sound stupid, but it is exactly what I’m going to do! So, as a complete OSX n00b, I looked into things like automation tools and stuff and so I stumbled upon AppleScript. Yes, that sounds as scary as it is! With this AppleScript, you can basically script everything on you Mac, in a programming language that you might call awkward at least… Especially for a ‘true’ developer. I played around with it for a bit and in no time, after some trail and error, I was able to open up the ’Enter Location ’ popup window and programmatically set a Longitude and Latitude. You can run this script in the Script Editor tool on your Mac if you want, but make sure the Simulator is already running!
Open Custom Location window through AppleScript
on run
tell application "System Events"
tell process "Simulator"
set frontmost to true
click menu item "Custom Location…" of menu of menu item "Location" of menu "Debug" of menu bar 1
set popup to window "Custom Location"
set value of text field 1 of popup to "51,051801"
set value of text field 2 of popup to "4,454144"
--> click button "OK" of popup
end tell
end tell
end run
The only thing left to do, is repeat this process and update the Longitude and Latitude each time. I found out that reading XML files with AppleScript is quite simple, so I went to https://gpxgenerator.com/. On this website, you can put waypoints on a map and generate a GPX file, which is just a simple XML file representing the route you outlined. Although, in the generated GPX file there is an indication about how long it take to get from one waypoint to the next, I’m going to ignore this for now and simply say in my script that there is a certain fixed amount of time between each waypoint.
Sample GPX file
<?xml version="1.0"?>
<gpx version="1.1" creator="gpxgenerator.com">
<wpt lat="50.84633694747007" lon="4.364619255065918">
<time>2017-02-10T10:48:50Z</time>
</wpt>
<wpt lat="50.845889847299254" lon="4.36431884765625">
<time>2017-02-10T10:49:28Z</time>
</wpt>
<wpt lat="50.84507692692001" lon="4.363868236541748">
<time>2017-02-10T10:50:36Z</time>
</wpt>
<wpt lat="50.84460271682405" lon="4.363675117492676">
<time>2017-02-10T10:51:14Z</time>
</wpt>
<wpt lat="50.84374912650492" lon="4.363245964050293">
<time>2017-02-10T10:52:25Z</time>
</wpt>
<wpt lat="50.84296326764228" lon="4.36281681060791">
<time>2017-02-10T10:53:31Z</time>
</wpt>
<wpt lat="50.84281578200512" lon="4.36181902885437">
<time>2017-02-10T10:54:22Z</time>
</wpt>
<wpt lat="50.84310709422066" lon="4.360542297363281">
<time>2017-02-10T10:55:30Z</time>
</wpt>
<wpt lat="50.84268028733167" lon="4.359984397888184">
<time>2017-02-10T10:56:13Z</time>
</wpt>
<wpt lat="50.84245672026023" lon="4.359222650527954">
<time>2017-02-10T10:56:55Z</time>
</wpt>
<wpt lat="50.843019023277556" lon="4.35808539390564">
<time>2017-02-10T10:58:07Z</time>
</wpt>
<wpt lat="50.84339840461739" lon="4.357527494430542">
<time>2017-02-10T10:58:48Z</time>
</wpt>
<wpt lat="50.84356777029096" lon="4.357130527496338">
<time>2017-02-10T10:59:12Z</time>
</wpt>
<wpt lat="50.844069089081536" lon="4.356368780136108">
<time>2017-02-10T11:00:07Z</time>
</wpt>
<wpt lat="50.84437550047113" lon="4.3559181690216064">
<time>2017-02-10T11:00:40Z</time>
</wpt>
<wpt lat="50.84555269015878" lon="4.354877471923828">
<time>2017-02-10T11:02:27Z</time>
</wpt>
<wpt lat="50.84620302096338" lon="4.354770183563232">
<time>2017-02-10T11:03:18Z</time>
</wpt>
<wpt lat="50.8467178597545" lon="4.354383945465088">
<time>2017-02-10T11:04:03Z</time>
</wpt>
<wpt lat="50.84665428412764" lon="4.3536436557769775">
<time>2017-02-10T11:04:40Z</time>
</wpt>
<wpt lat="50.84662380036855" lon="4.353042840957642">
<time>2017-02-10T11:05:10Z</time>
</wpt>
<wpt lat="50.846430736098434" lon="4.3524473905563354">
<time>2017-02-10T11:05:43Z</time>
</wpt>
<wpt lat="50.846213961280625" lon="4.351991415023804">
<time>2017-02-10T11:06:11Z</time>
</wpt>
<wpt lat="50.84603783095749" lon="4.3516212701797485">
<time>2017-02-10T11:06:34Z</time>
</wpt>
<wpt lat="50.845837989977895" lon="4.351256489753723">
<time>2017-02-10T11:06:58Z</time>
</wpt>
<wpt lat="50.84563476098514" lon="4.350859522819519">
<time>2017-02-10T11:07:23Z</time>
</wpt>
<wpt lat="50.84547556432245" lon="4.350618124008179">
<time>2017-02-10T11:07:40Z</time>
</wpt>
<wpt lat="50.84531975429677" lon="4.350387454032898">
<time>2017-02-10T11:07:56Z</time>
</wpt>
<wpt lat="50.845167330942075" lon="4.350119233131409">
<time>2017-02-10T11:08:14Z</time>
</wpt>
<wpt lat="50.84499536286211" lon="4.3499743938446045">
<time>2017-02-10T11:08:29Z</time>
</wpt>
</gpx>
Now I only have to read this XML file, loop over the elements and read the Longitude and Latitude of each one, enter these values in my ‘Enter Location’ popup window, wait a couple of seconds and continue my loop. Simple right? And this is what my final script looks likes. It takes 2 command line parameters: the location of the GPX file and the timeout between each iteration.
--> function to replace a particular char in a string with an other one
on replace_chars(this_text, search_string, replacement_string)
set AppleScript's text item delimiters to the search_string
set the item_list to every text item of this_text
set AppleScript's text item delimiters to the replacement_string
set this_text to the item_list as string
set AppleScript's text item delimiters to ""
return this_text
end replace_chars
on run arg
--> arg is a collection of the command line parameters
set xmlPathParam to item 1 of arg --> first param is the location of the gpx file
set sleepParam to item 2 of arg --> second param is the time (seconds) to sleep between each iteration
tell application "System Events"
tell XML file xmlPathParam
tell XML element "gpx"
set wptElements to every XML element whose name = "wpt" -->put wpt elements in a collection for later use
end tell
end tell
tell process "Simulator"
set frontmost to true
repeat with c from 1 to count of wptElements
set wptElement to item c of wptElements
tell wptElement
set lon to value of XML attribute "lon" of wptElement --> putting the lon value of the wpt element in a variable for later use
set lat to value of XML attribute "lat" of wptElement --> putting the lan value of the wpt element in a variable for later use
end tell
click menu item "Custom Location…" of menu of menu item "Location" of menu "Debug" of menu bar 1
set popup to window "Custom Location"
set value of text field 1 of popup to my replace_chars(lat, ".", ",")
set value of text field 2 of popup to my replace_chars(lon, ".", ",")
click button "OK" of popup
delay sleepParam --> sleep to simulate 'natural' movement
end repeat
end tell
end tell
end run
You can now easily call this script as follows in the terminal on your Mac: osascript [path to you script] [path to your gpx xml file] [time to sleep between each iteration] 
Simulator in action:
Done! Simple but effective imho! :-)
I’m putting this code on GitHub, so if you have any other ideas on how to improve the script or its functionality, just do a PR!
Have fun!
Did you enjoy reading this? If my work has saved you time or taught you something new, consider buying me a coffee.

Join the discussion