无法接收来自Firebase的通知。未注册的注册令牌

时间:2017-03-05 21:00:01

标签: firebase xamarin xamarin.android firebase-cloud-messaging

我按照本指南在Xamarin.Android应用程序中设置了Firebase: https://developer.xamarin.com/guides/android/application_fundamentals/notifications/remote-notifications-with-fcm/

它似乎首先工作,接收通知没有问题。然后我尝试更新代码并重新部署到Device,之后什么也没发生。由于我无法从Firebase控制台收到任何通知。

我试过了

  • 卸载应用程序并再次部署
  • 从Firebase控制台下载新的google-service.json
  • 删除并设置新的Firebase项目,并为此
  • 更新google-service.json

当新部署应用程序时,我尝试发送通知,但没有任何反应。更新和重新部署后,我在控制台中收到错误“未注册的注册令牌”。

在设置新的Firebase项目之前,尝试订阅主题时会出现以下错误 “INVALID_PARAMETERS”,但在创建新项目后,这个问题已经消失。现在订阅主题,它会在一段时间后出现在控制台中。但是尝试向主题发送通知,没有结果。

修改 - 添加代码

MainActivity.cs

[Activity(Label = "<<App Label>>", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
    private TextView msgText;
    private const string Tag = "MainActivity";
    private FirebaseAnalytics _analytics;

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        _analytics = FirebaseAnalytics.GetInstance(this);

        // Set our view from the "main" layout resource
        SetContentView (Resource.Layout.Main);
        msgText = FindViewById<TextView>(Resource.Id.msgText);

        if (Intent.Extras != null)
        {
            foreach (var key in Intent.Extras.KeySet())
            {
                var value = Intent.Extras.GetString(key);
                Log.Debug(Tag, "Key: {0} Value: {1}", key, value);
            }
        }

        IsPlayServicesAvailable();

        var logTokenButton = FindViewById<Button>(Resource.Id.logTokenButton);
        logTokenButton.Click += delegate {
            Log.Debug(Tag, "InstanceID token: " + FirebaseInstanceId.Instance.Token);
        };

        var subButton = FindViewById<Button>(Resource.Id.subscribeButton);
        subButton.Click += SubButton_Click;
    }

    private void SubButton_Click(object sender, System.EventArgs e)
    {
        FirebaseMessaging.Instance.SubscribeToTopic("A");
        Log.Debug(Tag, "Subscribed to A");
    }

    public bool IsPlayServicesAvailable()
    {
        int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.Success)
        {
            if (GoogleApiAvailability.Instance.IsUserResolvableError(resultCode))
                msgText.Text = GoogleApiAvailability.Instance.GetErrorString(resultCode);
            else
            {
                msgText.Text = "This device is not supported";
                Finish();
            }
            return false;
        }
        else
        {
            msgText.Text = "Google Play Services is available.";
            return true;
        }
    }
}

StwFirebaseInstanceIdService.cs

[Service]
[IntentFilter(new []{ "com.google.firebase.INSTANCE_ID_EVENT" })]
public class StwFirebaseInstanceIdService : FirebaseInstanceIdService
{
    private const string Tag = "StwFirebaseInstanceIdService";
    public override void OnTokenRefresh()
    {
        var refreshedToken = FirebaseInstanceId.Instance.Token;
        Log.Debug(Tag, "Refreshed Token: " + refreshedToken);
        //SendRegistrationToServer(refreshedToken);
    }

    private void SendRegistrationToServer(string token)
    {

    }
}

的AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="<<Package Name>>" android:versionCode="1" android:versionName="1.0" android:installLocation="auto">
<uses-sdk android:minSdkVersion="16" />
<application android:label="<<App Label>>">
    <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
    <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            <category android:name="${applicationId}" />
        </intent-filter>
    </receiver>
</application>

3 个答案:

答案 0 :(得分:1)

我碰到了同样的问题。尝试再次卸载应用程序,在获得令牌(旧令牌)之前,请调用刷新令牌以获取刷新的令牌:

public override void OnTokenRefresh()
    {
        var refreshedToken = FirebaseInstanceId.Instance.Token;
        Log.Debug(TAG, "Refreshed token: " + refreshedToken);
        SendRegistrationToServer(refreshedToken);
    }

    void SendRegistrationToServer(string token)
    { // Your custom implementation depends on your server }

有关详细信息,请访问Here

答案 1 :(得分:0)

上面提到的教程相当不错,但遗漏了几点。在我将应用程序的SHA1密钥添加到注册之前,我无法使用它。您可以通过以下命令获取此信息:

"C:\Program Files\Java\jdk1.8.0_161\bin\keytool.exe" -list -v -keystore "%USERPROFILE%\AppData\Local\Xamarin\Mono for Android\debug.keystore" -alias androiddebugkey -storepass android -keypass android

您可能需要编辑一下该命令以匹配您的Java版本。

第二件事是,DEBUG构建似乎存在一些问题。我从某个地方得到了这个方法(不知道现在在哪里)。

        private void ConfigureFireBase()
        {
#if DEBUG
            Task.Run(() =>
            {
                var instanceId = FirebaseInstanceId.Instance;
                instanceId.DeleteInstanceId();
                Android.Util.Log.Debug("TAG", "{0} {1}", instanceId?.Token?.ToString(), instanceId.GetToken(GetString(Resource.String.gcm_defaultSenderId), Firebase.Messaging.FirebaseMessaging.InstanceIdScope));
            });

            // For debug mode only - will accept the HTTPS certificate of Test/Dev server, as the HTTPS certificate is invalid /not trusted
            ServicePointManager.ServerCertificateValidationCallback += (o, certificate, chain, errors) => true;
#endif
        }

在OnCreate之后调用它,就像OnCreate一样:

        base.OnCreate(bundle);

        global::Xamarin.Forms.Forms.Init(this, bundle);

        ConfigureFireBase();

答案 2 :(得分:0)

我在Visual Studio for Mac(8.3.11)上使用Xamarin.Firebase.Messaging(71.1740.0)。在较旧的(API 21)和较新的(API 28)物理android设备上进行测试。

首次部署可以在两个设备上使用新令牌。对FCM的自定义REST API调用成功:

{"multicast_id":4160565375891761047,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1576702929647400%320d8b4c320d8b4c"}]}

更改代码,然后在“调试”模式下重新部署到相同的设备上可以正常工作。从Firebase控制台发送正常,将通知发送到FCM中同一项目应用中的两个设备。

几个小时后,自定义REST API返回旧设备令牌(无代码更改):

{"multicast_id":565695677811030352,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"NotRegistered"}]}

然后,再过几个小时,新设备令牌还将从自定义REST API返回“ NotRegistered”(无代码更改)。此外,Firebase控制台不再向设备发送通知。

发生这种情况后,我获得自定义REST API和Firebase控制台正确发送通知的唯一方法是使用Visual Studio手动从设备中删除应用程序:

Visual Studio Menu > Build > Remove from Device

再次部署将安装该应用程序,就像它是设备上的新设备一样,并请求新的令牌。

注意:在Visual Studio首选项中,已经取消选中“在应用程序部署之间保留数据/缓存”,没有重大更改。清除应用程序的数据/缓存也不起作用。

使用了来自GitHub的最新Microsoft代码(2019年12月):https://github.com/xamarin/GooglePlayServicesComponents/tree/master/samples/com.google.firebase/firebase-messaging