I am using Ionic 3 with Ionic Native Push Notifications on the client and Java com.notnoop.apns on the server.
I can get the Push Notifications to work successfully on an Android devise. However, on an iOS devise, the client does not display the notification.
client (ts)
let topics: string[] = [this.personModelLoggedIn.uid];
const options: PushOptions = {
android: {
senderID: "XXXXXXXXXXXXXX",
sound: "true",
vibrate: "true",
topics: topics
},
ios: {
alert: "true",
badge: false,
sound: "true"
},
windows: {}
};
const pushObject: PushObject = this.push.init(options);
pushObject.on('notification').subscribe((data: any) => {
alert('Received Notification!!! message = ' + data.message);
});
server (java)
Android
private String sendAndroidPushNotification(String device_token, String topics, String title, String message)
throws Exception {
String pushMessage = null;
if (device_token != null && !device_token.equals("null")) {
pushMessage = "{\"data\":{\"title\":\"" + title + "\",\"message\":\"" + message + "\"},\"to\":\""
+ device_token + "\"}";
} else {
pushMessage = "{\"data\":{\"title\":\"" + title + "\",\"message\":\"" + message + "\"},\"to\": \"/topics/"
+ topics + "\"}";
}
// Create connection to send FCM Message request.
URL url = new URL("https://fcm.googleapis.com/fcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "key=" + SERVER_KEY);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// Send FCM message content.
OutputStream outputStream = conn.getOutputStream();
outputStream.write(pushMessage.getBytes());
return "Android Push Notification: " + conn.getResponseCode() + " " + conn.getResponseMessage() + " - " + pushMessage;
}
iOS
private String sendIOSPushNotification(String device_token, String topics, String title, String message)
throws Exception {
ApnsService service = APNS.newService().withCert(PATH_TO_P12_CERT, CERT_PASSWORD).withSandboxDestination()
.build();
String payload = APNS.newPayload()
// .customFields(map)
.alertBody(title + " " + message).sound("default").build();
//service.push(Utilities.encodeHex(topics.getBytes()), payload);
service.push(device_token), payload);
return "iOS Push Notification: " + title + " " + message;
}
When the above two java methods get called with the appropriate devise tokens, the Android devise receives a notification, but the iOS devise does not.
Question
If anyone can advise what's wrong with my iOS code (either client or server), I would appreciate your advise.
UPDATE
If I try test my APNS on http://pushtry.com/, with my apps apns-prod-cert.p12, I get the following:
Push Notification sent Successfully
And the client does display the notification. So this makes me think there is something wrong with my server code.
Solution
private String sendIOSPushNotification(String device_token, String topics, String title, String message)
throws Exception {
ApnsServiceBuilder serviceBuilder = APNS.newService();
serviceBuilder.withCert(PATH_TO_P12_CERT, CERT_PASSWORD)
.withProductionDestination();
ApnsService service = serviceBuilder.build();
String payload = APNS.newPayload()
.alertBody(message)
.alertTitle(title)
.sound("default")
.customField("custom", "custom value").build();
service.push(device_token, payload);
return "iOS Push Notification: " + title + " " + message;
}
Related
My problem is, that my code, especially tc.addReactionById(messageID, emote);, dont adds a reaction. The whole code is following!
if(args[0].equalsIgnoreCase(prefix + "system") && args[1].equalsIgnoreCase("radd")){
if(args.length == 6){
Message message = event.getMessage();
List<TextChannel> channels = event.getMessage().getMentionedChannels();
List<Role> roles = message.getMentionedRoles();
if(!channels.isEmpty() && !roles.isEmpty()){
TextChannel tc = event.getMessage().getMentionedChannels().get(0);
Role role = roles.get(0);
String messageIDString = args[2];
try{
long messageID = Long.parseLong(messageIDString);
String emote = args[5];
tc.addReactionById(messageID, emote);
eb.setAuthor("Oni System");
eb.setColor(Color.MAGENTA);
eb.setDescription(emote);
eb.setFooter("Oni System | ©ONI", "https://media.discordapp.net/attachments/810910771557957672/810927512892604416/Bot.png?width=676&height=676");
channel.sendMessage(eb.build()).queue();
LiteSQL.onUpdate("INSERT INTO reactionroles(guildid, channelid, messageid, emoji, roleid) VALUES(" + event.getGuild().getIdLong() + ", " + tc.getIdLong() + ", " + messageID + ", '" + emote +"', " + role.getIdLong() + ")");
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
else{
eb.setAuthor("Oni System");
eb.setColor(Color.RED);
eb.setDescription(userMent + " bitte benutze !system radd <messageid> <#role> <channel> <emoji>");
eb.setFooter("Oni System | ©ONI", "https://media.discordapp.net/attachments/810910771557957672/810927512892604416/Bot.png?width=676&height=676");
channel.sendMessage(eb.build()).queue();
}
}
addReactionById is a RestAction in the JDA library, so you will need to queue the operation.
Replace
tc.addReactionById(messageID, emote);
with
tc.addReactionById(messageID, emote).queue();
Assuming the messageID and emote arguments are valid, the call to .queue() should process the reaction. In particular, emote needs to be one of either:
An Emote object created by JDA (usually these are custom server emotes), or
A Unicode string of the emoji you want to add
See the MessageChannel documentation for more info.
I'm having a encoding issue when I send a AJAX request to an API Endpoint.
I have this Endpoint in the code below using Java Spring:
#Autowired
ApiKeyRepository apiKeyRepository;
#RequestMapping(value= "/weather/{cityName}/{fuCity}/now", method = {RequestMethod.GET}, produces="application/json" )
public ResponseEntity<Weather> getWeatherNowByCityName(#PathVariable(value = "cityName") String cityName, #PathVariable(value = "fuCity") State fuCity) throws JSONException, ParseException, java.text.ParseException {
String newCityName = cityName.toLowerCase();
try {
newCityName = URLDecoder.decode(newCityName , "UTF-8").replace(" ", "%20");
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String weatherEndpoint = "/api/v1/locale/city?name=" + newCityName + "&state=" + fuCity.toString();
String appToken = apiKeyRepository.getByservice("climaTempo");
URL weatherDomain = new URL("http://apiadvisor.climatempo.com.br" + weatherEndpoint + "&token=" + appToken);
/// From here I send a JSON Request to the 'weatherDomain' to get the Weather from the city and her state that I get from the EndPoint Parameters
}
And I send this jQuery Ajax request to the Endpoint:
var uf = $("#colWeather #selectState").val();
var city = $("#colWeather #selectCity").val();
$.ajax({
url: host + '/weather/' + city + '/' + uf + '/now',
type: 'GET',
contentType: "application/x-www-form-urlencoded; charset=utf-8",
async: true
}).done(function (JSONReturn) {
//Actions with JSONReturn
});
But here in Brazil we have some cities with accents and cedilla like "Avaí" from "SP", "Mairiporã" from "SP" and "Missão Velha" from "CE".
If I send to the Endpoint an URL like "/weather/Americana/SP/now" or "/weather/Piracicaba/SP/now" the Endpoint gets the JSON return without problems.
But if I send to the Endpoint an URL like "/weather/Mairiporã/SP/now" or "/weather/Avaí/SP/now" the ClimaTempo API returns a null JSON and I get a NullPointerException.
I'm thinking that is a problem with the accents, but I can't send just "/weather/Mairipora/SP/now" without the accents because the ClimaTempo API demands that the city name must go with the accents, otherwise it returns a null JSON...
What am I doing wrong?
You need to encode and decode your characters.
Encode in JavaScript
Instead of url: host + '/weather/' + city + '/' + uf + '/now', go for
url: host + '/weather/' + encodeURIComponent(city) + '/' + uf + '/now'
Decode in Java
Instead of String newCityName = cityName.toLowerCase();, go for
String newCityName = URLDecoder.decode(cityName, Charsets.UTF_8.name()).toLowerCase();
Hey guys!
I'm currently trying to create an app that uses the Twitter API to get timelines of users. I'm currently stuck at a specific point! My user has already logged in and I've already received the access token and the token secret. I'm now trying to send a get request to the Twitter server.
My problem is that I'm always getting a 400 bad request error code WITHOUT any kind of message.
I'm using Volley to send the requests - Heres the code
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Response Time: " + error.getNetworkTimeMs() + " ms");
Log.e(TAG, "Code: " + error.networkResponse.statusCode);
Log.e(TAG, "Data: " + new String(error.networkResponse.data));
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
Long tsLong = System.currentTimeMillis() / 1000;
//I receive all the difference parts
String consumerKey = context.getString(R.string.twitter_consumer_key);
String nonce = GenerationHelper.generateNonce();
String signature_method = "HMAC-SHA1";
String timestamp = tsLong.toString();
String token = sTwitterToken;
String version = "1.0";
// I use this list to pass the parameters to the function
// generating the signature
List<String> param= new ArrayList<>();
param.add("screen_name=" + username);
param.add("count=" + count);
param.add("oauth_token" + sTwitterToken);
param.add("oauth_consumer_key=" + consumerKey);
param.add("oauth_nonce=" + nonce);
param.add("oauth_signature_method=" + signature_method);
param.add("oauth_timestamp=" + timestamp);
param.add("oauth_version=" + version);
String signature = GenerationHelper.generateSignature(context, param, "POST", "https://api.twitter.com/1.1/statuses/user_timeline.json");
// I create the header String
StringBuilder paramBuilder = new StringBuilder();
paramBuilder.append("oauth_consumer_key=\"" + consumerKey + "\", ");
paramBuilder.append("oauth_nonce=\"" + nonce + "\", ");
paramBuilder.append("oauth_signature=\"" + signature + "\", ");
paramBuilder.append("oauth_signature_method=\"" + "HMAC-SHA1" + "\", ");
paramBuilder.append("oauth_timestamp=\"" + timestamp + "\", ");
paramBuilder.append("oauth_token=\"" + sTwitterToken + "\", ");
paramBuilder.append("oauth_version=\"" + "1.0" + "\"");
String credentialString = paramBuilder.toString();
Log.d(TAG, credentialString);
params.put("Authorization", "OAuth " + credentialString);
return params;
}
};
My current response is
Code: 400
Data:
If I remove the line adding the authorization data I get the response
Code: 400
Data: {"errors":[{"code":215,"message":"Bad Authentication data."}]}
I'm pretty sure that I don't get rate limited because I'm just sending about 10 requests per 15 minutes.
Does anybody have any idea why I'm having this problem?
I am using play java for my project(java play ws API) and
private CompletionStage<String> getAuthToken() {
WSRequest request = ws.url(URL);
WSRequest complexRequest = request.setHeader("X-API-Key", X_API_KEY)
.setHeader(CONTENT_TYPE, CONTENT_TYPE_VALUE)
.setHeader(AUTHORIZATION, CLIENT_DETAILS_BASE64_ENCODE);
CompletionStage<WSResponse> responsePromise = complexRequest.post(GRANT_TYPE + "="
+ PASSWORD + "&" + USERNAME + "=" + USERNAME + "&" + PASSWORD + "=" + PASSWORD);
return responsePromise.thenApply(response-> getAuthToken2().toString());
}
private CompletionStage<String> getAuthToken2() {
WSRequest request = ws.url(URL);
WSRequest complexRequest = request.setHeader("X-API-Key", X_API_KEY)
.setHeader(CONTENT_TYPE, CONTENT_TYPE_VALUE)
.setHeader(AUTHORIZATION, CLIENT_DETAILS_BASE64_ENCODE);
CompletionStage<WSResponse> responsePromise = complexRequest.post(GRANT_TYPE + "="
+ PASSWORD + "&" + USERNAME + "=" + USERNAME + "&" + PASSWORD + "=" + PASSWORD);
return responsePromise.thenApply(response-> addIdentity(response.asJson().findValue("access_token").toString()).toString());
}
What is the mistake I am making? How do I make nested requests one after the other one?
I get
java.util.concurrent.CompletableFuture#75c6e852[Not completed]
as the response to my client
You have to use thenCompose to chain multiple http requests. Here is a working sample: for three sites, we will fetch their page and add the status code to a JSON object. At the end, we return that object.
public CompletionStage<Result> getSites() {
ObjectNode hosts = Json.newObject();
return ws.url("https://www.facebook.com").get()
.thenCompose(res -> {
hosts.put("facebook", res.getStatus());
return ws.url("https://www.google.com").get();
})
.thenCompose(res -> {
hosts.put("google", res.getStatus());
return ws.url("https://www.twitter.com").get();
})
.thenApply(res -> {
hosts.put("twitter", res.getStatus());
return ok(hosts);
});
}
I want to get JSON information from a route in my Android app using Google Directions API. But I always get "NOT_FOUND" as status code. If I enter the same URL of my request in the browser it works fine.
Here my code inside a AsyncTask:
#Override
protected String doInBackground(final String... params) {
String startAddress = params[0];
String finishAddress = params[1];
departureTime = params[2];
String travelMode = params[3];
String result = "";
String url = "http://maps.googleapis.com/maps/api/directions/json?origin=" + startAddress
+ "&destination=" + finishAddress + "&departure_time=" + departureTime + "&mode=" + travelMode + "&sensor=true";
url = url.trim().replace(' ', '+');
Log.d(TAG, "URL String: " + url);
try {
URL urlObject = new URL(url);
URLConnection urlConn = urlObject.openConnection();
BufferedReader in = new BufferedReader( new InputStreamReader(urlConn.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null){
result = result + inputLine;
}
in.close();
return result;
} catch (Exception e) {
exception = e.toString();
Log.e(TAG, "Exception getting route from Google Directions API: " + e.toString());
Logger.e(context, TAG, "Exception getting route from Google Directions API: " + e.toString());
return null;
}
}
The output looks like this:
02-23 08:54:01.811 25055-25055/de.bmw.ceprouteguide D/PlanRouteActivity﹕ startAddress: Hanauer Straße 46, München, endAddress: Westendstraße 11, München, travelMode: transit, date: 23-02-2015, time: 08:54
02-23 08:54:01.812 25055-25055/de.bmw.ceprouteguide D/PlanRouteActivity﹕ Millis since epoch:1424678040, date string: 23-02-2015 08:54
02-23 08:54:01.816 25055-25618/de.bmw.ceprouteguide D/PlanRouteActivity﹕ URL String: http://maps.googleapis.com/maps/api/directions/json?origin=Hanauer+Straße+46,+München&destination=Westendstraße+11,+München&departure_time=1424678040&mode=transit&sensor=true
02-23 08:54:02.116 25055-25055/de.bmw.ceprouteguide D/PlanRouteActivity﹕ Route: { "routes" : [], "status" : "NOT_FOUND"}
02-23 08:54:02.117 25055-25055/de.bmw.ceprouteguide D/PlanRouteActivity﹕ Google Directions status code: NOT_FOUND
Anyone an idea where the problem is?
If you have API key
you have to enable API from https://console.developers.google.com
Google Maps Direction API
Google Maps Android API
If not create credentials to access your enable API.
wait for 10 min and then retry.