НейроАгент

Уведомления Expo не работают на Android: Полное руководство по исправлению

Решите проблемы с push-уведомлениями Expo на Android. Узнайте, почему Expo GO не поддерживает уведомления на Android, правильно настройте FCM и исправьте систему уведомлений вашего React Native приложения.

Вопрос

Уведомления Expo не работают на Android в приложении React Native

Я разрабатываю приложение React Native с использованием Expo GO и реализовал push-уведомления. Хотя уведомления успешно приходят на устройствах iOS, они не отображаются на устройствах Android. Я использую .NET API для отправки уведомлений.

Может ли кто-нибудь помочь мне определить, что может вызывать эту проблему? Кроме того, я создал dev-сборку, но не уверен, как ее использовать или чем она отличается от Expo GO в отношении уведомлений Expo.

Вот моя текущая настройка уведомлений:

javascript
import { useState, useEffect, useRef } from 'react';
import { Text, View, Button, Platform, Alert } from 'react-native';
import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';

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

export default function Notification() {
  const [expoPushToken, setExpoPushToken] = useState(''); //это уникальный идентификатор
  const [channels, setChannels] = useState([]);
  const [notification, setNotification] = useState(
    undefined
  ); //это уведомление

  useEffect(() => {
    registerForPushNotificationsAsync().then(token => token && setExpoPushToken(token));

    if (Platform.OS === 'android') {
      Notifications.getNotificationChannelsAsync().then(value => setChannels(value ?? []));
    }

    //слушатели
    const notificationListener = Notifications.addNotificationReceivedListener(notification => {
      setNotification(notification);
    }); //для полученных уведомлений

    //ЭТО КЛЮЧЕВОЙ МОМЕНТ
    useEffect(() => {
      const subscription = Notifications.addNotificationResponseReceivedListener(response => {
        const { type, bunjoNovostiId } = response.notification.request.content.data;
        if(type === "news" && bunjoNovostiId != null){
          navigate('Akcija');
        }
      });

      return () => {
        subscription.remove();
      };
    }, []);


    return () => {
      notificationListener.remove();
      responseListener.remove();
    };
  }, []);

}

export async function registerForPushNotificationsAsync() {
  let token;

  if (Platform.OS === 'android') {
    await Notifications.setNotificationChannelAsync('myNotificationChannel', {
      name: 'A channel is needed for the permissions prompt to appear',
      importance: Notifications.AndroidImportance.MAX,
      vibrationPattern: [0, 250, 250, 250],
      lightColor: '#FF231F7C',
    });
  }

  if (Device.isDevice) {
    const { status: existingStatus } = await Notifications.getPermissionsAsync();
    let finalStatus = existingStatus;
    if (existingStatus !== 'granted') {
      const { status } = await Notifications.requestPermissionsAsync();
      finalStatus = status;
    }
    if (finalStatus !== 'granted') {
      Alert.alert('Вы не будете получать уведомления.');
      return;
    }

    try {
      const projectId =
        Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId;
      if (!projectId) {
        throw new Error('Project ID not found');
      }
      token = (
        await Notifications.getExpoPushTokenAsync({
          projectId,
        })
      ).data;
    } catch (e) {
      token = `${e}`;
    }
  } else {
    alert('Для push-уведомлений необходимо использовать физическое устройство');
  }

  return token;
}

Что может мешать работе уведомлений на Android, и как dev-сборки влияют на функциональность уведомлений по сравнению с Expo GO?

НейроАгент

Push-уведомления не работают на Android в вашем приложении Expo React Native: полное руководство

Проблема с неработающими push-уведомлениями на Android в вашем приложении Expo React Native является распространенной, в первую очередь потому, что Expo GO не поддерживает удаленные push-уведомления на устройствах Android - вы должны использовать development build или standalone приложение. Хотя ваши уведомления работают идеально на iOS из-за разных требований реализации, Android требует конкретной конфигурации и процессов сборки, которые Expo GO не может предоставить.

Содержание

Почему Expo GO не поддерживает push-уведомления на Android

Основная проблема, с которой вы сталкиваетесь, обусловлена архитектурными ограничениями Expo. Согласно официальной документации Expo, “функциональность push-уведомлений (удаленных уведомлений), предоставляемая expo-notifications, недоступна в Expo Go на Android начиная с SDK 53. Требуется development build для использования push-уведомлений.”

Это ограничение существует потому, что:

  • Expo GO использует общие учетные данные Expo для разработки
  • Android требует специфичных для приложения конфигураций Firebase Cloud Messaging (FCM)
  • Политики Google Play Store требуют правильного подписания приложений и управления ключами
  • Push-уведомления требуют глубокой интеграции с системой, что предотвращает песочница Expo GO

Как указано в FAQ Expo, “Expo Go использует учетные данные Expo, что позволяет работать с уведомлениями в разработке. Когда вы собираете приложение для магазинов приложений, вам нужно сгенерировать и использовать свои собственные…”

Development Build против Expo GO для уведомлений

Ключевое различие между этими средами для push-уведомлений:

Функция Expo GO (Android) Development Build/Standalone приложение
Push-уведомления ❌ Не поддерживается ✅ Полностью поддерживается
Локальные уведомления ✅ Поддерживается ✅ Поддерживается
Интеграция FCM ❌ Недоступна ✅ Требуется
Токен устройства Ограниченная функциональность Полный доступ к токену устройства
Тестирование Только базовое Полноценное тестирование возможно

Как объясняется в документации Expo, вам нужно “собирать с помощью EAS Build” для правильной работы push-уведомлений на Android.

Распространенные проблемы с уведомлениями на Android

Несколько специфичных проблем часто влияют на работу уведомлений на Android:

1. Отсутствует конфигурация FCM

  • Проблема: Отсутствуют или неверные ключи Firebase Cloud Messaging
  • Симптомы: Уведомления работают в Expo GO, но не работают в standalone сборках
  • Подтверждение: Пользователь Reddit отметил: “Убедитесь, что вы настроили ключи FCM для Android. В противном случае push-уведомления не работают в standalone сборках.”

2. Проблемы с каналами уведомлений

  • Проблема: Android требует правильной настройки каналов уведомлений
  • Симптомы: Уведомления появляются, но не издают звук или не отображаются правильно
  • Подтверждение: Некоторые пользователи сообщают, что уведомления только “показываются в виде значка на верхней панели” без всплывающего функционала

3. Проблемы реализации слушателя

  • Проблема: Слушатели уведомлений не правильно активируются на Android
  • Симптомы: Нажатие на уведомления не приводит к навигации к ожидаемым экранам
  • Подтверждение: Обсуждения на Stack Overflow упоминают “слушатель уведомлений не работает для Android в react native expo app - слушатель не активируется для Android, когда я нажимаю на уведомление”

Требования к конфигурации FCM

Чтобы push-уведомления работали на Android, вы должны правильно настроить Firebase Cloud Messaging:

  1. Создайте проект Firebase

    • Перейдите в Firebase Console
    • Создайте новый проект для вашего приложения
  2. Добавьте Android приложение

    • Зарегистрируйте имя пакета вашего Android приложения
    • Скачайте файл google-services.json
  3. Настройте EAS Build

    bash
    eas build:configure
    

    Это настроит необходимые файлы конфигурации Android

  4. Настройте переменные окружения

    • Добавьте ваш серверный ключ FCM в секреты EAS
    • Настройте ID проекта в конфигурации вашего приложения

Как объясняется в руководстве Expo по FCM, “узнайте, как отправлять уведомления с помощью FCM и APNs” для правильной настройки.

Проблемы в вашей реализации кода

Анализируя ваш код уведомлений, есть несколько проблем, которые нужно исправить:

1. Неопределенный слушатель ответа

javascript
// В вашем коде есть эта проблема:
useEffect(() => {
  const subscription = Notifications.addNotificationResponseReceivedListener(response => {
    // ...
  });
  return () => {
    subscription.remove();
  };
}, []);

// Но responseListener используется до определения в очистке:
return () => {
  notificationListener.remove();
  responseListener.remove(); // ❌ responseListener не определен здесь
};

2. Ограничения токена Expo

Метод getExpoPushTokenAsync() имеет ограничения в standalone сборках. Для Android следует использовать токен FCM устройства вместо этого.

3. Отсутствует обработка ошибок

Код не правильно обрабатывает случаи, когда получение токена не удается в standalone сборках.

Пошаговые решения

Решение 1: Создайте Development Build

bash
# Сначала настройте EAS
eas build:configure

# Создайте development build
eas build --platform android --profile development

Решение 2: Исправьте ваш код уведомлений

javascript
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';

export default function Notification() {
  const [expoPushToken, setExpoPushToken] = useState('');
  const [notification, setNotification] = useState(undefined);

  useEffect(() => {
    registerForPushNotificationsAsync().then(token => {
      if (token) setExpoPushToken(token);
    });

    // Настройте каналы уведомлений для Android
    if (Platform.OS === 'android') {
      setupNotificationChannels();
    }

    // Добавьте слушатели
    const notificationListener = Notifications.addNotificationReceivedListener(setNotification);
    const responseListener = Notifications.addNotificationResponseReceivedListener(handleNotificationResponse);

    return () => {
      notificationListener.remove();
      responseListener.remove();
    };
  }, []);

  const handleNotificationResponse = (response) => {
    const { type, bunjoNovostiId } = response.notification.request.content.data;
    if(type === "news" && bunjoNovostiId != null){
      // Навигация к вашему экрану здесь
      console.log('Навигация к новости:', bunjoNovostiId);
    }
  };

  const setupNotificationChannels = async () => {
    if (Platform.OS === 'android') {
      await Notifications.setNotificationChannelAsync('myNotificationChannel', {
        name: 'Мои уведомления',
        importance: Notifications.AndroidImportance.MAX,
        vibrationPattern: [0, 250, 250, 250],
        lightColor: '#FF231F7C',
      });
    }
  };
}

export async function registerForPushNotificationsAsync() {
  if (!Device.isDevice) {
    alert('Для push-уведомлений необходимо использовать физическое устройство');
    return;
  }

  // Запрос разрешений
  const { status: existingStatus } = await Notifications.getPermissionsAsync();
  let finalStatus = existingStatus;

  if (existingStatus !== 'granted') {
    const { status } = await Notifications.requestPermissionsAsync();
    finalStatus = status;
  }

  if (finalStatus !== 'granted') {
    Alert.alert('Разрешение на уведомления не предоставлено');
    return;
  }

  // Получение токена с правильным ID проекта
  const projectId = Constants.expoConfig.extra.eas.projectId;
  if (!projectId) {
    throw new Error('ID проекта не найден в конфигурации приложения');
  }

  return await Notifications.getExpoPushTokenAsync({
    projectId,
  });
}

Решение 3: Настройте FCM для продакшена

  1. Получите учетные данные FCM:

    • В Firebase Console перейдите в Настройки проекта
    • В разделе Cloud Messaging найдите Server Key и Sender ID
  2. Настройте секреты EAS:

    bash
    eas secret:create FCM_SERVER_KEY=ваш_серверный_ключ_здесь
    eas secret:create FCM_SENDER_ID=ваш_sender_id_здесь
    
  3. Обновите app.json:

    json
    {
      "expo": {
        "android": {
          "package": "com.yourcompany.yourapp"
        },
        "extra": {
          "eas": {
            "projectId": "ваш-id-проекта"
          }
        }
      }
    }
    

Тестирование и верификация

Тестирование вашего Development Build

  1. Установите development build на ваше Android устройство
  2. Убедитесь, что вы получаете push-уведомления
  3. Протестируйте ответы на уведомления и навигацию

Распространенные проблемы тестирования

  • Уведомления появляются, но не издают звук: Проверьте настройки важности канала уведомлений
  • Уведомления не появляются: Проверьте конфигурацию FCM и сетевые разрешения
  • Слушатели не активируются: Убедитесь в правильной очистке и настройке слушателей

Как предлагается в руководстве по устранению неполадок Expo, “это указывает на то, что вы либо неправильно настроили учетные данные, либо вообще не настроили их в вашем продакшн приложении.”

Заключение

Основная проблема, мешающая работе ваших Android уведомлений, заключается в том, что Expo GO не поддерживает push-уведомления на Android - вы должны использовать development build или standalone приложение. Ключевые выводы:

  1. Используйте Development Builds: Создайте EAS development build для правильной поддержки push-уведомлений на Android
  2. Правильно настройте FCM: Настройте Firebase Cloud Messaging с правильными серверными ключами и именами пакетов
  3. Исправьте проблемы в коде: Устраните неопределенный responseListener и улучшите обработку ошибок
  4. Тестируйте на физических устройствах: Уведомления не будут работать правильно на эмуляторах для standalone сборок

Для непрерывной разработки рассмотрите использование локальных уведомлений в Expo GO для тестирования UI компонентов, в то время как использование development builds для end-to-end тестирования push-уведомлений. Переход от Expo GO к standalone сборкам требует тщательного внимания к конфигурации FCM и правильной настройке сборки, но после реализации уведомления на Android будут работать как ожидается.