Friday 25 July 2014

Make HTTPS / HTTP Request in Android


In this tutorial we will learn how to make HTTP and HTTPS Request. For HTTPS Request we must have signed Certificate. Here I will show the demo of HTTPS but you can use this code for HTTP also.


Download Source Code DOWNLOAD

Project Hierarchy
1. Firstly create a CustomSSLSocketFactory.java class which extends SSLSocketFactory class.

package com.tutorialsface.httpsrequest;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.conn.ssl.SSLSocketFactory;

public class CustomSSLSocketFactory extends SSLSocketFactory{
      SSLContext sslContext = SSLContext.getInstance("TLS");
      /**
       * Generate Certificate for ssl connection
       * @param truststore
       * @throws NoSuchAlgorithmException
       * @throws KeyManagementException
       * @throws KeyStoreException
       * @throws UnrecoverableKeyException
       */
      public CustomSSLSocketFactory(KeyStore truststore)
                  throws NoSuchAlgorithmException, KeyManagementException,
                  KeyStoreException, UnrecoverableKeyException {
            super(truststore);
            TrustManager tm = new X509TrustManager(){
                  @Override
                  public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                              throws CertificateException {
                  }
                  @Override
                  public void checkServerTrusted(X509Certificate[] chain,
                              String authType) throws CertificateException {
                  }
                  @Override
                  public X509Certificate[] getAcceptedIssuers() {
                        return null;
                  }
            };
            sslContext.init(null, new TrustManager[] {tm}, null);
      }
     
      @Override
      public Socket createSocket(Socket socket, String host, int port,
                  boolean autoClose) throws IOException, UnknownHostException {
            return sslContext.getSocketFactory().createSocket(socket, host, port,
                        autoClose);
      }

      @Override
      public Socket createSocket() throws IOException {
            return sslContext.getSocketFactory().createSocket();
      }
}

1.1 Secondly create a HTTPUtils.java class which will have function that return HttpClient for HTTP & HTTPS server.

package com.tutorialsface.httpsrequest;

import java.security.KeyStore;
import org.apache.http.client.HttpClient;
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 org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;

public class HTTPUtils {
      /**
       * HttpClient
       * @param isHTTPS
       * @return
       */
      public static HttpClient getNewHttpClient(boolean isHTTPS) {
            try {
                  if(!isHTTPS){
                        return getNewHttpClient();
                  }
                  KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                  trustStore.load(null, null);
                  SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
                  sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

                  HttpParams params = new BasicHttpParams();
                  SchemeRegistry registry = new SchemeRegistry();
                  registry.register(new Scheme("https", sf, 443));

                  ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
                  return new DefaultHttpClient(ccm, params);
            } catch (Exception e) {
                  return null;
            }
      }
      /**
       * HttpClient for http request
       * @return
       */
      private static HttpClient getNewHttpClient(){
            HttpParams params = new BasicHttpParams();
            return new DefaultHttpClient(params);
      }
}

2. Now all thing are ready we just need to make a request. For demo purpose I will use google server apis.
i. For GET request we will use-
String REST_SERVER_HTTPS_GET_URI = "https://maps.googleapis.com/maps/api/geocode/json?address=NewDelhi,India";
ii. For POST request we will use-
String REST_SERVER_HTTPS_POST_URI = "https://www.googleapis.com/urlshortener/v1/url";


a) HttpClient httpClient = HTTPUtils.getNewHttpClient(REST_SERVER_HTTPS_POST_URI.startsWith(HTTPS_STRING));
b) URI newURI = URI.create(REST_SERVER_HTTPS_POST_URI);
c) HttpPost postMethod = new HttpPost(newURI);
OR
  HttpGet getMethod = new HttpGet(newURI);
d) For passing data with the request use setEntity. For the above post request link we will send following data-
JSONObject postJSON = new JSONObject();
postJSON.put("longUrl", "http://www.google.com/");

postMethod.setEntity(new StringEntity(postJSON.toString(), HTTP.UTF_8));

postMethod.setHeader("Content-Type", "application/json");
e) Now execute the httpPost request, and get Response-
HttpResponse response = httpClient.execute(postMethod);

2.1 Make a RestClient.java class which will have the request functions.

package com.tutorialsface.httpsrequest;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.protocol.HTTP;
import org.json.JSONObject;

public class RestClient {
      private static final String HTTPS_STRING = "https";
      /**
       * https://developers.google.com/maps/documentation/geocoding/
       * https://developers.google.com/url-shortener/v1/getting_started?csw=1#shorten
       */
      String REST_SERVER_HTTPS_GET_URI = "https://maps.googleapis.com/maps/api/geocode/json?address=NewDelhi,India";
      String REST_SERVER_HTTPS_POST_URI = "https://www.googleapis.com/urlshortener/v1/url";
     
      private RestClient(){
      }
      private static RestClient instance = null;
      public static RestClient getInstance(){
            if(instance == null) {
                  instance = new RestClient();
            }
            return instance;
      }
     
      public String postRequest() {
            String responseString = "";
            HttpClient httpClient = HTTPUtils.getNewHttpClient(REST_SERVER_HTTPS_POST_URI.startsWith(HTTPS_STRING));
            HttpResponse response = null;
            InputStream in;
            URI newURI = URI.create(REST_SERVER_HTTPS_POST_URI);
            HttpPost postMethod = new HttpPost(newURI);
           
            try {
                  JSONObject postJSON = new JSONObject();
                  postJSON.put("longUrl", "http://www.google.com/");

                  postMethod.setEntity(new StringEntity(postJSON.toString(), HTTP.UTF_8));
                  postMethod.setHeader("Content-Type", "application/json");
                  response = httpClient.execute(postMethod);
                  in = response.getEntity().getContent();
                  responseString = convertStreamToString(in);
            } catch (Exception e) {}
            return responseString;
      }
     
      public static String convertStreamToString(InputStream is) throws Exception {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                  sb.append(line);
            }
            is.close();
            return sb.toString();
      }
     
      public String getRequest() {
            String responseString = "";
            HttpClient httpClient = HTTPUtils.getNewHttpClient(REST_SERVER_HTTPS_GET_URI.startsWith(HTTPS_STRING));
            HttpResponse response = null;
            InputStream in;
            URI newURI = URI.create(REST_SERVER_HTTPS_GET_URI);
            HttpGet getMethod = new HttpGet(newURI);
            try {
                  response = httpClient.execute(getMethod);
                  in = response.getEntity().getContent();
                  responseString = convertStreamToString(in);
            } catch (Exception e) {}
            return responseString;
      }
}

Use this to call the functions of RestClient, and make sure you will call these methods from background thread, otherwise it will hang the UI-
RestClient restClient = RestClient.getInstance();    
restClient.postRequest();

restClient.getRequest();

3. Make a UI in activity_main.xml which will have two buttons one for GET Request and other for POST Request, and a TextView which will show the Response of the Request.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/btnGetRequest"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/get_request" />

    <Button
        android:id="@+id/btnPostRequest"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/post_request" />

    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <TextView
            android:id="@+id/textResponse"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:scrollbars="vertical" />
    </ScrollView>


</LinearLayout>

3.1 Open MainActivity.java and on the click of button call function of RestClient class.

package com.tutorialsface.httpsrequest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity{

      TextView textResponse;
      Button btnGetRequest, btnPostRequest;
      RestClient restClient;
      @Override
      protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            init();
      }

      private void init() {
            getViews();
            setListeners();
            restClient = RestClient.getInstance();
      }

      private void getViews() {
            btnGetRequest = (Button) findViewById(R.id.btnGetRequest);
            btnPostRequest = (Button) findViewById(R.id.btnPostRequest);
            textResponse = (TextView) findViewById(R.id.textResponse);
      }

      private void setListeners() {
            btnGetRequest.setOnClickListener(new OnClickListener() {
                  @Override
                  public void onClick(View v) {
                        new Thread(new Runnable() {
                              @Override
                              public void run() {
                                    String response = restClient.getRequest();
                                    setText("HTTPS Get Response:-\n" + response);
                              }
                        }).start();
                  }
            });
            btnPostRequest.setOnClickListener(new OnClickListener() {
                  @Override
                  public void onClick(View v) {
                        new Thread(new Runnable() {
                              @Override
                              public void run() {
                                    String response = restClient.postRequest();
                                    setText("HTTPS Post Response:-\n" + response);
                              }
                        }).start();
                  }
            });
      }
     
      private void setText(final String response) {
            MainActivity.this.runOnUiThread(new Runnable() {
                  @Override
                  public void run() {
                        textResponse.setText(response);
                  }
            });
      }
}


Download Source Code DOWNLOAD

5 comments:

  1. Here good example though for nwe user it is incomplete as it does not talk about Manifest file and activity files

    ReplyDelete
  2. Great example. Thank you so much!
    P.S. Add to manifest file ""

    ReplyDelete
  3. This is an unnecessarily complicated example :/

    ReplyDelete
  4. Any example using URLConnection?
    Since HttpClient deprecated in 23 API versions.

    ReplyDelete