Непредсказуемое поведение службы в сообщениях тем Firebase - PullRequest
0 голосов
/ 14 июня 2019

Я решил написать весь соответствующий код здесь, так как полностью работающий пример на c # - это то, чего мне очень не хватает, и я не знаю, где искать проблему. Я полностью застрял.

Я пробовал так много комбинаций, комментируя и раскомментируя части кода, но я просто не понимаю, как все это настроить. Я больше не вижу никакой логики в том, что я делаю. Это просто отчаянное копирование ...

Здесь текущее состояние моего кода:

Это мой манифест

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.alienchess.android" android:versionCode="87" android:versionName="Patrol on the Milky Way (87)" android:installLocation="preferExternal">
    <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="26" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.android.vending.BILLING" />
    <application android:label="Alien Chess" android:icon="@drawable/Alien">
        <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>
        <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.alienchess.android.provider" android:exported="false" android:grantUriPermissions="true">
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" />
        </provider>
        <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
        <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AIxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
    </application>
</manifest>

У меня не определены ни служба обмена сообщениями, ни служба идентификации экземпляра. Я тоже это попробовал, скопировал код из этого вопроса , но, как написано выше, я больше не знаю, что помогает приложению. Я не могу просто заполнить свой код тоном кода, которого я не понимаю.

Это файл с моей службой сообщений

using ...
namespace AlienChessAndroid
{
    [Service]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
    public class MyFirebaseMessagingService : FirebaseMessagingService
    {
        private async void SendNotification(RemoteMessage remoteMessage)
        {
            ...
            notificationBuilder = new NotificationCompat.Builder(this)
                .SetContentTitle(title)
                .SetAutoCancel(true)
                .SetSmallIcon(ali)
                .SetSound(defaultSoundUri)
                .SetCategory(systemCategory)
                .SetPriority(notificationPriority)
                .SetContentIntent(contentIntent);


            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
                notificationBuilder.SetChannelId(channel);
            ...
            var notificationManager = NotificationManager.FromContext(this);
            Notification notification = notificationBuilder.Build();
            notificationManager.Notify(0, notification);
        }
        public override void OnMessageReceived(RemoteMessage remoteMessage)
        {
            //base.OnMessageReceived(remoteMessage);
            SendNotification(remoteMessage);
        }
    }
}

Функция SendNotification работает. Я также тщательно протестировал только при воспроизведении системного звука. При некоторых обстоятельствах OnMessageReceived срабатывает корректно, а затем работает. Я напишу об этом позже.

Каналы Oreo

if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
   var notificationManager = NotificationManager.FromContext(LayoutBuilder.staticContext);

   NotificationChannel channel = new NotificationChannel(RING_ID, "Starting soon",NotificationImportance.Default);
   channel.Description="Last minute calls from topics inviting you to live streams.";
   channel.SetShowBadge(false);
   channel.EnableLights(true);
   channel.LightColor = Color.DeepSkyBlue.ToArgb();
   notificationManager.CreateNotificationChannel(channel);

   ...
}

Я не забыл создать каналы уведомлений Oreo. Это то, что я называю при каждом запуске приложения.

Это файл с идентификатором службы

using...
namespace AlienChessAndroid
{
    [Service]
    [IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
    public class MyFirebaseIIDService : FirebaseInstanceIdService
    {
        public override void OnTokenRefresh()
        {
            base.OnTokenRefresh();
        }
    }
}

Если честно, я так и не нашел, для чего это используется в обмене сообщениями в темах, и в других тестах я не использовал этот код. Казалось, мне больше нравятся вещи для обмена сообщениями один на один. Может быть, я ошибаюсь.

Сертификаты SHA

Я не знаю, предоставляет ли Firebase отпечатки пальцев SHA полезен для всего, что касается обмена сообщениями по темам, но сегодня я добавил отладку, выпуск и отпечатки пальцев SHA1 Play Store и в консоль Firebase, а также обновил google-services.json. Без изменений снова ...

Как отправлять сообщения с данными?

public static void SendDataMessage(MyNotification paramNotification)
{

    WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
    tRequest.Method = "post";
    //serverKey - Key from Firebase cloud messaging server  
    tRequest.Headers.Add(string.Format("Authorization: key={0}", LayoutBuilder.FCM_SECRET_SERVERKEY));
    //Sender Id - From firebase project setting  
    tRequest.Headers.Add(string.Format("Sender: id={0}", LayoutBuilder.FCM_SECRET_SENDERID));
    tRequest.ContentType = "application/json";

    string strExpirationFileTime = DateTime.Now.AddMinutes(int.Parse(paramNotification.expires)).ToFileTime().ToString();

    var payload = new
    {
        to = "/topics/" + paramNotification.topic,
        data = new
        {
            sbody = paramNotification.shortBody,
            lbody = paramNotification.longBody,
            title = paramNotification.title,
            channel = paramNotification.channel,
            image = paramNotification.image.description,
            link = paramNotification.link,
            expires = strExpirationFileTime,
        },
    };

    string postbody = JsonConvert.SerializeObject(payload).ToString();
    Byte[] byteArray = Encoding.UTF8.GetBytes(postbody);
    tRequest.ContentLength = byteArray.Length;
    using (Stream dataStream = tRequest.GetRequestStream())
    {
        dataStream.Write(byteArray, 0, byteArray.Length);
        using (WebResponse tResponse = tRequest.GetResponse())
        {
            using (Stream dataStreamResponse = tResponse.GetResponseStream())
            {
                if (dataStreamResponse != null)
                {
                    using (StreamReader tReader = new StreamReader(dataStreamResponse))
                    {
                        String sResponseFromServer = tReader.ReadToEnd();
                        //System.Diagnostics.Debug.WriteLine("Message response: " + sResponseFromServer);
                    }
                }
            }
        }
    }

Этот код взят из вопроса об отправке push-уведомления с c # и он работает. У меня есть кое-что, что нужно сделать по-другому, но это не связано с проблемой.

Как мне подписаться?

Firebase.Messaging.FirebaseMessaging.Instance.SubscribeToTopic("internal");

Я запускаю это при каждом запуске приложения. Функция вызывается не из потока пользовательского интерфейса.

И, наконец, что не так?

  1. Когда приложение установлено на любом из моих двух телефонов для тестирования (Oreo, Pie), и я отправляю уведомление, оно приходит всегда.
  2. Сообщение обычно не приходит после новой сборки, когда приложение выключено.
  3. Я заметил довольно очевидную закономерность: когда первое сообщение приходит на любой из моих тестируемых телефонов, оно продолжает приходить при любых обстоятельствах, даже если приложение выключено на несколько часов.
  4. Сообщения абсолютно не приходят к моим пользователям, даже если они заранее.
  5. Однако однажды пришло сообщение и на устройство одного из моих тестеров.

Числа 4 и 5 - это то, что я просто не понимаю. Я понимаю, что когда это происходит никогда или каждый раз, я могу представить высокий уровень успеха, но сообщение, которое почти никогда не приходит, это то, чего я не понимаю ...

...