I have a method (below) to get data from web services in my android program. It works fine with Android 2.2. But in 4.x it throws an exception with message "Error Requesting API". Not sure which part is causing the exception in my code and why only in 4.x Can someone give me some pointers?
public static synchronized String performHTTPRequest(HttpUriRequest request)
throws ApiException, ParseException, IOException {
HttpClientWrapper cli=new HttpClientWrapper();
HttpClient client;
try {
client=cli.getClient();
HttpResponse response = client.execute(request);
// Check if server response is valid
StatusLine status = response.getStatusLine() ;
if (status.getStatusCode() != HTTP_STATUS_OK) {
throw new ApiException("Invalid response from server: " + status.toString());
}
return EntityUtils.toString(response.getEntity());
} catch (MalformedURLException e) {
throw new Error(e);
} catch (Exception cnrce) {
throw new ApiException("Error requesting API:");
}
}
In 4.0 or the verions above honeycomb you can not perform any http request on ui thread.
You need to perform these in asynctask.
EDIT:
Documentation
Code example for asynctask
Related
I have some experience in Android application development. Now we developed an Android application where we need the exact date and time from Google or the internet. Already I test some code from Stack Overflow and from some other sites, but it did not work correctly. The app crashed. Can anyone help me?
Try this:
private long getTime() throws Exception {
String url = "https://time.is/Unix_time_now";
Document doc = Jsoup.parse(new URL(url).openStream(), "UTF-8", url);
String[] tags = new String[] {
"div[id=time_section]",
"div[id=clock0_bg]"
};
Elements elements= doc.select(tags[0]);
for (int i = 0; i <tags.length; i++) {
elements = elements.select(tags[i]);
}
return Long.parseLong(elements.text() + "000");
}
Gradle:
compile 'org.jsoup:jsoup:1.10.2'
This is enough to get what you wanted:
Using the HttpGet, Client and Response, I manage to get a server's current time from the response Date Header. I can call this all the times I want and will get confident responses (Google is almost 100% available and I can trust on getting correct Date and Time)
try{
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(new HttpGet("https://google.com/"));
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK){
String dateStr = response.getFirstHeader("Date").getValue();
//Here I do something with the Date String
System.out.println(dateStr);
} else{
//Closes the connection.
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
}catch (ClientProtocolException e) {
Log.d("Response", e.getMessage());
}catch (IOException e) {
Log.d("Response", e.getMessage());
}
ou can get time from internet time servers using the below program
import java.io.IOException;
import org.apache.commons.net.time.TimeTCPClient;
public final class GetTime {
public static final void main(String[] args) {
try {
TimeTCPClient client = new TimeTCPClient();
try {
// Set timeout of 60 seconds
client.setDefaultTimeout(60000);
// Connecting to time server
// Other time servers can be found at : http://tf.nist.gov/tf-cgi/servers.cgi#
// Make sure that your program NEVER queries a server more frequently than once every 4 seconds
client.connect("nist.time.nosc.us");
System.out.println(client.getDate());
} finally {
client.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
1.You would need Apache Commons Net library for this to work. Download the library and add to your project build path.
(Or you can also use the trimmed Apache Commons Net Library here : https://www.dropbox.com/s/bjxjv7phkb8xfhh/commons-net-3.1.jar. This is enough to get time from internet )
2.Run the program. You will get the time printed on your console.
It looks like my Android httpPost is limited to 5Kbytes!
public static boolean upload(String url, String content)
throws IOException {
Log.d(TAG, "upload data begin to url:" + url);
HttpClient httpClient = createHttpClient();
Uri uri = Uri.parse(url);
Uri.Builder builder = uri.buildUpon();
builder.appendQueryParameter("key", content);
HttpPost httpPost = new HttpPost(builder.build().toString());
try {
HttpResponse postResponse = httpClient.execute(httpPost);
int statusCode = postResponse.getStatusLine().getStatusCode();
postResponse.getEntity().consumeContent();
return statusCode == HttpStatus.SC_OK;
} catch (ClientProtocolException e) {
Log.w(TAG, "upload data failure", e);
throw e;
} catch (IOException e) {
Log.w(TAG, "upload data failure", e);
throw e;
} catch(Exception e) {
Log.w(TAG, "upload data failure", e);
}
return false;
}
When looking at the Apache logs I got:
[error] [client ] request failed: URI too long (longer than 8190)
It looks like it is sent as GET and not POST!
You should be using POST to begin with, not GET.
On another note, theoretically there is no limit, it is only limited by the value configured. See the Apache docs here for more information:
http://httpd.apache.org/docs/2.2/mod/core.html#limitrequestline
So it looks like it is sent as GET and not as POST
No. You just put everything in the URL. The constructor takes the URL, not the POST body.
Since HttpClient was removed from the Android SDK in Android 6.0, I cannot readily link you to Android's HttpPost documentation. However, AFAIK, it is similar to the 4.5.1 API, where the constructor parameter is the URL.
I use to make two types of httpGet call. One for parsing JSON with Gson and one for getting the string, for small JSONs....
This is what I use for parsing with GSON:
static HttpGet getRequest;
static HttpResponse getResponse;
#SuppressLint("NewApi")
public static InputStream retrieveStream(String url) {
if (android.os.Build.VERSION.SDK_INT >= 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
int timeout = 30000;
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, timeout);
HttpConnectionParams.setSoTimeout(httpParameters, timeout);
DefaultHttpClient client = new DefaultHttpClient(httpParameters);
getRequest = new HttpGet(url);
try {
getResponse = client.execute(getRequest);
final int statusCode = getResponse.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ERROR", "Error " + statusCode + " for URL " + url);
return null;
}
HttpEntity getResponseEntity = getResponse.getEntity();
return getResponseEntity.getContent();
} catch (IOException e) {
getRequest.abort();
Log.w("ERROR", "Error for URL " + url, e);
} catch (Exception e) {
getRequest.abort();
Log.w("ERROR", "Error for URL " + url, e);
}
return null;
}
Yes, almost always, if there are some errors on JSON or there's no connection, it gives me null and I handle it.
Yes, almost always, if JSON is correct and I have connection, I can parse it successfully.
But few times, I think around 10 or 11 in one month, it doesn't do anything. It stops and doesn't continue (I let it for 20 minutes). It doesn't return null due to URL error, JSON error or TIMEOUT, it just stops. In that moment, my connection is stopped (no movements) but my connection works normally (because I receive messages from, for example WhatsApp).
So, if I open a ProgressDialog, it never closes because I can't handle a null or a successful InputStream, so I can't make the user know that, in the worst of the cases, he/she has to retry.
I'm making all this stuff asynchronously.
What am I doing bad?
Thanks in advance.
I am having an unusual problem regarding the following code in an android application.
public InputStream retrieveStream(String url) {
HttpGet request = new HttpGet(url);
HttpParams httpParams = new BasicHttpParams();
int some_reasonable_timeout = (int) (10 * DateUtils.SECOND_IN_MILLIS);
HttpConnectionParams.setConnectionTimeout(httpParams, some_reasonable_timeout);
HttpConnectionParams.setSoTimeout(httpParams, some_reasonable_timeout);
HttpClient client = new DefaultHttpClient(httpParams);
try
{
HttpResponse response = client.execute(request);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK){
HttpEntity getResponseEntity = response.getEntity();
return getResponseEntity.getContent();
}
else
{
Log.w(getClass().getSimpleName(),
"Error " + statusCode + " for URL " + url);
return null;
}
}
catch (ClientProtocolException e)
{
Log.e("Methods", "HTTP Error", e);
return null;
}
catch (IOException e)
{
Log.e("Methods", "Connection Error", e);
return null;
}
}
Within the application I attempt to connect to a localhost.(In an AsyncTask)
InputStream source = retrieveStream("http://10.0.2.2:27080/testdb/_hello")
When running on the emulator, this code works fine and if the localhost is down, "source" is returned as null as expected. Similarly when running the code on a mobile device (HTC Nexus One, Android Version 2.2), the code reports "source" as null as expected.
However when running the same APK on another mobile device (Samsung Galaxy S2, Android Version 4.0.3, samsung release), the status code returned is given as HttpStatus.SC_OK, even though it couldnt possibly be connecting to the localhost. Has anyone encountered a similar problem?
Android > 3.0 does not allow to execute web request on Main UI Thread. you need to use AsyncTask to make web request. IN android > 3.0
I am trying to implement asynchronus http client for Android and I am haveing a trouble with type mismatch:
The method execute(HttpUriRequest) in the type HttpClient is not applicable for the arguments (HttpRequest)
I am doing all based on this tutorial: http://blog.androgames.net/12/retrieving-data-asynchronously/
Have found a type in AsynchronousSender - private HttpRequest request; but I have still problem with above which occurs in:
public void run() {
try {
final HttpResponse response;
synchronized (httpClient) {
response = getClient().execute(request); //<-- here is that problem
}
// process response
wrapper.setResponse(response);
handler.post(wrapper);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Can you suggest anything ?
cheers,
/Marcin
The code snippets on http://blog.androgames.net/12/retrieving-data-asynchronously/ are wrong. To fix it just replace HttpRequest with HttpUriRequest since the method signature is: HttpClient#execute(HttpUriRequest). It shouldn't be any problem since most requests you work with are HttpUriRequest instances.