import { useEffect, useState } from "react";
import BackgroundGeolocation, {
State,
AuthorizationEvent,
HttpEvent,
} from "react-native-background-geolocation";
import { TokenManager } from "@/lib/token-manager";
import API_CONFIG from "@/config/api.config";
interface UseBackgroundGeoProps {
hubId?: string;
}
const useBackgroundGeolocation = ({ hubId }: UseBackgroundGeoProps) => {
const [enabled, setEnabled] = useState(false);
const [token, setToken] = useState<string | null>(null);
const [refreshToken, setRefreshToken] = useState<string | null>(null);
const syncLibraryTokens = async () => {
try {
const accessToken = await TokenManager.getAccessToken();
const refreshToken = await TokenManager.getRefreshToken();
if (!accessToken || !refreshToken) return;
await BackgroundGeolocation.setConfig({
authorization: {
strategy: "JWT",
accessToken: accessToken,
refreshToken: refreshToken,
refreshUrl: `${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINTS.AUTH.REFRESH_GEO_LOCATION}`,
refreshPayload: {
"refresh_token": "{refreshToken}",
},
refreshHeaders: {
"platform-type": "app",
"app-secret-key": "Test",
},
}
});
} catch (error: any) {
if (error?.includes && error.includes("busy")) {
console.log("ℹ️ [Geo] Library busy, it will retry later.");
}
}
};
useEffect(() => {
const loadTokens = async () => {
try {
const t = await TokenManager.getAccessToken();
const rt = await TokenManager.getRefreshToken();
setToken(t);
setRefreshToken(rt);
} catch (error) {
console.error("Failed to load tokens", error);
}
};
loadTokens();
}, []);
useEffect(() => {
BackgroundGeolocation.onLocation((location) => {
console.log("📍 LOCATION DETECTED", {
lat: location.coords.latitude,
lng: location.coords.longitude,
accuracy: location.coords.accuracy,
event: location.event,
odometer: location.odometer,
});
});
BackgroundGeolocation.onMotionChange((motion) => {
console.log("Motion change", motion);
});
BackgroundGeolocation.onAuthorization(async (event: AuthorizationEvent) => {
if (event.success) {
await TokenManager.setTokens(
event.response?.access_token || event.response?.data?.access_token,
event.response?.refresh_token || event.response?.data?.refresh_token
);
} else {
syncLibraryTokens();
}
});
BackgroundGeolocation.onHttp((response: HttpEvent) => {
console.log(`[http] ${response.status} ${response.responseText}`);
});
BackgroundGeolocation.ready({
persistence: {
persistMode: BackgroundGeolocation.PersistMode.None,
},
geolocation: {
desiredAccuracy: BackgroundGeolocation.DesiredAccuracy.Navigation,
locationUpdateInterval: 5000,
fastestLocationUpdateInterval: 5000,
locationAuthorizationRequest: BackgroundGeolocation.LocationRequest.Always,
distanceFilter:0
},
app: {
stopOnTerminate: false,
startOnBoot: true,
enableHeadless: true,
notification: {
title: "Background Geolocation",
text: "Tracking location",
smallIcon: "mipmap/ic_launcher",
sticky: true,
},
},
logger: {
logLevel: BackgroundGeolocation.LogLevel.Verbose,
debug:false,
logMaxDays:1
},
http: {
autoSync:false
},
}).then((state: State) => {
console.log("[ready] Plugin initialized, enabled:", state.enabled);
setEnabled(state.enabled);
});
return () => {
BackgroundGeolocation.removeListeners();
};
}, []);
useEffect(() => {
if (!token || !refreshToken || !hubId) return;
BackgroundGeolocation.setConfig({
persistence: {
persistMode: BackgroundGeolocation.PersistMode.All,
disableProviderChangeRecord: true,
locationTemplate:
'{"lat":<%= latitude %>,"lng":<%= longitude %>,"timestamp": "<%= timestamp %>","metadata":{"latitude":<%= latitude %>,"longitude":<%= longitude %>,"accuracy":<%= accuracy %>,"speed":<%= speed %>,"heading":<%= heading %>,"altitude":<%= altitude %>,"ellipsoidal_altitude":<%= ellipsoidal_altitude %>,"activity":{"type":"<%= activity.type %>","confidence":<%= activity.confidence %>},"battery":{"level":<%= battery.level %>,"is_charging":<%= battery.is_charging %>},"odometer":<%= odometer %>}}',
extras: {
hub_id: hubId,
},
},
geolocation: {
desiredAccuracy: BackgroundGeolocation.DesiredAccuracy.Navigation,
locationUpdateInterval: 5000,
fastestLocationUpdateInterval: 5000,
locationAuthorizationRequest: BackgroundGeolocation.LocationRequest.Always,
distanceFilter:0
},
http: {
url: `${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINTS.RIDER.UPDATE_LOCATION}`,
method: "POST",
autoSync: true,
batchSync: true,
rootProperty: "data",
maxBatchSize:100,
headers: {
"Content-Type": "application/json",
"platform-type": "app",
"app-secret-key": "Test",
},
},
authorization: {
strategy: "JWT",
accessToken: token,
refreshToken: refreshToken,
refreshUrl: `${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINTS.AUTH.REFRESH_GEO_LOCATION}`,
refreshPayload: {
"refresh_token": "{refreshToken}",
},
refreshHeaders: {
"platform-type": "app",
"app-secret-key": "Test",
},
},
}).then(() => {
BackgroundGeolocation.getState().then(async(state) => {
if (!state.enabled) {
await BackgroundGeolocation.start();
// await BackgroundGeolocation.changePace(true);
setEnabled(true);
}
});
});
}, [token, refreshToken, hubId]);
const handldeCloseGeoLocation = () => {
BackgroundGeolocation.stop().then(() => {
console.log("geolocation sdk is off now");
setEnabled(false);
});
};
return { enabled, setEnabled, handldeCloseGeoLocation };
};
export default useBackgroundGeolocation;
Required Reading
Plugin Version
5.0.3
Mobile operating-system(s)
Device Manufacturer(s) and Model(s)
vivo V2059
Device operating-systems(s)
13
React Native / Expo version
No response
What happened?
plugin not working in background for a interval btw 10:06:47 and 10:40:45
99b68b6966bb44f580bf5c67c3b1baa6.gz
Plugin Code and/or Config
Relevant log output