Location & maps
Written for Titanium SDK 13.4.0 and later
Location needs permission, and the permission has kinds: while-in-use or always, and on iOS precise or approximate. Ask for the least you need.
if (!Ti.Geolocation.hasLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE)) {
Ti.Geolocation.requestLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE, (e) => {
if (e.success) {
locate();
}
});
} else {
locate();
}
tiapp.xml needs the matching usage string on iOS:
<ios>
<plist>
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Show which notes were written near you.</string>
</dict>
</plist>
</ios>
Asking for AUTHORIZATION_ALWAYS is a much bigger request, is reviewed harder,
and on iOS the user is asked again later whether they meant it. Do not request
it for a feature that works while the app is open.
One position
function locate() {
Ti.Geolocation.getCurrentPosition((e) => {
if (!e.success) {
Ti.API.error(`location failed: ${e.error}`);
return;
}
const { latitude, longitude, accuracy } = e.coords;
Ti.API.info(`${latitude}, ${longitude} +/- ${accuracy}m`);
});
}
accuracy on the result is a radius in metres, and it is the number that
decides whether a fix is usable. A first fix indoors can be several hundred
metres wide; treat anything above your tolerance as "not yet" rather than as an
answer.
Tracking
Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_HIGH;
Ti.Geolocation.distanceFilter = 10;
function onLocation(e) {
if (!e.success) return;
Ti.API.info(`moved to ${e.coords.latitude}, ${e.coords.longitude}`);
}
Ti.Geolocation.addEventListener('location', onLocation);
distanceFilter is metres of movement before another event, and it is the
single most effective thing you can set: without it you get an event per fix,
which is a battery complaint waiting to happen.
Remove the listener when the screen goes away. Location updates continue while a listener is attached, whether or not anything is looking at them.
win.addEventListener('close', () => {
Ti.Geolocation.removeEventListener('location', onLocation);
});
Set accuracy to the loosest value that works. ACCURACY_HIGH powers the GPS
radio; a "which city" feature does not need it.
Addresses
reverseGeocoder turns coordinates into an address and forwardGeocoder does
the reverse. Both are network calls against a platform service, so they fail
offline and are rate limited:
Ti.Geolocation.reverseGeocoder(latitude, longitude, (e) => {
if (e.success && e.places.length) {
Ti.API.info(e.places[0].address);
}
});
Maps
Maps are not in the core SDK. ti.map is a module, maintained by TiDev,
and it wraps Google Maps on Android and MapKit on iOS.
<modules>
<module platform="android">ti.map</module>
<module platform="iphone">ti.map</module>
</modules>
const Map = require('ti.map');
const view = Map.createView({
mapType: Map.NORMAL_TYPE,
region: { latitude: 51.5, longitude: -0.12, latitudeDelta: 0.05, longitudeDelta: 0.05 },
annotations: [
Map.createAnnotation({ latitude: 51.5, longitude: -0.12, title: 'Here' })
]
});
win.add(view);
Android additionally needs a Google Maps API key in tiapp.xml, and a build
without one shows an empty grid rather than an error. If your map is blank grey
squares, that is the reason.
See using modules for installing it, and the module's own reference for the full API.

Next
Notifications covers local and push.