Skip to main content
The Geolocation API provides methods to retrieve the device’s current GPS location, check location permission status, and request location permissions from the user.

Usage

Get the device’s current location:
use Native\Mobile\Facades\Geolocation;

Geolocation::getCurrentPosition();
Location data is returned asynchronously via the LocationReceived event.

Methods

getCurrentPosition(bool $fineAccuracy = false)

Retrieve the device’s current GPS location. Parameters:
  • $fineAccuracy (bool) - Use high accuracy GPS mode (default: false)
Returns: PendingGeolocation - Fluent interface for configuring the request Events:
  • Geolocation\LocationReceived - Dispatched with location data
Example:
Geolocation::getCurrentPosition(true); // High accuracy
High accuracy mode uses GPS, which provides better precision but consumes more battery. Standard mode uses network-based location (WiFi/cellular) which is faster and more energy-efficient.

checkPermissions()

Check the current location permission status. Returns: PendingGeolocation - Fluent interface for configuring the request Events:
  • Geolocation\PermissionStatusReceived - Dispatched with permission status
Example:
Geolocation::checkPermissions();

requestPermissions()

Request location permissions from the user. Returns: PendingGeolocation - Fluent interface for configuring the request Events:
  • Geolocation\PermissionRequestResult - Dispatched with the user’s response
Example:
Geolocation::requestPermissions();

Fluent API

The PendingGeolocation class provides a fluent interface:

id(string $id)

Set a unique identifier for the geolocation request. Example:
Geolocation::getCurrentPosition()
    ->id('user-location-request');

event(string $eventClass)

Dispatch a custom event instead of the default event. Example:
Geolocation::getCurrentPosition()
    ->event(MyCustomLocationEvent::class);

fineAccuracy(bool $fine = true)

Request high accuracy GPS location (only for getCurrentPosition). Example:
Geolocation::getCurrentPosition()
    ->fineAccuracy(true);

remember()

Store the request ID in the session for later retrieval. Example:
Geolocation::getCurrentPosition()
    ->remember();

// Later
$id = PendingGeolocation::lastId();

get()

Explicitly execute the geolocation operation (called automatically if not invoked). Example:
Geolocation::getCurrentPosition()
    ->fineAccuracy()
    ->id('my-location')
    ->get();

Events

Native\Mobile\Events\Geolocation\LocationReceived

Dispatched when location data is received. Properties:
  • success (bool) - Whether location was retrieved successfully
  • latitude (float|null) - Latitude coordinate
  • longitude (float|null) - Longitude coordinate
  • accuracy (float|null) - Location accuracy in meters
  • timestamp (int|null) - Unix timestamp of location reading
  • provider (string|null) - Location provider (‘gps’, ‘network’, ‘fused’)
  • error (string|null) - Error message if failed
  • id (string|null) - Request identifier if set
Example:
use Native\Mobile\Events\Geolocation\LocationReceived;

class LocationListener
{
    public function handle(LocationReceived $event)
    {
        if ($event->success) {
            Log::info('Location received', [
                'lat' => $event->latitude,
                'lng' => $event->longitude,
                'accuracy' => $event->accuracy,
                'provider' => $event->provider,
            ]);
        } else {
            Log::error('Location error: ' . $event->error);
        }
    }
}

Native\Mobile\Events\Geolocation\PermissionStatusReceived

Dispatched with the current permission status.

Native\Mobile\Events\Geolocation\PermissionRequestResult

Dispatched with the result of a permission request.

Examples

Basic Location Retrieval

use Native\Mobile\Facades\Geolocation;
use Native\Mobile\Events\Geolocation\LocationReceived;

// Request location
public function getLocation()
{
    Geolocation::getCurrentPosition()
        ->fineAccuracy()
        ->id('user-location');
}

// Handle location
class LocationListener
{
    public function handle(LocationReceived $event)
    {
        if ($event->success) {
            session([
                'latitude' => $event->latitude,
                'longitude' => $event->longitude,
            ]);
        }
    }
}

Store Check-In Location

use Native\Mobile\Facades\Geolocation;
use Native\Mobile\Events\Geolocation\LocationReceived;

public function checkIn(Store $store)
{
    Geolocation::getCurrentPosition()
        ->fineAccuracy()
        ->id("checkin-{$store->id}")
        ->remember();
}

class CheckInListener
{
    public function handle(LocationReceived $event)
    {
        $expectedId = PendingGeolocation::lastId();
        
        if ($event->id === $expectedId && $event->success) {
            $storeId = str_replace('checkin-', '', $event->id);
            
            CheckIn::create([
                'user_id' => auth()->id(),
                'store_id' => $storeId,
                'latitude' => $event->latitude,
                'longitude' => $event->longitude,
                'accuracy' => $event->accuracy,
                'checked_in_at' => now(),
            ]);
        }
    }
}

Permission Flow

use Native\Mobile\Facades\Geolocation;
use Native\Mobile\Events\Geolocation\PermissionStatusReceived;
use Native\Mobile\Events\Geolocation\PermissionRequestResult;

public function setupLocation()
{
    // First check if we already have permission
    Geolocation::checkPermissions()->id('permission-check');
}

class PermissionStatusListener
{
    public function handle(PermissionStatusReceived $event)
    {
        if ($event->granted) {
            // Permission already granted, get location
            Geolocation::getCurrentPosition();
        } else {
            // Need to request permission
            Geolocation::requestPermissions()->id('permission-request');
        }
    }
}

class PermissionRequestListener
{
    public function handle(PermissionRequestResult $event)
    {
        if ($event->granted) {
            // Permission granted, now get location
            Geolocation::getCurrentPosition();
        } else {
            // Permission denied
            Dialog::alert(
                'Location Required',
                'This app needs location access to function properly.'
            );
        }
    }
}

Nearby Places Finder

use Native\Mobile\Facades\Geolocation;
use Native\Mobile\Events\Geolocation\LocationReceived;
use Illuminate\Support\Facades\Http;

public function findNearbyPlaces(string $type = 'restaurant')
{
    Geolocation::getCurrentPosition()
        ->id("nearby-{$type}")
        ->remember();
}

class NearbyPlacesListener
{
    public function handle(LocationReceived $event)
    {
        if (!$event->success) {
            return;
        }
        
        $type = str_replace('nearby-', '', $event->id);
        
        // Query places API
        $response = Http::get('https://api.example.com/places/nearby', [
            'lat' => $event->latitude,
            'lng' => $event->longitude,
            'type' => $type,
            'radius' => 5000, // 5km
        ]);
        
        $places = $response->json()['results'];
        
        // Calculate distances
        foreach ($places as &$place) {
            $place['distance'] = $this->calculateDistance(
                $event->latitude,
                $event->longitude,
                $place['lat'],
                $place['lng']
            );
        }
        
        // Sort by distance
        usort($places, fn($a, $b) => $a['distance'] <=> $b['distance']);
        
        session(['nearby_places' => $places]);
    }
    
    private function calculateDistance($lat1, $lon1, $lat2, $lon2)
    {
        $earthRadius = 6371; // km
        
        $dLat = deg2rad($lat2 - $lat1);
        $dLon = deg2rad($lon2 - $lon1);
        
        $a = sin($dLat/2) * sin($dLat/2) +
             cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
             sin($dLon/2) * sin($dLon/2);
        
        $c = 2 * atan2(sqrt($a), sqrt(1-$a));
        
        return $earthRadius * $c;
    }
}

Delivery Tracking

use Native\Mobile\Facades\Geolocation;
use Native\Mobile\Events\Geolocation\LocationReceived;

class DeliveryTracker
{
    private $trackingActive = false;
    
    public function startTracking(Order $order)
    {
        $this->trackingActive = true;
        $this->updateLocation($order);
    }
    
    private function updateLocation(Order $order)
    {
        if (!$this->trackingActive) {
            return;
        }
        
        Geolocation::getCurrentPosition()
            ->fineAccuracy()
            ->id("delivery-{$order->id}");
    }
}

class DeliveryLocationListener
{
    public function handle(LocationReceived $event)
    {
        if (!str_starts_with($event->id, 'delivery-')) {
            return;
        }
        
        if ($event->success) {
            $orderId = str_replace('delivery-', '', $event->id);
            
            // Update delivery location in database
            DeliveryLocation::create([
                'order_id' => $orderId,
                'latitude' => $event->latitude,
                'longitude' => $event->longitude,
                'accuracy' => $event->accuracy,
                'timestamp' => $event->timestamp,
            ]);
            
            // Broadcast to customer
            broadcast(new DeliveryLocationUpdated($orderId, [
                'lat' => $event->latitude,
                'lng' => $event->longitude,
            ]));
        }
    }
}

Geofencing

use Native\Mobile\Facades\Geolocation;
use Native\Mobile\Events\Geolocation\LocationReceived;

class GeofenceMonitor
{
    public function checkGeofence(Geofence $geofence)
    {
        Geolocation::getCurrentPosition()
            ->id("geofence-{$geofence->id}");
    }
}

class GeofenceListener
{
    public function handle(LocationReceived $event)
    {
        if (!str_starts_with($event->id, 'geofence-')) {
            return;
        }
        
        if (!$event->success) {
            return;
        }
        
        $geofenceId = str_replace('geofence-', '', $event->id);
        $geofence = Geofence::find($geofenceId);
        
        $distance = $this->calculateDistance(
            $event->latitude,
            $event->longitude,
            $geofence->latitude,
            $geofence->longitude
        );
        
        if ($distance <= $geofence->radius) {
            // User entered geofence
            event(new UserEnteredGeofence($geofence, auth()->user()));
            
            Dialog::toast("Welcome to {$geofence->name}!");
        }
    }
}

Platform Notes

iOS

Permissions

  • Requires NSLocationWhenInUseUsageDescription in Info.plist
  • For background: NSLocationAlwaysUsageDescription
  • Two levels: “When In Use” and “Always”
  • Users can change permissions in Settings

Accuracy

  • fineAccuracy: false - Network/WiFi location (faster, less battery)
  • fineAccuracy: true - GPS location (slower, more accurate, more battery)
  • Typical accuracy: 5-10m (GPS), 50-100m (network)

Provider

  • Returns ‘gps’, ‘network’, or ‘fused’
  • iOS automatically selects best provider

Android

Permissions

  • Requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION
  • Android 10+: Background requires ACCESS_BACKGROUND_LOCATION
  • Runtime permissions required (Android 6+)

Accuracy

  • fineAccuracy: false - Coarse location (network-based)
  • fineAccuracy: true - Fine location (GPS-based)
  • Uses Fused Location Provider for best results

Provider

  • Returns ‘gps’, ‘network’, or ‘fused’
  • Fused provider combines GPS, WiFi, and cell tower data
Location requests can fail if the user has disabled location services at the system level. Always check event.success and handle errors gracefully.
High accuracy GPS location can take several seconds to acquire the first fix, especially indoors or with obstructed sky view. Consider showing a loading indicator to users.
Location accuracy varies based on environment, device capabilities, and location provider. The accuracy property in the event indicates the estimated accuracy radius in meters.

Build docs developers (and LLMs) love