I have a class for Httpclient. The same instance is used throughout the application. So if the client == null it should create one else it will return the existing instance. Everything works until i try to release the resource on exit by doing: client.getConnectionManager().shutdown();....after this i am not able to login again. It gives Sysem error saying : connection pool shutdown. Heres the class:
public class HttpClientFactory {
private static DefaultHttpClient client;
public synchronized static DefaultHttpClient getThreadSafeClient() {
if (client != null)
return client;
client = new DefaultHttpClient();
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
HttpParams params = new BasicHttpParams();
SingleClientConnManager mgr = new SingleClientConnManager(params, schemeRegistry);
client = new DefaultHttpClient(mgr, params);
return client;
}
}
After this i simply run client.getConnectionManager().shutdown(); onBackPressed(), can somebody please help me
Ok..i got the solution...I was not setting it back to null and connection shutdown is suppose to be done in the same global class...
I have faced similar issue, but set
client.getConnectionManager().shutdown()
client.getConnectionManager() = null
could not resolved the problem.
Finally, I found out that, I did close all connections in onPostExecute, which is incorrect, so after moving them into doInBackground, it works.
Hope this helps someone!
Related
In one of our old project we are using DefaultHttpClient for networking. its working fine below lollipop devices but in lollipop get request hangs execute method call.
We are creating HttpClient like this.
public static MyHttpClient createHttpClient(Context ctx) {
try {
if(mgr == null){
SSLSocketFactory sf = SSLSocketFactory.getSocketFactory();
sf.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
httpParameters = new BasicHttpParams();
HttpProtocolParams.setVersion(httpParameters, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(httpParameters, HTTP.UTF_8);
HttpConnectionParams.setConnectionTimeout(httpParameters, HOST_REACH_TIMEOUT);
HttpConnectionParams.setSoTimeout(httpParameters, HOST_REACH_TIMEOUT);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
mgr = new ThreadSafeClientConnManager(httpParameters, registry);
}
return new MyHttpClient(mgr, httpParameters);
} catch (Exception e) {
return new MyHttpClient(ctx);
}
}
We are also setting timeouts. Any idea why its freezing there and how we can fix that?
Edit: one more thing that i have missed. It only happens when we hit same URL 3rd time. First two times it works fine.
Instantiate every time a new mgr.
I am using Single HTTP client for whole app to manage session on server side .
It works fine until two async task access same HTTP client at the same time.
I got this error .
"Invalid use of SingleClientConnManager: connection still allocated"
What to do in such situation. ?
You could create a custom HttpClient, that uses a ThreadSafeClientConnManager
public class MyGreatHttpClient extends DefaultHttpClient {
#Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
(...)
return new ThreadSafeClientConnManager(httpparams, registry);
}
}
I am working on an Android app that needs to read a line from a web page right when it starts. I am doing this with the following code:
try{
URL url = new URL("http://www.example.com");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
line = reader.readLine();
}
catch(Exception e){
e.printStackTrace();
}
It is working fine, but sometimes the connection or the server are slow, and the app freezes or crashes.
I want to put a timeout of 5 seconds, and should it reach that timeout I want to show a toast to the user saying the network is busy, asking him to try again later.
I tried the HttpURLConnection setConnectTimeout() method but it didn't work.
Any clues how I can achieve this? Thanks forehand.
Probably better solution if you setConnectionTimeout to 5 sec, catch SocketTimeoutException and show Toast from there. When you set ConnectionTimeout to some value and connection didn't get response code will throw SocketTimeoutException. Here you can catch it and call handler to show a toast in UI. Finally will close the connection and release memory.
class MyHttpClient extends DefaultHttpClient {
#Override
protected ClientConnectionManager createClientConnectionManager() {
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https",
mSSLSocketFactory != null
? mSSLSocketFactory
: SSLSocketFactory.getSocketFactory(),
443));
return new SingleClientConnManager(getParams(), registry);
}
MyHttpClient httpClient = new MyHttpClient();
// set http params
HttpParams params = httpClient.getParams();
params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, new Integer(30000));
params.setParameter(CoreConnectionPNames.SO_TIMEOUT, new Integer(30000));
httpClient.setParams(params);
....
httpClient.execute(httpUriRequest)
Consider using AndroidHttpClient class instead, it has nice preset timeouts so you wouldn't have to do anything.
I had seen a few examples in Android implement maybeCreateHttpClient(), especially in Google sample, which it does is to check if HttpClient object is instantiated, if not, instantiate it, and reuse it.
Why this approach? Is creating new HttpClient expensive?
Use a connection pool (eg. ThreadSafeClientConnManager) to manage your clients.
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager connman = new ThreadSafeClientConnManager(params, registry);
client = new DefaultHttpClient(connman, params);
client is a singleton object which can be reused, to fire a request:
HttpResponse response = client.execute(new HttpGet(URL));
A HttpClient is fairly large and complex object. You might make tens (or probably more) http calls in your app. If you created a new one for each http request you would quickly run into memory problems and would certainly notice garbage collection slow downs.
The http client is a generic component to help you make http calls, just reuse it. There is no reason not too.
I'm using a ThreadSafeClientConnManager to perform simultaneous requests in background threads on Android, set up with:
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager connman = new ThreadSafeClientConnManager(params, registry);
client = new DefaultHttpClient(connman, params);
And executing requests with (note that I'm using outh-signpost):
HttpGet request = new HttpGet("https://" + API_HOST + "/" + API_VERSION + path);
OAuthConsumer consumer = new CommonsHttpOAuthConsumer(key, secret);
consumer.sign(request);
HttpResponse response = client.execute(request);
The problem is that after a while I start getting
java.net.SocketException: The operation timed out
Do I need to do something to explicitly release the connection after the request?
From the usage guide of apache httpclient, you need to make sure to consume all content on any pooled resource to guarantee it returns to the pool to be available for other threads later on -
http://hc.apache.org/httpcomponents-core-4.0.1/tutorial/html/fundamentals.html#d0e244
In case there's an exception thrown by the underlying library, it is best to abort the HttpMethod that you were trying to run, in which case the connection will be terminated.