離線推送
App 不在前臺時,新訊息和來電透過系統推送提醒使用者。Android 的推送用 im-push 模組接入,支援 FCM 和華為、榮耀、小米、OPPO、vivo、魅族的廠商通道。使用者的免打擾設定見提醒與舉報。
開始之前,先在租戶控制檯為應用配置各通道的推送憑據。
| 要做什麼 | 看哪裡 |
|---|---|
| 初始化推送 | 初始化 |
| 接入 FCM(海外) | FCM |
| 接入國內手機廠商的通道 | 國內廠商 |
| 申請通知許可權、設定通知渠道 | 通知許可權與渠道 |
| 使用者點選通知後開啟對應的會話 | 登記與點選 |
| 清除通知、更新角標 | 清理通知與角標 |
初始化
import com.deeprespond.im.*
import com.deeprespond.im.push.*
val options = DRClientOptions(
appKey = "org#app",
apiUrl = "https://api.example.com",
push = DRPushOptions(
credentials = mapOf(PushChannel.FCM to "控制台凭据编号"),
),
)credentials的值是控制檯中的憑據編號,不是廠商的服務端金鑰。- 在使用者同意隱私政策後初始化,推送在主程序中登記。
- 初始化後用
DRPush.of(im)取得推送的控制器;沒有傳push選項或沒有引入im-push時為null。
FCM
App 自己配置 Firebase 專案、加入 google-services.json 並初始化 Firebase。SDK 自帶一個接收 FCM 訊息的服務 DRFirebaseMessagingService,不需要額外配置。
如果你的 App 已經有自己的 FCM 服務:一個 App 只能有一個生效的 FCM 接收服務,所以在 AndroidManifest.xml 中移除 SDK 的服務,保留你自己的:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<service android:name="com.deeprespond.im.push.DRFirebaseMessagingService"
tools:node="remove" />
<service android:name=".AppMessagingService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>再在你的服務中把訊息轉交給 SDK:
import com.deeprespond.im.push.DRPush
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
class AppMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(message: RemoteMessage) {
if (!DRPush.handleRemoteMessage(this, message)) {
// 处理 App 自己的其他推送。
}
}
override fun onNewToken(token: String) {
DRPush.handleNewToken(this, token)
}
override fun onDeletedMessages() {
DRPush.handleDeletedMessages(this)
}
}較新的 Firebase 版本有 onRegistered / onUnregistered,請分別轉交給 handleRegistered(context, installationId) 和 handleUnregistered(context)。按 Firebase 安裝 ID(FID)登記還需要服務端和 App 都支援;不支援時 SDK 仍按推送令牌登記。只改了客戶端程式碼,不代表 FID 方式已經可用。
國內廠商
| 通道 | 製品 | VendorPush 構造 | App 配置 |
|---|---|---|---|
| 華為 | im-push-huawei | HuaweiPush() | HMS / AGConnect 配置和 Huawei 倉庫 |
| 榮耀 | im-push-honor | HonorPush() | 清單 com.hihonor.push.app_id 和 Honor 倉庫 |
| 小米 | im-push-xiaomi | XiaomiPush(appId, appKey) | App 加入真實廠商 SDK |
| OPPO | im-push-oppo | OppoPush(appKey, appSecret) | App 加入真實廠商 SDK |
| vivo | im-push-vivo | VivoPush() | 清單 com.vivo.push.app_id、com.vivo.push.api_key 和 vivo 倉庫 |
| 魅族 | im-push-meizu | MeizuPush(appId, appKey) | 廠商應用配置和真實依賴 |
- 這些類在
com.deeprespond.im.push.<厂商>包中。把例項傳給DRPushOptions.vendors,並在credentials中給出對應通道的憑據編號。 - 構造引數是廠商要求的客戶端配置,與控制檯中的服務端憑據不是一回事。
- 華為、榮耀、vivo 的 Maven 倉庫分別是
https://developer.huawei.com/repo/、https://developer.hihonor.com/repo、https://repos.vivo.com.cn/maven/repository/external-lib/,可以按依賴組限定範圍。 - 小米、OPPO 的 SDK 要從廠商處下載 AAR,放進 App 的
libs或私有倉庫。原始碼中的vendor-stubs只是用來透過編譯的空實現,不能用於執行。
廠商模組目前透過了編譯和模擬測試。真實的推送通道、通知分類、點選、角標和省電策略,還需要用廠商賬號在真機上驗證。
通知許可權與渠道
通知許可權:Android 13 起,App 要在合適的時機申請通知許可權;使用者關閉了某個通知渠道時,也可能收不到提醒。
controller.permission()返回GRANTED、DENIED或NOT_DETERMINED。- 推薦的申請方式:在 Activity 建立時用
registerForActivityResult註冊permissionContract(),在使用者點選時launch(Unit);這樣旋轉螢幕後結果也不會丟。也可以在協程中呼叫requestPermission(activity)。 - 如果你自己申請過許可權,呼叫
markPermissionRequested()告訴 SDK;被拒絕後用shouldShowRationale(activity)判斷還能不能再申請。
通知渠道:
DRPushOptions.androidChannels預設有dr_message(訊息)、dr_call(來電)、dr_silent(靜默)三個渠道。控制檯中的渠道配置要與 App 一致。- 每個渠道(
AndroidChannel)有id、name、kind、description、sound,kind為MESSAGE、CALL或SILENT。 DRPushOptions還可以設定smallIcon、accentColor、language、badge。- 渠道建立後,它的聲音等設定歸使用者和系統管,再次初始化也不會覆蓋使用者的選擇。
controller.channelStates觀察各渠道是否開啟,openNotificationSettings(activity, channelId?)開啟系統的通知設定;isHibernationExempt/openHibernationSettings檢查和開啟應用休眠的設定。
登記與點選
import com.deeprespond.im.push.DRPush
val controller = DRPush.of(im)
controller?.register()
val registration = controller?.currentRegistration()
val launch = controller?.takeLaunchOpen()
println(registration)
println(launch)登記:register() 把這臺裝置登記到服務端,registrations 訂閱登記的結果;setEnabled 開啟或關閉這臺裝置的通知,language 修改通知的語言。
點選通知:
- 在啟動 Activity 的
onCreate和onNewIntent中呼叫DRPush.handleIntent(intent)。同一次點選只處理一次。 - App 執行時的點選從
opened收到。它只能有一個收集者,請在 App 的統一入口處收集。 - 點選通知啟動 App 時,用
takeLaunchOpen()取出這次點選(取一次後就沒有了)。 - 先等 SDK 恢復登入,再按
PushOpened跳轉到對應的會話:forCurrentUser為false時,這條通知屬於之前登入的另一個賬號,只開啟首頁,不要跳進當前賬號的會話;trusted為true表示點選的是 SDK 自己發出的通知;- 目標不明或對不上時,回到首頁。
清理通知與角標
clearDeliveredNotifications()清除已顯示的通知(來電通知除外)。cancelNotification(tag)按標籤取消你 App 自己發的通知;dr:開頭的標籤留給 SDK。- 角標:
BadgeMode.AUTO按未讀數自動更新;MANUAL時由你呼叫setBadge(count),count為null時清除。能否顯示角標取決於手機系統。角標只是顯示,不會改變服務端的已讀位置。
完整原生入口見DRPushController,與來電相關的許可權見音視訊通話。
