httpurlconnection and special characters - android

i can send with my app a http post.
Problem is, that the special characters like ä, ö , ... will not be correct.
this is my code:
#Override
protected String doInBackground(String... params) {
try {
URL url = new URL("https://xxx");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
String urlParameters = "&name" + name;
connection.setRequestMethod("POST");
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setDoOutput(true);
DataOutputStream dStream = new DataOutputStream(connection.getOutputStream());
dStream.writeBytes(urlParameters);
dStream.flush();
dStream.close();
} catch (MalformedURLException e) {
Log.e("-->", Log.getStackTraceString(e));
} catch (IOException e) {
Log.e("-->", Log.getStackTraceString(e));
}
return null;
}
This http post will send to a php file, which saves the value name into a database.
Example:
The App send the value "Getränke"
Result in the database: "Getr"
where is my mistake?

Try this it may be help to you.
You need to set the encoding in your Content-Type header.
Set it to application/x-www-form-urlencoded; charset=utf-8. instead of
Accept-Charset.

The internal string representation in Java is always UTF-16.
Every encoding has to be done when strings enter or leave the VM. That means in your case you have to set the encoding when you write the body to the stream.
Try with following:
dStream.writeBytes(urlParameters.getBytes("UTF-8"));
Also you may need to set the encoding in your Content-Type header.
Set it to "application/x-www-form-urlencoded; charset=utf-8".
Currently you are only setting the Accept-Charset - this tells the server what to send back.

Related

XMLPullParser black diamond question marks with certain characters

I'm making an android app, that needs to fetch and parse XML. The class for that was made following the instructions from here http://www.tutorialspoint.com/android/android_rss_reader.htm and the fetcher method looks like this:
public void fetchXML() {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
InputStream stream = conn.getInputStream();
xmlFactoryObject = XmlPullParserFactory.newInstance();
xmlFactoryObject.setValidating(false);
xmlFactoryObject.setFeature(Xml.FEATURE_RELAXED, true);
xmlFactoryObject.setNamespaceAware(true);
XmlPullParser myparser = xmlFactoryObject.newPullParser();
//myparser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
myparser.setInput(new InputStreamReader(stream, "UTF-8"));
parseXMLAndStoreIt(myparser);
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
Parser looks like the one in tutorial, with my parsing logic in it.
As you can see from
myparser.setInput(new InputStreamReader(stream, "UTF-8"));
I'm using UTF-8 charset. Now when I use getText() method in my parser for example on the word 'Jõhvi', the logcat output is 'J�hvi'. It's the same for other characters of my native language, Estonian, that aren't in English alphabet. I need to use this string as a key and in the user interface, so this isn't acceptable. I'm thinking it's a charset problem, but there is no info at the XML site I'm pulling this from and using
conn.getContentEncoding()
returns null so I'm in the dark here.
Content encoding and character encoding are not the same thing.
Content encoding refers to compression such as gzip. Since getContentEncoding() is null, that tells you there's no compression.
You should be looking at conn.getContentType(), because the character encoding can usually be found in the content-type response header.
conn.getContentType() might return something like:
text/xml; charset=ISO-8859-1
so you will have to do some parsing. Look for the character set name after "charset=" but be prepared for the case where the mime type is specified but the charset is not.

how to send unicode charcters in http post request from asyncTask

I saw this post How to send unicode characters in an HttpPost on Android but I usaully do request in this way in AsyncTask class.My log is also printing local language in urlParameters but server is returning no result while it is perfect for english Strings:
#Override
protected String doInBackground(String... URLs) {
StringBuffer response = new StringBuffer();
try {
URL obj = new URL(URLs[0]);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// add request header
con.setRequestMethod("POST");
if (URLs[0].equals(URLHelper.get_preleases)) {
urlCall = 1;
} else
urlCall = 2;
// String urlParameters = "longitude=" + longitude + "&latitude="+latitude;
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
if (responseCode == 200) {
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return response.toString();
}
Is there a way to set character set UTF-8 to request parameters coding this way?
String urlParameters = "longitude=" + longitude + "&latitude="+latitude;
You need to URL-encode components you are injecting into an application/x-www-form-urlencoded context. (Even aside from non-ASCII characters, characters like the ampersand will break otherwise.)
Specify the string-to-bytes encoding that you are using for your request in that call, for example:
String urlParameters = "longitude=" + URLEncoder.encode(longitude, "UTF-8")...
...
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
A DataOutputStream is for sending struct-like Java-typed binary data down a stream. It doesn't give you anything you need for writing HTTP request bodies. Maybe you meant OutputStreamWriter?
But since you already have the string all in memory you could simply do:
con.getOutputStream().write(urlParameters.getBytes("UTF-8"))
(Note the UTF-8 here is somewhat superfluous. Because you will already have URL-encoded all the non-ASCII characters into %xx escapes, there will be nothing to UTF-8-encoded. However in general it is almost always better to specify a particular encoding than omit it and revert to the unreliable system default encoding.)
new InputStreamReader(con.getInputStream())
is also omitting the encoding and reverting to the default encoding which is probably not the encoding of the response. So you will probably find non-ASCII characters get read incorrectly in the response too.

issue in httpurlconnection getting status 500

I am trying to login through url and i am getting status code 500 in httpurlconnevtion
public static String excutePost(String targetURL, String urlParameters)
{
URL url;
HttpURLConnection connection = null;
try {
//Create connection
url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Length", "" +
Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setRequestProperty("Accept-Encoding", "");
connection.setUseCaches (false);
connection.setDoInput(true);
connection.setDoOutput(true);
//Send request
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream ());
wr.writeBytes (urlParameters);
wr.flush ();
wr.close ();
System.out.println("status :"+connection.getResponseCode());
System.out.println("getErrorStream() :"+connection.getErrorStream());
//Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if(connection != null) {
connection.disconnect();
}
}
}
and my params are
String urlParameters =
"pwd1=" + URLEncoder.encode("DEMO123", "UTF-8") +
"&badge=" + URLEncoder.encode("1233", "UTF-8");
i am getting logcat
status :500
getErrorStream() :libcore.net.http.FixedLengthInputStream#417bc5c0
thank you
**EDITED 2**
I have also try with
DataOutputStream dos = new DataOutputStream(connection.getOutputStream());
// Add badge
dos.writeBytes(LINE_START + BOUNDRY + LINE_END);
dos.writeBytes("Content-Disposition: form-data; name='badge';");
dos.writeBytes(LINE_END + LINE_END);
dos.writeBytes("1233");
dos.writeBytes(LINE_END);
// Add password
dos.writeBytes(LINE_START + BOUNDRY + LINE_END);
dos.writeBytes("Content-Disposition: form-data; name='pwd1';");
dos.writeBytes(LINE_END + LINE_END);
dos.writeBytes("DEMO123");
dos.writeBytes(LINE_END);
500 denotes an Internal Server Error. There is probably no error on your side, it's on the server. Even if you are sending something incorrectly and it's causing the server to return 500, it's still a server problem.
Edit:
Okey, the server should rather return something like 400 Bad Request instead of 500 Internal Server Error but I found your error now:
connection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length));
...
//Send request
DataOutputStream wr = new DataOutputStream (connection.getOutputStream ());
wr.writeBytes (urlParameters);
The problem here is that your first get the the bytes from urlParameters using getBytes which (quoting javadoc):
Encodes this String into a sequence of bytes using the platform's default charset
And then you write the bytes using DataOutputStream.writeBytes which (quoting javadoc):
Each character in the string is written out, in sequence, by discarding its high eight bits.
In summary, your Content-Length doesn't match the data. So the server returns you the
java.io.IOException: exceeded content-length limit of 20 bytes
Solution:
//consider urlParameters.getBytes("UTF-8") method instead of using default encoding
byte[] bodyData = urlParameters.getBytes();
connection.setRequestProperty("Content-Length", Integer.toString(bodyData.length));
...
//Send request
InputStream out = connection.getOutputStream();
out.write(bodyData);
Edit 2:
Edit 1 is definitely valid, however, looking over the problem again, I believe the error is definitely caused by the server. I think the server is returning a bad Content-Length header and, when the data is read on Android, the system realizes there is more data coming from the server than it should be by the Content-Length and throws an exception, also replacing the status code by 500 because it really is a server error.
Edit 3:
connection.setRequestProperty("Content-Language", "en-US");
connection.setRequestProperty("Accept-Encoding", "");
Instead of setting Content-Language which is not neccessary here, you should set Content-Encoding to UTF-8 and instead of empty Accept-Encoding, you should add the real expected MIME-type. I believe this is a server error, but you maybe it won't appear if you set the request headers correctly.
Status code 500 means Internal Server Error. Why this is thrown at you, only the server behind targetURL knows.
Verify that you're making correct usage of the API. Taking a look at the response's body (besides the status code) may provide a hint.

GCM push message encoding

I am trying to send push notifications using following code:
Message message = new Message.Builder().addData("appName", appData.name)
.addData("message", pushData.message).build();
On the receiving side my code is:
String message = intent.getStringExtra("message");
When the message is in English, latin charset, everything works. However, when I try other languages or the character ç, they arrive as question marks or are deleted from the string.
Note: it's encoded in utf-8
Java server
Message messagePush = new Message.Builder().addData("message", URLEncoder.encode("your message éèçà", "UTF-8")))
Android application
String message = URLDecoder.decode(intent.getStringExtra("message"), "UTF-8");
I was having the same issue. Non ASCII characters where corrupted when received on the Android client. I personally believe this is a problem within the Google GCM server library implementation.
In the Android GCM library I see the method:
com.google.android.gcm.server.Sender.sendNoRetry(Message, List<String>)
That method does the following
HttpURLConnection conn = post(GCM_SEND_ENDPOINT, "application/json", requestBody)
They should atleast specify "application/json; charset=utf-8" or whatever encoding they used or better yet force it to UTF-8. Isn't this is a BIG problem?
Digging even deeper I find the method:
com.google.android.gcm.server.Sender.post(String, String, String)
which does:
byte[] bytes = body.getBytes()
Why do they use the platform default charset? Especially since it is not likely to align with the devices default charset.
Work Around
Pass the following property as an argument to the JVM "-Dfile.encoding=UTF-8" This instructs Java to use UTF-8 as the platform default charset when doing things like "blah".getBytes(). This is bad practice but what can you do when it is someone else's library?
I had a similar problem with the gcm-server library. My workaround was using a custom sender to override the post method and use UTF8 as encoding in the getBytes() call.
It works on Google App Engine.
The code of the custom sender class:
import java.io.Closeable;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.util.logging.Level;
import com.google.android.gcm.server.Sender;
/**
* Workaround to avoid issue #13 of gcm-server
* #see https://code.google.com/p/gcm/issues/detail?id=13&q=encoding
*
* #author rbarriuso /at/ tribalyte.com
*
*/
public class Utf8Sender extends Sender {
private final String key;
public Utf8Sender(String key) {
super(key);
this.key = key;
}
#Override
protected HttpURLConnection post(String url, String contentType, String body) throws IOException {
if (url == null || body == null) {
throw new IllegalArgumentException("arguments cannot be null");
}
if (!url.startsWith("https://")) {
logger.warning("URL does not use https: " + url);
}
logger.fine("Utf8Sender Sending POST to " + url);
logger.finest("POST body: " + body);
byte[] bytes = body.getBytes(UTF8);
HttpURLConnection conn = getConnection(url);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setFixedLengthStreamingMode(bytes.length);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", contentType);
conn.setRequestProperty("Authorization", "key=" + key);
OutputStream out = conn.getOutputStream();
try {
out.write(bytes);
} finally {
close(out);
}
return conn;
}
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);
}
}
}
}
These were some good solutions, however they didnt help me because I was using topic messaging to send notifications. As per this
The HTTP header must contain the following headers:
Authorization: key=YOUR_API_KEY
Content-Type: application/json for
JSON; application/x-www-form-urlencoded;charset=UTF-8 for plain text.
If Content-Type is omitted, the format is assumed to be plain text.
However, because I am using cloud endpoints and my app (already out in the wild) is expecting json, formatting the request in plain text wasnt viable. The solution was to ignore the document above, and in my backend, format the http request header as such:
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
Like magic, suddenly all special characters (read: Japanese) is going through to my application with no front end changes being made. My complete http post code is below( where payload = Cloud endpoint model object, converted to json<String> via Gson):
try {
URL url = new URL("https://gcm-http.googleapis.com/gcm/send");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
connection.setRequestProperty("Authorization", "key=" + API_KEY);
connection.setRequestMethod("POST");
byte[] bytes=payload.getBytes("UTF-8");
OutputStream out = connection.getOutputStream();
try {
out.write(bytes);
} finally {
out.close();
}
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
// OK
log.warning("OK");
} else {
// Server returned HTTP error code.
log.warning("some error "+connection.getResponseCode());
}
} catch (MalformedURLException e) {
// ...
}
Break with the debugger and view the bytes of the message you think you're sending

Does Android Support a server made on ashx or ASP.NET Web Handler file

I have an android application that have to communicate with the server using post method in HTTP. My application work fine whenever i open some other sites having basic page may be html or others but whenever i want to open my server file it gives nothing even though with get method in HTTP.
The blank response from the server can be understandable that what i am getting because i have to send some headers with post method as a request and ashx will send some response to it.
But still as expected by get method in HTTP the basic information of the page have to be retrieved.
for eg. my server url is http://172.17.3.90/RMALite/RLHandler.ashx
and the basic response from the get method have to be like this.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=windows-1252"></HEAD>
<BODY></BODY></HTML>
Unfortunately i am getting nothing
but whenever i changed the url to open other sites it work fine and i got the response in text html format.
So my Question is, Android require some stuff to handle ASP.NET handler or ashx file as compare to other sites or URL's?
I know it late now but other can get benefit. Below is code snippet which help me to get accomplished same issue.
public static String excutePost(String targetURL, String urlParameters) {
//targetURL =http://172.17.3.90/RMALite/RLHandler.ashx
URL url;
HttpURLConnection connection = null;
try {
// Create connection
url = new URL(targetURL);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", ""
+ Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setRequestProperty("method-name", "parameter-value");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
// // Send request
DataOutputStream wr = new DataOutputStream(connection
.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
String field1 = connection.getHeaderField("field1");
String field2 = connection.getHeaderField("field2");
return anyArray;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
I believe it would be helpful n much appreciated to this post
thanks much
-y

Categories

Resources