问题
When sending notifications to single recipients over Google Firebase Cloud Messaging, sometimes a response comes back (200 + error:MissingRegistration
, 200 + error:InvalidRegistration
, 200 + error:NotRegistered
), which requires deleting the token of that recipient (because she for example reinstalled the Android app and the token has changed).
My question is:
How to pass that string (the FCM token) back to the response callback of the non-blocking Jetty HTTP client?
Currently my workaround is to add a custom HTTP header to my request:
X-token: APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...
and then I retrieve it in the response callback. But this is a hack, because FCM does not specify such a header and also I need to pass more custom data (the internal user id in my app) back.
Here is my current source code with the custom HTTP header, how to change it please?
private static final String FCM_URL = "https://fcm.googleapis.com/fcm/send";
private static final String FCM_KEY = "key=REPLACE_BY_YOUR_KEY";
private static final String FCM_RESULTS = "results";
private static final String FCM_ERROR = "error";
private static final String FCM_NOT_REGISTERED = "NotRegistered";
private static final String FCM_MISSING_REGISTRATION = "MissingRegistration";
private static final String FCM_INVALID_REGISTRATION = "InvalidRegistration";
private static final String FCM_X_TOKEN = "X-token";
private static final String TOKEN = "APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...";
private static final Map<String, Object> REQUEST = new HashMap<>();
private static final Map<String, Object> NOTIFICATION = new HashMap<>();
private static final Map<String, Object> DATA = new HashMap<>();
static {
REQUEST.put("to", TOKEN);
REQUEST.put("notification", NOTIFICATION);
REQUEST.put("data", DATA);
NOTIFICATION.put("body", "great match!");
NOTIFICATION.put("title", "Portugal vs. Denmark");
NOTIFICATION.put("icon", "myicon");
DATA.put("Nick", "Mario");
DATA.put("Room", "PortugalVSDenmark");
}
private static final SslContextFactory sFactory = new SslContextFactory();
private static final HttpClient sHttpClient = new HttpClient(sFactory);
private static final BufferingResponseListener sFcmListener = new BufferingResponseListener() {
@Override
public void onComplete(Result result) {
if (!result.isSucceeded()) {
System.err.println(result.getFailure());
return;
}
String body = getContentAsString(StandardCharsets.UTF_8);
try {
Map<String, Object> resp = (Map<String, Object>) JSON.parse(body);
Object[] results = (Object[]) resp.get(FCM_RESULTS);
Map map = (Map) results[0];
String error = (String) map.get(FCM_ERROR);
System.out.printf("error: %s\n", error);
if (FCM_NOT_REGISTERED.equals(error) ||
FCM_MISSING_REGISTRATION.equals(error) ||
FCM_INVALID_REGISTRATION.equals(error)) {
String token = result.getRequest().getHeaders().get(FCM_X_TOKEN);
System.out.printf("TODO delete invalid FCM token from the database: %s\n", token);
}
} catch (Exception ex) {
System.err.println(ex);
}
}
};
public static void main(String[] args) throws Exception {
sHttpClient.start();
sHttpClient.POST(FCM_URL)
.header(HttpHeader.AUTHORIZATION, FCM_KEY)
.header(HttpHeader.CONTENT_TYPE, "application/json")
.header(FCM_X_TOKEN, TOKEN) // Workaround, how to improve?
.content(new StringContentProvider(JSON.toString(REQUEST)))
.send(sFcmListener);
}
回答1:
You want to set the token as a request attribute and the retrieve it back:
httpClient.POST(url)
.attribute(key, token)
...
.send(new BufferingResponseListener() {
@Override
public void onComplete(Result result) {
Object token = result.getRequest().getAttribute(key);
...
}
});
来源:https://stackoverflow.com/questions/44870396/how-to-pass-user-context-object-to-the-response-callback-of-async-jetty-http-cli