Or spoofing their actual location.
That, or a number of co-operating clients located at various locations in and out of the range.
A simple fix would be to have every sender generate a random vector of random length 0-100 meters (and re-generate every time you've moved at least 100 meters, you don't want to regenerate if the sender doesn't move as you'd be able to zero-in on a prolific sender), and have the message "originate" from the end of that vector.
That kind of thing combined with some rate limits (how often one can attempt to connect to a user) should be effective.
(edit) Actually, I think I like mseebach's suggestion even more: For each user, pick a random location about 100m away from them, then pretend they're there until they've moved far enough away, then repeat.
For example an attacker can just spoof enough accounts to sample from your distribution to figure out the true center. Imagine spoofing a grid of users with let's say K fake accounts per dot, then if you plot the histogram of who managed to connect you will see a very clear bump in the 2d histogram in the shape of circle.
The solution in your edit is much better.
[0] https://en.m.wikipedia.org/wiki/Restrictions_on_geographic_d...
Using triangulation to pinpoint an other users location would therefore require to move in and out of range (while the targeted user is continuously sending messages). Thus significantly more difficult than if the actual distance measure was depicted in the UI or leaked elsewhere.
Finally closing the API to outside requests limits the ease with which the above could be automated. Any idea's for further improving these security measures are most welcome!