flutter消息推送客戶端集成方案詳解

一、背景

公司一個CRM APP項目是用Flutter寫的,根據業務要求,需要集成消息推送功能。所謂的消息推送就是系統會根據某些行為自動推送信息,手機的通知欄會接收到信息,點擊可以打開app的某個指定頁面。

二、第三方消息推送——個推

為瞭追求效率,我們不打算從底層開始寫,而是挑選瞭第三方消息推送平臺——個推。所以這隻是一個基於個推平臺的消息推送集成方案,僅供參考。

1、簡介

個推是一個數據智能服務商,不僅有消息推送服務,還有用戶畫像、數據統計等服務。目前我們隻使用瞭消息推送服務.

2、註冊開通

要使用服務,首先需要去個推官網進行賬號註冊。

註冊完後可以新增應用/服務,選擇個推-消息推送。

新建應用,填寫android和iOS包名

然後找到應用管理,在操作菜單欄中選擇去集成。這裡可以下載演示的DEMO進行安裝。也可以直接根據提供的App Key 直接在項目中集成。

3、自定義消息推送——透傳

個推的消息推送分為“通知消息”和“消息透傳”。

通知消息:指定通知標題和內容後,由個推 SDK 自動處理在系統通知欄中展示通知欄消息。

消息透傳:即自定義消息,消息體格式客戶可以自己定義,如純文本、json 串等。透傳消息個推隻傳遞數據,不做任何處理,客戶端接收到透傳消息後需要自己去做後續動作處理,如通知欄展示、彈框等。

我們選擇瞭消息透傳的方式進行開發。

三、項目集成

創建好個推消息推送服務後,就可以開始在項目中集成瞭

1、個推客戶端flutter插件

在flutter項目的pubspec.yaml文件中添加個推sdk依賴

getuiflut: ^0.2.13 #個推SDK

2、Android和IOS配置

1)Android

打開android/app/build.gradle 文件修改如下內容

android {
    // ...
    defaultConfig {
        manifestPlaceholders = [           
            //填寫你的個推應用app id
            GETUI_APPID: "H58mSiMN6L9zpMxmawsoP9",
        ]        
    }
}
dependencies: {
    //個推SDK
    implementation 'com.getui:gtsdk:3.2.11.0'  
    //個推核心組件
    implementation 'com.getui:gtc:3.1.10.0' 
}

2) iOS

啟用notification:xcode主工程配置 > Signing & Capabilities > +Push Noticifations

3、通知欄插件flutter_local_notifications

因為使用的是消息透傳,通知欄的消息需要我們自己處理。這裡推薦使用flutter_local_notifications,如果flutter 3x以上的版本,它同時支持macOS、linux的系統通知。 在flutter項目的pubspec.yaml文件中添加依賴

flutter_local_notifications: ^9.7.0 #本地推送

android需要在AndroidManifest.xml 添加 INTERNET 權限

<uses-permission android:name="android.permission.INTERNET" />

4、個推消息與通知欄整合

在flutter的main.dart加載個推的主入口

void main() {
    // 個推管理初始化
    GetuiflutManage();
    // ...
}

創建getuiflut_manage.dart文件

import 'dart:io';
import 'package:crm_flutter/common/logger.dart';
import 'package:crm_flutter/common/notifications/getuiflut_handle.dart';
import 'package:getuiflut/getuiflut.dart';
/// 密鑰
const appId = 'aaaaaabbbbbccccccdddddd';
const appKey = 'aaaaaabbbbbccccccdddddd';
const appSecret = 'aaaaaabbbbbccccccdddddd';
/// 個推管理
class GetuiflutManage {
  static final GetuiflutManage _internal = GetuiflutManage._();
  factory GetuiflutManage() => _internal;
  GetuiflutManage._() {
    _initPlatform();
  }
  /// 客戶端id
  String? get clientId => _clientId;
  String? _clientId;
  /// 初始化個推sdk
  Future<void> _initGetuiSdk() async {
    if (Platform.isIOS) {
      Getuiflut().startSdk(
        appId: appId,
        appKey: appKey,
        appSecret: appSecret,
      );
    }
    if (Platform.isAndroid) {
      try {
        Getuiflut.initGetuiSdk;
      } catch (e) {
        e.toString();
      }
    }
    getClientId();
  }
  /// 初始化
  Future<void> _initPlatform() async {
    _initGetuiSdk();
    /// 監聽本地推送通知內容點擊
    ln.selectNotification.listen((value) {
      GetuiflutHandle.handleNavigate(value);
    });
    /// 個推事件處理
    Getuiflut().addEventHandler(
      onReceiveClientId: (String cid) async {
        logger.debugPrint('cid: ${cid}');
        _clientId = cid;
      },
      onReceiveMessageData: (Map<String, dynamic> msg) async {
        logger.debugPrint("fonReceiveMessageData: $msg");
        GetuiflutHandle.push(msg['payload']);
      },
      onReceivePayload: (Map<String, dynamic> message) async {
        logger.debugPrint("flutter onReceivePayload: $message");
        /// 離線則不再次發送
        if (message['offLine']) return;
        GetuiflutHandle.push(message['payloadMsg']);
      },
      onReceiveNotificationResponse: (Map<String, dynamic> message) async {
        GetuiflutHandle.handleNavigate(message['payload']);
      },
    );
  }
  Future<void> getClientId() async {
    try {
      _clientId = await Getuiflut.getClientId;
      logger.debugPrint('cid: ${_clientId}');
    } catch (e) {
      logger.debugPrint(e.toString());
    }
  }
}

創建getuiflut_handle.dart個推處理工具函數。

import 'dart:convert';
import 'package:crm_flutter/common/global.dart';
import 'package:crm_flutter/common/logger.dart';
import 'package:crm_flutter/common/notifications/clientid_bind.dart';
import 'package:crm_flutter/common/notifications/local_notifications.dart';
import 'package:crm_flutter/common/notifications/router_map.dart';
import 'package:crm_flutter/common/login/user_data_helper.dart';
import 'package:crm_flutter/psmb/model/push_payload_model.dart';
import 'package:crm_flutter/routes/routes.dart';
import 'package:flutter/material.dart';
/// 本地通知
final LocalNotifications ln = LocalNotifications();
/// 個推處理工具
class GetuiflutHandle {
  /// 獲取實例
  static PushPayloadModel payloadInstance(String value) {
    Map<String, dynamic> payloadMap = json.decode(value);
    return PushPayloadModel.fromJson(payloadMap);
  }
  /// 通知欄推送
  static void push(String value) {
    PushPayloadModel payload = GetuiflutHandle.payloadInstance(value);
    /// 進行本地消息推送
    ln.send(
      title: payload.aps?.alert?.title ?? '',
      body: payload.aps?.alert?.body ?? '',
      payload: value,
    );
  }
  // ...
}

創建local_notifications.dart 文件

import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:rxdart/subjects.dart';
/// 本地通知
class LocalNotifications {
  static final FlutterLocalNotificationsPlugin np =
      FlutterLocalNotificationsPlugin();
  static final LocalNotifications _internal = LocalNotifications._();
  factory LocalNotifications() => _internal;
  final BehaviorSubject<String?> selectNotification =
      BehaviorSubject<String?>();
  LocalNotifications._() {
    /// 安卓應用通知顯示的圖標,註意android/app/src/main/res/drawable目錄
    /// 添加對應的app_icon.png圖標文件
    var android = const AndroidInitializationSettings('app_icon');
    var ios = const IOSInitializationSettings();
    np.initialize(InitializationSettings(android: android, iOS: ios),
        onSelectNotification: (String? payload) async {
      selectNotification.add(payload);
    });
  }
  /// push消息
  void send({
    required String title,
    required String body,
    String? payload,
    String channelId = '1',
    String channelName = 'crm_psmb',
  }) {
    var androidDetails = AndroidNotificationDetails(channelId, channelName,
        importance: Importance.max, priority: Priority.high);
    var iosDetails = const IOSNotificationDetails();
    var details = NotificationDetails(android: androidDetails, iOS: iosDetails);
    np.show(
      DateTime.now().millisecondsSinceEpoch >> 10,
      title,
      body,
      details,
      payload: payload,
    );
  }
}

最後

以上就是flutter消息推送客戶端集成方案。隻要過程順利你現在已經可以利用個推平臺進行透傳消息推送瞭。但這隻是開始,我們仍有很多問題並未解決:

1、通知欄收到消息,點擊跳轉到目標app頁面要如何處理?

2、安卓機子app離線瞭收不到消息怎麼辦?

3、服務端如何集成個推?服務端如何精準推送到目標用戶?

以上就是flutter消息推送客戶端集成方案詳解的詳細內容,更多關於flutter消息推送客戶端集成的資料請關註WalkonNet其它相關文章!

推薦閱讀: