Location (GPS)
Access device GPS location
Overview
Supports getting the current location via GPS and network. Android and iOS use the same JS API.
| Feature | Android | iOS |
|---|---|---|
| Get current location | ✓ (Android 7.0+) | ✓ (iOS 13+) |
| Watch location changes | ✓ (Android 7.0+) | ✓ (iOS 13+) |
Supported Plan: Basic and above
iOS Prerequisites
To use location features on iOS, add a location usage description to Info.plist.
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location access is required to provide location-based services.</string>The usage description must accurately reflect the actual purpose of location access to pass App Store review. If background location is needed, also add NSLocationAlwaysAndWhenInUseUsageDescription.
Android Permission Notes
To use location features on Android, first uncomment the location permissions in AndroidManifest.xml. The SDK ships these permissions commented out by default, so enable only the ones you actually use (Google Play Data Safety policy).
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />When the SDK requests location permission, the options shown to the user vary by Android version.
| Android Version | User Options |
|---|---|
| Android 11 and below | While using the app / Only this time / Deny |
| Android 12 – 16 | User can choose precise or approximate location |
| Android 17+ | New option: grant precise location temporarily (while app is open only) |
If the user selects Approximate location, coordinates within a ~3 km radius are returned. The SDK requests precise location (ACCESS_FINE_LOCATION) but cannot override the user's choice.
With the temporary precise location option introduced in Android 17, the permission may expire after the app moves to the background. The SDK handles this automatically — if the permission is missing on the next request, the permission dialog is shown again, and if location retrieval fails, the callback is called with isSuccess: false.
Get Current Location
window.unveilyBridge.location.get({
accuracy: "high", // "high" | "medium" | "low"
timeout: 10000, // Maximum wait time (ms)
onResult: "onLocationResult",
onError: "onLocationError"
});
function onLocationResult(result) {
const { latitude, longitude, accuracy } = JSON.parse(result);
console.log(`Lat: ${latitude}, Lng: ${longitude}, Accuracy: ${accuracy}m`);
}
function onLocationError(error) {
const { code, message } = JSON.parse(error);
if (code === "PERMISSION_DENIED") {
alert("Please allow location permission.");
}
}Response Structure
{ "latitude": 37.5665, "longitude": 126.9780, "accuracy": 15.0 }Watch Location Changes (continuous)
window.unveilyBridge.location.watch({
minDistance: 10, // Callback triggers when moved at least this distance (m)
onUpdate: "onLocationUpdate"
});
function onLocationUpdate(result) {
const { latitude, longitude } = JSON.parse(result);
updateMap(latitude, longitude);
}
// Stop watching
window.unveilyBridge.location.stopWatch();Error Codes
| Code | Description |
|---|---|
PERMISSION_DENIED | No location permission |
TIMEOUT | Could not get location within specified time |
UNAVAILABLE | GPS or network location unavailable |
Server-side Location Storage
app.post('/api/location', (req, res) => {
const { latitude, longitude } = req.body;
const userId = req.session.userId;
db.query(
'INSERT INTO user_locations (user_id, latitude, longitude, recorded_at) VALUES (?, ?, ?, NOW())',
[userId, latitude, longitude]
);
res.json({ ok: true });
});[HttpPost("location")]
[Authorize]
public async Task<IActionResult> SaveLocation([FromBody] LocationRequest request)
{
await _locationService.SaveAsync(User.GetUserId(), request.Latitude, request.Longitude);
return Ok(new { ok = true });
}@PostMapping("/api/location")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<?> saveLocation(@RequestBody LocationRequest request,
@AuthenticationPrincipal UserDetails user) {
locationService.save(user.getUsername(), request.getLatitude(), request.getLongitude());
return ResponseEntity.ok(Map.of("ok", true));
}<?php
$data = json_decode(file_get_contents('php://input'), true);
$stmt = $pdo->prepare(
'INSERT INTO user_locations (user_id, latitude, longitude, recorded_at) VALUES (?, ?, ?, NOW())'
);
$stmt->execute([$_SESSION['user_id'], $data['latitude'], $data['longitude']]);
echo json_encode(['ok' => true]);<%
Dim lat, lng
lat = Request.Form("latitude")
lng = Request.Form("longitude")
Dim conn
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open Application("ConnectionString")
conn.Execute "INSERT INTO user_locations (user_id, latitude, longitude) VALUES (" & _
Session("user_id") & ", " & lat & ", " & lng & ")"
Response.ContentType = "application/json"
Response.Write "{""ok"": true}"
%>