You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于自有后端实现Flutter推送通知的方案及设备ID获取咨询

自有后端实现App推送:设备ID传递与完整方案

核心实现思路

要实现自有后端直接推送,核心是获取平台专属推送令牌并同步到后端,再通过对应平台的官方推送API发送通知,流程如下:

  1. 客户端向系统申请通知权限,获取推送令牌(iOS为APNs Device Token,Android为各厂商Push Token)
  2. 将令牌与用户身份(若有)绑定,通过API发送到后端存储
  3. 后端根据存储的令牌,调用对应平台的推送API下发通知

客户端代码示例

iOS(Swift)获取APNs令牌并同步到后端

import UIKit
import UserNotifications

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // 请求通知权限
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, _ in
            if granted {
                DispatchQueue.main.async {
                    application.registerForRemoteNotifications()
                }
            }
        }
        UNUserNotificationCenter.current().delegate = self
        return true
    }

    // 成功获取APNs令牌
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // 转换为字符串格式
        let tokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
        // 同步到后端
        syncTokenToBackend(token: tokenString, platform: "iOS")
    }

    // 获取令牌失败处理
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("APNs令牌获取失败: \(error.localizedDescription)")
    }

    // 向后端发送令牌的网络请求
    private func syncTokenToBackend(token: String, platform: String) {
        guard let url = URL(string: "https://your-api-domain.com/api/device-tokens") else { return }
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        let payload = [
            "device_token": token,
            "platform": platform,
            "user_id": "当前用户ID(如果有)"
        ]
        request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
        
        URLSession.shared.dataTask(with: request) { _, response, error in
            if let error = error {
                print("令牌同步失败: \(error)")
                return
            }
            // 可根据后端响应处理成功逻辑
        }.resume()
    }
}

Android(Kotlin)获取厂商推送令牌(以华为为例)并同步到后端

如果不用Firebase,推荐使用Android厂商自带推送通道(华为、小米、OPPO等),以下是华为Push Token的获取示例:

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.huawei.hms.push.HmsMessaging
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody

class MainActivity : AppCompatActivity() {
    private val client = OkHttpClient()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 获取华为Push Token
        HmsMessaging.getInstance(this).token.addOnCompleteListener { task ->
            if (task.isSuccessful) {
                task.result?.let { token ->
                    syncTokenToBackend(token, "Android-Huawei")
                }
            } else {
                print("华为Push Token获取失败: ${task.exception?.localizedDescription}")
            }
        }
    }

    // 同步令牌到后端
    private fun syncTokenToBackend(token: String, platform: String) {
        val url = "https://your-api-domain.com/api/device-tokens"
        val mediaType = "application/json; charset=utf-8".toMediaType()
        val payload = """
            {
                "device_token": "$token",
                "platform": "$platform",
                "user_id": "当前用户ID(如果有)"
            }
        """.trimIndent()
        val requestBody = payload.toRequestBody(mediaType)
        
        val request = Request.Builder()
            .url(url)
            .post(requestBody)
            .build()
        
        client.newCall(request).enqueue(object : okhttp3.Callback {
            override fun onFailure(call: okhttp3.Call, e: java.io.IOException) {
                e.printStackTrace()
            }

            override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
                response.close()
                // 处理成功响应
            }
        })
    }
}

后端关键处理逻辑

  1. 令牌存储:提供POST接口接收客户端发送的令牌,将其与用户ID(若有)、平台类型关联,存入数据库(注意令牌可能更新,需覆盖旧值)
  2. 推送发送:
    • iOS:调用APNs HTTP/2 API,需提前在苹果开发者平台申请APNs证书或密钥,请求示例(Node.js):
      const axios = require('axios');
      const jwt = require('jsonwebtoken');
      const fs = require('fs');
      
      // 生成APNs JWT令牌
      const generateAPNsToken = () => {
          const privateKey = fs.readFileSync('apns-private-key.p8');
          return jwt.sign({}, privateKey, {
              algorithm: 'ES256',
              issuer: '你的Team ID',
              header: { kid: '你的Key ID' }
          });
      };
      
      // 发送APNs通知
      const sendAPNsNotification = async (deviceToken, title, content) => {
          const apnsToken = generateAPNsToken();
          await axios.post(`https://api.push.apple.com/3/device/${deviceToken}`, {
              aps: {
                  alert: { title, body: content },
                  sound: 'default'
              }
          }, {
              headers: {
                  'Authorization': `bearer ${apnsToken}`,
                  'apns-topic': '你的App Bundle ID'
              }
          });
      };
      
    • Android厂商通道:调用对应厂商的推送API(如华为Push API、小米Push API),需在厂商开发者平台申请API密钥,按文档构造请求即可

注意事项

  • 令牌可能因用户重装App、系统更新、设备重置等情况变更,客户端需在每次获取到新令牌时重新同步到后端
  • 处理用户拒绝通知权限的场景,可引导用户前往设置开启
  • 后端需监听推送API的错误响应(如令牌失效),及时从数据库移除无效令牌,避免无效推送请求

内容的提问来源于stack exchange,提问作者Ilian Gion Häsler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:17:45