Я решил написать весь соответствующий код здесь, так как полностью работающий пример на 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");
Я запускаю это при каждом запуске приложения. Функция вызывается не из потока пользовательского интерфейса.
И, наконец, что не так?
- Когда приложение установлено на любом из моих двух телефонов для тестирования (Oreo, Pie), и я отправляю уведомление, оно приходит всегда.
- Сообщение обычно не приходит после новой сборки, когда приложение выключено.
- Я заметил довольно очевидную закономерность: когда первое сообщение приходит на любой из моих тестируемых телефонов, оно продолжает приходить при любых обстоятельствах, даже если приложение выключено на несколько часов.
- Сообщения абсолютно не приходят к моим пользователям, даже если они заранее.
- Однако однажды пришло сообщение и на устройство одного из моих тестеров.
Числа 4 и 5 - это то, что я просто не понимаю. Я понимаю, что когда это происходит никогда или каждый раз, я могу представить высокий уровень успеха, но сообщение, которое почти никогда не приходит, это то, чего я не понимаю ...