How BrokerOS tracks field agent locations in the background every minute using Expo TaskManager, SecureStore persistence, and low-power foreground services.
BrokerOS automatically monitors the real-time geographic location of field agents (Sales Executives, Sourcing Managers, and Closing Managers) during their scheduled working shifts.This tracking provides two core enterprise capabilities:
Live Management Oversight: Sales managers can view their entire field team on an interactive Google Maps overlay in the web dashboard.
Site Visit Validation: Real-time coordinates verify that sales executives were physically present at designated project sites during client meetings.
When the mobile application is minimized or the device screen is locked, Android spawns a headless JavaScript context to execute location updates. In this headless environment:
React state, context hooks, and component memory do not exist
Active session objects and web clients are uninitialized
To ensure the backend knows which employee is broadcasting coordinates, the dashboard shell writes the authenticated userId to expo-secure-store during boot. The headless task reads USER_ID_KEY from disk on every execution tick.
To prevent the Android operating system from killing the tracking process during background battery optimization, BrokerOS runs an Android Foreground Service with a persistent notification:
await Location.startLocationUpdatesAsync(LOCATION_TASK_NAME, { accuracy: Location.Accuracy.Balanced, timeInterval: 1 * 60 * 1000, // Executes every 1 minute distanceInterval: 0, // Triggers even if stationary deferredUpdatesInterval: 1 * 60 * 1000, showsBackgroundLocationIndicator: true, foregroundService: { notificationTitle: 'Live Tracking Active', notificationBody: 'Your location is being shared with the dashboard.', notificationColor: '#2563eb', },});
This persistent notification informs field employees that their location is being actively logged and ensures continuous execution across all Android OEM battery managers (Samsung, Xiaomi, OnePlus, Google Pixel).
Skips redundant backend API calls if the agent has moved less than 10 meters since the previous recorded ping:
const dist = getDistanceMeters(Number(lastLat), Number(lastLng), lat, lng);if (dist < 10) { // Movement under 10 meters. Skip API transmission to save battery. return;}
Requested upon initial dashboard mount. Provides high-precision coordinates.
Background Location
ACCESS_BACKGROUND_LOCATION
Prompts user to select “Allow all the time” in Android system settings.
Foreground Service
FOREGROUND_SERVICE_LOCATION
Required for continuous location broadcast notifications on Android 14+.
If an employee revokes background location permissions, tracking terminates when the app is minimized. The management dashboard will display their last known pin with a “Location Stale” warning indicator.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"BrokerOS","colors":{"primary":"#4F46E5","light":"#818CF8","dark":"#3730A3"},"favicon":"https://mintcdn.com/brokeros/h3YNa7FZnZrwhmKZ/favicon.ico?fit=max\u0026auto=format\u0026n=h3YNa7FZnZrwhmKZ\u0026q=85\u0026s=e72ec9d0d4a35947353f8573e171d278","navbar":{"links":[{"href":"/api-reference/overview","label":"API Reference"},{"href":"https://github.com/trybrokeros/BrokerOS/discussions","label":"Support"}],"primary":{"type":"button","label":"Open CRM","href":"https://github.com/trybrokeros/BrokerOS"}},"footer":{"socials":{"github":"https://github.com/trybrokeros/brokeros","linkedin":"https://linkedin.com/company/brokeros"}},"search":{"prompt":"Search for Leads, Campaigns, Voice Agents, Site Visits, APIs..."},"seo":{"metatags":{"canonical":"https://brokeros.mintlify.site","og:site_name":"BrokerOS Documentation","og:type":"website","twitter:site":"@brokeros","twitter:card":"summary_large_image"},"organization":{"name":"BrokerOS","url":"https://brokeros.com","logo":"https://brokeros.mintlify.site/favicon.ico","sameAs":["https://github.com/trybrokeros/brokeros","https://linkedin.com/company/brokeros"]}},"styling":{"eyebrows":"breadcrumbs","latex":true},"banner":{"content":"🚀 **BrokerOS Enterprise CRM \u0026 AI Voice Engine** — Built for serious real estate brokerage firms. [Explore Guides →](/overview/introduction)","dismissible":true},"contextual":{"options":["copy","view","chatgpt","claude","perplexity","cursor","vscode"],"display":"header"},"thumbnails":{"fonts":{"family":"Geist"}},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"brokeros","hasAudioNarration":false,"actualSubdomain":"brokeros","customDomains":[],"gitSource":{"type":"github","owner":"trybrokeros","repo":"brokeros","deployBranch":"main","contentDirectory":"docs","isPrivate":false,"mountPath":"","label":""},"chroma":{"latestBuiltDeploymentHistoryId":"6ad30e2da9ed954cf987da2a","collectionId":"0f6e40a0-0684-45d7-ba7a-f46d065ba882","liveDeploymentHistoryId":"6ad30e2da9ed954cf987da2a","schemaVersion":"v3"},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6ad30e2da9ed954cf987da2a","clientVersion":"0.0.3964","searchFilterCounts":[{"language":"default","tag":"Marketing","count":50},{"language":"default","tag":"Integrations","count":35},{"language":"default","tag":"Developer","count":23},{"language":"default","tag":"Brokerage CRM","count":23},{"language":"default","tag":"API Reference","count":17},{"language":"default","tag":"WhatsApp","count":13},{"language":"default","tag":"Mobile App","count":12},{"language":"default","tag":"Email","count":11},{"language":"default","tag":"SMS","count":11},{"language":"default","tag":"SMS Gateways","count":10}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-v7-file-tree","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"pause-universal-search-reconcile","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"per-site-search-delta","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-private-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-nav-generations","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-agent-model-picker","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"isAtlas":false,"googleFontsInlined":false},"customCss":[{"filePath":"custom.css","content":"@keyframes brokeros-search-glow{0%,to{box-shadow:0 0 0 2px rgba(79,70,229,.15),0 4px 12px rgba(79,70,229,.08)}50%{box-shadow:0 0 0 3px rgba(99,102,241,.28),0 6px 20px rgba(79,70,229,.2)}}div[class*=\"peer-[.is-not-custom]\"],div[class*=max-w-8xl]{max-width:100%!important;padding-left:2rem!important;padding-right:2rem!important}#sidebar,aside:first-of-type,aside:has(nav),nav#sidebar{width:240px!important;min-width:240px!important;max-width:240px!important;flex:0 0 240px!important}#sidebar a,aside:has(nav) a,nav#sidebar a{font-size:.875rem!important;padding-top:5px!important;padding-bottom:5px!important}#content-side-layout{width:210px!important;min-width:210px!important;max-width:210px!important;flex:0 0 210px!important;margin-left:0!important;margin-right:0!important}#table-of-contents-layout{padding-left:1rem!important;padding-right:0!important}#table-of-contents,#table-of-contents-layout{width:100%!important;min-width:0!important;max-width:100%!important}#content-side-layout h2,#table-of-contents h2,[id*=on-this-page]{font-size:.8125rem!important;font-weight:600!important;letter-spacing:.03em!important;text-transform:uppercase!important;margin-bottom:.75rem!important}#table-of-contents a,#table-of-contents-content a,.toc a,[data-component-part=scroll-area-content] a{font-size:.8125rem!important;line-height:1.45!important;padding-top:4px!important;padding-bottom:4px!important;display:block!important;word-break:break-word!important}#content-area{flex:1 1 0%!important;width:auto!important;max-width:none!important;margin-left:0!important;margin-right:0!important;padding-left:1.5rem!important;padding-right:2rem!important}#content,.mdx-content,.prose,[class*=prose],article{max-width:960px!important;width:100%!important}body,html{font-size:16px!important}#content,#content p,.prose,.prose p,[class*=prose],[class*=prose] p,article,article p,main{font-size:1rem!important;line-height:1.72!important}#content p,.prose p,[class*=prose] p,article p{margin-top:1rem!important;margin-bottom:1rem!important;color:#d1d5db!important}#content h1,#page-title,.prose h1,[class*=prose] h1,h1{font-size:1.65rem!important;line-height:1.3!important;font-weight:700!important;letter-spacing:-.02em!important;margin-bottom:.75rem!important}#content h2:not([data-component-part=card-title]):not(.card h2),.prose h2:not([data-component-part=card-title]):not(.card h2),h2:not([data-component-part=card-title]):not(.card h2){font-size:1.4rem!important;line-height:1.35!important;font-weight:600!important;letter-spacing:-.015em!important;margin-top:2rem!important;margin-bottom:.75rem!important}.card h2,[data-component-part=card-title],h2[data-component-part=card-title]{letter-spacing:-.01em!important}#content .card h2,#content [data-component-part=card-title],.card [data-component-part=card-title],.card h2.not-prose{font-size:1.1rem!important;line-height:1.35!important;font-weight:600!important;margin-top:.5rem!important;margin-bottom:.25rem!important;letter-spacing:-.01em!important}#content h4,.card [data-component-part=card-content],.card [data-component-part=card-content] p,.card [data-component-part=card-content] span,.prose h4,h4{font-size:.785rem!important;line-height:1.45!important}#content h3,.prose h3,h3{font-size:1.2rem!important;line-height:1.4!important;font-weight:600!important;margin-top:1.5rem!important;margin-bottom:.5rem!important}#content h4,.prose h4,h4{font-size:1.05rem!important;font-weight:600!important}#content ol,#content ul,.prose ol,.prose ul{font-size:1rem!important;line-height:1.68!important;margin-top:.5rem!important;margin-bottom:.85rem!important}#content li,.prose li{margin-top:.3rem!important;margin-bottom:.3rem!important}.DocSearch-Button,.mintlify-search,.search-button,[aria-label*=search],[data-search-button],[placeholder*=Search],button[data-testid*=search]{background:rgba(79,70,229,.04)!important;border:2px solid #4f46e5!important;box-shadow:0 0 0 2px rgba(79,70,229,.15),0 4px 14px rgba(79,70,229,.1)!important;border-radius:12px!important;transition:all .25s cubic-bezier(.16,1,.3,1)!important;min-width:270px!important;padding:10px 16px!important}.DocSearch-Button:hover,.mintlify-search:hover,.search-button:hover,[aria-label*=search]:hover,[data-search-button]:hover,[placeholder*=Search]:hover,button[data-testid*=search]:hover{transform:translateY(-2px)!important;border-color:#6366f1!important;box-shadow:0 0 0 3px rgba(99,102,241,.25),0 8px 24px rgba(79,70,229,.22)!important}.DocSearch-Button,[data-search-button]{animation:brokeros-search-glow 3s ease-in-out infinite!important}*{scrollbar-width:thin;scrollbar-color:#4f46e5 transparent}::-webkit-scrollbar{width:4px;height:4px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:#4f46e5;border-radius:9999px}::-webkit-scrollbar-thumb:hover{background:#3730a3}.card,[class*=CardGroup]>*,[class*=card]{border-radius:12px!important;transition:transform .2s ease,border-color .2s ease,box-shadow .2s ease!important;font-size:.85rem!important}.card:hover,[class*=CardGroup]>:hover,[class*=card]:hover{transform:translateY(-3px)!important;box-shadow:0 12px 28px -6px rgba(79,70,229,.12),0 4px 12px -2px rgba(0,0,0,.05)!important}.card h1,.card h2,.card h3,.card h4,.not-prose[data-component-part=card-title],[class*=CardGroup] [data-component-part=card-title],[class*=CardGroup] h1,[class*=CardGroup] h2,[class*=CardGroup] h3,[class*=CardGroup] h4,[class*=Card] [class*=title],[class*=card] [class*=title],[class*=card] h1,[class*=card] h2,[class*=card] h3,[data-component-part=card-title],h2[data-component-part=card-title]{font-size:.7rem!important;font-weight:600!important;line-height:1.2!important;margin-top:.35rem!important;margin-bottom:.1rem!important}.card p,.card span,[class*=CardGroup] p,[class*=CardGroup] span,[class*=card] [class*=description],[class*=card] p,[data-component-part=card-content],[data-component-part=card-content] *,[data-component-part=card-content] p,[data-component-part=card-content] span{font-size:.8rem!important;line-height:1.42!important;margin:0!important}.badge-cp{background-color:rgba(16,185,129,.12);color:#059669;border:1px solid rgba(16,185,129,.3);display:inline-flex;align-items:center}.badge-brokerage,.badge-cp,.badge-hot{padding:2px 8px;border-radius:9999px;font-size:.75rem;font-weight:600}.badge-brokerage{background-color:rgba(79,70,229,.12);color:#4f46e5;border:1px solid rgba(79,70,229,.3);display:inline-flex;align-items:center}.badge-hot{background-color:rgba(239,68,68,.12);color:#dc2626;border:1px solid rgba(239,68,68,.3)}pre code,table{font-size:.825rem!important}pre code{font-family:var(--font-geist-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace)!important}table{border-collapse:separate;border-spacing:0;width:100%;margin-top:.75rem!important;margin-bottom:1.25rem!important;border-radius:8px;overflow:hidden;border:1px solid rgba(229,231,235,.8)}table td,table th{padding:8px 12px!important}table th{background-color:rgba(24,24,24,.8);font-weight:600;text-align:left;font-size:.8rem!important;border-bottom:1px solid #e5e7eb}table td{font-size:.8125rem!important;line-height:1.45!important;border-bottom:1px solid #f3f4f6}table tr:last-child td{border-bottom:none}"}],"page":{"pagePath":"mobile/field/gps-tracking","slug":"/mobile/field/gps-tracking","pageMetadata":{"title":"Continuous Background GPS Location Tracking","sidebarTitle":"GPS Tracking","description":"How BrokerOS tracks field agent locations in the background every minute using Expo TaskManager, SecureStore persistence, and low-power foreground services.","href":"/mobile/field/gps-tracking"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"How BrokerOS tracks field agent locations in the background every minute using Expo TaskManager, SecureStore persistence, and low-power foreground services.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,hr:`hr`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Mermaid,Table,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Mermaid)_missingMdxReference(`Mermaid`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(Heading,{level:`2`,id:`overview`,children:`Overview`}),`\n`,_jsx(_components.p,{children:`BrokerOS automatically monitors the real-time geographic location of field agents (Sales Executives, Sourcing Managers, and Closing Managers) during their scheduled working shifts.`}),`\n`,_jsx(_components.p,{children:`This tracking provides two core enterprise capabilities:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Live Management Oversight`}),`: Sales managers can view their entire field team on an interactive Google Maps overlay in the web dashboard.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Site Visit Validation`}),`: Real-time coordinates verify that sales executives were physically present at designated project sites during client meetings.`]}),`\n`]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`tracking-pipeline-architecture`,children:`Tracking Pipeline Architecture`}),`\n`,_jsx(Mermaid,{chart:`sequenceDiagram\n autonumber\n actor Agent as Field Agent (Android Device)\n participant Shell as Dashboard Layout ((dashboard)/_layout.tsx)\n participant Task as Expo TaskManager (background-location-task)\n participant SecureStore as Android Keystore (SecureStore)\n participant LocationAPI as Android Location Services (Fused Location)\n participant API as BrokerOS Users API (/api/users/:id/location)\n participant Manager as Manager Live Map (Web Dashboard)\n\n Agent->>Shell: Opens Mobile App\n Shell->>SecureStore: setItemAsync('tracking_user_id', userId)\n Shell->>Task: startLocationUpdatesAsync(accuracy: Balanced, interval: 60s)\n \n loop Every 60 Seconds (Runs in Headless Background Context)\n LocationAPI->>Task: Deliver LocationObject (lat, lng, accuracy)\n Task->>SecureStore: getItemAsync('tracking_user_id')\n SecureStore-->>Task: Return userId\n Task->>API: PATCH /api/users/:userId/location { latitude, longitude }\n API->>API: Update User.latitude \u0026 User.longitude in PostgreSQL\n API->>Manager: Broadcast live coordinate update via WebSocket\n end`}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`headless-background-task-architecture`,children:`Headless Background Task Architecture`}),`\n`,_jsxs(_components.p,{children:[`The location tracking subsystem (`,_jsx(_components.a,{href:`https://github.com/trybrokeros/BrokerOS/blob/main/apps/mobile/lib/location-tracking.ts`,children:_jsx(_components.code,{children:`apps/mobile/lib/location-tracking.ts`})}),`) uses `,_jsx(_components.code,{children:`expo-location`}),` and `,_jsx(_components.code,{children:`expo-task-manager`}),` to register a background task:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`export`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` LOCATION_TASK_NAME`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'background-location-task'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` USER_ID_KEY`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'tracking_user_id'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`why-securestore-is-required-for-headless-tasks`,children:`Why SecureStore is Required for Headless Tasks`}),`\n`,_jsxs(_components.p,{children:[`When the mobile application is minimized or the device screen is locked, Android spawns a `,_jsx(_components.strong,{children:`headless JavaScript context`}),` to execute location updates. In this headless environment:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`React state, context hooks, and component memory do not exist`}),`\n`,_jsx(_components.li,{children:`Active session objects and web clients are uninitialized`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`To ensure the backend knows which employee is broadcasting coordinates, the dashboard shell writes the authenticated `,_jsx(_components.code,{children:`userId`}),` to `,_jsx(_components.strong,{children:_jsx(_components.code,{children:`expo-secure-store`})}),` during boot. The headless task reads `,_jsx(_components.code,{children:`USER_ID_KEY`}),` from disk on every execution tick.`]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`foreground-service-configuration`,children:`Foreground Service Configuration`}),`\n`,_jsx(_components.p,{children:`To prevent the Android operating system from killing the tracking process during background battery optimization, BrokerOS runs an Android Foreground Service with a persistent notification:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`12`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`12`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` Location`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`startLocationUpdatesAsync`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:`LOCATION_TASK_NAME`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` accuracy:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` Location`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`Accuracy`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`Balanced`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` timeInterval:`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 1`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` *`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 60`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` *`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 1000`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Executes every 1 minute`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` distanceInterval:`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 0`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Triggers even if stationary`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` deferredUpdatesInterval:`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 1`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` *`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 60`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` *`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 1000`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` showsBackgroundLocationIndicator:`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` true`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` foregroundService:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` notificationTitle:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'Live Tracking Active'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` notificationBody:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'Your location is being shared with the dashboard.'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` notificationColor:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '#2563eb'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`});`})}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`This persistent notification informs field employees that their location is being actively logged and ensures continuous execution across all Android OEM battery managers (Samsung, Xiaomi, OnePlus, Google Pixel).`}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`production-optimizations-\u0026-privacy-filters`,children:`Production Optimizations \u0026 Privacy Filters`}),`\n`,_jsxs(_components.p,{children:[`The tracking module in `,_jsx(_components.a,{href:`https://github.com/trybrokeros/BrokerOS/blob/main/apps/mobile/lib/location-tracking.ts`,children:_jsx(_components.code,{children:`apps/mobile/lib/location-tracking.ts`})}),` contains configurable enterprise safeguards:`]}),`\n`,_jsx(Heading,{level:`3`,id:`1-off-duty-hours-filter`,children:`1. Off-Duty Hours Filter`}),`\n`,_jsx(_components.p,{children:`Prevents tracking outside business operating hours (e.g., between 11:00 PM and 6:00 AM):`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`5`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` currentHour`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` new`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` Date`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`().`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`getHours`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`();`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`currentHour`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` >=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 23`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` ||`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` currentHour`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 6`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) {`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // Off-duty hours. Skip location transmission.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`2-distance-threshold-haversine-delta`,children:`2. Distance Threshold (Haversine Delta)`}),`\n`,_jsx(_components.p,{children:`Skips redundant backend API calls if the agent has moved less than 10 meters since the previous recorded ping:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`5`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` dist`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` getDistanceMeters`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`Number`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`lastLat`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`), `}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`Number`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`lastLng`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`), `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`lat`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`lng`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`dist`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 10`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) {`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // Movement under 10 meters. Skip API transmission to save battery.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`required-permissions-\u0026-user-experience`,children:`Required Permissions \u0026 User Experience`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{style:{textAlign:`left`},children:`Permission Scope`}),_jsx(_components.th,{style:{textAlign:`left`},children:`Android Declaration`}),_jsx(_components.th,{style:{textAlign:`left`},children:`User Experience`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{style:{textAlign:`left`},children:_jsx(_components.strong,{children:`Foreground Location`})}),_jsxs(_components.td,{style:{textAlign:`left`},children:[_jsx(_components.code,{children:`ACCESS_FINE_LOCATION`}),`, `,_jsx(_components.code,{children:`ACCESS_COARSE_LOCATION`})]}),_jsx(_components.td,{style:{textAlign:`left`},children:`Requested upon initial dashboard mount. Provides high-precision coordinates.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{style:{textAlign:`left`},children:_jsx(_components.strong,{children:`Background Location`})}),_jsx(_components.td,{style:{textAlign:`left`},children:_jsx(_components.code,{children:`ACCESS_BACKGROUND_LOCATION`})}),_jsx(_components.td,{style:{textAlign:`left`},children:`Prompts user to select “Allow all the time” in Android system settings.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{style:{textAlign:`left`},children:_jsx(_components.strong,{children:`Foreground Service`})}),_jsx(_components.td,{style:{textAlign:`left`},children:_jsx(_components.code,{children:`FOREGROUND_SERVICE_LOCATION`})}),_jsx(_components.td,{style:{textAlign:`left`},children:`Required for continuous location broadcast notifications on Android 14+.`})]})]})]}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`If an employee revokes background location permissions, tracking terminates when the app is minimized. The management dashboard will display their last known pin with a “Location Stale” warning indicator.`})})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Continuous Background GPS Location Tracking","sidebarTitle":"GPS Tracking","description":"How BrokerOS tracks field agent locations in the background every minute using Expo TaskManager, SecureStore persistence, and low-power foreground services.","href":"/mobile/field/gps-tracking"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Overview","slug":"overview","depth":2,"children":[]},{"title":"Tracking Pipeline Architecture","slug":"tracking-pipeline-architecture","depth":2,"children":[]},{"title":"Headless Background Task Architecture","slug":"headless-background-task-architecture","depth":2,"children":[{"title":"Why SecureStore is Required for Headless Tasks","slug":"why-securestore-is-required-for-headless-tasks","depth":3,"children":[]}]},{"title":"Foreground Service Configuration","slug":"foreground-service-configuration","depth":2,"children":[]},{"title":"Production Optimizations \u0026 Privacy Filters","slug":"production-optimizations-\u0026-privacy-filters","depth":2,"children":[{"title":"1. Off-Duty Hours Filter","slug":"1-off-duty-hours-filter","depth":3,"children":[]},{"title":"2. Distance Threshold (Haversine Delta)","slug":"2-distance-threshold-haversine-delta","depth":3,"children":[]}]},{"title":"Required Permissions \u0026 User Experience","slug":"required-permissions-\u0026-user-experience","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"brokeros","siteName":"BrokerOS","title":"Continuous Background GPS Location Tracking - BrokerOS","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-13T12:06:38.323Z","originalFileLocation":"mobile/field/gps-tracking.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"How BrokerOS tracks field agent locations in the background every minute using Expo TaskManager, SecureStore persistence, and low-power foreground services.\">\u003cmeta data-mint-head name=\"application-name\" content=\"BrokerOS\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/brokeros/wxNdPJILcEdSzuyA/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/brokeros/wxNdPJILcEdSzuyA/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/brokeros/wxNdPJILcEdSzuyA/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/brokeros/wxNdPJILcEdSzuyA/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/brokeros/wxNdPJILcEdSzuyA/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/brokeros/wxNdPJILcEdSzuyA/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/brokeros/wxNdPJILcEdSzuyA/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/brokeros/wxNdPJILcEdSzuyA/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/brokeros/wxNdPJILcEdSzuyA/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Continuous Background GPS Location Tracking - BrokerOS\">\u003cmeta data-mint-head property=\"og:description\" content=\"How BrokerOS tracks field agent locations in the background every minute using Expo TaskManager, SecureStore persistence, and low-power foreground services.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"BrokerOS Documentation\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://brokeros.mintlify.site/mobile/field/gps-tracking\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://brokeros.mintlify.app/_mintlify/api/og/v2?division=Field+Operations\u0026amp;title=Continuous+Background+GPS+Location+Tracking\u0026amp;description=How+BrokerOS+tracks+field+agent+locations+in+the+background+every+minute+using+Expo+TaskManager%2C+SecureStore+persistence%2C+and+low-power+foreground+services.\u0026amp;theme=30ed8906c1b11c23546517d5\u0026amp;signature=36e3e98b3c3e4291d820d67a80bfbb40f837dfa94697b1ddc2941c07bb0594c5\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Continuous Background GPS Location Tracking - BrokerOS\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"How BrokerOS tracks field agent locations in the background every minute using Expo TaskManager, SecureStore persistence, and low-power foreground services.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://brokeros.mintlify.app/_mintlify/api/og/v2?division=Field+Operations\u0026amp;title=Continuous+Background+GPS+Location+Tracking\u0026amp;description=How+BrokerOS+tracks+field+agent+locations+in+the+background+every+minute+using+Expo+TaskManager%2C+SecureStore+persistence%2C+and+low-power+foreground+services.\u0026amp;theme=30ed8906c1b11c23546517d5\u0026amp;signature=36e3e98b3c3e4291d820d67a80bfbb40f837dfa94697b1ddc2941c07bb0594c5\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/brokeros/wxNdPJILcEdSzuyA/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"BrokerOS\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#4F46E5\">\u003clink data-mint-head rel=\"canonical\" href=\"https://brokeros.mintlify.site/mobile/field/gps-tracking\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/mobile/field/gps-tracking.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://brokeros.com/#organization\",\"name\":\"BrokerOS\",\"url\":\"https://brokeros.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://brokeros.mintlify.site/favicon.ico\"},\"sameAs\":[\"https://github.com/trybrokeros/brokeros\",\"https://linkedin.com/company/brokeros\"]},{\"@type\":\"WebSite\",\"@id\":\"https://brokeros.mintlify.site#website\",\"name\":\"BrokerOS\",\"url\":\"https://brokeros.mintlify.site\",\"publisher\":{\"@id\":\"https://brokeros.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://brokeros.mintlify.site/mobile/field/gps-tracking#webpage\",\"url\":\"https://brokeros.mintlify.site/mobile/field/gps-tracking\",\"name\":\"Continuous Background GPS Location Tracking\",\"description\":\"How BrokerOS tracks field agent locations in the background every minute using Expo TaskManager, SecureStore persistence, and low-power foreground services.\",\"dateModified\":\"2026-10-13T12:06:38.323Z\",\"isPartOf\":{\"@id\":\"https://brokeros.mintlify.site#website\"},\"breadcrumb\":{\"@id\":\"https://brokeros.mintlify.site/mobile/field/gps-tracking#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://brokeros.mintlify.site/mobile/field/gps-tracking#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"BrokerOS\",\"item\":\"https://brokeros.mintlify.site\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Continuous Background GPS Location Tracking\",\"item\":\"https://brokeros.mintlify.site/mobile/field/gps-tracking\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://brokeros.mintlify.site/mobile/field/gps-tracking#article\",\"headline\":\"Continuous Background GPS Location Tracking\",\"name\":\"Continuous Background GPS Location Tracking\",\"description\":\"How BrokerOS tracks field agent locations in the background every minute using Expo TaskManager, SecureStore persistence, and low-power foreground services.\",\"url\":\"https://brokeros.mintlify.site/mobile/field/gps-tracking\",\"mainEntityOfPage\":{\"@id\":\"https://brokeros.mintlify.site/mobile/field/gps-tracking#webpage\"},\"dateModified\":\"2026-10-13T12:06:38.323Z\",\"publisher\":{\"@id\":\"https://brokeros.com/#organization\"},\"isPartOf\":{\"@id\":\"https://brokeros.mintlify.site#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"BrokerOS\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"BrokerOS","nav":{"global":null,"tabs":[{"tab":"Overview","icon":"compass","pages":[{"title":"Overview","href":"/overview/introduction"}]},{"tab":"Brokerage CRM","icon":"building","pages":[{"title":"Brokerage CRM","href":"/brokerage/leads/lifecycle"}]},{"tab":"Channel Partner (CP)","icon":"handshake","pages":[{"title":"Channel Partner (CP)","href":"/channel-partner/overview"}]},{"tab":"Marketing","icon":"bullhorn","pages":[{"title":"Marketing","href":"/marketing/overview"}]},{"tab":"Integrations","icon":"puzzle-piece","pages":[{"title":"Integrations","href":"/integrations/overview"}]},{"tab":"Mobile App","icon":"mobile","groups":[{"group":"The App","pages":[{"title":"BrokerOS Mobile App","sidebarTitle":"Overview","href":"/mobile/overview"},{"title":"Mobile App Setup, Tooling \u0026 Build Guide","sidebarTitle":"Setup \u0026 Tooling","href":"/mobile/app/setup-and-tools"},{"title":"14 Role-Specific Mobile Workspaces","sidebarTitle":"Role Workspaces","href":"/mobile/app/role-workspaces"},{"title":"Real-Time In-App Team Chat","sidebarTitle":"Team Chat","href":"/mobile/app/chat"},{"title":"Authentication \u0026 Session Management","sidebarTitle":"Auth \u0026 Sessions","href":"/mobile/app/auth"}]},{"group":"Auto-Dialer (Telecalling)","pages":[{"title":"Auto-Dialer Architecture \u0026 Native Engine","sidebarTitle":"How It Works","href":"/mobile/auto-dialer/architecture"},{"title":"The Mobile Lead Calling Queue","sidebarTitle":"Calling Queue","href":"/mobile/auto-dialer/calling-queue"},{"title":"Call Recording \u0026 AI Transcription","sidebarTitle":"Call Recording","href":"/mobile/auto-dialer/call-recording"},{"title":"Offline Operations \u0026 Queue Synchronization","sidebarTitle":"Offline Mode","description":"How the BrokerOS mobile application operates without cellular data, preserves call outcomes, and synchronizes data when connectivity resumes.","href":"/mobile/auto-dialer/offline-mode"}]},{"group":"Field Operations","pages":[{"title":"Continuous Background GPS Location Tracking","sidebarTitle":"GPS Tracking","href":"/mobile/field/gps-tracking"},{"title":"GPS-Verified Site Visits \u0026 Anti-Spoofing","sidebarTitle":"Site Verification","description":"How sales executives verify physical project visits using live camera selfie captures, GPS proximity validation, and manager approval workflows.","href":"/mobile/field/site-verification"},{"title":"Push Notifications \u0026 Real-Time Alerts","sidebarTitle":"Push Notifications","href":"/mobile/field/push-notifications"}]}]},{"tab":"Developer","icon":"code","pages":[{"title":"Developer","href":"/developer/monorepo"}]}]},"title":"Continuous Background GPS Location Tracking - BrokerOS","buildId":"dpl_HcHmUS6i3UwswnTHJUEdcTtwfdTQ","deploymentId":"dpl_HcHmUS6i3UwswnTHJUEdcTtwfdTQ","dynamics":["10e4515597"],"chunks":["BannerMarkdown-DblVYOPe.js","dist-BnkC_6oA.js","lib--scc4DXi.js","lib-B8HbPgcC.js","clsx-CCOYKgaU.js","html-void-elements-mCSPHezU.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js"]}