1 |
|
2 |
|
3 | import {
|
4 | NativeEventEmitter,
|
5 | NativeModules,
|
6 | Platform,
|
7 | } from 'react-native';
|
8 |
|
9 | type LocationOptions = {
|
10 | enableHighAccuracy: ?bool,
|
11 | timeInterval: ?number,
|
12 | distanceInterval: ?number,
|
13 | }
|
14 |
|
15 | type LocationData = {
|
16 | coords: {
|
17 | latitude: number,
|
18 | longitude: number,
|
19 | altitude: number,
|
20 | accuracy: number,
|
21 | heading: number,
|
22 | speed: number,
|
23 | },
|
24 | timestamp: number,
|
25 | }
|
26 |
|
27 | type LocationCallback = (data: LocationData) => any;
|
28 |
|
29 | const LocationEventEmitter = new NativeEventEmitter(NativeModules.ExponentLocation);
|
30 |
|
31 | let nextWatchId = 0;
|
32 | let watchCallbacks: { [watchId: number]: LocationCallback } = {};
|
33 | let deviceEventSubscription: ?Function;
|
34 |
|
35 | export function getCurrentPositionAsync(options: LocationOptions) {
|
36 |
|
37 | if (Platform.OS === 'android') {
|
38 | return NativeModules.ExponentLocation.getCurrentPositionAsync(options);
|
39 | }
|
40 |
|
41 |
|
42 |
|
43 | return new Promise(async (resolve, reject) => {
|
44 | try {
|
45 |
|
46 | let done = false;
|
47 |
|
48 | let subscription;
|
49 | subscription = await watchPositionAsync(options, (location) => {
|
50 | if (!done) {
|
51 | resolve(location);
|
52 | done = true;
|
53 | }
|
54 | if (subscription) {
|
55 | subscription.remove();
|
56 | }
|
57 | });
|
58 |
|
59 |
|
60 | if (done) {
|
61 | subscription.remove();
|
62 | }
|
63 | } catch (e) {
|
64 | reject(e);
|
65 | }
|
66 | });
|
67 | }
|
68 |
|
69 | export async function watchPositionAsync(options: LocationOptions, callback: LocationCallback) {
|
70 | let { ExponentLocation } = NativeModules;
|
71 |
|
72 | if (!deviceEventSubscription) {
|
73 | deviceEventSubscription = LocationEventEmitter.addListener(
|
74 | 'Exponent.locationChanged',
|
75 | ({ watchId, location }) => {
|
76 | const callback = watchCallbacks[watchId];
|
77 | if (callback) {
|
78 | callback(location);
|
79 | } else {
|
80 | ExponentLocation.removeWatchAsync(watchId);
|
81 | }
|
82 | },
|
83 | );
|
84 | }
|
85 |
|
86 | const watchId = nextWatchId++;
|
87 | watchCallbacks[watchId] = callback;
|
88 | await ExponentLocation.watchPositionImplAsync(watchId, options);
|
89 |
|
90 | let removed = false;
|
91 | return {
|
92 | remove() {
|
93 | if (!removed) {
|
94 | ExponentLocation.removeWatchAsync(watchId);
|
95 | delete watchCallbacks[watchId];
|
96 | if (Object.keys(watchCallbacks).length === 0) {
|
97 | LocationEventEmitter.removeSubscription(deviceEventSubscription);
|
98 | deviceEventSubscription = null;
|
99 | }
|
100 | removed = true;
|
101 | }
|
102 | },
|
103 | };
|
104 | }
|
105 |
|