There is very little info about AndroidHttpClient, specifically I can't find any good examples. From what I read - I can use this client and it is preconfigured for SSL. I target 2.2+ so it will work for me well.
Thanks!
My own answer (see code below).
My version of Application singleton. See comments on top with details on command lines I used to generate all the stuff. Use same password throughout to make sure it works. PKS file password have to match.
import android.net.http.AndroidHttpClient;
import android.app.Application;
import android.util.Log;
import idatt.mobile.android.providers.DBLog;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import java.io.InputStream;
import java.security.KeyStore;
/*
To generate PKS:
1. Created cert in IIS7 and then exported as pfx. Follow instruction on SelfSSL: http://www.robbagby.com/iis/self-signed-certificates-on-iis-7-the-easy-way-and-the-most-effective-way/
1a. Download tool: http://cid-3c8d41bb553e84f5.skydrive.live.com/browse.aspx/SelfSSL
1b. Run: SelfSSL /N:CN=mydomainname /V:1000 /S:1 /P:8081
I use port 8081 on my server
1c. Export from IIS manager to cert.pfx
2. Run command line in SSL to convert file into X.509:
openssl pkcs12 -in C:\cert.pfx -out C:\cert.cer -nodes
3. Edit file and delete all except -----BEGIN.... END CERTIFICATE----- IMPORTANT! It was working when I got proper (5) amount of dashes and put tags and data on separate lines
4. use keytool. C:\Java\JDK\bcprov.jar was downloaded separately
C:\Users\Ivan>keytool -import -v -trustcacerts -alias key_alias -file C:\cert.cer -keystore C:\mystore.bks -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath C:\Java\JDK\bcprov.jar -storepass 123456
*/
public class MyApplication extends Application
{
private static final String LOG_TAG = "MyApplication";
private AndroidHttpClient androidHttpClient;
@Override
public void onCreate()
{
super.onCreate();
androidHttpClient = createAndroidHttpClient();
}
@Override
public void onLowMemory()
{
super.onLowMemory();
shutdownAndroidHttpClient();
}
@Override
public void onTerminate()
{
super.onTerminate();
shutdownAndroidHttpClient();
}
private AndroidHttpClient createAndroidHttpClient()
{
Log.d(LOG_TAG,"createAndroidHttpClient");
AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
//This is optional call to inject custom BKS that was created from self-signed certificate
client = addCustomCertificate(client);
return client;
}
public AndroidHttpClient getAndroidHttpClient()
{
return androidHttpClient;
}
private void shutdownAndroidHttpClient()
{
if(androidHttpClient!=null && androidHttpClient.getConnectionManager()!=null)
{
androidHttpClient.getConnectionManager().shutdown();
}
}
private AndroidHttpClient addCustomCertificate(AndroidHttpClient client)
{
SSLSocketFactory sf = SSLSocketFactory.getSocketFactory();
try
{
InputStream in = getResources().openRawResource(R.raw.home_server);
KeyStore trustStore = KeyStore.getInstance("BKS");
trustStore.load(in, "123456".toCharArray());
in.close();
sf = new SSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
}
catch (Exception t)
{
DBLog.InsertError(this, t);
}
//Lets register our custom factory here
client.getConnectionManager().getSchemeRegistry().register(new Scheme("https", sf, 443));
return client;
}
}
Here is how I use this client(I call it in AsyncTask)
private String processPOST(String url, String requestData)
{
String responseData = null;
application = (MyApplication)getApplication();
AndroidHttpClient client = application.getAndroidHttpClient();
HttpPost request = new HttpPost(url);
try
{
StringEntity entity = new StringEntity(requestData);
entity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
request.setEntity(entity);
ResponseHandler<String> handler = new BasicResponseHandler();
responseData = client.execute(request, handler);
}
catch (Throwable e)
{
DBLog.InsertError(ctxt, e);
}
return responseData;
}
This combination seems to be 100% working on 2.2 and 2.3 devices. When I was using snippets with DefaultHttpClient I had issues with 2.3.1 timing out on requests (Nexus S)
You can use Apache HttpClient.
public HttpClient getNewHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance("BKS");
InputStream in = getResources().openRawResource(R.raw.mykeystore);
try {
trustStore.load(in, "mypassword".toCharArray());
} finally {
in.close();
}
SSLSocketFactory sf = new SSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
return new DefaultHttpClient();
}
}
In web server, IIS can create self-signed certificate and export as PFX, then convert it to PEM using openssl tool, edit it to conatin only certificate, then create a keystore that contain the certificate using keytool of JDK and Bouncy Castle jar. The created keystore can be imported to your project as shown in above code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With