Создание приложения Expo и запуск прикрепленного уведомления приводит к исключению NullPointerException через 15-60 минут.
Вот код RN
//backgroundTasks.js
import {Permissions} from 'react-native-unimodules';
import * as Location from 'expo-location';
import * as TaskManager from "expo-task-manager";
import {getStore} from "../redux/configureStore";
import {newLocation} from "../redux/actions/device";
import {Log} from "./log";
import {Colors} from "./style/colors";
import * as db from '../utils/db';
import {getTranslator, secondsToInterval} from "./functions";
import {showAlert} from "../redux/actions/app";
import {APP} from "../redux/constants/app";
import {setIgnoreState} from "./state";
export const BG_TRACKING = 'BG_TRACKING';
Log.info(`Unregister all tasks`);
TaskManager.unregisterAllTasksAsync().then(() => {
Log.info(`Defined new background task ${BG_TRACKING}`);
TaskManager.defineTask(BG_TRACKING, async ({ data: { locations }, error }) => {
if(error) {
Log.error('Error received for locations', error);
} else {
locations.forEach(l => getStore().dispatch(newLocation(l)));
}
});
});
export const unregister = async () => {
if(await Location.hasStartedLocationUpdatesAsync(BG_TRACKING)) {
await Location.stopLocationUpdatesAsync(BG_TRACKING);
}
};
let permissionIndicationOpen = false;
export const register = async () => {
let user = getStore().getState().get(APP).get('currentUser');
if(!user) return;
let permissionState = await Permissions.getAsync(Permissions.LOCATION);
if(!permissionState.granted || permissionState.canAskAgain) {
if(permissionIndicationOpen) return;
permissionIndicationOpen = true;
setIgnoreState(true);
permissionState = await Permissions.askAsync(Permissions.LOCATION);
setIgnoreState(false);
if(permissionState.granted) {
permissionIndicationOpen = false;
} else {
const t = await getTranslator();
getStore().dispatch(showAlert(t('needPermission'), t('locationPermissionNeeded'), {
onConfirm: () => {
permissionIndicationOpen = false;
register()
}
}));
}
}
const start = async () => {
const t = await getTranslator();
try {
Log.info(`Registering background task ${BG_TRACKING}`);
let trackingInterval = await db.getValue('trackingInterval');
if (!trackingInterval) return;
let interval = +trackingInterval;
if (interval < 0) interval = 60 * 60 //every hour, but it will be ignored by the server;
await unregister();
await Location.startLocationUpdatesAsync(BG_TRACKING, {
accuracy: Location.Accuracy.Highest,
timeInterval: interval * 1000,
foregroundService: {
notificationBody: +trackingInterval > 0 ? t('yourPositionIsBeingMonitored', {
period: secondsToInterval(t, interval)
}) : t('positionSentOnlyOnAlarm'),
notificationColor: Colors.primary
}
});
Log.info(`Successfully registered background task ${BG_TRACKING}`);
} catch (e) {
Log.error(`Failed registering background task ${BG_TRACKING}`);
Log.error(e);
}
};
await start();
};
Этот файл вызывается в index.js
, точка входа.
Затем я вижу эту трассировку стека в Crashlytics.
Fatal Exception: java.lang.RuntimeException: Unable to start service expo.modules.location.services.LocationTaskService@97ff6c3 with null: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Bundle android.content.Intent.getExtras()' on a null object reference
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4222)
at android.app.ActivityThread.access$2100(ActivityThread.java:231)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1984)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7682)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)