首頁 > 軟體

flutter訊息推播使用者端整合方案詳解

2022-12-23 14:00:09

一、背景

公司一個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訊息推播使用者端整合的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com