Converted Native to Turbo Module
This commit is contained in:
parent
b1f1f1e6ea
commit
9ae4a15260
299
App.tsx
299
App.tsx
|
@ -8,29 +8,28 @@
|
||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {useEffect} from 'react';
|
||||||
import {
|
import {
|
||||||
SafeAreaView,
|
SafeAreaView,
|
||||||
ScrollView,
|
|
||||||
StatusBar,
|
StatusBar,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Text,
|
Text,
|
||||||
View,
|
View,
|
||||||
Switch,
|
Switch,
|
||||||
Button,
|
Button,
|
||||||
Alert,
|
|
||||||
PermissionsAndroid,
|
PermissionsAndroid,
|
||||||
// ToastAndroid,
|
// ToastAndroid,
|
||||||
NativeModules,
|
// NativeModules,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
|
||||||
import BackgroundFetch from 'react-native-background-fetch';
|
|
||||||
import Geolocation, {
|
import Geolocation, {
|
||||||
GeolocationError,
|
GeolocationError,
|
||||||
GeolocationResponse,
|
// GeolocationResponse,
|
||||||
} from '@react-native-community/geolocation';
|
} from '@react-native-community/geolocation';
|
||||||
|
|
||||||
const {ForegroundHeadlessModule} = NativeModules;
|
import NativeTaskRunner from './specs/NativeTaskRunner';
|
||||||
|
|
||||||
|
// const {ForegroundHeadlessModule} = NativeModules;
|
||||||
|
|
||||||
const Colors = {
|
const Colors = {
|
||||||
gold: '#fedd1e',
|
gold: '#fedd1e',
|
||||||
|
@ -42,14 +41,37 @@ const Colors = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Util class for handling fetch-event peristence in AsyncStorage.
|
/// Util class for handling fetch-event peristence in AsyncStorage.
|
||||||
import Event from './src/Event';
|
// import Event from './src/Event';
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
import * as Location from 'expo-location';
|
||||||
|
|
||||||
Geolocation.setRNConfiguration({
|
Geolocation.setRNConfiguration({
|
||||||
skipPermissionRequests: true,
|
skipPermissionRequests: true,
|
||||||
locationProvider: 'auto',
|
locationProvider: 'auto',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
function geoLocationPromise(): Promise<GeolocationResponse | GeolocationError> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
Geolocation.getCurrentPosition(
|
||||||
|
info => {
|
||||||
|
console.log(info);
|
||||||
|
resolve(info);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log(error);
|
||||||
|
reject(error);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timeout: 20000,
|
||||||
|
maximumAge: 0,
|
||||||
|
// enableHighAccuracy: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
const requestPermissions = async () => {
|
const requestPermissions = async () => {
|
||||||
try {
|
try {
|
||||||
const granted = await PermissionsAndroid.request(
|
const granted = await PermissionsAndroid.request(
|
||||||
|
@ -85,219 +107,32 @@ const requestPermissions = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function geoLocationPromise(): Promise<GeolocationResponse | GeolocationError> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
Geolocation.getCurrentPosition(
|
|
||||||
info => {
|
|
||||||
console.log(info);
|
|
||||||
resolve(info);
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
console.log(error);
|
|
||||||
reject(error);
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timeout: 20000,
|
|
||||||
maximumAge: 0,
|
|
||||||
// enableHighAccuracy: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [enabled, setEnabled] = React.useState(false);
|
const [enabled, setEnabled] = React.useState(false);
|
||||||
const [status, setStatus] = React.useState(-1);
|
|
||||||
const [events, setEvents] = React.useState<Event[]>([]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
useEffect(() => {
|
||||||
async function asyncTask() {
|
async function getCurrentLocation() {
|
||||||
await requestPermissions();
|
let location = await Location.getLastKnownPositionAsync({});
|
||||||
initBackgroundFetch();
|
console.log(location);
|
||||||
loadEvents();
|
|
||||||
}
|
}
|
||||||
|
async function xy() {
|
||||||
asyncTask();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
/// Configure BackgroundFetch.
|
|
||||||
///
|
|
||||||
const initBackgroundFetch = async () => {
|
|
||||||
const status: number = await BackgroundFetch.configure(
|
|
||||||
{
|
|
||||||
minimumFetchInterval: 15, // <-- minutes (15 is minimum allowed)
|
|
||||||
stopOnTerminate: false,
|
|
||||||
enableHeadless: true,
|
|
||||||
startOnBoot: false,
|
|
||||||
// Android options
|
|
||||||
forceAlarmManager: false, // <-- Set true to bypass JobScheduler.
|
|
||||||
requiredNetworkType: BackgroundFetch.NETWORK_TYPE_NONE, // Default
|
|
||||||
requiresCharging: false, // Default
|
|
||||||
requiresDeviceIdle: false, // Default
|
|
||||||
requiresBatteryNotLow: false, // Default
|
|
||||||
requiresStorageNotLow: false, // Default
|
|
||||||
},
|
|
||||||
async (taskId: string) => {
|
|
||||||
console.log('[BackgroundFetch] taskId', taskId);
|
|
||||||
|
|
||||||
if (taskId === 'react-native-background-fetch') {
|
|
||||||
// console.log('[BackgroundFetch] taskId', taskId);
|
|
||||||
const event = await Event.create(taskId, false);
|
|
||||||
// Update state.
|
|
||||||
setEvents(prev => [...prev, event]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (taskId === 'com.transistorsoft.customtask') {
|
|
||||||
// Geolocation.getCurrentPosition(
|
|
||||||
// async info => {
|
|
||||||
// console.log(info);
|
|
||||||
// const event = await Event.create(taskId, false, `lat-${info.coords.latitude};long-${info.coords.longitude}`);
|
|
||||||
// },
|
|
||||||
// err => console.log(err),
|
|
||||||
// {
|
|
||||||
// timeout: 10000,
|
|
||||||
// maximumAge: 10000,
|
|
||||||
// enableHighAccuracy: false,
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
try {
|
try {
|
||||||
const locInfo = (await geoLocationPromise()) as GeolocationResponse;
|
await requestPermissions();
|
||||||
const event = await Event.create(
|
const x = await AsyncStorage.getItem('locationtask');
|
||||||
taskId,
|
if (x === '1') {
|
||||||
false,
|
|
||||||
`lat-${locInfo.coords.latitude};long-${locInfo.coords.longitude}`,
|
|
||||||
);
|
|
||||||
// Update state.
|
|
||||||
setEvents(prev => [...prev, event]);
|
|
||||||
} catch (error) {
|
|
||||||
const g = error as GeolocationError;
|
|
||||||
if (g.message) {
|
|
||||||
const event = await Event.create(taskId, false, `${g.message}`);
|
|
||||||
// Update state.
|
|
||||||
setEvents(prev => [...prev, event]);
|
|
||||||
} else {
|
|
||||||
const event = await Event.create(taskId, false);
|
|
||||||
// Update state.
|
|
||||||
setEvents(prev => [...prev, event]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// console.log('Running [customtask] here!');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finish.
|
|
||||||
BackgroundFetch.finish(taskId);
|
|
||||||
},
|
|
||||||
(taskId: string) => {
|
|
||||||
// Oh No! Our task took too long to complete and the OS has signalled
|
|
||||||
// that this task must be finished immediately.
|
|
||||||
console.log('[Fetch] TIMEOUT taskId:', taskId);
|
|
||||||
BackgroundFetch.finish(taskId);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
setStatus(status);
|
|
||||||
setEnabled(true);
|
setEnabled(true);
|
||||||
};
|
|
||||||
|
|
||||||
/// Load persisted events from AsyncStorage.
|
|
||||||
///
|
|
||||||
const loadEvents = () => {
|
|
||||||
Event.all()
|
|
||||||
.then(data => {
|
|
||||||
setEvents(data as Event[]);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
Alert.alert('Error', 'Failed to load data from AsyncStorage: ' + error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Toggle BackgroundFetch ON/OFF
|
|
||||||
///
|
|
||||||
const onClickToggleEnabled = (value: boolean) => {
|
|
||||||
setEnabled(value);
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
BackgroundFetch.start();
|
|
||||||
} else {
|
} else {
|
||||||
BackgroundFetch.stop();
|
setEnabled(false);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
/// [Status] button handler.
|
getCurrentLocation();
|
||||||
///
|
} catch (error) {
|
||||||
const onClickStatus = () => {
|
console.log('Something went wrong', error);
|
||||||
BackgroundFetch.status().then((status: number) => {
|
|
||||||
let statusConst = '';
|
|
||||||
switch (status) {
|
|
||||||
case BackgroundFetch.STATUS_AVAILABLE:
|
|
||||||
statusConst = 'STATUS_AVAILABLE';
|
|
||||||
break;
|
|
||||||
case BackgroundFetch.STATUS_DENIED:
|
|
||||||
statusConst = 'STATUS_DENIED';
|
|
||||||
break;
|
|
||||||
case BackgroundFetch.STATUS_RESTRICTED:
|
|
||||||
statusConst = 'STATUS_RESTRICTED';
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
Alert.alert('BackgroundFetch.status()', `${statusConst} (${status})`);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/// [scheduleTask] button handler.
|
|
||||||
/// Schedules a custom-task to fire in 5000ms
|
|
||||||
///
|
|
||||||
const onClickScheduleTask = () => {
|
|
||||||
const delay = 600000;
|
|
||||||
BackgroundFetch.scheduleTask({
|
|
||||||
taskId: 'com.transistorsoft.customtask',
|
|
||||||
stopOnTerminate: false,
|
|
||||||
enableHeadless: true,
|
|
||||||
delay: delay,
|
|
||||||
forceAlarmManager: false,
|
|
||||||
periodic: true,
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
Alert.alert(
|
|
||||||
'scheduleTask',
|
|
||||||
'Scheduled task with delay: ' + delay + 'ms',
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
Alert.alert('scheduleTask ERROR', error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Clear the Events list.
|
|
||||||
///
|
|
||||||
const onClickClear = () => {
|
|
||||||
Event.destroyAll();
|
|
||||||
setEvents([]);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Fetch events renderer.
|
|
||||||
///
|
|
||||||
const renderEvents = () => {
|
|
||||||
if (!events.length) {
|
|
||||||
return (
|
|
||||||
<Text style={{padding: 10, fontSize: 16}}>
|
|
||||||
Waiting for BackgroundFetch events...
|
|
||||||
</Text>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return events
|
|
||||||
.slice()
|
xy();
|
||||||
.reverse()
|
}, []);
|
||||||
.map(event => (
|
|
||||||
<View key={event.key} style={styles.event}>
|
|
||||||
<View style={{flexDirection: 'row'}}>
|
|
||||||
<Text style={styles.taskId}>
|
|
||||||
{event.taskId} {event.isHeadless ? '[Headless]' : ''}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<Text style={styles.remark}>Remark - {event.location}</Text>
|
|
||||||
<Text style={styles.timestamp}>{event.timestamp}</Text>
|
|
||||||
</View>
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
async function onLocPress(): Promise<void> {
|
async function onLocPress(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
@ -306,7 +141,18 @@ const App = () => {
|
||||||
// `lat-${locInfo.coords.latitude};long-${locInfo.coords.longitude}`,
|
// `lat-${locInfo.coords.latitude};long-${locInfo.coords.longitude}`,
|
||||||
// 5000,
|
// 5000,
|
||||||
// );
|
// );
|
||||||
ForegroundHeadlessModule.startService();
|
if (enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// ForegroundHeadlessModule.startService();
|
||||||
|
NativeTaskRunner.startService();
|
||||||
|
setEnabled(true);
|
||||||
|
AsyncStorage.setItem('locationtask', '1');
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
console.log('Did it run?');
|
console.log('Did it run?');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const g = error as GeolocationError;
|
const g = error as GeolocationError;
|
||||||
|
@ -319,19 +165,14 @@ const App = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLocStop() {
|
function onLocStop() {
|
||||||
ForegroundHeadlessModule.stopService();
|
try {
|
||||||
AsyncStorage.getItem('watchId', (err, result) => {
|
// ForegroundHeadlessModule.stopService();
|
||||||
if (err) {
|
NativeTaskRunner.stopService();
|
||||||
console.log('Couldnt get WatchID', err);
|
setEnabled(false);
|
||||||
return;
|
AsyncStorage.setItem('locationtask', '0');
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(result);
|
|
||||||
|
|
||||||
if (result) {
|
|
||||||
Geolocation.clearWatch(+result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -342,19 +183,9 @@ const App = () => {
|
||||||
<Text style={styles.title}>BGFetch Demo</Text>
|
<Text style={styles.title}>BGFetch Demo</Text>
|
||||||
<Button title="Loc" onPress={onLocPress} />
|
<Button title="Loc" onPress={onLocPress} />
|
||||||
<Button title="Stop" onPress={onLocStop} />
|
<Button title="Stop" onPress={onLocStop} />
|
||||||
<Switch value={enabled} onValueChange={onClickToggleEnabled} />
|
|
||||||
</View>
|
</View>
|
||||||
<ScrollView
|
|
||||||
contentInsetAdjustmentBehavior="automatic"
|
|
||||||
style={styles.eventList}>
|
|
||||||
{renderEvents()}
|
|
||||||
</ScrollView>
|
|
||||||
<View style={styles.toolbar}>
|
<View style={styles.toolbar}>
|
||||||
<Button title={'status: ' + status} onPress={onClickStatus} />
|
<Switch value={enabled} />
|
||||||
<Text> </Text>
|
|
||||||
<Button title="scheduleTask" onPress={onClickScheduleTask} />
|
|
||||||
<View style={{flex: 1}} />
|
|
||||||
<Button title="clear" onPress={onClickClear} />
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class ForegroundHeadlessService extends Service {
|
||||||
HeadlessJsTaskService.acquireWakeLockNow(context);
|
HeadlessJsTaskService.acquireWakeLockNow(context);
|
||||||
|
|
||||||
// Schedule next execution
|
// Schedule next execution
|
||||||
handler.postDelayed(this, 60000);
|
handler.postDelayed(this, 120000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
package com.poclocationgather
|
package com.poclocationgather
|
||||||
|
import expo.modules.ReactActivityDelegateWrapper
|
||||||
|
|
||||||
import com.facebook.react.ReactActivity
|
import com.facebook.react.ReactActivity
|
||||||
import com.facebook.react.ReactActivityDelegate
|
import com.facebook.react.ReactActivityDelegate
|
||||||
|
@ -18,5 +19,5 @@ class MainActivity : ReactActivity() {
|
||||||
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
|
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
|
||||||
*/
|
*/
|
||||||
override fun createReactActivityDelegate(): ReactActivityDelegate =
|
override fun createReactActivityDelegate(): ReactActivityDelegate =
|
||||||
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
|
ReactActivityDelegateWrapper(this, BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
package com.poclocationgather
|
package com.poclocationgather
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import expo.modules.ApplicationLifecycleDispatcher
|
||||||
|
import expo.modules.ReactNativeHostWrapper
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import com.facebook.react.PackageList
|
import com.facebook.react.PackageList
|
||||||
|
@ -11,16 +14,27 @@ import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
|
||||||
import com.facebook.react.defaults.DefaultReactNativeHost
|
import com.facebook.react.defaults.DefaultReactNativeHost
|
||||||
import com.facebook.react.soloader.OpenSourceMergedSoMapping
|
import com.facebook.react.soloader.OpenSourceMergedSoMapping
|
||||||
import com.facebook.soloader.SoLoader
|
import com.facebook.soloader.SoLoader
|
||||||
|
import com.nativetaskrunner.NativeTaskRunnerPackage
|
||||||
|
|
||||||
class MainApplication : Application(), ReactApplication {
|
class MainApplication : Application(), ReactApplication {
|
||||||
|
|
||||||
override val reactNativeHost: ReactNativeHost =
|
override val reactNativeHost: ReactNativeHost =
|
||||||
object : DefaultReactNativeHost(this) {
|
ReactNativeHostWrapper(this, object : DefaultReactNativeHost(this) {
|
||||||
|
|
||||||
override fun getPackages(): List<ReactPackage> =
|
override fun getPackages(): List<ReactPackage> =
|
||||||
PackageList(this).packages.apply {
|
PackageList(this).packages.apply {
|
||||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||||
add(ForegroundHeadlessPackage())
|
add(ForegroundHeadlessPackage())
|
||||||
|
add(NativeTaskRunnerPackage())
|
||||||
}
|
}
|
||||||
|
// override fun getPackages(): List<ReactPackage> {
|
||||||
|
// val packages = PackageList(this).packages
|
||||||
|
// // Packages that cannot be autolinked yet can be added manually here, for example:
|
||||||
|
// packages.add(new MyReactNativePackage());
|
||||||
|
// packages.add(new ForegroundHeadlessPackage());
|
||||||
|
// packages.add(new NativeTaskRunnerPackage());
|
||||||
|
// return packages
|
||||||
|
// }
|
||||||
|
|
||||||
override fun getJSMainModuleName(): String = "index"
|
override fun getJSMainModuleName(): String = "index"
|
||||||
|
|
||||||
|
@ -28,10 +42,10 @@ class MainApplication : Application(), ReactApplication {
|
||||||
|
|
||||||
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
|
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
|
||||||
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
|
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
|
||||||
}
|
})
|
||||||
|
|
||||||
override val reactHost: ReactHost
|
override val reactHost: ReactHost
|
||||||
get() = getDefaultReactHost(applicationContext, reactNativeHost)
|
get() = ReactNativeHostWrapper.createReactHost(applicationContext, reactNativeHost)
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
@ -40,5 +54,11 @@ class MainApplication : Application(), ReactApplication {
|
||||||
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
||||||
load()
|
load()
|
||||||
}
|
}
|
||||||
|
ApplicationLifecycleDispatcher.onApplicationCreate(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
|
super.onConfigurationChanged(newConfig)
|
||||||
|
ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,6 @@ allprojects {
|
||||||
// Android JSC is installed from npm
|
// Android JSC is installed from npm
|
||||||
url("$rootDir/../node_modules/jsc-android/dist")
|
url("$rootDir/../node_modules/jsc-android/dist")
|
||||||
}
|
}
|
||||||
maven {
|
|
||||||
// react-native-background-fetch
|
|
||||||
url("${project(':react-native-background-fetch').projectDir}/libs")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
|
pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
|
||||||
plugins { id("com.facebook.react.settings") }
|
plugins { id("com.facebook.react.settings") }
|
||||||
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
|
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex ->
|
||||||
|
def command = [
|
||||||
|
'node',
|
||||||
|
'--no-warnings',
|
||||||
|
'--eval',
|
||||||
|
'require(require.resolve(\'expo-modules-autolinking\', { paths: [require.resolve(\'expo/package.json\')] }))(process.argv.slice(1))',
|
||||||
|
'react-native-config',
|
||||||
|
'--json',
|
||||||
|
'--platform',
|
||||||
|
'android'
|
||||||
|
].toList()
|
||||||
|
ex.autolinkLibrariesFromCommand(command)
|
||||||
|
}
|
||||||
rootProject.name = 'POCLocationGather'
|
rootProject.name = 'POCLocationGather'
|
||||||
include ':app'
|
include ':app'
|
||||||
includeBuild('../node_modules/@react-native/gradle-plugin')
|
includeBuild('../node_modules/@react-native/gradle-plugin')
|
||||||
|
|
||||||
|
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle")
|
||||||
|
useExpoModules()
|
12
app.json
12
app.json
|
@ -1,4 +1,14 @@
|
||||||
{
|
{
|
||||||
"name": "POCLocationGather",
|
"name": "POCLocationGather",
|
||||||
"displayName": "POCLocationGather"
|
"displayName": "POCLocationGather",
|
||||||
|
"expo": {
|
||||||
|
"plugins": [
|
||||||
|
[
|
||||||
|
"expo-location",
|
||||||
|
{
|
||||||
|
"locationAlwaysAndWhenInUsePermission": "Allow $(PRODUCT_NAME) to use your location."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
|
00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
containerPortal = 83CBB9F71A601CBA00E9B192;
|
||||||
proxyType = 1;
|
proxyType = 1;
|
||||||
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
||||||
remoteInfo = POCLocationGather;
|
remoteInfo = POCLocationGather;
|
||||||
|
@ -85,7 +85,7 @@
|
||||||
name = Libraries;
|
name = Libraries;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
83CBB9F61A601CBA00E9B192 = {
|
83CBB9F61A601CBA00E9B192 /* PBXGroup */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13B07FAE1A68108700A75B9A /* POCLocationGather */,
|
13B07FAE1A68108700A75B9A /* POCLocationGather */,
|
||||||
|
@ -143,7 +143,7 @@
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
83CBB9F71A601CBA00E9B192 /* Project object */ = {
|
83CBB9F71A601CBA00E9B192 = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 1210;
|
LastUpgradeCheck = 1210;
|
||||||
|
@ -161,7 +161,7 @@
|
||||||
en,
|
en,
|
||||||
Base,
|
Base,
|
||||||
);
|
);
|
||||||
mainGroup = 83CBB9F61A601CBA00E9B192;
|
mainGroup = 83CBB9F61A601CBA00E9B192 /* PBXGroup */;
|
||||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
|
@ -409,6 +409,7 @@
|
||||||
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
||||||
);
|
);
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
|
@ -475,6 +476,7 @@
|
||||||
);
|
);
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
@ -501,5 +503,5 @@
|
||||||
};
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
};
|
};
|
||||||
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
rootObject = 83CBB9F71A601CBA00E9B192;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import ExpoModulesCore
|
||||||
|
import Expo
|
||||||
import React
|
import React
|
||||||
import React_RCTAppDelegate
|
import React_RCTAppDelegate
|
||||||
import ReactAppDependencyProvider
|
import ReactAppDependencyProvider
|
||||||
|
|
||||||
@main
|
@main
|
||||||
class AppDelegate: RCTAppDelegate {
|
class AppDelegate: ExpoAppDelegate {
|
||||||
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
||||||
self.moduleName = "POCLocationGather"
|
self.moduleName = "POCLocationGather"
|
||||||
self.dependencyProvider = RCTAppDependencyProvider()
|
self.dependencyProvider = RCTAppDependencyProvider()
|
||||||
|
|
20
ios/Podfile
20
ios/Podfile
|
@ -1,3 +1,4 @@
|
||||||
|
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
|
||||||
# Resolve react_native_pods.rb with node to allow for hoisting
|
# Resolve react_native_pods.rb with node to allow for hoisting
|
||||||
require Pod::Executable.execute_command('node', ['-p',
|
require Pod::Executable.execute_command('node', ['-p',
|
||||||
'require.resolve(
|
'require.resolve(
|
||||||
|
@ -15,7 +16,24 @@ if linkage != nil
|
||||||
end
|
end
|
||||||
|
|
||||||
target 'POCLocationGather' do
|
target 'POCLocationGather' do
|
||||||
config = use_native_modules!
|
use_expo_modules!
|
||||||
|
|
||||||
|
if ENV['EXPO_USE_COMMUNITY_AUTOLINKING'] == '1'
|
||||||
|
config_command = ['node', '-e', "process.argv=['', '', 'config'];require('@react-native-community/cli').run()"];
|
||||||
|
else
|
||||||
|
config_command = [
|
||||||
|
'node',
|
||||||
|
'--no-warnings',
|
||||||
|
'--eval',
|
||||||
|
'require(require.resolve(\'expo-modules-autolinking\', { paths: [require.resolve(\'expo/package.json\')] }))(process.argv.slice(1))',
|
||||||
|
'react-native-config',
|
||||||
|
'--json',
|
||||||
|
'--platform',
|
||||||
|
'ios'
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
config = use_native_modules!(config_command)
|
||||||
|
|
||||||
use_react_native!(
|
use_react_native!(
|
||||||
:path => config[:reactNativePath],
|
:path => config[:reactNativePath],
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
|
@ -9,12 +9,21 @@
|
||||||
"start": "react-native start",
|
"start": "react-native start",
|
||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
|
"codegenConfig": {
|
||||||
|
"name": "NativeTaskRunnerSpec",
|
||||||
|
"type": "modules",
|
||||||
|
"jsSrcsDir": "specs",
|
||||||
|
"android": {
|
||||||
|
"javaPackageName": "com.nativetaskrunner"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-native-async-storage/async-storage": "^2.1.2",
|
"@react-native-async-storage/async-storage": "^2.1.2",
|
||||||
"@react-native-community/geolocation": "^3.4.0",
|
"@react-native-community/geolocation": "^3.4.0",
|
||||||
|
"expo": "~52.0.0",
|
||||||
|
"expo-location": "~18.0.10",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-native": "0.77.0",
|
"react-native": "0.77.0"
|
||||||
"react-native-background-fetch": "^4.2.7"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import type {TurboModule} from 'react-native';
|
||||||
|
import {TurboModuleRegistry} from 'react-native';
|
||||||
|
|
||||||
|
export interface Spec extends TurboModule {
|
||||||
|
startService(): void;
|
||||||
|
stopService(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TurboModuleRegistry.getEnforcing<Spec>('NativeTaskRunner');
|
|
@ -1,29 +1,33 @@
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
// import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
import Geolocation from '@react-native-community/geolocation';
|
// import Geolocation from '@react-native-community/geolocation';
|
||||||
|
import * as Location from 'expo-location';
|
||||||
|
|
||||||
module.exports = async () => {
|
module.exports = async () => {
|
||||||
console.log('Background Geolocation task has hopefully started');
|
console.log('Background Geolocation task has hopefully started');
|
||||||
|
|
||||||
Geolocation.setRNConfiguration({
|
// Geolocation.setRNConfiguration({
|
||||||
skipPermissionRequests: false,
|
// skipPermissionRequests: false,
|
||||||
locationProvider: 'playServices',
|
// locationProvider: 'playServices',
|
||||||
});
|
// });
|
||||||
|
|
||||||
const watchId = Geolocation.getCurrentPosition(
|
// const watchId = Geolocation.getCurrentPosition(
|
||||||
pos =>
|
// pos =>
|
||||||
console.log(
|
// console.log(
|
||||||
'[Background location]',
|
// '[Background location]',
|
||||||
pos.coords.latitude,
|
// pos.coords.latitude,
|
||||||
'//',
|
// '//',
|
||||||
pos.coords.longitude,
|
// pos.coords.longitude,
|
||||||
),
|
// ),
|
||||||
err => console.log('Location Error while running in Background', err),
|
// err => console.log('Location Error while running in Background', err),
|
||||||
{
|
// {
|
||||||
interval: 180000,
|
// interval: 180000,
|
||||||
maximumAge: 0,
|
// maximumAge: 0,
|
||||||
timeout: 20000,
|
// timeout: 20000,
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
|
|
||||||
await AsyncStorage.setItem('watchId', `${watchId}`);
|
let location = await Location.getLastKnownPositionAsync({});
|
||||||
|
console.log(location);
|
||||||
|
|
||||||
|
// await AsyncStorage.setItem('watchId', `${watchId}`);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue