Перейти к основному содержимому

Плагин Pushed Messaging для Flutter

Если вы пишете мобильное приложение на Flutter, используйте готовый плагин flutter_pushed_messaging.


Начало работы

Установка

Добавьте в ваш pubspec.yaml:

dependencies:
flutter_pushed_messaging: ^1.6.8

Затем выполните:

flutter pub get

Импорт

import 'package:flutter_pushed_messaging/flutter_pushed_messaging.dart';

Содержание


Начало работы

Установка

Добавьте в ваш pubspec.yaml:

dependencies:
flutter_pushed_messaging: ^1.6.8

Затем выполните:

flutter pub get

Импорт

import 'package:flutter_pushed_messaging/flutter_pushed_messaging.dart';

Настройка iOS

Базовая настройка iOS

Предварительные условия: Убедитесь, что ваше iOS-приложение правильно настроено для push-уведомлений.

Необходимые возможности

  1. Откройте ваш iOS-проект в Xcode
  2. Добавьте возможность Push Notifications:
    • Выберите ваш target → Signing & Capabilities
    • Нажмите + CapabilityPush Notifications
  3. Добавьте возможность Background Modes:
    • Нажмите + CapabilityBackground Modes
    • Включите Remote notifications

Настройка AppDelegate

Добавьте это в ваш AppDelegate.swift (или AppDelegate.m) в метод didFinishLaunchingWithOptions:

if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}

Следующий шаг: Настройка iOS Extension


Notification Service Extension

Зачем это нужно? Notification Service Extension обеспечивает расширенные возможности push-уведомлений, такие как богатый контент, отслеживание доставки и фоновая обработка.

Создание Extension

Шаг 1: Создание Extension Target

  1. В Xcode: FileNewTargetNotification Service Extension
  2. Product Name: extension (или ваше предпочитаемое имя)
  3. Нажмите: Activate
  4. Язык: Swift (рекомендуется)

Шаг 2: Настройка Build Phases

Критический шаг: Это обеспечивает правильный порядок сборки.

  1. Выберите ваш основной target (Runner)
  2. Перейдите: на вкладку Build Phases
  3. Перетащите: Embed Foundation Extensions НАД Run Script

Шаг 3: Конфигурация сборки

# Выполните это в корне вашего проекта
flutter build ios --config-only

Настройка Podfile

Редактируйте ios/Podfile

Найдите эту строку:

flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

Добавьте сразу после:

target 'extension' do  # ← Замените 'extension' на фактическое имя вашего extension
inherit! :search_paths
end

Обновите зависимости

cd ios
pod update

Реализация NotificationService.swift

Замените содержимое вашего NotificationService.swift на:

import UserNotifications
import flutter_pushed_messaging

class NotificationService: UNNotificationServiceExtension {

var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?

override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

FlutterPushedMessagingPlugin.confirmExtension(userInfo: request.content.userInfo)

if let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}

override func serviceExtensionTimeWillExpire() {
// Вызывается непосредственно перед завершением extension системой.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}

Настройка Extension

  1. Выберите ваш extension target
  2. Перейдите в: Signing & Capabilities
  3. Добавьте: Keychain Sharing capability
  4. Добавьте keychain group: $(AppIdentifierPrefix)com.yourcompany.yourapp.shared

💡 Совет профи: Замените com.yourcompany.yourapp на ваш фактический bundle identifier


Настройка Keychain Sharing

КРИТИЧЕСКИ ВАЖНО: Без этой настройки Extension не будет работать!

Настройка основного приложения

  1. Выберите ваш основной app target (Runner)
  2. Перейдите в: Signing & Capabilities
  3. Добавьте: Keychain Sharing capability
  4. Добавьте keychain group: $(AppIdentifierPrefix)com.yourcompany.yourapp.shared

Настройка Extension

  1. Выберите ваш extension target
  2. Перейдите в: Signing & Capabilities
  3. Добавьте: Keychain Sharing capability
  4. Добавьте ТУ ЖЕ keychain group: $(AppIdentifierPrefix)com.yourcompany.yourapp.shared

Настройка Android

Настройка Firebase (FCM)

Для приложений Google Play Store и большинства Android-устройств

Шаг 1: Зависимости в корневом build.gradle

Добавьте в android/build.gradle:

buildscript {
dependencies {
classpath 'com.google.gms:google-services:4.3.15'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
// ... другие зависимости
}
}

Шаг 2: Добавьте файл конфигурации

  1. Скачайте google-services.json из Firebase Console
  2. Поместите в: папку android/app/

Шаг 3: Конфигурация на уровне приложения

Добавьте в android/app/build.gradle:

apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'

Настройка Huawei (HMS)

Для устройств Huawei и AppGallery

Шаг 1: Конфигурация корневого build.gradle

Добавьте в android/build.gradle:

buildscript {
repositories {
maven { url 'https://developer.huawei.com/repo/' }
// ... другие репозитории
}
dependencies {
classpath 'com.huawei.agconnect:agcp:1.5.2.300'
// ... другие зависимости
}
}

allprojects {
repositories {
maven { url 'https://developer.huawei.com/repo/' }
// ... другие репозитории
}
}

Шаг 2: Добавьте файл конфигурации

  1. 📥 Скачайте agconnect-services.json из Huawei Developer Console
  2. 📂 Поместите в: папку android/app/

Шаг 3: Конфигурация на уровне приложения

Добавьте в android/app/build.gradle:

dependencies {
implementation 'com.huawei.agconnect:agconnect-core:1.5.2.300'
// ... другие зависимости
}

apply plugin: 'com.huawei.agconnect'

Настройка RuStore

Для RuStore (российский магазин приложений)

Добавьте в android/app/src/main/AndroidManifest.xml:

<application>
<!-- ... другие настройки ... -->

<meta-data
android:name="ru.rustore.sdk.pushclient.project_id"
android:value="Ваш RuStore project ID" />

</application>

Реализация

Обработчик фоновых сообщений

import 'package:flutter_pushed_messaging/flutter_pushed_messaging.dart';

// 🔄 Этот обработчик работает даже когда ваше приложение закрыто
@pragma('vm:entry-point')
Future<void> backgroundMessage(Map<dynamic, dynamic> message) async {
print("Получено фоновое сообщение: $message");

// - Добавьте вашу логику здесь
// - Сохранение в локальную базу данных
// - Показ кастомного уведомления
// - Обновление значка приложения
}

Настройка основного приложения

void main() async {
WidgetsFlutterBinding.ensureInitialized();

// Инициализация плагина
await FlutterPushedMessaging.init(
backgroundMessage,
notificationChannel: "messages", // Только для Android
askPermissions: true, // Автозапрос разрешений
loggerEnabled: false, // Включите для отладки
applicationId: "YOUR_APP_ID", // Кастомный идентификатор (опционально)
);

// Получение уникального токена клиента
print("Токен клиента: ${FlutterPushedMessaging.token}");

runApp(const MyApp());
}

Прослушивание сообщений

class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
_setupMessageListeners();
}

void _setupMessageListeners() {
// Сообщения на переднем плане
FlutterPushedMessaging.onMessage().listen((message) {
print("Сообщение на переднем плане: $message");

// Обработка сообщения
_showInAppNotification(message);
});

// Статус соединения
FlutterPushedMessaging.onStatus().listen((status) {
print("Статус: $status");

switch (status) {
case ServiceStatus.active:
print("Подключен и готов!");
break;
case ServiceStatus.disconnected:
print("Переподключение...");
break;
case ServiceStatus.notActive:
print("Сервис неактивен");
break;
}
});
}
}

🔐 Ручной запрос разрешений

// 📱 Запрос разрешений вручную при необходимости
await FlutterPushedMessaging.askPermissions(
askNotificationPermission: true, // Показ уведомлений
askBackgroundPermission: true, // 🤖 Фоновая работа Android
);

Решение проблем

Проблемы iOS

🔴 Extension не работает

Проверьте эти распространенные проблемы:

  1. Keychain Sharing – оба target должны иметь одинаковую keychain-group.
  2. Build Phases – Extension должен быть встроен перед Run Script.
  3. Podfile – Extension-target должен быть правильно настроен.
  4. Подписание – Extension должен быть правильно подписан.

Шаги отладки:

# Очистка и пересборка
flutter clean
cd ios && pod install
flutter build ios --config-only
🔴 Push-уведомления не появляются

Проверьте:

  1. Capabilities – Push Notifications + Background Modes включены.
  2. APNs-сертификат – действителен и не истёк.
  3. Device Token – приложение успешно зарегистрировано для push.
  4. Payload – формат сообщения правильный.

Тестирование:

# Проверка регистрации устройства
print("Токен: ${FlutterPushedMessaging.token}");

Проблемы Android

🔴 FCM не работает

Проверьте:

  1. google-services.json – файл существует в android/app/.
  2. Плагины – оба плагина применены в app/build.gradle.
  3. Зависимости – правильные версии в build.gradle.
  4. Имя пакета – совпадает с Firebase-проектом.

Отладка:

# Проверка Firebase регистрации
flutter run --verbose
# Ищите логи "Firebase"
🔴 Фоновые сообщения не работают

Проверьте:

  1. Оптимизация батареи – приложение не ограничено.
  2. Автозапуск – приложению разрешён автоматический запуск.
  3. Фоновый обработчик – правильно зарегистрирован.
  4. Разрешения – разрешение фоновой работы предоставлено.

Тестирование:

// Добавьте логирование в фоновый обработчик
@pragma('vm:entry-point')
Future<void> backgroundMessage(Map<dynamic, dynamic> message) async {
print("ФОНОВОЕ: $message");
}

Общие проблемы

🔴 Плагин не инициализируется

Распространённые причины:

  1. Отсутствует await – убедитесь, что используете await для init().
  2. Неправильное время – инициализируйте после WidgetsFlutterBinding.
  3. Зависимости – убедитесь, что все зависимости установлены.

Правильная инициализация:

void main() async {
WidgetsFlutterBinding.ensureInitialized(); // ← Важно!
await FlutterPushedMessaging.init(backgroundMessage); // ← Await!
runApp(MyApp());
}

Часто задаваемые вопросы

Могу ли я настроить внешний вид уведомлений?

Да! На Android вы можете настроить канал уведомлений. На iOS настройте payload в вашем NotificationService-extension.

🔄 Как обрабатывать обновления приложения?

Токен остаётся действительным после обновлений приложения. Однако всегда тестируйте push-уведомления после крупных обновлений для обеспечения совместимости.

🌍 Работает ли это с несколькими языками?

Да! Плагин поддерживает интернационализацию. Настройте содержимое уведомлений на основе локали пользователя.

📊 Могу ли я отслеживать доставку сообщений?

Да! Используйте Extension на iOS и уведомления о доставке FCM на Android для отслеживания статуса доставки сообщений.


Всё готово!

Ваше приложение теперь готово к получению push-уведомлений

Сделано с ❤️ командой Multipushed