Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bertoncelj.fcm.client;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Helper class to send messages to the GCM service using an API Key.
*/
public class Sender {
protected static final String UTF8 = "UTF-8";
/**
* Initial delay before first retry, without jitter.
*/
protected static final int BACKOFF_INITIAL_DELAY = 1000;
/**
* Maximum delay before a retry.
*/
protected static final int MAX_BACKOFF_DELAY = 1024000;
protected static final Logger logger =
Logger.getLogger(Sender.class.getName());
protected final Random random = new Random();
private final String key;
private String endpoint;
private int connectTimeout;
private int readTimeout;
/**
* Default constructor.
*
* @param key API key obtained through the Google API Console.
*/
public Sender(String key) {
this(key, Constants.FCM_SEND_ENDPOINT);
}
/**
* Full options constructor.
*
* @param key FCM Server Key obtained through the Firebase Web Console.
* @param endpoint Endpoint to use when sending the message.
*/
public Sender(String key, String endpoint) {
this.key = nonNull(key);
this.endpoint = nonNull(endpoint);
}
private static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
// ignore error
logger.log(Level.FINEST, "IOException closing stream", e);
}
}
}
/**
* Creates a map with just one key-value pair.
*/
protected static final Map newKeyValues(String key,
String value) {
Map keyValues = new HashMap(1);
keyValues.put(nonNull(key), nonNull(value));
return keyValues;
}
/**
* Creates a {@link StringBuilder} to be used as the body of an HTTP POST.
*
* @param name initial parameter for the POST.
* @param value initial value for that parameter.
* @return StringBuilder to be used an HTTP POST body.
*/
protected static StringBuilder newBody(String name, String value) {
return new StringBuilder(nonNull(name)).append('=').append(nonNull(value));
}
/**
* Adds a new parameter to the HTTP POST body.
*
* @param body HTTP POST body.
* @param name parameter's name.
* @param value parameter's value.
*/
protected static void addParameter(StringBuilder body, String name,
String value) {
nonNull(body).append('&')
.append(nonNull(name)).append('=').append(nonNull(value));
}
/**
* Convenience method to convert an InputStream to a String.
*
* If the stream ends in a newline character, it will be stripped.
*
* If the stream is {@literal null}, returns an empty string.
*/
protected static String getString(InputStream stream) throws IOException {
if (stream == null) {
return "";
}
BufferedReader reader =
new BufferedReader(new InputStreamReader(stream));
StringBuilder content = new StringBuilder();
String newLine;
do {
newLine = reader.readLine();
if (newLine != null) {
content.append(newLine).append('\n');
}
} while (newLine != null);
if (content.length() > 0) {
// strip last newline
content.setLength(content.length() - 1);
}
return content.toString();
}
private static String getAndClose(InputStream stream) throws IOException {
try {
return getString(stream);
} finally {
if (stream != null) {
close(stream);
}
}
}
static T nonNull(T argument) {
if (argument == null) {
throw new IllegalArgumentException("argument cannot be null");
}
return argument;
}
public String getEndpoint() {
return endpoint;
}
/**
* Set the underlying URLConnection's connect timeout (in milliseconds). A timeout value of 0 specifies an infinite timeout.
*
* Default is the system's default timeout.
*
* @see java.net.URLConnection#setConnectTimeout(int)
*/
public final void setConnectTimeout(int connectTimeout) {
if (connectTimeout < 0) {
throw new IllegalArgumentException("timeout can not be negative");
}
this.connectTimeout = connectTimeout;
}
/**
* Set the underlying URLConnection's read timeout (in milliseconds). A timeout value of 0 specifies an infinite timeout.
*
* Default is the system's default timeout.
*
* @see java.net.URLConnection#setReadTimeout(int)
*/
public final void setReadTimeout(int readTimeout) {
if (readTimeout < 0) {
throw new IllegalArgumentException("timeout can not be negative");
}
this.readTimeout = readTimeout;
}
/**
* Sends a message to one device, retrying in case of unavailability.
*
*
* Note: 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 to registration token, notification key, or topic 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 to 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 to, int retries)
throws IOException {
int attempt = 0;
Result result;
int backoff = BACKOFF_INITIAL_DELAY;
boolean tryAgain;
do {
attempt++;
if (logger.isLoggable(Level.FINE)) {
logger.fine("Attempt #" + attempt + " to send message " +
message + " to regIds " + to);
}
result = sendNoRetry(message, to);
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;
}
/**
* Sends a message without retrying in case of service unavailability. See
* {@link #send(Message, String, int)} for more info.
*
* @return result of the post, or {@literal null} if the GCM service was
* unavailable or any network exception caused the request to fail,
* or if the response contains more than one result.
* @throws InvalidRequestException if GCM didn't returned a 200 status.
* @throws IllegalArgumentException if to is {@literal null}.
*/
public Result sendNoRetry(Message message, String to) throws IOException {
nonNull(to);
Map