I try to push notification from java server to IOS client
and i have this error(response from codename one server)
{"error":"Failed to send push to APNS: com.notnoop.exceptions.NetworkIOException: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake"}
String GOOGLE_SERVER_KEY = "********************************************";
HttpsURLConnection connection;
String url = "https://push.codenameone.com/push/push";
String TOKEN = "******-****-*****-*****-**************";
String URL_ENCODED_LINK_TO_YOUR_P12_FILE =
"https://dl.dropboxusercontent.com/*/******************/Certificates.p12";
String URL_ENCODED_CERTIFICATE_PASSWORD = "******";
String deviceId =
"cn1-gcm-*******************************************************";
String deviceId2 =
"cn1-ios-***************************************************";
String MESSAGE_BODY = "This notification message coming from server";
try {
connection = (HttpsURLConnection)new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
String query =
"token=" + TOKEN + "&device=" + deviceId + "&device=" +
deviceId2 + "&type=1&auth=" + GOOGLE_SERVER_KEY +
"&certPassword=" + URL_ENCODED_CERTIFICATE_PASSWORD +
"&cert=" + URL_ENCODED_LINK_TO_YOUR_P12_FILE + "&body=" +
URLEncoder.encode(MESSAGE_BODY, "UTF-8") + "&production=false";
try {
OutputStream output = connection.getOutputStream();
output.write(query.getBytes("UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("ResponseCode : " + connection.getResponseCode());
System.out.println("ResponsenMessage : " +
connection.getResponseMessage());
BufferedReader br =new BufferedReader(new InputStreamReader((connection.getInputStream())));
String output;
String result = "";
System.out.println("Output .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
result += output + "\n";
}
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
Output from codename one Server
Response Code : 200
Response Message : OK
Output ....
{"error":"Failed to send push to APNS: com.notnoop.exceptions.NetworkIOException: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake"}
A handshake exception would generally mean the Codename One servers failed to connect due to a security issue. This probably means your P12 is incorrect.
Are you sure you used the right P12 file? Keep in mind that there are 2 push certificates (not to be confused with the 2 signing certificates) and only one of them should be used based on the value of the sandbox flag.
Did you use the certificate wizard?
I think 2195 and 2196 ports are disabled on either the server or client side which needs to be enabled for apple push notification.
Related
I am creating an android app too write and run java code in an android device using Android studio
we tried using the jdoodle API to compile and run the java code in the app. But whenever we tried to compile the code ye are getting error 400.
Please tell me how can I implement this API so that i can execute a java file.
we are using java language to write the program
Getting error code 400 while executing this:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
try {
String clientId = "af52e5b3d******c2d81bade***6c055"; //Replace with your client ID
String clientSecret = "e868414f******183267d398d578a448c6a1a70bf8be2896ebc******b013bc"; //Replace with your client Secret
String script = editText.getText().toString();
String language = "java";
String versionIndex = "0";
URL url = new URL("https://api.jdoodle.com/v1/execute");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
String input = "{\"clientId\": \"" + clientId + "\",\"clientSecret\":\"" + clientSecret + "\",\"script\":\"" + script +
"\",\"language\":\"" + language + "\",\"versionIndex\":\"" + versionIndex + "\"} ";
System.out.println(input);
OutputStream outputStream = connection.getOutputStream();
outputStream.write(input.getBytes());
outputStream.flush();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new RuntimeException("Please check your inputs : HTTP error code : " + connection.getResponseCode());
}
BufferedReader bufferedReader;
bufferedReader = new BufferedReader(new InputStreamReader(
(connection.getInputStream())));
StringBuilder results = new StringBuilder();
String output1;
System.out.println("Output from JDoodle .... \n");
while ((output1 = bufferedReader.readLine()) != null) {
results.append(output1);
}
connection.disconnect();
output.setText(results);
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
here we are pass
Error code 400 is a server side error. I means the server didn't understand your request. If I was to take a guess it would have to do with your input string. It does not appear to be written in the normal way variables are sent in post. That being said, a server can be written to accept the variables any way it wants to. But if it is the reason this is how the string should look.
name=value&name2=value2
You get the idea. Also JDoodle is a pay service. Most pay services will help you, they don't want to lose a client.
I made a andoid application in which I am getting response from php server, requesting in POST format. I am using below code for http connection:
// random string as boundary for multi-part http post
String strBoundary = "3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f";
String endLine = "\r\n";
OutputStream os;
String url = encodeUrl(methodType, graphURL, params);
Log.d("url - ",url);
Log.d("Method Type - ", methodType + " URL - " + url);
HttpURLConnection conn = (HttpURLConnection) new URL(url)
.openConnection();
conn.setConnectTimeout(60000);
conn.setReadTimeout(30000);
conn.setRequestProperty("User-Agent", System.getProperties()
.getProperty("http.agent"));
if (!methodType.equals("GET")) {
Bundle dataparams = new Bundle();
for (String key : params.keySet()) {
if (params.getByteArray(key) != null) {
dataparams.putByteArray(key, params.getByteArray(key));
}
}
// use method override
if (!params.containsKey("method")) {
params.putString("method", methodType);
}
if (params.containsKey("access_token")) {
#SuppressWarnings("deprecation")
String decoded_token = URLDecoder.decode(params
.getString("access_token"));
params.putString("access_token", decoded_token);
}
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + strBoundary);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.connect();
os = new BufferedOutputStream(conn.getOutputStream());
os.write(("--" + strBoundary + endLine).getBytes());
os.write((encodePostBody(params, strBoundary)).getBytes());
os.write((endLine + "--" + strBoundary + endLine).getBytes());
if (!dataparams.isEmpty()) {
for (String key : dataparams.keySet()) {
os.write(("Content-Disposition: form-data; filename=\""
+ key + "\"" + endLine).getBytes());
os
.write(("Content-Type: content/unknown" + endLine + endLine)
.getBytes());
os.write(dataparams.getByteArray(key));
os.write((endLine + "--" + strBoundary + endLine)
.getBytes());
}
}
os.flush();
}
String response = "";
try {
response = parseXmlSvn(conn.getInputStream());
} catch (FileNotFoundException e) {
// Error Stream contains JSON that we can parse to a FB error
//response = read(conn.getErrorStream());
Log.i("RESPONSE",""+response);
}
Log.i("RESPONSE", ""+response);
return response;
Everything is working fine on my demo server, I uploaded my PHP service to clients server. I am getting proper response from his server also.
But when client access app in 3G or 4G in some other country in his android devices, he is getting Blank response while the same service of same server can be accessible in iOS code easily by him. Is it some packet loss while getting response or any other problem?
I would really appreciate any help you can give me.
Thanks
Code
public HttpRequest(BufferedReader from) {
String firstLine = "";
try {
firstLine = from.readLine();
} catch (IOException e) {
System.out.println("Error reading request line: " + e);
}
String[] tmp = firstLine.split(" ");
method = tmp[0];
URI = tmp[1];
version = tmp[2];
System.out.println("URI is: " + URI);
if(method.equals("POST")){
try {
String line = from.readLine();
while (line.length() != 0) {
headers += line + CRLF;
if (line.startsWith("Host:")) {
tmp = line.split(" ");
if (tmp[1].indexOf(':') > 0) {
String[] tmp2 = tmp[1].split(":");
host = tmp2[0];
port = Integer.parseInt(tmp2[1]);
} else {
host = tmp[1];
port = HTTP_PORT;
}
}
line = from.readLine();
}
headers += "Connection: close" + CRLF;
headers += CRLF;
}
catch (IOException e) {
System.out.println("Error reading from socket: " + e);
return;
}
}
else {
System.out.println("Error: Method not supported");
return;
}
System.out.println("Host to contact is: " + host + " at port " + port);
}
Problem
I am making a proxy server using Java.
The code above handles an HTTP POST Request. It successfully reads the POST header and prints it in the command prompt but the body is missing.
Can you take look at my code and see the problem? Thanks.
(NOTE: I excluded the GET part because there were no problems with that.)
Result
The problem is that you still have things to read on the InputStream. That's why when you shut down the browser, there's nothing else to read so is printed. You have to read exactly the number of bytes that is declared in "Content-Length"
Try something like this:
int cL = Integer.valueOf(contentLength);
byte[] buffer = new byte[cL];
String postData = "";
System.out.println("Reading "+ cL + "bytes");
in.read(buffer, 0, cL);
postData = new String(buffer, 0, buffer.length);
System.out.println(postData);
The body request will be in the postData string.
This is not how to write a proxy server. A proxy server only has to do the following:
Accept incoming connections. For each connection:
Read an HTTP CONNECT request.
Connect to the target host specified in the CONNECT request and send an appropriate response to the client.
If the connect succeeded, copy bytes between the upstream server and the downstream client, in both directions simultaneously.
When you read EOS in one direction, shutdown the opposite socket for output.
When you have shutdown in both directions, close both sockets.
That's it. There is no parsing of POST requests or anything else required. Not even a Reader.
I'am trying to implement a simple HTTP/1.1 client application against a remote HTTP server. If I have a 301 Moved Permanently response from server, I will try to download the file from it's new location given in server's response. I am able to send first GET message to server and retrieve the new URL where the file I asked was moved.
The problem is that when I send second GET request from my client with new location of the file, server returns null. Not sure if anything goes wrong with writing the client message or reading the server response. Here is my code, any help is appreciated.
else if(serverMessage.equals("HTTP/1.1 301 Moved Permanently"))
{
System.out.println(" A new permanent URL is assigned to the file " + fileName);
serverMessage="";
lineCount=0;
while((serverMessage = reader.readLine()) != null)
{
lineCount++;
System.out.println("reply: " + serverMessage);
if(serverMessage.indexOf("Location") >= 0 )
{
for(int x=serverMessage.indexOf("Location")+10; x<serverMessage.length(); x++)
{
newURL= newURL + serverMessage.charAt(x);
}
}
}
System.out.println("newURL : " + newURL);
host = findHost(newURL);
path = findPath(newURL);
fileName=findFileName(newURL);
clientMessage = "GET ";
clientMessage = clientMessage + path;
clientMessage = clientMessage + " HTTP/1.1\r\nHost: ";
clientMessage = clientMessage + host;
clientMessage = clientMessage + "\r\n\r\n";
System.out.println("client message: \"" + clientMessage +"\"");
writer.newLine();
writer.write(clientMessage);
writer.flush();
serverMessage = reader.readLine();
System.out.println("reply2: " + serverMessage); //returns null!!!
while((serverMessage=reader.readLine())!=null)
{
System.out.println("reply2: " + serverMessage);
}
}
EDIT: Variables of client message are the followings (they all work correctly, tested for existing file - successfully downloaded!)
newURL : http://wlab.cs.bilkent.edu.tr/~cs421/pa1/302-redirect-success.txt
host2: wlab.cs.bilkent.edu.tr
path2: /~cs421/pa1/302-redirect-success.txt
fileName2: 302-redirect-success.txt
Are you using a persistent URLConnection / HttpURLConnection?
You may be receiving null if the connection has been closed by the server.
If you are using persistent connections, the server might have not had the time to respond.
This might describe the problem a little better. Check out the timeout given in doHttpUrlConnectionAction(String desiredUrl). You might find the answer there.
If this is your problem, you can try to do multiple reads at 0.1 second intervals for say ... 1-5 seconds. This is to make sure you get the response fast and don't have to wait the full timeout to make sure that the server has responded.
I'm receiving the following SSLHandshakeException when trying to send a push notification through the C2DM servers.
javax.net.ssl.SSLHandshakeException: Could not verify SSL certificate for: https://android.apis.google.com/c2dm/send
The code to send the message is as follows, and is running on App Engine. Everything works fine when I use cURL, so I know that the server authentication code and device registration ID are correct.
public static void sendHttpPostToC2dmService(String msg, PrintWriter out) {
String authCode = "XXXX";
String regID = "YYYY";
try {
URL url = new URL("https://android.apis.google.com/c2dm/send");
String data = URLEncoder.encode("registration_id", "UTF-8") + "="
+ URLEncoder.encode(regID, "UTF-8");
data += "&"
+ URLEncoder.encode("Authorization: GoogleLogin auth",
"UTF-8") + "="
+ URLEncoder.encode(authCode, "UTF-8");
data += "&" + URLEncoder.encode("collapse_key", "UTF-8") + "="
+ URLEncoder.encode("something", "UTF-8");
data += "&" + URLEncoder.encode("data.message", "UTF-8") + "="
+ URLEncoder.encode(msg, "UTF-8");
out.println("data=" + data);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
OutputStreamWriter writer = new OutputStreamWriter(
connection.getOutputStream());
writer.write(data);
writer.close();
out.println("responseCode=" + connection.getResponseCode());
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
String responseLine = new BufferedReader(new InputStreamReader(
connection.getInputStream())).readLine();
out.println("responseLine=" + responseLine);
} else {
// Server returned HTTP error code.
}
} catch (MalformedURLException e) {
out.println("MalformedURL");
out.println(e.getMessage());
} catch (IOException e) {
out.println("IOException");
out.println(e.getMessage());
e.printStackTrace(out);
}
}
It seems like others have also had this problem, but I haven't been able to find a clear solution (at least not one I'm able to understand). Appreciate any help.
You need to use HttpsURLConnection instead of HttpURLConnection.
AFAIK, HttpURLConnection doesn't verify hostnames.
If you are in the testing phase, you could use the non-secure url to push a notification.
http://android.apis.google.com/c2dm/send
I also got around this issue by adding a certificate validation callback to accept any certificate, but this was on a C# server. I'm sure there is a Java equivalent for this.
In production code you would want to verify the correct certificate or maybe just encrypt the data you are sending.