Http Util Class Make HttpURLConnection And OkHttp Reusable

This example show you how to encapsulate HttpURLConnection and OkHttp in a http util class that can make http request through HttpURLConnection or OkHttp reusable.

1. Encapsulate HttpURLConnection Or OkHttp Diagram.

Because http request is a frequently used function, so we had better encapsulate it in a util class.

Also because http request is a synchronous process, it may take long time to block main thread. So we had better encapsulate http request action in a child thread. In the child thread run method, we do the http request logic.

This will lead to an issue that is when the thread start, the main thread continue to run to exit. But the http process in child thread do not complete, so the main thread can not get http response data.

To resolve this issue, we create a callback object that is used when http request process complete in child thread. When the request success, it will invoke the callback object’s onSuccess method, when the request fail, it will call the callback object’s onFailure method.

This way, we can transfer http request response data out to main thread through callback object when child thread complete.

But please remember, because the callback object run in child thread, so we have to use message handler in main activity to update UI controls.

2. Http Util Class Example.

Click the first button will get http response header and body string from www.bing.com. Click the second button will get and display header and body data from www.baidu.com.

http util class make httpurlconnection and okhttp reusable

2.1 Http Util Class File Structure.

http util class file structure

2.2 Http Util Class.

This is the http util class java file. It contains two method, one encapsulate HttpURLConnection the other encapsulate OkHttp.

HttpTool.java

package com.dev2qa.example.network.util;

import android.webkit.URLUtil;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;

/**
 * Created by Jerry on 3/6/2018.
 */

public class HttpTool {

    public static final String HTTP_REQUEST_METHOD_GET = "GET";

    public static final String HTTP_REQUEST_METHOD_POST = "POST";

    private static final int CONNECTION_TIME_OUT = 10000;

    private static final int READ_TIME_OUT = 10000;

    /*This method will send http request using HttpURLConnection.
      Because the process will be executed in a child thread that can avoid main thread block.
      So this method need a httpCallback input parameter which will process the request result asynchronously.

      String urlString : The http target url.
      String method : GET or POST.
      Map<String, String> postParamsMap : If the request method is post, then this is the post parameters map.
      HttpCallback httpCallback : This is the object which will process the request result when the http request complete in child thread.
      */
    public static void sendHttpRequestUseHttpURLConnection(final String urlString, final String method, final Map<String, String> postParamsMap, final HttpCallback httpCallback)
    {
        // Create a thread object.
        Thread workerThread = new Thread()
        {
            @Override
            public void run() {
                // Declare HttpURLConnection object.
                HttpURLConnection httpURLConnection = null;
                try
                {
                    // Check whether the url address string is valid or not.
                    if(!URLUtil.isHttpsUrl(urlString) && !URLUtil.isHttpUrl(urlString))
                    {
                        Exception ex = new Exception(urlString + " is not a valid http or https url. The url must start with http or https.");
                        throw ex;
                    }else {
                        // Create URL object.
                        URL url = new URL(urlString);

                        // Open URLConnection.
                        URLConnection urlConnection = url.openConnection();

                        // Cast to HttpURLConnection.
                        httpURLConnection = (HttpURLConnection)urlConnection;

                        // Set request method.
                        httpURLConnection.setRequestMethod(method);

                        // Set connection timeout value.
                        httpURLConnection.setConnectTimeout(CONNECTION_TIME_OUT);

                        // Set read timeout value.
                        httpURLConnection.setReadTimeout(READ_TIME_OUT);

                        // If http post request.
                        if(HTTP_REQUEST_METHOD_POST.equals(method))
                        {
                            // Write output stream.
                            httpURLConnection.setDoOutput(true);

                            // Get post parameters key value pair from postParamsMap.
                            StringBuffer postParamsBuf = new StringBuffer();
                            if( postParamsMap != null )
                            {
                                // Loop the key and value in map object.
                                Set<String> keySet = postParamsMap.keySet();
                                Iterator<String> it = keySet.iterator();
                                while(it.hasNext())
                                {
                                    String key = it.next();
                                    String value = postParamsMap.get(key);

                                    // Append url key value pair.
                                    postParamsBuf.append(key);
                                    postParamsBuf.append("=");
                                    postParamsBuf.append(value);
                                    postParamsBuf.append("&");
                                }
                            }

                            // Read input stream.
                            httpURLConnection.setDoInput(true);

                            // Get output stream from http url connection to post data to server.
                            OutputStream outputStream = httpURLConnection.getOutputStream();
                            // Create output stream writer.
                            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
                            // Create buffered writer to make write more efficiency.
                            BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
                            // Write post params to server.
                            bufferedWriter.write(postParamsBuf.toString());

                            // Do not forget flush and close output stream at end.
                            bufferedWriter.flush();
                            outputStreamWriter.flush();
                            outputStream.flush();

                            bufferedWriter.close();
                            outputStreamWriter.close();
                            outputStream.close();
                        }

                        // Get header fields map.
                        Map<String, List<String>> headerFieldsMap = httpURLConnection.getHeaderFields();

                        // Get input stream.
                        InputStream inputStream = httpURLConnection.getInputStream();

                        // Create input stream reader.
                        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);

                        // Create buffered input stream reader.
                        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

                        StringBuffer respBuffer = new StringBuffer();

                        // Read line of response string.
                        String lineData = bufferedReader.readLine();

                        while(lineData != null)
                        {
                            // Append the line string if is not null.
                            respBuffer.append(lineData);
                            lineData = bufferedReader.readLine();
                        }

                        bufferedReader.close();
                        inputStreamReader.close();
                        inputStream.close();


                        if(httpCallback != null)
                        {
                            // Call custom callback object's onSuccess method with the response string.
                            httpCallback.onSuccess(respBuffer.toString(), headerFieldsMap);
                        }
                    }
                }catch(Exception ex)
                {
                    // If error occurred, call custom callback object's onFailure method with exception object.
                    httpCallback.onFailure(ex);
                }finally
                {
                    if( httpURLConnection != null )
                    {
                        // Disconnect http url connection.
                        httpURLConnection.disconnect();
                        httpURLConnection = null;
                    }
                }
            }
        };

        // Start the child thread.
        workerThread.start();
    }


    /*This method will send http request using HttpURLConnection.
     Because the process will be executed in a child thread that can avoid main thread block.
     So this method need a httpCallback input parameter which will process the request result asynchronously.

     String urlString : The http target url.
     String method : GET or POST.
     Map<String, String> postParamsMap : If the request method is post, then this is the post parameters map.
     Callback callback : This is the okhttp Callback object which will process the request result when the http request complete in child thread.
     */
    public static void sendHttpRequestUseOkHttp(final String urlString, final String method, final Map<String, String> postParamsMap, final Callback callback)
    {
        // Create a OkHttp client.
        OkHttpClient okHttpClient = new OkHttpClient();

        // Create okhttp request builder.
        Request.Builder builder = new Request.Builder();

        // Set url address.
        builder.url(urlString);

        // If http post request.
        if(HTTP_REQUEST_METHOD_POST.equals(method)) {
            // Create okhttp3 form body builder.
            FormBody.Builder formBodyBuilder = new FormBody.Builder();

            // Add form parameters from params map.
            if (postParamsMap != null) {
                // Get map object key set.
                Set<String> keySet = postParamsMap.keySet();

                // Get keyset iterator.
                Iterator<String> it = keySet.iterator();

                // Iterate each key and value, add key value pair in post form body builder.
                while (it.hasNext()) {
                    String key = it.next();
                    String value = postParamsMap.get(key);
                    formBodyBuilder.add(key, value);
                }
            }

            // Build form body.
            FormBody formBody = formBodyBuilder.build();

            // Add http post form body.
            builder.post(formBody);
        }

        // Build okhttp request.
        Request request = builder.build();

        // Create an okhttp Call object.
        Call call = okHttpClient.newCall(request);

        // Execute the http request in okhttp auto started child thread.
        call.enqueue(callback);
    }
}

2.3 Custom Http Callback Class.

OkHttp has default callback class which is okhttp.Callback. But HttpURLConnection do not has built-in callback class, so we have to write a custom callback class for HttpURLConnection. This class has two methods, one is invoked when request is success the other is called when request fail.

READ :   Android Keep Broadcast Receiver Running After Application Exit

HttpCallback.java

package com.dev2qa.example.network.util;

import android.util.Log;

import java.util.List;
import java.util.Map;

/**
 * Created by Jerry on 3/6/2018.
 */

public class HttpCallback {

    // Log tag string.
    private static final String TAG_HTTP_CALL_BACK = "TAG_HTTP_CALL_BACK";

    /* This method is invoked when http request success.
    *  String respString : This is the response page text.
    *  Map<String, List<String>> headerFieldsMap : This is the response header fields map.
    * */
    public void onSuccess(String respString, Map<String, List<String>> headerFieldsMap)
    {
        Log.d(TAG_HTTP_CALL_BACK, respString);
    }


    // This method is invoked when http request fail.
    public void onFailure(Exception ex)
    {
        Log.e(TAG_HTTP_CALL_BACK, ex.getMessage(), ex);
    }
}

2.4 Main Activity Class.

HttpToolActivity.java

package com.dev2qa.example.network.util;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.dev2qa.example.R;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import okhttp3.Call;
import okhttp3.Headers;
import okhttp3.Response;

public class HttpToolActivity extends AppCompatActivity {

    private Button sendUseHttpURLConnectionButton = null;

    private Button sendUseOkHttpButton = null;

    private TextView showResultTextView = null;

    private Handler showResultHandler = null;

    private static final int MESSAGE_SHOW_RESULT = 1;

    private static final String KEY_RESULT = "KEY_RESULT";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_http_tool);

        setTitle("dev2qa.com - Http Request Wrapper Tool Example.");

        // Initialize this example UI controls.
        initControls();

        // When click send http request use HttpURLConnection button.
        sendUseHttpURLConnectionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // Create a new custom HttpCallback instance.
                HttpCallback httpCallback = new HttpCallback(){
                    @Override
                    public void onSuccess(String respString, Map<String, List<String>> headerFieldsMap) {
                        StringBuffer respBuf = new StringBuffer();

                        // Append response header data.
                        Set<String> keySet = headerFieldsMap.keySet();
                        Iterator<String> it = keySet.iterator();
                        while(it.hasNext())
                        {
                            String headerName = it.next();

                            if(headerName!=null && !TextUtils.isEmpty(headerName.trim())) {
                                List<String> headerValueList = headerFieldsMap.get(headerName);

                                respBuf.append(headerName);
                                respBuf.append(" = ");

                                if(headerValueList != null)
                                {
                                    for(String headerValue : headerValueList)
                                    {
                                        respBuf.append(headerValue);
                                        respBuf.append(" , ");
                                    }
                                }

                                respBuf.append(" \r\n\r\n ");
                            }
                        }

                        // Append response body string.
                        respBuf.append(respString);

                        showHttpRequestResult(respBuf.toString());
                    }

                    @Override
                    public void onFailure(Exception ex) {
                        showHttpRequestResult("Http request error, exception class name : " + ex.getClass().getSimpleName() + " , exception message : " + ex.getMessage());
                    }
                };

                // Send http request use HttpURLConnection.
                HttpTool.sendHttpRequestUseHttpURLConnection("http://www.bing.com", HttpTool.HTTP_REQUEST_METHOD_GET, null, httpCallback);
            }
        });

        // Click this button to send http request through OkHttp..
        sendUseOkHttpButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // Create a OkHttp Callback instance.
                okhttp3.Callback okhttpCallback = new okhttp3.Callback(){

                    @Override
                    public void onFailure(Call call, IOException ex) {
                        showHttpRequestResult("Http request error, exception class name : " + ex.getClass().getSimpleName() + " , exception message : " + ex.getMessage());
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        StringBuffer respBuf = new StringBuffer();

                        // Append response header data.
                        Headers headers = response.headers();
                        Set<String> headerNames = headers.names();
                        Iterator<String> it = headerNames.iterator();
                        while(it.hasNext())
                        {
                            String headerName = it.next();
                            String headerValue = headers.get(headerName);

                            respBuf.append(headerName);
                            respBuf.append(" = ");
                            respBuf.append(headerValue);
                            respBuf.append("\r\n\r\n");

                        }

                        // Append response body string.
                        String respString = response.body().string();
                        respBuf.append(respString);

                        showHttpRequestResult(respBuf.toString());
                    }
                };

                // Send http request use OkHttp3.
                HttpTool.sendHttpRequestUseOkHttp("http://www.baidu.com", HttpTool.HTTP_REQUEST_METHOD_GET, null, okhttpCallback);
            }
        });

    }

    private void initControls()
    {
        if(sendUseHttpURLConnectionButton == null)
        {
            sendUseHttpURLConnectionButton = (Button)findViewById(R.id.http_tool_send_use_httpurlconnection_button);
        }

        if(sendUseOkHttpButton == null)
        {
            sendUseOkHttpButton = (Button)findViewById(R.id.http_tool_send_use_okhttp_button);
        }

        if(showResultTextView == null)
        {
            showResultTextView = (TextView)findViewById(R.id.http_tool_show_page_result_view);
        }

        if(showResultHandler == null)
        {
            // This Handler is used to listen to child thread 'show http request result page' message..
            showResultHandler = new Handler()
            {
                @Override
                public void handleMessage(Message msg) {
                    // If show request result page.
                    if(msg.what == MESSAGE_SHOW_RESULT)
                    {
                        // Get result page text.
                        Bundle bundle = msg.getData();
                        String pageData = bundle.getString(KEY_RESULT);

                        // Show text in textview.
                        showResultTextView.setText(pageData);
                    }
                }
            };
        }
    }


    /* Because each call back object will be executed in a child thread,
    *  so we still need to update the activity UI in main thread use Handler.*/
    private void showHttpRequestResult(String respString)
    {
        Message msg = new Message();
        msg.what = MESSAGE_SHOW_RESULT;

        Bundle bundle = new Bundle();
        bundle.putString(KEY_RESULT, respString);

        msg.setData(bundle);

        showResultHandler.sendMessage(msg);
    }

}

2.5 Layout Xml File.

activity_http_tool.xml

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="http://www.bing.com"/>

    <Button
        android:id="@+id/http_tool_send_use_httpurlconnection_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send Request With HTTPURLConnection"
        android:textAllCaps="false"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="http://www.baidu.com"/>

    <Button
        android:id="@+id/http_tool_send_use_okhttp_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send Request With OkHttp"
        android:textAllCaps="false"/>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/http_tool_show_page_result_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </ScrollView>

</LinearLayout>

2.6 Android Manifest Xml File.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.dev2qa.example">

    <!-- Required permission. -->
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        
        <activity android:name=".network.util.HttpToolActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
(Visited 149 times, 1 visits today)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.