I tried looking for answers for this since last few days with no luck, Even some of the stackoverflow answers did not help.
I am trying to checkin a user after receiving his UserToken via Android. I get a FileNotfoundException at getInputStream(), non authenticated APIs like
"https://api.foursquare.com/v2/venues/categories" work well. Am i missing something?
URL url = new URL("https://api.foursquare.com/v2/checkins/add?oauth_token="+token);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.addRequestProperty("venueId","12238");
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setAllowUserInteraction(true);
conn.connect();
InputStream is = conn.getInputStream();
String response = streamToString(is);
return response;
Managed to solve this after lot of effort. See my answer below.
Try adding the oauth_token using the same method you use to add the venueid. Also, your venueid is invalid, so make sure you are checking the user in to a real venue.
The HttpURLConnection class is misleading in that it will throw a FileNotFoundException for any HTTP error code of 400 or above.
So it's not necessarily an incorrect URL (404) it could be 400 (bad request), 403 (forbidden), 500 (internal server error) etc.
Use the getResponseCode method to get a more precise indication of the problem.
first: Yoy have https url, and trying to create HttpURLConnection. You should use HttpsURLConnection.
Second: You can try to add conn.setDoOutput(true), "post" request requires it. And without it server can try give a get request from you despite on conn.setRequestMethod("POST"). Also you can check headers from your browser plugin, and put them into your request.
Okie I finally managed to solve the problem, I don't know what exactly was the problem with my code above but the following worked.
This API requires a POST call but even the venueID must be part of the URL and addRequestProperty does not seem to be sending the venueID properly. Hence I changed the code to
URL url = new URL("https://api.foursquare.com/v2/checkins/add?venueId=12238&oauth_token="+token);
And this solved the problem. Thanks all
Related
I am not able to reach the create Method in tests_controller.rb with this code.
String newUrl = "http://10.0.2.2:3000/tests";
httpcon = (HttpURLConnection) ((new URL(newUrl).openConnection()));
httpcon.setDoOutput(true);
httpcon.setRequestProperty("Content-Type", "application/json");
httpcon.setRequestProperty("Accept", "application/json");
httpcon.setRequestMethod("POST");
httpcon.connect();
And here is my routes.rb (I use model scaffold to create the RoR app).
resources :tests
Am i wrong in routing or something. When i run this code in Android, the create method is not run at all.
It's hard to tell the reason for the failure you have. Your routes seem OK. You can check couple other things:
Is your Rails server listening on the right interface and port?
Is there any network problem between the machine your client is working on and the server?
Instead of going through the cycle of edit-compile-deploy-run of Android, simply use curl or a similar tool to try the POST request from the console.
When you pinpoint the place of the problem, then you can ask another question, or, more likely, already find the answer online.
Eventhough I have set to not follow redirects:
HttpURLConnection urlConnection = url.openConnection();
urlConnection.setInstanceFollowRedirects(false);
I still can't get my POST request to work. I get response code: 302 (it means the website offers me redirection) and I think this is the reason because everything works perfectly with other websites that doesn't redirect. How to completely avoid redirection so to make my POST request to work?
I have some typical codes which used HttpURLConnection to get a file with an URL.
They worked fine in android 1.x and 2.x. But failed in Android 4.1!
I searched on the web but found little similar information.
Would anybody please help to investigate this issue?
private String mURLStr;
private HttpURLConnection mHttpConnection;
...
url = new URL(mURLStr);
...
mHttpConnection = (HttpURLConnection) url.openConnection();
mHttpConnection.setDoOutput(true);
mHttpConnection.setRequestMethod("GET");
...
InputStream is = mHttpConnection.getInputStream();
The getInputStream method throws an exception:
08-01 15:56:48.856: W/System.err(13613): java.io.IOException: No authentication challenges found
08-01 15:56:48.856: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.getAuthorizationCredentials(HttpURLConnectionImpl.java:427)
08-01 15:56:48.866: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.processAuthHeader(HttpURLConnectionImpl.java:407)
08-01 15:56:48.866: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.processResponseHeaders(HttpURLConnectionImpl.java:356)
08-01 15:56:48.866: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:292)
08-01 15:56:48.866: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:168)
...
I am currently facing the same problem. On 4.1 Jelly Bean I receive an IOException "No authentication challenges found" when calling getResponseCode() on the HttpURLConnection.
I have searched online to see what has changed in the Android source code and found the following:
4.0.4 (working): https://bitbucket.org/seandroid/libcore/src/7ecbe081ec95/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java
4.1.1 (not working): https://bitbucket.org/seandroid/libcore/src/6b27266a2856/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java
As one can see in 4.1 JB the method getAuthorizationCredentials() throws the IOException. It parses the challenge headers it finds in the response using HeaderParser.parseChallenges(..), if the response code is 401 or 407. If the returned List is empty the Exception is thrown.
https://bitbucket.org/seandroid/libcore/src/6b27266a2856/luni/src/main/java/libcore/net/http/HeaderParser.java
We are currently investigating what exactly causes that List to be empty, but have the suspicion that our server might use realm=... instead of realm="..." in the challenge header. Missing quotation marks might be the cause for this problem. We have to investigate further if that is indeed the case and if we can make it work.
Per RFC2617:
The 401 (Unauthorized) response message is used by an origin server
to challenge the authorization of a user agent. This response MUST
include a WWW-Authenticate header field containing at least one
challenge applicable to the requested resource.
In Android, the HttpURLConnection getResponseCode() method throws java.io.IOException: No authentication challenges found when the server returns either a 401 Unauthorized or 407 Proxy Authentication Required status code without the WWW-Authenticate header set.
If you own the server-side API, then you can fix it by adding the required WWW-Authenticate header when you return 401 or 407. In my case, I fixed it in PHP as follows:
header('WWW-Authenticate: OAuth realm="users"');
header('HTTP/1.1 401 Unauthorized');
I have the same problem. I found this workaround, but it is not working on Android 2. On Jelly Bean, it works fine. Just use getErrorStream() instead of getInputStream().
try
{
responseStream = new BufferedInputStream(connection.getInputStream());
}
catch(IOException e)
{
responseStream = new BufferedInputStream(connection.getErrorStream());
}
Heading
I have fixed the problem for the Jelly bean. Please use the below code for the above scenario
DefaultHttpClient client = new DefaultHttpClient();
client.getCredentialsProvider().setCredentials(new AuthScope(null, -1), new UsernamePasswordCredentials(userName,userPass));
HttpGet request = new HttpGet();
request.addHeader("Accept", "application/xml");
request.setURI(new URI(service));
HttpResponse response = client.execute(request);
you got the proper response as you needed.
I ran into a similar issue with a web service that required cookies to operate correctly. Apparently Jelly Bean doesn't automatically create a cookie store by default (unlike previous versions), so the service wasn't able to find my session and threw a 401 every time I tried to access it. Adding the following lines of code to my application initialization fixed the problem:
// enable VM-wide cookie support for HttpUrlConnection
// see http://developer.android.com/reference/java/net/HttpURLConnection.html for details
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
When using Basic authentication and not calling setDoOutput(true) we still had this issue:
Here is the solution:
HTTP Basic Authentication issue on Android Jelly Bean 4.1 using HttpURLConnection
Check if your server is returning an Error 401 - Not Authorised. I believe the Android code sees that response and believes it was meant to provide authentication details. In my case I was just providing the wrong token to my server.
There is one Solution
In your code Remove this
HttpConnection.setDoOutput(true);
It will work on ICS or Jelly Bean
A solution I used for this (I'm using Android's Volley library) was to use
Square's OkHttp library. Their implementation correctly handles this issue and will return the 401 as expected.
I am having the following API call:
http://rollout.gr/api/?query={%22search%22:%22places%22,%22page%22:1}
This API call is executed correctly in my browser. But when I use a DefaultHttpClient to execute this url in my Android application, I get a null response.
I suppose the problem is the JSON data in the HTTP url. Thus, I would like to ask which is the proper way to handle such url in an Android application?
Thanks a lot in advance!
The accolades aren't valid URL characters. The browser is userfriendly enough to automatically URL-encode them, but DefaultHttpClient isn't. The correct line to use from code is:
http://rollout.gr/api/?query=http://rollout.gr/api/?query=%7b%22search%22:%22places%22,%22page%22:1%7d
Note the encoding for the accolades (%7b, %7d).
Your problem may be the strictmode here.
I recommend to do http request in threads or asynctasks. strictmode doesnt let app do http reauest in uithread. maybe your console shows a warning and you get null from http response because of this.
This project may solve your problem:
http://loopj.com/android-async-http/
Not knowing your particular HTTP initialization code, I'm going to assume you didn't provide an explicit JSON accept header. A lot of REST endpoints require this.
httpget.setHeader("Accept", "application/json");
I have some typical codes which used HttpURLConnection to get a file with an URL.
They worked fine in android 1.x and 2.x. But failed in Android 4.1!
I searched on the web but found little similar information.
Would anybody please help to investigate this issue?
private String mURLStr;
private HttpURLConnection mHttpConnection;
...
url = new URL(mURLStr);
...
mHttpConnection = (HttpURLConnection) url.openConnection();
mHttpConnection.setDoOutput(true);
mHttpConnection.setRequestMethod("GET");
...
InputStream is = mHttpConnection.getInputStream();
The getInputStream method throws an exception:
08-01 15:56:48.856: W/System.err(13613): java.io.IOException: No authentication challenges found
08-01 15:56:48.856: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.getAuthorizationCredentials(HttpURLConnectionImpl.java:427)
08-01 15:56:48.866: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.processAuthHeader(HttpURLConnectionImpl.java:407)
08-01 15:56:48.866: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.processResponseHeaders(HttpURLConnectionImpl.java:356)
08-01 15:56:48.866: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:292)
08-01 15:56:48.866: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:168)
...
I am currently facing the same problem. On 4.1 Jelly Bean I receive an IOException "No authentication challenges found" when calling getResponseCode() on the HttpURLConnection.
I have searched online to see what has changed in the Android source code and found the following:
4.0.4 (working): https://bitbucket.org/seandroid/libcore/src/7ecbe081ec95/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java
4.1.1 (not working): https://bitbucket.org/seandroid/libcore/src/6b27266a2856/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java
As one can see in 4.1 JB the method getAuthorizationCredentials() throws the IOException. It parses the challenge headers it finds in the response using HeaderParser.parseChallenges(..), if the response code is 401 or 407. If the returned List is empty the Exception is thrown.
https://bitbucket.org/seandroid/libcore/src/6b27266a2856/luni/src/main/java/libcore/net/http/HeaderParser.java
We are currently investigating what exactly causes that List to be empty, but have the suspicion that our server might use realm=... instead of realm="..." in the challenge header. Missing quotation marks might be the cause for this problem. We have to investigate further if that is indeed the case and if we can make it work.
Per RFC2617:
The 401 (Unauthorized) response message is used by an origin server
to challenge the authorization of a user agent. This response MUST
include a WWW-Authenticate header field containing at least one
challenge applicable to the requested resource.
In Android, the HttpURLConnection getResponseCode() method throws java.io.IOException: No authentication challenges found when the server returns either a 401 Unauthorized or 407 Proxy Authentication Required status code without the WWW-Authenticate header set.
If you own the server-side API, then you can fix it by adding the required WWW-Authenticate header when you return 401 or 407. In my case, I fixed it in PHP as follows:
header('WWW-Authenticate: OAuth realm="users"');
header('HTTP/1.1 401 Unauthorized');
I have the same problem. I found this workaround, but it is not working on Android 2. On Jelly Bean, it works fine. Just use getErrorStream() instead of getInputStream().
try
{
responseStream = new BufferedInputStream(connection.getInputStream());
}
catch(IOException e)
{
responseStream = new BufferedInputStream(connection.getErrorStream());
}
Heading
I have fixed the problem for the Jelly bean. Please use the below code for the above scenario
DefaultHttpClient client = new DefaultHttpClient();
client.getCredentialsProvider().setCredentials(new AuthScope(null, -1), new UsernamePasswordCredentials(userName,userPass));
HttpGet request = new HttpGet();
request.addHeader("Accept", "application/xml");
request.setURI(new URI(service));
HttpResponse response = client.execute(request);
you got the proper response as you needed.
I ran into a similar issue with a web service that required cookies to operate correctly. Apparently Jelly Bean doesn't automatically create a cookie store by default (unlike previous versions), so the service wasn't able to find my session and threw a 401 every time I tried to access it. Adding the following lines of code to my application initialization fixed the problem:
// enable VM-wide cookie support for HttpUrlConnection
// see http://developer.android.com/reference/java/net/HttpURLConnection.html for details
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
When using Basic authentication and not calling setDoOutput(true) we still had this issue:
Here is the solution:
HTTP Basic Authentication issue on Android Jelly Bean 4.1 using HttpURLConnection
Check if your server is returning an Error 401 - Not Authorised. I believe the Android code sees that response and believes it was meant to provide authentication details. In my case I was just providing the wrong token to my server.
There is one Solution
In your code Remove this
HttpConnection.setDoOutput(true);
It will work on ICS or Jelly Bean
A solution I used for this (I'm using Android's Volley library) was to use
Square's OkHttp library. Their implementation correctly handles this issue and will return the 401 as expected.