做者:隋晓旭html
你是否想过从头开发一款相似 QQ、微信的聊天应用?又或者,想要在你开发的应用中加入聊天功能,方便用户交流,加强用户粘性?那么,这篇文章就是为你准备的。在这篇文章中,我将介绍如何基于 Flutter 快速实现一款聊天应用。java
这个基于 Flutter 开发的应用还在持续完善中,现已经支持以下功能:react
第一步:Flutter 安装和环境搭建直接查看: Flutter 文档。
第二步:登陆 LeanCloud 控制台,建立 LeanCloud 应用。android
在 pubspec.yaml 中,将 LeanCloud Flutter SDK 添加到依赖项列表:ios
dependencies: leancloud_official_plugin: ^1.0.0-beta.8 //即时通讯插件 leancloud_storage: ^0.2.9 //数据存储 SDK
而后运行 flutter pub get 安装 SDK。git
由于 leancloud_official_plugin 是基于 Swift SDK 以及 Java Unified SDK 开发,因此还要安装后面两个 SDK,这样应用才能分别在 iOS 和 Android 设备运行。github
须要经过 CocoaPods 安装 Swift SDK,这一步和安装 iOS 其余第三方库是同样的,在应用的 ios 目录下执行 pod update 便可。swift
$ cd ios/ $ pod update # 或者 $ pod install --repo-update
一样的,须要配置 Gradle 来安装 Java Unified SDK,打开工程目录 android/app/build.gradle,添加以下依赖,用 Android Studio 打开工程下的 android 目录,同步更新 Gradle 便可。后端
dependencies { implementation 'cn.leancloud:storage-android:6.5.11' implementation 'cn.leancloud:realtime-android:6.5.11' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' }
小 tips: 安装 SDK 期间遇到任何困难均可在 LeanCloud 社区 发帖求助。
SDK 安装成功之后,须要分别 初始化 iOS 和 Android 平台。服务器
Demo 里面并无内置用户系统,能够选择联系人列表中的用户名来登陆聊天系统。LeanCloud 即时通讯服务端中只须要传入一个惟一标识字符串既能够表示一个「用户」,对应惟一的 Client, 在应用内惟一标识本身的 ID(clientId)。
在本身的项目中,若是已经有独立的用户系统也很方便维护。
或者使用 LeanStorage 提供的用户系统。
会话列表要展现当前用户所参与的会话,会话名称、会话的成员,会话的最后一条消息。还须要展现未读消息数目。
会话列表对应 Conversation 表,查询当前用户的所有会话只须要下面两行代码:
ConversationQuery query = client.conversationQuery(); await query.find();
按照会话的更新时间排序:
query.orderByDescending('updatedAt');
为了展现会话的最新一条消息,查询的时候要额外加上这行代码:
//让查询结果附带一条最新消息 query.includeLastMessage = true;
这样会话页面的后端数据就搞定了。下面看一下如何显示数据。
会话查询成功返回的数据格式是 Conversation 类型的 List。
若是要在 Android 设备上运行,须要在初始化 Java SDK 的时候加上下面这行代码,表示开启未读消息数通知:
AVIMOptions.getGlobalOptions().setUnreadNotificationEnabled(true);
swift SDK 是默认支持,无需额外设置。
能够监听 onUnreadMessageCountUpdated 时间获取未读消息数通知:
client.onUnreadMessageCountUpdated = ({ Client client, Conversation conversation, }) { // conversation.unreadMessageCount 即该 conversation 的未读消息数量 };
注意要在如下两处清除未读消息数:
查询聊天记录的时候,先查最近的 10 条消息,而后以第一页的最先的消息做为开始,继续向前拉取消息:
List<Message> messages; try { //第一次查询成功 messages = await conversation.queryMessage( limit: 10, ); } catch (e) { print(e); } try { // 返回的消息必定是时间增序排列,也就是最先的消息必定是第一个 Message oldMessage = messages.first; // 以第一页的最先的消息做为开始,继续向前拉取消息 List<Message> messages2 = await conversation.queryMessage( startTimestamp: oldMessage.sentTimestamp, startMessageID: oldMessage.id, startClosed: true, limit: 10, ); } catch (e) { print(e); }
对话的名称是会话表 Conversation 默认的属性,更新会话名称只须要执行:
await conversation.updateInfo(attributes: { 'name': 'New Name', });
LeanCloud 即时通讯 SDK 提供了下面几种默认的消息类型,Demo 中只用到了文本消息,图像消息和语音消息。
注意,图片与语音消息须要先保存成 LCFile,而后再调用发消息接口发消息。
好比发送音频消息。第一步先保存音频文件为 LCFile:
LCFile file = await LCFile.fromPath('message.wav', path); await file.save();
第二步,再发消息:
//发送消息 AudioMessage audioMessage = AudioMessage.from( binaryData: file.data, format: 'wav', ); await this.widget.conversation.send(message: audioMessage);
还要注意 iOS 设备发送图片消息注意打开相册和相机权限,语音消息须要麦克风权限:
<key>NSMicrophoneUsageDescription</key> <string>录音功能须要访问麦克风,若是不容许,你将没法在聊天过程当中发送语音消息。</string> <key>NSCameraUsageDescription</key> <string>发送图片功能须要访问您的相机。若是不容许,你将没法在聊天过程当中发送图片消息。</string> <key>NSPhotoLibraryUsageDescription</key> <string>发送图片功能须要访问您的相册。若是不容许,你将没法在聊天过程当中发送相册中的图片。</string>
当用户下线之后,收到消息的时候,每每但愿能有推送提醒。最简单的一种推送设置就是在 LeanCloud 控制台 > 消息 > 即时通信 > 设置 > 离线推送设置 页面,填入:
{ "alert": "您有新的消息", "badge": "Increment" }
这样 iOS 设备有离线消息的时候会收到提醒。这里 badge 参数为 iOS 设备专用,用于增长应用 badge 上的数字计数。
若是想在 Android 设备上实现离线推送,要增长一步接入 Android 混合推送。
固然在实际项目中,离线消息的提醒每每会要求更加具体,好比推送中要包括消息的内容或者消息类型等。LeanCloud 也提供了其余几种定制离线推送的方法,感兴趣能够自行查阅文档。
还要注意,iOS 推送必定要正确配置 配置 APNs 推送证书,并打开 Xcode 的推送开关:
AppDelegate.swift 中开启推送,要这样设置:
import Flutter import LeanCloud import UserNotifications @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { do { LCApplication.logLevel = .all try LCApplication.default.set( id: "你的APPID", key: "你的 APPKey", serverURL: "服务器地址") GeneratedPluginRegistrant.register(with: self) /* register APNs to access token, like this: */ UNUserNotificationCenter.current().getNotificationSettings { (settings) in switch settings.authorizationStatus { case .authorized: DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } case .notDetermined: UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .sound]) { (granted, error) in if granted { DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } } } default: break } _ = LCApplication.default.currentInstallation } return super.application(application, didFinishLaunchingWithOptions: launchOptions) } catch { fatalError("\(error)") } } override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { /* set APNs deviceToken and Team ID. */ LCApplication.default.currentInstallation.set( deviceToken: deviceToken, apnsTeamId: "你的 TeamId") /* save to LeanCloud. */ LCApplication.default.currentInstallation.save { (result) in switch result { case .success: break case .failure(error: let error): print(error) } } } override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { //若是注册推送失败,能够检查 error 信息 print(error) } }
在 APP Store 审核过程当中,由于用户能够随意发送消息,被要求对用户生成的内容要有适当的预防措施。
要求提供下面这两条内容:
用户标记不良信息的机制,就是举报功能。
用户阻止滥用用户的机制,实际就是黑名单。
个人解决办法是在消息处长按弹出举报窗口。
使用 LeanCloud 存储服务,新建一张 Report 表用于记录举报信息:
//保存一条举报信息 LCObject report = LCObject('Report'); report['clientID'] = Global.clientID; //举报人 report['messageID'] = messageID; //消息 ID report['conversationID'] = this.widget.conversation.id; //会话 ID report['content'] = _selectedReportList.toString(); //举报内容 await report.save(); //保存举报信息
能够在控制台查看举报内容:
个人解决办法是,在联系人列表处单击联系人弹框提示是否加入黑名单。
黑名单实现思路是新建一张 BlackList 表,来保存每一个用户的黑名单列表,使用 LeanCloud 云函数 实现屏蔽消息。在 _messageReceived 这个 Hook 函数下(这个 hook 发生在消息到达 LeanCloud 云端以后),先查此条消息的发件人与收件人是否在黑名单列表,若是在黑名单列表就删除其中要求屏蔽的收件人,返回新的收件人列表。
实现起来也比较简单,把下面这个云函数粘贴在 LeanCloud 控制台 > 云引擎 >云函数在线编辑框中便可。
步骤先点击「建立函数」,而后选择 _messageReceived 类型,粘贴下面的代码,最后点击「部署」按钮。
等待部署完成,黑名单功能就已经实现成功,将再也不收到加入黑名单用户的所有消息。
//下面这个函数粘贴在 LeanCloud 控制台 AV.Cloud.define('_messageReceived', async function(request) { let fromPeer = request.params.fromPeer; let toPeersNew = request.params.toPeers; var query = new AV.Query('BlackList'); query.equalTo('blackedList', fromPeer); query.containedIn('clientID', toPeersNew); return query.find().then((results) => { if (results.length > 0) { var clientID = results[0].get('clientID'); var index = toPeersNew.indexOf(clientID); if (index > -1) { toPeersNew.splice(index, 1); } return { toPeers: toPeersNew } } return { } }); })
APP 项目完整代码见 Github-FlutterRealtimeDemo