Could not post JSON requests to GCM after 6 attempts
I am having the same problem as this. I will try and provide more information.
I am using Play Framework, writing in Java. I wrote a plugin called PushNotificationQueue. PushNotificationQueue runs both an iOS and an Android Push Message Queue. Below, for reference, is my GCM implementation.
public class AndroidPushNotificationQueue {
// (constructors and fields not included for brevity)
// constructor starts a daemon thread
/**
* Sends a notification.
* @param notifyKeys - device tokens
* @param data - data to send
**/
public void sendNotification(List<String> notifyKeys, Map<String, String> data) {
if (notifyKeys.size() == 0) {
return;
}
Builder b = new Message.Builder();
if (data != null) {
for (String key : data.keySet()) {
b.addData(key, data.get(key));
}
}
if (testMode) {
b.dryRun(true);
}
Message message = b.build();
queue.add(new Notification(notifyKeys, message));
}
public void stop() {
stopped = true;
sendingThread.interrupt();
}
private class SendNotificationRunner implements Runnable {
@Override
public void run() {
while (true) {
try {
sendNotifications();
//TODO: handle errors
} catch (InterruptedException e) {
if (stopped) break;
Logger.error("Error processing android notification", e);
} catch (InvalidRequestException e) {
if (stopped) break;
Logger.error("Error processing android notification", e);
} catch (IOException e) {
if (stopped) break;
Logger.error("Error processing android notification", e);
} catch (Exception e) {
if (stopped) break;
Logger.error("Unexpected Exception in Android Notification thread", e);
}
}
Logger.info("Stopping Android push queue");
}
private void sendNotifications() throws IOException, InterruptedException, InvalidRequestException {
Notification n = queue.take(); // will wait until an element becomes available
MulticastResult result = sender.send(n.message, n.notifyKeys, NUM_RETRIES);
List<Result> results = result.getResults();
for (int i = 0; i < results.size(); ++i) {
Result r = results.get(i);
String mId = r.getMessageId();
String notifyKey = n.notifyKeys.get(i);
if (mId == null) {
String error = r.getErrorCodeName();
if (error.equals(Constants.ERROR_NOT_REGISTERED)) {
removeDeadRegistration(notifyKey);
} else {
//TODO: something better when error occurs
Logger.error("Error sending android notification to " + notifyKey + ": " + error);
}
} else {
String newNotifyKey = r.getCanonicalRegistrationId();
if (newNotifyKey != null && !newNotifyKey.equals(notifyKey)) {
// do something to handle this error case - not included for brevity
}
}
}
}
}
This works ... sometimes. Most of the time I get the following error.
java.io.IOException: Could not post JSON requests to GCM after 6 attempts
at com.google.android.gcm.server.Sender.send(Sender.java:319) ~[classes/:na]
at utils.AndroidPushNotificationQueue$SendNotificationRunner.sendNotifications(AndroidPushNotificationQueue.java:131) ~[classes/:na]
at utils.AndroidPushNotificationQueue$SendNotificationRunner.run(AndroidPushNotificationQueue.java:103) ~[classes/:na]
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_55]
[debug] application - Endpoint - BaseStationAuth.getUsername
I did some digging and found this in the GCM implementation.
/**
* Sends a message to one device, retrying in case of unavailability.
*
* <p>
* <strong>Note: </strong> this method uses exponential back-off to retry in
* case of service unavailability and hence could block the calling thread
* for many seconds.
*
* @param message message to be sent, including the device's registration id.
* @param registrationId device where the message will be sent.
* @param retries number of retries in case of service unavailability errors.
*
* @return result of the request (see its javadoc for more details).
*
* @throws IllegalArgumentException if registrationId is {@literal null}.
* @throws InvalidRequestException if GCM didn't returned a 200 or 5xx status.
* @throws IOException if message could not be sent.
*/
public Result send(Message message, String registrationId, int retries)
throws IOException {
int attempt = 0;
Result result = null;
int backoff = BACKOFF_INITIAL_DELAY;
boolean tryAgain;
do {
attempt++;
if (logger.isLoggable(Level.FINE)) {
logger.fine("Attempt #" + attempt + " to send message " +
message + " to regIds " + registrationId);
}
result = sendNoRetry(message, registrationId);
tryAgain = result == null && attempt <= retries;
if (tryAgain) {
int sleepTime = backoff / 2 + random.nextInt(backoff);
sleep(sleepTime);
if (2 * backoff < MAX_BACKOFF_DELAY) {
backoff *= 2;
}
}
} while (tryAgain);
if (result == null) {
throw new IOException("Could not send message after " + attempt +
" attempts");
}
return result;
}
I have varied the number of attempts - 5, 10, 15.
I had a same problem. but fix it.
1. I think just edit Interval time varible that 'Sender.BACKOFF_INITIAL_DELAY = 1000;" to 'Sender.BACKOFF_INITIAL_DELAY = 10000;' in Sender.java on com.google.android.gcm.server.
you can read Sender.java file. it's open source.
2. I changed collaps_key value as long type in gcm payload. I think google server not accept the special char for collaps_key. ".", ",", any alpabet.
Good luck.
Clearing all the IP addresses accepted (allows from any IP) in the GCM server config fixed this for me. Since a secret key is already used, limiting the IP addresses is (for most) an unnecessary precaution.
My application thrown also the exception with the message "GCM - Could not post JSON requests to GCM after 6 attempts". So I set a breakpoint at the post(...) method call (line 190 of Sender.java) in the sendNoRetry(...) method call and stepped around in order to get some useful info regarding the response.
In my case I got a 401 http status code because I used a wrong api key.
链接地址: http://www.djcxy.com/p/81486.html上一篇: C#字符串比较等同于假