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);
}
}
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 have developed an Android app and it is running smooth. Not yet into production. This app communicates with the server using REST services. Now
arrived an issue. As of now I am using HTTP to communicate with the server and get the info back from the server.
I wish to have the data transmission more secured. Can anyone please shed some light on how to accomplish this? I am clueless about HTTPS and implementing it in Android.
Any pointers and links will be helpful like how to start. Do I need to purchase certificates and get it signed.
Thanks
I fairly certain you don't need to do anything special for HTTPS in Android, just change your url to start with "https". new URL(url).openConnection() should work fine with that. If you're using Apache's HttpClient stuff, you might need to define your own client. Below is code I have from a project I'm currently working on.
public static DefaultHttpClient makeHTTPClient() {
BasicHttpParams mHttpParams = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
// The default value is zero, that means the timeout is not used.
int timeoutConnection = 15000;
HttpConnectionParams.setConnectionTimeout(mHttpParams, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 20000;
HttpConnectionParams.setSoTimeout(mHttpParams, timeoutSocket);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
final SSLSocketFactory sslSocketFactory = SSLSocketFactory.getSocketFactory();
sslSocketFactory.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
registry.register(new Scheme("https", sslSocketFactory, 443));
ClientConnectionManager cm = new ThreadSafeClientConnManager(mHttpParams, registry);
DefaultHttpClient defaultHttpClient = new DefaultHttpClient(cm, mHttpParams);
return defaultHttpClient;
}
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 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!
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.