In the "doInBackground" function of a AsyncTask, I got the following piece of code :
try
{
URL url = new URL(myUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
Authenticator.setDefault(new Authenticator(){
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication ("myUsername", "myPassword".toCharArray());
}
});
conn.connect();
int response = conn.getResponseCode();
inputStream = conn.getInputStream();
String content = convertInputStreamToString(inputStream);
return content;
catch (Exception e) {
e.printStackTrace();
return null;
}
When the credentials are ok, everything works fine and the ResponseCode is 200. But if I put the wrong credentials, getResponseCode() makes the AsyncTask wait for an answer indefinitely (timeout won't work). Looking at HttpUrlConnection object tells me that the ResponseCode is -1.
I need to handle every situation, even if the user provides a bad credential. How can I get an usable answer? Should I use another class than HttpUrlConnection?
Are you returning String back from this function and are you handling exceptions? Did you write onPostExecute?
Here is the code that works perfectly for me:
URL url = new URL(strUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Host", "myhost.com");
conn.setRequestProperty("Authorization", "Basic " + Base64.encodeToString(toencode, Base64.DEFAULT));
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:1.3.1)");
conn.setRequestProperty("Accept-Charset", "UTF-8");
conn.setConnectTimeout (5000) ;
conn.setDoOutput(true);
conn.setDoInput(true);
BufferedInputStream in = new BufferedInputStream(conn.getInputStream());
result = Utilities.readStream(in);
status_code = conn.getResponseCode();
return result;
} catch (MalformedURLException e) {
return e.getMessage();
} catch (ProtocolException e) {
try {
status_code = conn.getResponseCode();
} catch (IOException e1) {
status_code = -1;
}
return e.getMessage();
} catch (IOException e) {
try {
status_code = conn.getResponseCode();
} catch (IOException e1) {
status_code = -1;
}
return e.getMessage();
} catch ( Exception e ) {
try {
status_code = conn.getResponseCode();
} catch (IOException e1) {
status_code = -1;
}
return e.getMessage();
}
finally
{
conn = null;
}
Related
I have the following method which uses a proxy to retrieve information from a server. Sometimes due to a bad proxy I get SocketException, SSLException, SSLHandshakeException or ConnectException
As you can see in my method I am already using catch (IOException ioe) I need to do that in order to get the contents of server response if the server returns anything other than code 200.
How can I make the method retry in case of the above exceptions?
public String getMeta() throws IOException
{
HttpsURLConnection con = null;
InputStream is = null;
StringWriter writer = new StringWriter();
try
{
String url = "https://api.myapp.com/meta";
URL urlObj = new URL(url);
if (useProxy && fullProxy)
{
myapp.Proxy proxyCustom = getRandomProxy();
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyCustom.getProxyIp(), proxyCustom.getProxyPort()));
con = (HttpsURLConnection) urlObj.openConnection(proxy);
}
else
{
con = (HttpsURLConnection) urlObj.openConnection();
}
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Content-Type", "application/json; charset=utf-8");
con.setRequestProperty("host", urlObj.getHost());
con.setRequestProperty("Connection", "Keep-Alive");
int responseCode = 0;
responseCode = con.getResponseCode();
is = con.getInputStream();
writer = new StringWriter();
IOUtils.copy(is, writer, "UTF-8");
}
catch (IOException ioe)
{
if (con instanceof HttpsURLConnection)
{
HttpsURLConnection httpConn = (HttpsURLConnection) con;
int statusCode = httpConn.getResponseCode();
if (statusCode != 200)
{
is = httpConn.getErrorStream();
writer = new StringWriter();
IOUtils.copy(is, writer, "UTF-8");
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return writer.toString();
}
How can I make the method retry in case of the above exceptions?
One way shown below is to have the getMeta method actually throw the IOException. You can then then have a caller method recursively call itself due to any caught Exception.
I hope there is an simple way of setting how times it should retry
To be able to call the method n number of times, pass in the number of times as an argument and deal with the stopping criteria logic accordingly. For example:
public String caller(int total) throws IOException{
return callerImpl(1, total);
}
public String callerImpl(int current, int total) throws IOException{
try{
return getMeta();
}catch(IOException e){
current++;
if ( current > total ){
throw e;//or return null or empty string, depending upon upstream requirements
}
return callerImpl(current, total);
}
return null;
}
In getMeta:
try{
....
}catch(IOException io){
//log or handle io
throw io;
}
Note the above doesn't deal with the logging/logic of the thrown exceptions, which you may want to handle in some way.
The way I would do is create a new retry method and invoke it at the end of your getMeta() method so it is called in only in case of abnormalities
I am assuming you should call the retry only a few times and hence getMeta should throw some exception like RetryException after certain number of times
public String getMeta() throws IOException, RetryException
{
HttpsURLConnection con = null;
InputStream is = null;
StringWriter writer = new StringWriter();
try
{
String url = "https://api.myapp.com/meta";
URL urlObj = new URL(url);
if (useProxy && fullProxy)
{
myapp.Proxy proxyCustom = getRandomProxy();
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyCustom.getProxyIp(), proxyCustom.getProxyPort()));
con = (HttpsURLConnection) urlObj.openConnection(proxy);
}
else
{
con = (HttpsURLConnection) urlObj.openConnection();
}
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Content-Type", "application/json; charset=utf-8");
con.setRequestProperty("host", urlObj.getHost());
con.setRequestProperty("Connection", "Keep-Alive");
int responseCode = 0;
responseCode = con.getResponseCode();
is = con.getInputStream();
writer = new StringWriter();
IOUtils.copy(is, writer, "UTF-8");
return writer.toString();
}
catch (IOException ioe)
{
if (con instanceof HttpsURLConnection)
{
HttpsURLConnection httpConn = (HttpsURLConnection) con;
int statusCode = httpConn.getResponseCode();
if (statusCode != 200)
{
is = httpConn.getErrorStream();
writer = new StringWriter();
IOUtils.copy(is, writer, "UTF-8");
return writer.toString();
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return retryGetMeta();
}
private String retryGetMeta()
{
try
{
return getMeta();
}
finally
{
//Do your stuff
}
}
public RetryException extends Exception
{
private String message = "Retries exceeded";
public String getMessage()
{
return message;
}
}
If an exception is thrown in your getMeta(), catch will do its stuff as you are doing now, but after that , retryGetMeta will be called
I have problem with connecting to my server. Following code returns -1 as response code and null as response message.
protected Boolean doInBackground(MyTaskParams... params) {
URL url = null;
String load = params[0].jobj.toString();
try {
url = new URL(params[0].serverUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(3000);
urlConnection.setReadTimeout(3000);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
urlConnection.setChunkedStreamingMode(0);
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.connect();
OutputStreamWriter osw = new OutputStreamWriter(urlConnection.getOutputStream());
osw.write(load);
osw.flush();
osw.close();
if(urlConnection.getResponseCode()==200 && urlConnection.getResponseMessage().contains("true") ) return true;
else return false;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
While debbuging url and body content (which is load in code) are correct. When I try to connect with the server using those params with Fiddler it works perfectly and I get 200 status code. Do you have any ideas what is wrong?
Im passing jData object as the jobj:
JSONObject User=new JSONObject();
JSONObject Mobile=new JSONObject();
JSONObject jData=new JSONObject();
try {
User.put ("UserLogin", "test");
User.put ("UserPassword", "test");
Mobile.put ("MobileIDD", IDD);
Mobile.put("MobileToken", token);
jData.put("Mobile", Mobile);
jData.put("User", User);
} catch (JSONException e) {
e.printStackTrace();
}
#EDIT
Solution with System.setProperty("http.keepAlive", "false") didnt help.
I solved the problem. It was in this line:
if(urlConnection.getResponseCode()==200 && urlConnection.getResponseMessage().contains("true") ) return true;
When I changed it to:
int code = urlConnection.getResponseCode();
if (code==200.....)
It started working.
I have the following code in my program, used for inserting record -
private Void downloadUrl() throws IOException {
String postParameters;
HttpURLConnection urlConnection = null;
postParameters = "name="+ URLEncoder.encode(user.name,"UTF-8")
+"&age="+URLEncoder.encode(user.age+"","UTF-8")
+"&username="+URLEncoder.encode(user.username,"UTF-8")
+"&password="+URLEncoder.encode(user.password,"UTF-8");
if (postParameters != null) {
Log.i("Post", "POST parameters: " + postParameters);
try {
URL urlToRequest = new URL(SERVER_ADDRESS);
urlConnection = (HttpURLConnection) urlToRequest.openConnection();
urlConnection.setReadTimeout(30000 /* milliseconds */);
urlConnection.setConnectTimeout(30000 /* milliseconds */);
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
urlConnection.setFixedLengthStreamingMode(
postParameters.getBytes().length);
PrintWriter out = new PrintWriter(urlConnection.getOutputStream());
out.print(postParameters.getBytes());
out.close();
// handle issues
int statusCode = urlConnection.getResponseCode();
Log.e("Response", "The response is: " + statusCode);
} catch (MalformedURLException e) {
// handle invalid URL
Log.e("Response", "invalid URL");
} catch (SocketTimeoutException e) {
// hadle timeout
Log.e("Response", "handle timeout");
} catch (IOException e) {
// handle I/0
Log.e("Response", "handle IO problem");
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
return null;
}
The code is showing no errors and the logged entries are
09-27 12:24:17.944 5006-5039/? E/Response﹕ The response is: 200
09-27 12:24:33.729 5006-5118/? I/Post﹕ POST parameters: name=vibha&age=25&username=vib&password=1234
But when I check the database, the new record is not created.
But if I use PHP code in a file and post the same parameters,the records are getting inserted.
My requirement for help and guidance is how to pass the post parameter in the HttpURLConnection class
I get an EOFException from getInputStream in the following Android Code.
private void downloadUrl() {
HttpsURLConnection conn = null;
DataOutputStream printout = null;
try {
try {
conn = (HttpsURLConnection) new URL("some url").openConnection();
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setAllowUserInteraction(false);
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
}
catch (ProtocolException e){
}
JSONObject jsonReq = new JSONObject();
jsonReq.put("userID", "id");
jsonReq.put("password", "1234");
OutputStream output = conn.getOutputStream();
try {
OutputStreamWriter wr = new OutputStreamWriter(output);
wr.write(URLEncoder.encode(jsonReq.toString(),"utf-8"));
wr.flush();
wr.close();
}
catch (IOException e) {
}
InputStream in = conn.getInputStream(); //I get EOFException here
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(in));
String responseSingle = null;
while ((responseSingle = rd.readLine()) != null) {
response = response + responseSingle;
}
rd.close();
}
catch (IOException e) {
}
finally {
if (in != null)
in.close();
}
}
catch (IOException e){
}
catch (JSONException e) {
}
finally{
if(conn!=null)
conn.disconnect();
}
}
What is causing this Exception?
public class EOFException extends IOException:
Signals that an end of file or end of stream has been reached unexpectedly during input.
http://docs.oracle.com/javase/7/docs/api/java/io/EOFException.html
You are calling conn.getOutputStream(); and then calling conn.getInputStream(); without resetting. You are already at the end of the file.
I try to send post request, but webserver returns that I added no post-values. I spent a lot of time trying to solve this issue, but no result. Here is the code:
public static String post(String url, String postParams)
{
URLConnection connection = null;
try
{
connection = initializeConnection(url);
connection.setDoOutput(true);
((HttpURLConnection) connection).setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "text/xml");
connection.setRequestProperty("Accept", "text/xml");
connection.setUseCaches(false);
connection.setDoInput(true);
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.write(postParams.getBytes());
wr.flush();
wr.close();
// Get Response
InputStream is = connection.getInputStream();
return inputStreamToString(is);
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
protected static HttpURLConnection initializeConnection(String stringUrl)
{
HttpURLConnection connection;
URL url = null;
try
{
url = new URL(stringUrl);
}
catch (MalformedURLException e1)
{
e1.printStackTrace();
}
try
{
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
return connection;
}
public static String inputStreamToString(InputStream is)
{
BufferedReader r = new BufferedReader(new InputStreamReader(is));
StringBuilder total = new StringBuilder();
String line;
try
{
while ((line = r.readLine()) != null)
{
total.append(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
return total.toString();
}
I receive a message from webserver where it is told that no post-values are added. As far as I understand from the code, the values are added. I'm stuck.
It turned out that all I had to do was to replace
connection.setRequestProperty("Content-Type", "text/xml");
with
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
So simple and so much time spent to clear it out...
By the way, how could I know that server requires this header? I thought that all the work that is essential to the request would be automatically done by java..
P.S. Installing fiddler helped to solve the issue, thanks for that.
debug the 'postParams' parameter and check what been sent.