2

I have a question here about getting an Invalid Registration FCM error. I want to send notification to specific device through Backend .Net (EF)

First of all I saved the deviceToken to the server (Xamarin iOS).

I read the error from https://firebase.google.com/docs/cloud-messaging/http-server-ref

200 + error:InvalidRegistration Check the format of the registration token you pass to the server. Make sure it matches the registration token the client app receives from registering with Firebase Notifications. Do not truncate or add additional characters.

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    //FirebasePushNotificationManager.DidRegisterRemoteNotifications(deviceToken);

    //byte[] bytes = deviceToken.ToArray<byte>();
    //string[] hexArray = bytes.Select(b => b.ToString("x2")).ToArray();
    //DeviceToken = string.Join(string.Empty, hexArray);


    string deviceTokenString;
    if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
    {
        deviceTokenString = BitConverter.ToString(deviceToken.ToArray());
    }
    else
    {
        deviceTokenString = deviceToken.ToString();
    }

    Preferences.Set("TokenDevice", deviceTokenString);
}

I saved the deviceToken to Preferences and also saved it to the server. My deviceToken code on Xamarin iOS:

1A-F5-BE-DC-E4-22-07-46-AA-C4-87-CC-08-F5-D7-09-D4-AB-43-18-26-E0-65-3B-39-4E-6F-5E-02-35-9E-3A

I don't know if this method of getting the deviceToken on Xamarin iOS is really correct at this time?

Backend I write API to send:

private static Uri FireBasePushNotificationsURL = new Uri("https://fcm.googleapis.com/fcm/send");
private static string ServerKey = "key=AAAAqOId6Is:APxxxxxxxxxxxxxxxxxxxx....";

[HttpPost]
public async void PushNotificationToFCM(string deviceTokens, string title, string body, object data, string linkdirection)
{
    using (var client = new HttpClient())
    {
        var messageInformation = new Message()
        {
            notification = new NotificationFirebases()
            {
                title = title,
                text = body
            },
            data = new Dictionary<string, string>()
            {
                { "link", linkdirection },
            },
            to = deviceTokens
        };
        //Object to JSON STRUCTURE => using Newtonsoft.Json;
        string jsonMessage = JsonConvert.SerializeObject(messageInformation);

        string postBody = JsonConvert.SerializeObject(messageInformation).ToString();

        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", ServerKey);

        var response = client.PostAsync(FireBasePushNotificationsURL, new StringContent(postBody, Encoding.UTF8, "application/json"));
        var responseString = response.Result.Content.ReadAsStringAsync().Result;
    }
}

public class Message
{
    public string to { get; set; }
    public NotificationFirebases notification { get; set; }
    public object data { get; set; }
}
public class NotificationFirebases
{
    public string title { get; set; }
    public string text { get; set; }
}

When I test I get the error: {\"multicast_id\":7343900550378569449,\"success\":0,\"failure\":1,\"canonical_ids\":0, \" results\":[{\"error\":\"InvalidRegistration\"}]}. I have tried with deviceToken on Android and it succeeds. Appears only with deviceToken on Xamarin iOS

Please note that I tried sending a notification in Firebase Cloud Messaging: https://console.firebase.google.com/u/0/project/.... then I got a notification, so you can see that my APNS configuration is not wrong.

Looking forward to everyone's help. I also spent more than 2 weeks searching and trying to no avail. Thank you very much.

Update Backend I write API to send:

public void PushNotificationToFCM(string deviceTokens, string title, string body, object data, string linkdirection)
{
    FirebaseApp.Create(new AppOptions() { 
        Credential= GoogleCredential.FromFile("private_key.json")
    });

    // This registration token comes from the client FCM SDKs.
    var registrationToken = deviceTokens;

    // See documentation on defining a message payload.
    var message = new Message()
    {
        Apns = new ApnsConfig { Aps = new Aps { ContentAvailable = true, Sound = "default" } },
        Data = new Dictionary<string, string>()
        {
            { "link", linkdirection },
        },
        Token = registrationToken,
        Notification= new FirebaseAdmin.Messaging.Notification()
        {
            Title = title,
            Body = body,
            
        }
    };

    // Send a message to the device corresponding to the provided
    // registration token.
    string response = FirebaseMessaging.DefaultInstance.SendAsync(message).Result;
    // Response is a message ID string.
    Debug.WriteLine("Successfully sent message: " + response);
}

I don't know if such iOS device's TokenDevice code is correct? I tried to submit it, however getting the error: System.AggregateException: 'One or more errors occurred. (The registration token is not a valid FCM registration token)'

I uninstalled and reinstalled the app, I got a new tokenDevice. However when I send the notification I still get the same error

Chim Di Tru
  • 495
  • 4
  • 17

1 Answers1

1

As an alternative workaround, you can use this NuGet package Plugin.FirebasePushNotification.

1. After Creating the iOS Project, add "GoogleService-Info.plist" file to your iOS Project and update the property to BundleResource.

2. In Info.plist and FinishedLaunching method, add following line:

 <key>FirebaseAppDelegateProxyEnabled</key>
  <false/>
     public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App());

            FirebasePushNotificationManager.Initialize(options, true);
            return base.FinishedLaunching(app, options);
        }

3. Then add the below in App Construct.


 CrossFirebasePushNotification.Current.OnTokenRefresh += (s, p) =>
            {
                System.Diagnostics.Debug.WriteLine($"TOKEN : {p.Token}");
            };
            CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
            {

                System.Diagnostics.Debug.WriteLine("Received");
                foreach (var data in p.Data)
                {
                    System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}");
                }

            };
            CrossFirebasePushNotification.Current.OnNotificationOpened += (s, p) =>
            {
                System.Diagnostics.Debug.WriteLine("Opened");
                foreach (var data in p.Data)
                {
                    System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}");
                }


            }; 

4. After getting the FCM registration token. then click Test, the targeted client device (with the app in the background) should receive the notification in the system notifications tray.

Alexandar May - MSFT
  • 6,536
  • 1
  • 8
  • 15
  • So is `p.Token` a tokenDevice that I can store it in the Database Server? And one more thing is that the Token Device code is only generated when running on the real device? – Chim Di Tru Aug 03 '22 at 05:56
  • The `p.Token` is a `FCM registration token`. After you click Test, the targeted client device (with the app in the background) should receive the notification in the system notifications tray. You can refer to [this thread](https://firebase.google.com/docs/cloud-messaging/android/first-message?authuser=0&hl=zh#retrieve-the-current-registration-token) for more details. – Alexandar May - MSFT Aug 03 '22 at 06:58
  • I will try it. And will respond here for you. Thank you so much – Chim Di Tru Aug 03 '22 at 10:47