Я использую сервис Google Cloud Messaging (GCM) для своего приложения для Android. Я реализовал его в соответствии со всеми правилами, и он работает. Ну, почти.Отправка сообщения GCM (серверная сторона) часто терпит неудачу - но далеко не всегда
Чаще всего, я бы сказал, что в 60-70% случаев я могу успешно отправить сообщение GCM с моего сервера, используя веб-сервис, как описано на веб-страницах google.
Обычно я получаю следующий ответ от веб-сервиса, который указывает, что я успешно отправил сообщение GCM:
{
"multicast_id":8378088572050307085,
"success":1,
"failure":0,
"canonical_ids":0,
"results":
[
{
"message_id":"0:1363080282442710%7c4250c100000031"
}
]
}
Это говорит: все ОК, сообщение отправлено.
Однако во многих случаях я получаю сообщение об ошибке HTTP при вызове веб-сервиса, который говорит:
Невозможно прочитать данные из транспортного соединения: установлено соединение было прервано с помощью программного обеспечения в вашей машине ,
Это сообщение .NET, чтобы сообщить мне, что вызов веб-службы (с использованием HttpWebRequest и POST) завершился неудачно.
Это некоторые сообщения журнала, который показывает проблему:
Это код, я использую для вызова WS:
public static string SendMessage(string registrationId, string command, string extra, bool retry)
{
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://android.googleapis.com/gcm/send");
request.Method = PostWebRequest;
request.KeepAlive = false;
GCMPostPacket json = new GCMPostPacket()
{
collapse_key = "1",
time_to_live = 60,
registration_ids = new List<string>(new string[] { registrationId }),
data = new GcmData()
{
message = command,
misc = extra
}
};
// Converting to JSON string
string jsonString = SICJsonProtocol.JSONHelper.Serialize<GCMPostPacket>(json);
byte[] byteArray = Encoding.UTF8.GetBytes(jsonString);
request.ContentType = "application/json";
request.ContentLength = byteArray.Length;
request.ProtocolVersion = HttpVersion.Version10;
request.Headers.Add(HttpRequestHeader.Authorization, "key=" + "MyVerySecretKey");
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
using (WebResponse response = request.GetResponse())
{
HttpStatusCode responseCode = ((HttpWebResponse)response).StatusCode;
if (responseCode.Equals(HttpStatusCode.Unauthorized) || responseCode.Equals(HttpStatusCode.Forbidden))
{
Console.WriteLine("Unauthorized - need new token");
}
else if (!responseCode.Equals(HttpStatusCode.OK))
{
Console.WriteLine("Response from web service not OK :");
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
}
StreamReader reader = new StreamReader(response.GetResponseStream());
string responseLine = reader.ReadLine();
Console.WriteLine("************************");
Console.WriteLine("GCM send: " + responseCode + " | " + responseLine);
// This is the log shown in the image above
SRef.main.gui.ServiceUpdate("GCM send: " + responseCode + " | " + responseLine);
reader.Close();
response.Close();
return responseLine;
}
}
catch (Exception e)
{
// This is the log shown in the image above
SRef.main.gui.ServiceUpdate("Failed send GCM, " + (retry ? "retrying in 20 sec" : "not retrying") + ". Error=" + e.Message);
if (retry)
{
System.Threading.ThreadPool.QueueUserWorkItem(delegate(object obj)
{
try
{
System.Threading.Thread.Sleep(20000);
SendMessage(registrationId, command, extra, false);
}
catch (Exception ex)
{
}
});
}
return null;
}
}
Может кто-нибудь увидеть, если я делаю что-то неправильно, или если мне что-то не хватает вообще?
Возможно ли зарегистрировать значение 'e' внутри внешнего блока catch? Он может содержать полезную информацию. – Nachi
Несомненно, я добавлю это и посмотрю, поможет ли это – Ted
Собственно, оно уже есть. e.Message записывается на выходе, то есть сообщение об ошибке u видит там ... * + ". Error =" + e.Message); * – Ted