I am using gcm to push notifications to one or multiple devices, However I constantly get the error message: "mismatched sender ID".
Here is my code:
public static void post(String apiKey){
try{
// prepare JSON
JSONObject jGcmData = new JSONObject();
JSONObject jData = new JSONObject();
jData.put("message", "{good luck}");
jGcmData.put("to","token ID");
jGcmData.put("data", jData);
// Create connection to send GCM Message request.
URL url = new URL("https://android.googleapis.com/gcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "key=" + apiKey);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// Send GCM message content.
OutputStream outputStream = conn.getOutputStream();
outputStream.write(jGcmData.toString().getBytes());
// Read GCM response.
InputStream inputStream = conn.getInputStream();
String resp = IOUtils.toString(inputStream);
System.out.println(resp);
} catch (IOException e) {
System.out.println("Unable to send GCM message. "+e);
}
}
Also, when I used jGcmData.put("to","/topics/foo-bar");instead of jGcmData.put("to","token ID");, the notification can be sent successfully. However what I want is to push notification to selected devices.
For the mismatched sender ID:
Try uninstalling the app and run it again.This will clear any created keys of the App.
error:MismatchSenderId
A registration token is tied to a certain group of senders. When a client app registers for GCM, it must specify which senders are allowed to send messages. You should use one of those sender IDs when sending messages to the client app. If you switch to a different sender, the existing registration tokens won't work.
According to this SO answer, ""mismatchSenderId happens because the app within the same device have logged with different keys.""
For the Topic Subscription / Topic Sending
This may be related to this Subscribe to topics suddenly throws "java.io.IOException: InternalServerError", it says that "We identified an issue in our backed that affected a small percentage of the topic subscriptions during the last 24 hours. The issue has already been fixed, and the subscriptions should work correctly on all devices."
I hope this helps you.
Related
I'm having trouble receiving notification from API in JSON format. I've made a SpringBoot application that gets entities from the URL from the server (port:1026). However, the API has a subscription and notification system that I am supposed to utilize.
I'm having trouble realizing the implementation of getting the notification from API. When I subscribe to API a JSON entity is sent that I'm subscribing to I send an endpoint URL (localhost on port:1028) on which the notification is being sent. (entity and endpoint are in the same POST request to API to subscribe).
The issue is I don't know how to listen to that notification and show it on a webpage so when a call is made on API for value of that entity to change I see the notification on server log and see it in real time on my browser webpage.
This is the code that needs to be reworked. Here I just get a GET call from API to see what entities are created but when I make a PUT/POST to API via postman, manual refreshing is needed in order to see the change, and it's not utilizing the subscription system.
I think I need some kind of GET listener from server (localhost:1026) in order to parse the entity.
try {
URL url = new URL("http://localhost:1026/v2/entities");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.connect();
//Check if connection is made
int responseCode = conn.getResponseCode();
// 200 OK
if (responseCode != 200) {
throw new RuntimeException("HttpResponseCode: " + responseCode);
} else {
informationString = new StringBuilder();
Scanner scanner = new Scanner(url.openStream());
while (scanner.hasNext()) {
informationString.append(scanner.nextLine());
logger.info("Entity updated");
}
//Close the scanner
scanner.close();
logger.info(String.valueOf(informationString));
//return String.valueOf(informationString);
}
} catch (Exception e) {
e.printStackTrace();
}
return String.valueOf(informationString);
You can use setTimeout() on the webpage to periodically call your API then display the response immediately
This question already has an answer here:
How to track FCM push notifications send form server side or Rest Client? [duplicate]
(1 answer)
Closed 5 years ago.
Here is my code that I am attempting to set up a firebase call to send a message to a topic. I get a 200 response code back but nothing appears on the FCM console. Am i doing something wrong.
public static void pushFCMNotification() throws Exception{
String authKey = Constants.AUTH_KEY_FCM;
String FMCurl = Constants.API_URL_FCM;
URL url = new URL(FMCurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization","key="+authKey);
conn.setRequestProperty("Content-Type","application/json");
JSONObject json = new JSONObject();
JSONObject info = new JSONObject();
try {
info.put("title", "New notification"); // Notification title
info.put("body", "A new notification has been added to the notice board"); // Notification body
json.put("notification", info);
json.put("to", "/topics/notif"); //replace userDeviceIdKey with the unique notification key for the group
} catch (JSONException e) {
e.printStackTrace();
}
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(json.toString());
wr.flush();
conn.getInputStream();
}
Thanks for the help in advance.
Messages sent through the REST API don't appear in the console (regardless if it's sent to a token or to a topic).
Usually, if you use the REST API to send to a token, you could view it in the Diagnostics Page. However, messages sent to topics don't appear there as well. (see the Possible duplicate post I linked in the comments section)
Using Java code (scroll down to view) I am sending a notification message to my Android using FCM, when providing the correct server key token I receive the response message seen below.
The following response message is received from FCM after
Response: 200
Success Message: '{"multicast_id":-1,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}'
Error Message: ''
Process finished with exit code 0
This means the server key token is correct and there's some sort of authorization established with FCM. When I use incorrect server key token(s) I get a different error message. However, the message above although labeled "Success Message*" still states that the success value =0 and the failure value =1, error:InvalidRegistration. If this is indeed an error, does the error imply the notification was not received by FCM, or not by the endpoint Android application?
Android App
The Android application is able to receive notifications from FCM using the console. Does this mean the Android app is set to receive the same notifications from the Java server I wrote or does the app need additional code to process these notifications that are not sent from the console?
(Just for information purspose, code is clean and runs without errors, not all files of the project are shown below, just the relevant main function and HTTP POST file).
Java server
public class Sample {
private static String SERVER_KEY = "AAAA-NCJais:APA91b----CENSORED-------";
public static void main(String[] args) {
com.pushraven.Pushraven.setKey(SERVER_KEY);
// create Notification object
Notification raven = new Notification();
HashMap<String, Object> data = new HashMap<String, Object>();
data.put("Hello", "World!");
data.put("Rami", "Imar");
data.put("Test1", "Test2");
// build raven message using the builder pattern
raven.to("/topics/ALL")
.collapse_key("a_collapse_key")
.priority(1)
.delay_while_idle(true)
.time_to_live(100)
.restricted_package_name("com.example.******")
.dry_run(true)
.data(data)
.title("Testing")
.body("Hello World!");
// push the raven message
FcmResponse response = Pushraven.push(raven);
// alternatively set static notification first.
Pushraven.setNotification(raven);
response = Pushraven.push();
// prints response code and message
System.out.println(response);
}
}
--------------------------------- other file ------------------------------
public static FcmResponse push(Notification n) {
if(FIREBASE_SERVER_KEY == null){
System.err.println("No Server-Key has been defined.");
return null;
}
HttpsURLConnection con = null;
try{
String url = API_URL;
URL obj = new URL(url);
con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
// Set POST headers
con.setRequestProperty("Authorization", "key="+FIREBASE_SERVER_KEY);
con.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
// Send POST body
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(wr, "UTF-8"));
writer.write(n.toJSON());
writer.close();
wr.close();
wr.flush();
wr.close();
con.getResponseCode();
}
catch(Exception e){
e.printStackTrace();
}
return new FcmResponse(con);
}
InvalidRegistration error means that the token you're sending the message to is invalid:
Check the format of the registration token you pass to the server. Make sure it matches the registration token the client app receives from registering with Firebase Notifications. Do not truncate or add additional characters.
Double check the value you're passing in your to parameter. In your code, I see that you're using news. If you were intending to send to a topic, you'll have to add the prefix /topics/. So it should be something like /topics/news/. See the Topic Messaging docs for more details.
I am trying to send notification to registered devices using gcm. But it send "null" instead of message. I have tried lot of solutions. If any basic thing is missing kindly share. I have attached the code spinet.
JSONObject jGcmData = new JSONObject();
JSONObject jData = new JSONObject();
String msg = "new order came";
jData.put("message", msg);
// Where to send GCM message.
if (!(id == null)) {
jGcmData.put("to", id);
} else {
jGcmData.put("to", "/topics/global");
}
// What to send in GCM message.
jGcmData.put("data", jData);
// Create connection to send GCM Message request.
URL url = new URL("https://android.googleapis.com/gcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "key=" + API_KEY);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// Send GCM message content.
OutputStream outputStream = conn.getOutputStream();
outputStream.write(jGcmData.toString().getBytes());
The url you are using is incorrect. It should be https://gcm-http.googleapis.com/gcm/send. See Server changes.
I am trying to send a post request to a url using HttpURLConnection (for using cUrl in java).
The content of the request is xml and at the end point, the application processes the xml and stores a record to the database and then sends back a response in form of xml string. The app is hosted on apache-tomcat locally.
When I execute this code from the terminal, a row gets added to the db as expected. But an exception is thrown as follows while getting the InputStream from the connection
java.io.FileNotFoundException: http://localhost:8080/myapp/service/generate
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1401)
at org.kodeplay.helloworld.HttpCurl.main(HttpCurl.java:30)
Here is the code
public class HttpCurl {
public static void main(String [] args) {
HttpURLConnection con;
try {
con = (HttpURLConnection) new URL("http://localhost:8080/myapp/service/generate").openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.setDoInput(true);
File xmlFile = new File("test.xml");
String xml = ReadWriteTextFile.getContents(xmlFile);
con.getOutputStream().write(xml.getBytes("UTF-8"));
InputStream response = con.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(response));
for (String line ; (line = reader.readLine()) != null;) {
System.out.println(line);
}
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Its confusing because the exception is traced to the line InputStream response = con.getInputStream(); and there doesn't seem to be any file involved for a FileNotFoundException.
When I try to open a connection to an xml file directly, it doesn't throw this exception.
The service app uses spring framework and Jaxb2Marshaller to create the response xml.
The class ReadWriteTextFile is taken from here
Thanks.
Edit:
Well it saves the data in the DB and sends back a 404 response status code at the same time.
I also tried doing a curl using php and print out the CURLINFO_HTTP_CODE which turns out to be 200.
Any ideas on how do I go about debugging this ? Both service and client are on the local server.
Resolved:
I could solve the problem after referring to an answer on SO itself.
It seems HttpURLConnection always returns 404 response when connecting to a url with a non standard port.
Adding these lines solved it
con.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
con.setRequestProperty("Accept","*/*");
I don't know about your Spring/JAXB combination, but the average REST webservice won't return a response body on POST/PUT, just a response status. You'd like to determine it instead of the body.
Replace
InputStream response = con.getInputStream();
by
int status = con.getResponseCode();
All available status codes and their meaning are available in the HTTP spec, as linked before. The webservice itself should also come along with some documentation which overviews all status codes supported by the webservice and their special meaning, if any.
If the status starts with 4nn or 5nn, you'd like to use getErrorStream() instead to read the response body which may contain the error details.
InputStream error = con.getErrorStream();
FileNotFound is just an unfortunate exception used to indicate that the web server returned a 404.
To anyone with this problem in the future, the reason is because the status code was a 404 (or in my case was a 500). It appears the InpuStream function will throw an error when the status code is not 200.
In my case I control my own server and was returning a 500 status code to indicate an error occurred. Despite me also sending a body with a string message detailing the error, the inputstream threw an error regardless of the body being completely readable.
If you control your server I suppose this can be handled by sending yourself a 200 status code and then handling whatever the string error response was.
For anybody else stumbling over this, the same happened to me while trying to send a SOAP request header to a SOAP service. The issue was a wrong order in the code, I requested the input stream first before sending the XML body. In the code snipped below, the line InputStream in = conn.getInputStream(); came immediately after ByteArrayOutputStream out = new ByteArrayOutputStream(); which is the incorrect order of things.
ByteArrayOutputStream out = new ByteArrayOutputStream();
// send SOAP request as part of HTTP body
byte[] data = request.getHttpBody().getBytes("UTF-8");
conn.getOutputStream().write(data);
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
Log.d(TAG, "http response code is " + conn.getResponseCode());
return null;
}
InputStream in = conn.getInputStream();
FileNotFound in this case was an unfortunate way to encode HTTP response code 400.
FileNotFound in this case means you got a 404 from your server - could it be that the server does not like "POST" requests?
FileNotFound in this case means you got a 404 from your server
You Have to Set the Request Content-Type Header Parameter
Set “content-type” request header to “application/json” to send the request content in JSON form.
This parameter has to be set to send the request body in JSON format.
Failing to do so, the server returns HTTP status code “400-bad request”.
con.setRequestProperty("Content-Type", "application/json; utf-8");
Full Script ->
public class SendDeviceDetails extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String data = "";
String url = "";
HttpURLConnection con = null;
try {
// From the above URL object,
// we can invoke the openConnection method to get the HttpURLConnection object.
// We can't instantiate HttpURLConnection directly, as it's an abstract class:
con = (HttpURLConnection)new URL(url).openConnection();
//To send a POST request, we'll have to set the request method property to POST:
con.setRequestMethod("POST");
// Set the Request Content-Type Header Parameter
// Set “content-type” request header to “application/json” to send the request content in JSON form.
// This parameter has to be set to send the request body in JSON format.
//Failing to do so, the server returns HTTP status code “400-bad request”.
con.setRequestProperty("Content-Type", "application/json; utf-8");
//Set Response Format Type
//Set the “Accept” request header to “application/json” to read the response in the desired format:
con.setRequestProperty("Accept", "application/json");
//To send request content, let's enable the URLConnection object's doOutput property to true.
//Otherwise, we'll not be able to write content to the connection output stream:
con.setDoOutput(true);
//JSON String need to be constructed for the specific resource.
//We may construct complex JSON using any third-party JSON libraries such as jackson or org.json
String jsonInputString = params[0];
try(OutputStream os = con.getOutputStream()){
byte[] input = jsonInputString.getBytes("utf-8");
os.write(input, 0, input.length);
}
int code = con.getResponseCode();
System.out.println(code);
//Get the input stream to read the response content.
// Remember to use try-with-resources to close the response stream automatically.
try(BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"))){
StringBuilder response = new StringBuilder();
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
System.out.println(response.toString());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (con != null) {
con.disconnect();
}
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.e("TAG", result); // this is expecting a response code to be sent from your server upon receiving the POST data
}
and call it
new SendDeviceDetails().execute("");
you can find more details in this tutorial
https://www.baeldung.com/httpurlconnection-post
The solution:
just change localhost for the IP of your PC
if you want to know this: Windows+r > cmd > ipconfig
example: http://192.168.0.107/directory/service/program.php?action=sendSomething
just replace 192.168.0.107 for your own IP (don't try 127.0.0.1 because it's same as localhost)
Please change
con = (HttpURLConnection) new URL("http://localhost:8080/myapp/service/generate").openConnection();
To
con = (HttpURLConnection) new URL("http://YOUR_IP:8080/myapp/service/generate").openConnection();