networking

Additional

Language
N/A
Version
N/A
Created
Nov 16, 2017
Updated
Mar 29, 2020
Owner
David (eukaprotech)
Contributor
David (eukaprotech)
1
Activity
Badge
Generate
Download
Source code

Announcement

Versions

Version 1.0.6

Description

An android asynchronous http client based on HttpURLConnection.

Updates

  • Use of java Future object to allow optional blocking of current thread until the asynchronous http client returns results.

Getting Started

Add the dependency in build.gradle (App module)

compile 'com.eukaprotech.networking:networking:1.0.6@aar'

Add permission in manifest file

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

Request Methods Covered

  • GET
  • POST
  • PUT
  • DELETE
  • HEAD
  • OPTIONS

GET request:

AsyncConnection asyncConnection = new AsyncConnection();
asyncConnection.get("url", new AsyncConnectionHandler() { 
    @Override
    public void onStart() {
       //you can choose to show a progress bar here.
    }

    @Override
    public void onSucceed(int responseCode, HashMap<String, String> headers, byte[] response) {
        //consume the success response here.
    }

    @Override
    public void onFail(int responseCode, HashMap<String, String> headers, byte[] response, Exception error) {
        //consume the fail response here
    }

    @Override
    public void onComplete() {
       //you can dismiss the progress bar here.
    }
});

Sample GET request:

AsyncConnection asyncConnection = new AsyncConnection();
asyncConnection.get("https://www.google.com", new AsyncConnectionHandler() { 
    @Override
    public void onStart() {
       //you can choose to show a progress bar here.
    }

    @Override
    public void onSucceed(int responseCode, HashMap<String, String> headers, byte[] response) {
        //consume the success response here.
    }

    @Override
    public void onFail(int responseCode, HashMap<String, String> headers, byte[] response, Exception error) {
        //consume the fail response here.
    }

    @Override
    public void onComplete() {
       //you can dismiss the progress bar here.
    }
});

Sample Blocking GET request:

The AsyncConnection http method calls return a Future object which handles a result of type HashMap<String, Object>. If you want to block the current thread until you get the result, call the get() function of the Future object as shown below. Note the difference between the http get() and the blocking get() function.

AsyncConnection asyncConnection = new AsyncConnection();
HashMap<String, Object> map = asyncConnection.get("https://www.google.com", new AsyncConnectionHandler() { 
    @Override
    public void onStart() {
       //you can choose to show a progress bar here.
    }

    @Override
    public void onSucceed(int responseCode, HashMap<String, String> headers, byte[] response) {
        //consume the success response here.
    }

    @Override
    public void onFail(int responseCode, HashMap<String, String> headers, byte[] response, Exception error) {
        //consume the fail response here.
    }

    @Override
    public void onComplete() {
       //you can dismiss the progress bar here.
    }
}).get();// the blocking call. 

OR

AsyncConnection asyncConnection = new AsyncConnection();
HashMap<String, Object> map = asyncConnection.get("https://www.google.com", null).get();// the blocking call. 

The HashMap<String, Object> contains the following key-value pairs:

status: String //"success" or "fail
responseCode: integer 
headers: HashMap<String, String>
response: byte[]
error: Exception

File Download Handler

A File download handler, FileAsyncConnectionHandler, is used to directly write a connection response to a file:

asyncConnection.get("url", new FileAsyncConnectionHandler() {
    @Override
    public void onStart() {
        //you can choose to show a progress bar here.
    }

    @Override
    public String onGetFileAbsolutePath(String contentType) {
        //you can determine the file-extension to use based on contentType
        File file = new File("path");
        return file.getAbsolutePath();
    }

    @Override
    public void onSucceed(int responseCode, HashMap<String, String> headers, File response) {
        //the response is the file whose path you provided. You can use the file at this point
    }

    @Override
    public void onFail(int responseCode, HashMap<String, String> headers, byte[] response, Exception error) {
        
    }

    @Override
    public void onComplete() {
        //you can dismiss the progress bar here.
    }
});

Query Parameters

To attach query parameters to a url:

Parameters query_parameters = new Parameters();
query_parameters.put("key1", "value1");
query_parameters.put("key2", "value2");

String url = URLBuilder.build("initial_url", query_parameters);
//if the initial_url already contains query parameters, the new query parameters are just added at the end of existing ones.
//in case of conflicting keys between the existing query parameters and the new ones; the new ones are given priority.
//you can then use the resulting url in a request

Sample:

Parameters query_parameters = new Parameters();
query_parameters.put("q", "discover");
String url = URLBuilder.build("https://www.google.com/search", query_parameters);
//will result into https://www.google.com/search?q=discover
//you can then use the resulting url in a request

AsyncConnection asyncConnection = new AsyncConnection();
asyncConnection.get(url, new AsyncConnectionHandler() {
    // the implemented listener functions onStart, onSucceed, onFail & onComplete
});

Body Parameters (Used for POST & PUT)

To attach parameters as the body/content of the request

Parameters parameters = new Parameters();
parameters.put("key1", "value1");
parameters.put("key2", "value2");

//For a POST request
AsyncConnection asyncConnection = new AsyncConnection();
asyncConnection.post("url", parameters, new AsyncConnectionHandler() {  
    // the implemented listener functions here. 
});

//For a PUT request
AsyncConnection asyncConnection = new AsyncConnection();
asyncConnection.put("url", parameters, new AsyncConnectionHandler() {  
    // the implemented listener functions here. 
});

Request Headers

To attach request headers:

HashMap<String, String> headers = new HashMap<>();
headers.put("Authorization", "basicAuth value");
Parameters parameters = new Parameters();
parameters.put("key1", "value1");
parameters.put("key2", "value2");

//For a POST request
AsyncConnection asyncConnection = new AsyncConnection();
asyncConnection.post("url", headers, parameters, new AsyncConnectionHandler() { 
    // the implemented listener functions here. 
});

//For a GET request
AsyncConnection asyncConnection = new AsyncConnection();
asyncConnection.get("url", headers, new AsyncConnectionHandler() { 
    // the implemented listener functions here.  
});
//Other request methods have similar way of attaching request headers

Body JSONObject (Used for POST & PUT)

JSONObject can be used in place of Parameters as the body/content of the request:

JSONObject jsonObject = new JSONObject();
try{
    jsonObject.put("key1", "value1");
    jsonObject.put("key2", "value2");
}catch (Exception ex){}

HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");    //header for JSONObject being the body/content

//For a POST request
AsyncConnection asyncConnection = new AsyncConnection();
asyncConnection.post("url", headers, jsonObject, new AsyncConnectionHandler() {  
    // the implemented listener functions here.
});

//For a PUT request
AsyncConnection asyncConnection = new AsyncConnection();
asyncConnection.put("url", headers, jsonObject, new AsyncConnectionHandler() {  
    // the implemented listener functions here.
});

Basic Authentication

To attach a basic auth in the request headers:

Method 1: (Handle it)

HashMap<String, String> headers = new HashMap<>();
String username = "example@gmail.com"; 
String password = "123456789";
String auth_value = username+":"+password;
String basicAuth = "basic "+ Base64.encodeToString(auth_value.getBytes(), Base64.NO_WRAP);
headers.put("Authorization", basicAuth);

Method 2: (Let AsyncConnection handle it)

String username = "example@gmail.com"; 
String password = "123456789";
AsyncConnection asyncConnection = new AsyncConnection();
asyncConnection.setBasicAuthentication(username, password); 

Track the Upload and Download Progress of a Single Connection

Both handlers, AsyncConnectionHandler and FileAsyncConnectionHandler have functions to track the upload and download progress of a connection. These functions are onUploadProgressUpdate and onDownloadProgressUpdate. The functions are optional; you can choose to implement them or not.

Tracking upload and download progress with AsyncConnectionHandler:

asyncConnection.post("url", parameters, new AsyncConnectionHandler() {// you can use any http method other than POST
    @Override
    public void onStart() {
        //you can choose to show a progress bar here.
    }
    
    @Override
    public void onUploadProgressUpdate(long progress, long length) {
        //length is the total size of the content/parameters being uploaded or written to the connection.
        //You can use a determinate progress bar at this point.
    }

    @Override
    public void onDownloadProgressUpdate(long progress, long length) {
        //length is the total size of the content being downloaded or read from the connection.
        //NOTE: length depends on the server returning a content-length header. 
        //If the server returns chunked transfer-encoding header, content-length header is not available, the length is unknown 
        //When the length is not known, the value of length will be -1.
        //If length is -1, avoid displaying a determinate progress bar.
    }
    
    @Override
    public void onSucceed(int responseCode, HashMap<String, String> headers, byte[] response) {
        
    }

    @Override
    public void onFail(int responseCode, HashMap<String, String> headers, byte[] response, Exception error) {
        
    }

    @Override
    public void onComplete() {
        //you can dismiss the progress bar here.
    }
});

Tracking upload and download progress with FileAsyncConnectionHandler:

asyncConnection.post("url", parameters, new FileAsyncConnectionHandler() {// you can use any http method other than POST
    @Override
    public void onStart() {
        //you can choose to show a progress bar here.
    }
    
    @Override
    public void onUploadProgressUpdate(long progress, long length) {
        //length is the total size of the content/parameters being uploaded or written to the connection.
        //You can use a determinate progress bar at this point.
    }

    @Override
    public void onDownloadProgressUpdate(long progress, long length) {
        //length is the total size of the content being downloaded or read from the connection.
        //NOTE: length depends on the server returning a content-length header. 
        //If the server returns chunked transfer-encoding header, content-length header is not available, the length is unknown 
        //When the length is not known, the value of length will be -1.
        //If length is -1, avoid displaying a determinate progress bar.
    }

    @Override
    public String onGetFileAbsolutePath(String contentType) {
        
    }

    @Override
    public void onSucceed(int responseCode, HashMap<String, String> headers, File response) {
        
    }

    @Override
    public void onFail(int responseCode, HashMap<String, String> headers, byte[] response, Exception error) {
        
    }

    @Override
    public void onComplete() {
        //you can dismiss the progress bar here.
    }
});

Track the Upload and Download Progress of Multiple Connections

MultipleAsyncConnections multipleAsyncConnections = new MultipleAsyncConnections();
List<AsyncConnection> asyncConnectionList = multipleAsyncConnections.generateConnections(2);
// 2 is the number of connections you desire to monitor
AsyncConnection asyncConnection1 = asyncConnectionList.get(0);
AsyncConnection asyncConnection2 = asyncConnectionList.get(1);
        
asyncConnection1.post("url", parameters1, new AsyncConnectionHandler() {// you can use any http method other than POST
    // the implemented listener functions here
});
asyncConnection2.post("url", parameters2, new FileAsyncConnectionHandler() {// you can use any http method other than POST
    // the implemented listener functions here
});

//For Connections generated by MultipleAsyncConnections to start processing;
multipleAsyncConnections.startConnections(new MultipleAsyncConnectionsHandler() {
    @Override
    public void onStart() {
        //called once when connections start.
        //you can choose to show a progress bar here.
    }

    @Override
    public void onUploadProgressUpdate(long progress, long length) {
        //progress is the cumulative size uploaded across all the connections being tracked
        //length is the cumulative total size to be uploaded across all the connections being tracked
        //You can use a determinate progress at this point.
    }

    @Override
    public void onDownloadProgressUpdate(long progress, long length) {
        //progress is the cumulative size downloaded across all the connections being tracked
        //length is the cumulative total size to be downloaded across all the connections being tracked
        //NOTE: length depends on the server returning a content-length header to each of the connections being tracked. 
        //If the server returns chunked transfer-encoding header, content-length header is not available, the length is unknown 
        //When the length is not known, the cumulative value of length across the connections will not be useful.
        //Avoid displaying a determinate progress bar here at all.
    }

    @Override
    public void onComplete() {
        //called once when all connections complete.
        //you can dismiss the progress bar here.
    }
});

Uploading Files

To upload a File, include it in the body parameters

File file = new File("file path");
Parameters parameters = new Parameters();
try {
    parameters.put("key1", file);
} catch (IOException e) {

}
parameters.put("key2", "value2");

Uploading Array of Files

To upload array of files, include the array in the body parameters

File file1 = new File("file path1");
File file2 = new File("file path2");

Parameters parameters = new Parameters();
File[] arrayFiles = new File[]{file1, file2};
try {
    parameters.put("key1", arrayFiles);
} catch (IOException e) {

}
parameters.put("key2", "value2");

Uploading Files Whose Content is Your Bytes or InputStream

A class named FileItem is used. Note that parameters of value FileItem are uploaded to the server just like any other file; difference being that the content is read from the bytes or inputstream you provide.

To upload a file with your own bytes as content, include it as a FileItem in the body parameters.

byte[] bytes = "Hey there".getBytes();
FileItem fileItem = new FileItem("sample.txt", bytes); // "sample.txt" is the file name which must not be a name of an existing file
Parameters parameters = new Parameters();
parameters.put("key1", fileItem);
parameters.put("key2", "value2");

To upload a file with your own InputStream as content, include it as a FileItem in the body parameters

InputStream inputStream = null;
File file = new File("file path"); //must be a path of an existing file
try {
    inputStream = new BufferedInputStream(new FileInputStream(file));
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
long length = file.length();
FileItem fileItem = new FileItem("index.html", length, inputStream); //the length is important for progress monitoring, "index.html" is the file name which must not be a name of an existing file
Parameters parameters = new Parameters();
parameters.put("key1", fileItem);
parameters.put("key2", "value2");

To upload array of files with your own bytes or InputStream as content, include them as array of FileItem in the body parameters

byte[] bytes = "Hey there".getBytes();
FileItem fileItem1 = new FileItem("sample.txt", bytes);

InputStream inputStream = null;
File file = new File("file path"); //must be a path of an existing file
try {
    inputStream = new BufferedInputStream(new FileInputStream(file));
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
long length = file.length();
FileItem fileItem2 = new FileItem("index.html", length, inputStream);

FileItem[] arrayFiles = new FileItem[]{fileItem1, fileItem2};
Parameters parameters = new Parameters();
parameters.put("key1", arrayFiles);
parameters.put("key2", "value2");

Uploading Bytes

To upload bytes, include them as BytesItem in the body parameters

Parameters parameters = new Parameters();
byte[] bytes = "Hey bytes".getBytes()// your bytes here;
parameters.put("key1", new BytesItem(bytes));
parameters.put("key2", "value2");

Provide Your InputStream for Upload

To provide your own inputstream, include it as an InputStreamItem in the body parameters. An example of using an input stream from a file:

Parameters parameters = new Parameters();
InputStream inputStream = null;
File file = new File("file path"); //must be a path of an existing file
try {
    inputStream = new BufferedInputStream(new FileInputStream(file));
} catch (FileNotFoundException e) {

}
long length = file.length();
parameters.put("key1", new InputStreamItem(length, inputStream));
parameters.put("key2", "value2");

An example of using an input stream of bytes:

Parameters parameters = new Parameters();
byte[] bytes = "Hey bytes".getBytes();
InputStream inputStream = new ByteInputStream(bytes);
long length = bytes.length;
parameters.put("key1", new InputStreamItem(length, inputStream));
parameters.put("key2", "value2");

Redirects

By default AsyncConnection does not follow redirects to different protocols such as HTTP to HTTPS or HTTPS to HTTP. To enable protocol shift redirects:

AsyncConnection asyncConnection = new AsyncConnection();
asyncConnection.setFollowProtocolShiftRedirects(true);

Setting Time Out

AsyncConnection asyncConnection = new AsyncConnection();
int time_out_in_milliseconds = 5000;
asyncConnection.setTimeOut(time_out_in_milliseconds);

NOTE

To consume the byte array response as a String:

String responseBody = new String(response); //OR
String responseBody = new String(response, "UTF-8");