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

基于自有服务器实现Xamarin跨平台应用动态推送通知方案咨询

嘿,我之前帮不少Xamarin开发者搞定过类似的需求——绕开Firebase用自有服务器实现动态推送,其实核心就是让你的服务器直接对接苹果和谷歌的官方推送API,Xamarin端只负责拿设备令牌、上报给服务器,再处理收到的通知就行。我给你拆解成清晰的步骤,跟着来应该没问题:

第一步:Xamarin端实现令牌获取与上报

首先得让每个设备把自己的推送令牌(iOS叫deviceToken,Android叫FCM Token)上报到你的自有服务器,这样服务器才知道要推给谁。

iOS端配置与令牌上报

  1. 开启推送权限:在iOS项目的Info.plist里添加推送相关配置,然后在AppDelegate.cs的FinishedLaunching方法里请求用户授权:
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    // 请求通知权限
    UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound, (granted, error) => {
        if (granted)
        {
            // 注册远程通知
            UIApplication.SharedApplication.RegisterForRemoteNotifications();
        }
    });
    return base.FinishedLaunching(app, options);
}
  1. 获取并上报令牌:重写RegisteredForRemoteNotifications方法拿到deviceToken,转换成字符串后POST到你的服务器:
public override async void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    // 格式化deviceToken(去掉尖括号和空格)
    var token = deviceToken.Description.Replace("<", "").Replace(">", "").Replace(" ", "");
    
    // 上报到自有服务器(这里记得替换成你的API地址)
    using var httpClient = new HttpClient();
    var payload = new { Token = token, Platform = "iOS", UserId = "当前用户ID(可选)" };
    var content = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json");
    var response = await httpClient.PostAsync("https://你的服务器域名/api/register-push-token", content);
    
    // 可以加个简单的重试逻辑,避免网络波动导致上报失败
    if (!response.IsSuccessStatusCode)
    {
        // 重试逻辑,比如延迟几秒后再发一次
    }
}

Android端配置与令牌上报

注意:Android没有原生的系统推送服务,所以还是得集成FCM的客户端SDK,但咱只用来获取令牌和接收通知,推送逻辑完全由你的自有服务器控制,不用依赖Firebase的控制台或其他服务

  1. 集成FCM SDK:在Android项目的NuGet里安装Xamarin.Firebase.Messaging和Xamarin.GooglePlayServices.Base,然后从Firebase控制台下载google-services.json放到Android项目根目录(设置生成操作为GoogleServicesJson)。
  2. 创建消息服务类:继承FirebaseMessagingService,重写OnNewToken方法获取FCM令牌并上报,同时重写OnMessageReceived处理收到的通知:
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
    // 获取新的FCM令牌并上报
    public override async void OnNewToken(string token)
    {
        base.OnNewToken(token);
        using var httpClient = new HttpClient();
        var payload = new { Token = token, Platform = "Android", UserId = "当前用户ID(可选)" };
        var content = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json");
        await httpClient.PostAsync("https://你的服务器域名/api/register-push-token", content);
    }

    // 处理收到的推送通知,显示本地通知
    public override void OnMessageReceived(RemoteMessage message)
    {
        base.OnMessageReceived(message);
        var title = message.Notification.Title;
        var body = message.Notification.Body;
        
        // 构建并显示本地通知(Android 13+需要先申请POST_NOTIFICATIONS权限)
        var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
        // 这里省略具体的通知构建代码,你可以用Xamarin Android的NotificationCompat类来实现
    }
}
  1. 申请权限:在AndroidManifest里添加必要权限,Android 13+还需要动态申请POST_NOTIFICATIONS权限。
第二步:自有服务器实现推送逻辑

服务器这边要做的就是存储所有设备的令牌,然后在需要推送时,分别调用苹果APNs和谷歌FCM的官方API发送通知。

iOS推送:调用APNs HTTP/2 API

  1. 准备凭证:在Apple开发者后台创建推送证书,生成p8格式的密钥,记录下你的团队ID、密钥ID和应用Bundle ID。
  2. 服务器端代码示例(C#):
public async Task SendIosPushNotification(string deviceToken, string title, string body)
{
    var apnsAuthKey = "你的p8密钥内容";
    var teamId = "Apple开发者团队ID";
    var keyId = "p8密钥的ID";
    var bundleId = "iOS应用的Bundle ID";

    // 生成APNs需要的JWT令牌
    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(apnsAuthKey));
    var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
    var jwt = new JwtSecurityToken(
        issuer: teamId,
        expires: DateTime.UtcNow.AddMinutes(20),
        signingCredentials: credentials,
        headers: new JwtHeader { { "kid", keyId } }
    );
    var jwtToken = new JwtSecurityTokenHandler().WriteToken(jwt);

    // 发送请求到APNs
    using var httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
    httpClient.DefaultRequestHeaders.Add("apns-topic", bundleId);
    
    var payload = new
    {
        aps = new
        {
            alert = new { title = title, body = body },
            sound = "default",
            badge = 1 // 可选:设置应用图标角标
        }
    };
    var content = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json");
    
    // 测试环境用https://api.development.push.apple.com,生产环境用https://api.push.apple.com
    var response = await httpClient.PostAsync($"https://api.push.apple.com/3/device/{deviceToken}", content);
    
    // 处理响应,比如记录日志或处理失败情况
    if (!response.IsSuccessStatusCode)
    {
        var errorContent = await response.Content.ReadAsStringAsync();
        // 记录错误信息,方便排查
    }
}

Android推送:调用FCM HTTP v1 API

  1. 准备凭证:在Firebase控制台创建服务账号,下载JSON格式的密钥文件,记录下你的Firebase项目ID。
  2. 服务器端代码示例(C#):
public async Task SendAndroidPushNotification(string fcmToken, string title, string body)
{
    var serviceAccountJson = "你的Firebase服务账号JSON内容";
    var projectId = "Firebase项目ID";

    // 获取FCM API的访问令牌
    var credential = GoogleCredential.FromJson(serviceAccountJson)
        .CreateScoped(new[] { "https://www.googleapis.com/auth/firebase.messaging" });
    var accessToken = await credential.UnderlyingCredential.GetAccessTokenForRequestAsync();

    // 发送请求到FCM API
    using var httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    
    var payload = new
    {
        message = new
        {
            token = fcmToken,
            notification = new { title = title, body = body },
            android = new { notification = new { sound = "default" } }
        }
    };
    var content = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json");
    
    var response = await httpClient.PostAsync($"https://fcm.googleapis.com/v1/projects/{projectId}/messages:send", content);
    
    // 处理响应
    if (!response.IsSuccessStatusCode)
    {
        var errorContent = await response.Content.ReadAsStringAsync();
        // 记录错误
    }
}
第三步:测试与排坑要点
  • iOS环境区分:测试用真机(模拟器不支持推送),测试环境用APNs的沙箱地址,上线前切换到生产地址。
  • Android权限:Android 13+必须动态申请POST_NOTIFICATIONS权限,否则通知不会显示。
  • 令牌有效期:FCM令牌可能会刷新,所以Xamarin端要在OnNewToken里重新上报;APNs的deviceToken一般不会变,但卸载重装会更新。
  • 服务器IP白名单:如果你的服务器有防火墙,要确保允许访问APNs和FCM的API地址。

内容的提问来源于stack exchange,提问作者Roberen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:12:11