[expo-notifications] Android background notification task failed

SDK 45
Development build (no Expo Go)

Hi! On Android, when receiving a notification and the app is in the background I get this error from the TaskManager:

TaskManager: Task “BACKGROUND-NOTIFICATION-TASK” failed:, [Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app
    See Rules of Hooks – React for tips about how to debug and fix this problem.]
    at node_modules/expo-task-manager/build/TaskManager.js:143:16 in eventEmitter.addListener$argument_1
    at node_modules/expo-task-manager/build/TaskManager.js:133:57 in eventEmitter.addListener$argument_1
    at node_modules/react-native/Libraries/vendor/emitter/_EventEmitter.js:150:10 in EventEmitter#emit

The task seems to be registered Ok:

Notifications.registerTaskAsync(BACKGROUND_NOTIFICATION_TASK); // returns null
TaskManager.isTaskRegisteredAsync(BACKGROUND_NOTIFICATION_TASK); returns true
TaskManager.getRegisteredTasksAsync() // returns Array [
  Object {
    "options": Object {},
    "taskName": "BACKGROUND-NOTIFICATION-TASK",
    "taskType": "remote-notification",
  },
]

This is my partial setupNotifications.js file:

import { useEffect, useRef } from 'react';
import * as Device from 'expo-device';
import * as TaskManager from 'expo-task-manager';
import * as Notifications from 'expo-notifications';
import { AppState, Platform } from 'react-native';
import Constants from 'expo-constants';

const BACKGROUND_NOTIFICATION_TASK = 'BACKGROUND-NOTIFICATION-TASK';
TaskManager.defineTask(BACKGROUND_NOTIFICATION_TASK, ({ data, error, executionInfo }) => {
  console.log('Received a notification in the background!', data);
});

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: false,
  }),
});

export default function setupNotifications() {
  const notificationListener = useRef();
  const responseListener = useRef();

  useEffect(() => {
    registerBackgroundTask()
      .then(() => null)
      .catch(() => null);

    registerForPushNotificationsAsync()
      .then(() => null)
      .catch(() => null);

    // This listener is fired whenever a notification is received while the app is foregrounded
    notificationListener.current = Notifications.addNotificationReceivedListener((notification) => {
      console.log('Received a notification in the foreground!', notification);

      // addNotification(notification);
    });

    // This listener is fired whenever a user taps on or interacts with a notification (works when app is foregrounded, backgrounded, or killed)
    responseListener.current = Notifications.addNotificationResponseReceivedListener((response) => {
      console.log('Received a notification response!', response);

      if (AppState.currentState.match(/inactive|background/)) {
        // addNotification(response.notification.request.content);
      }
    });

    return () => {
      Notifications.removeNotificationSubscription(notificationListener.current);
      Notifications.removeNotificationSubscription(responseListener.current);
    };
  }, []);
...
...
...
}

In app.config.js I’ve added the corresponding plist

ios: {



infoPlist: {
UIBackgroundModes: [‘remote-notification’],
},


},

Got it working by creating an exclusive hook for the task creation

App.tsx

...
...
import {
...
...
  setupNotificationsBackgroundTask,
} from './app/hooks';
...
...

export default function App() {
...
...
  setupNotificationsBackgroundTask();
...
...

setupNotificationsBackgroundTask.js

import { useEffect } from 'react';
import * as TaskManager from 'expo-task-manager';
import { Platform } from 'react-native';
import * as Notifications from 'expo-notifications';

const BACKGROUND_NOTIFICATION_TASK = 'BACKGROUND-NOTIFICATION-TASK';
TaskManager.defineTask(BACKGROUND_NOTIFICATION_TASK, ({ data, error, executionInfo }) => {
  console.log('Received a notification in the background!', Platform.OS, data);
});

export default function setupNotificationsBackgroundTask() {
  useEffect(() => {
    registerBackgroundTask()
      .then(() => null)
      .catch(() => null);
  }, []);
}

async function registerBackgroundTask() {
  try {
    await Notifications.registerTaskAsync(BACKGROUND_NOTIFICATION_TASK);
  } catch (e) {
    console.log(e);
  }
}

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.