Skip to content

Repository files navigation

KnHttp

APILicense

Why use KnHttp ?

  • TLS 1.3 and ECC (certificates + curves) support on all Android versions (5.0+) with help of Conscrypt
  • Brotli + Gzip support
  • It uses OkHttp, more importantly it supports HTTP/2.
  • As it uses Okio, no more GC overhead in android applications. Okio is made to handle GC overhead while allocating memory. Okio does some clever things to save CPU and memory.
  • Ultra fast JSON mapping and parsing with the help of FASTJSON2.
  • No other single library does each and everything like making request, downloading any type of file, uploading file, etc. There are some libraries but they are outdated.
  • No other library provides simple interface for doing all types of things in networking like setting priority, cancelling, etc.
  • Recent removal of HttpClient in Android Marshmallow(Android M) made other networking libraries obsolete.

Installation

allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_21
targetCompatibility JavaVersion.VERSION_21
}
}
dependencies {
implementation 'com.github.Karewan:KnHttp:4.0.1'
}

Do not forget to add internet permission in manifest if already not present

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

Then initialize :

KnHttp.init(getApplicationContext());

Customization

Use custom settings

KnSettingssettings = newKnSettings.Builder()
.setCallTimeout(0) // Call timeout ms (Default: 0)
.setConnectTimeout(15_000) // Connect timeout ms (Default: 15s)
.setReadTimeout(30_000) // Read timeout ms (Default: 30s)
.setWriteTimeout(30_000) // Write timeout ms (Default: 30s)
.setAllowObsoleteTls(false) // Obsolete TLS 1.0 and 1.1 (Default: false)
.setAllowInvalidTlsCertificates(false) // Invalid TLS Certificates (Default: false)
.setEnableCache(false) // Request caching (Default: false)
.setEnableBrotli(true) // Brotli (+ Gzip) (Default: true), if false gzip stay enabled (OkHttp default behavior)
.setFollowRedirect(false) // Follow redirect (Default: false)
.build();
KnHttp.init(getApplicationContext(), settings);

Use a custom OkHttpClient

OkHttpClientokHttpClient = newOkHttpClient.Builder()
.followRedirects(false)
.build();
KnHttp.init(okHttpClient);

Asynchronous request

GET: response as String

KnHttp.get("https://jsonplaceholder.typicode.com/posts")
.build()
.getAsString(newStringRequestListener() {
@OverridepublicvoidonResponse(Stringstr, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

GET: response as JSON Object

KnHttp.get("https://jsonplaceholder.typicode.com/posts/{postID}")
.addPathParameter("postID", "1")
.build()
.getAsJSONObject(newJSONObjectRequestListener() {
@OverridepublicvoidonResponse(JSONObjectobj, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

GET: response as parsed Object

publicclassPostItem {
publicintuserId;
publicintid;
publicStringtitle;
publicStringbody;
}
KnHttp.get("https://jsonplaceholder.typicode.com/posts/{postID}")
.addPathParameter("postID", "1")
.build()
.getAsObject(PostItem.class, newParsedRequestListener<PostItem>() {
@OverridepublicvoidonResponse(PostItempost, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

GET: response as JSON Array

KnHttp.get("https://jsonplaceholder.typicode.com/posts")
.build()
.getAsJSONArray(newJSONArrayRequestListener() {
@OverridepublicvoidonResponse(JSONArrayarr, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

GET: response as parsed Object list

KnHttp.get("https://jsonplaceholder.typicode.com/posts")
.build()
.getAsObjectList(PostItem.class, newParsedRequestListener<List<PostItem>>() {
@OverridepublicvoidonResponse(List<PostItem> posts, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

GET: response as OkHttpResponse

KnHttp.get("https://jsonplaceholder.typicode.com/posts")
.build()
.getAsOkHttpResponse(newOkHttpResponseListener() {
@OverridepublicvoidonResponse(ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

POST: response as parsed Object

KnHttp.post("https://jsonplaceholder.typicode.com/posts")
.addBodyParameter("title", "foo")
.addBodyParameter("body", "bar")
.addBodyParameter("userId", "1")
.build()
.getAsObject(PostItem.class, newParsedRequestListener<PostItem>() {
@OverridepublicvoidonResponse(PostItempost, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

POST: send json + get response as parsed Object

// Create JSON manuallyJSONObjectpostItem = newJSONObject();
postItem.put("title", "foo");
postItem.put("body", "bar");
postItem.put("userId", 1);
// OR use classpublicclassPostItem {
publicintuserId;
publicintid;
publicStringtitle;
publicStringbody;
}
PostItempostItem = newPostItem();
JSONObjectjson = (JSONObject) JSON.toJSON(postItem);
KnHttp.post("https://jsonplaceholder.typicode.com/posts")
.addJSONObjectBody(json) // Content-Type header is set automatically
.build()
.getAsObject(PostItem.class, newParsedRequestListener<PostItem>() {
@OverridepublicvoidonResponse(PostItempost, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

PUT: send json + get response as parsed Object

// Create JSON manuallyJSONObjectpostItem = newJSONObject();
postItem.put("title", "foo");
postItem.put("body", "bar");
postItem.put("userId", 1);
// OR use classpublicclassPostItem {
publicintuserId;
publicintid;
publicStringtitle;
publicStringbody;
}
PostItempostItem = newPostItem();
JSONObjectjson = (JSONObject) JSON.toJSON(postItem);
KnHttp.put("https://jsonplaceholder.typicode.com/posts/{postID}")
.addPathParameter("postId", "1")
.addJSONObjectBody(json) // Content-Type header is set automatically
.build()
.getAsObject(PostItem.class, newParsedRequestListener<PostItem>() {
@OverridepublicvoidonResponse(PostItempost, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

HEAD and OPTIONS request are based on the GET request constructor

KnHttp.head(url)
...
KnHttp.options(url)
...

PUT, DELETE, PATCH request are based on the POST request constructor

KnHttp.put(url)
...
KnHttp.delete(url)
...
KnHttp.patch(url)
...

Download a file

KnHttp.download("https://jsonplaceholder.typicode.com/posts", absoluteDirPath, "posts.json")
.build()
.setDownloadProgressListener(newDownloadProgressListener() {
@OverridepublicvoidonProgress(longbytesDownloaded, longtotalBytes) {
// on download progress
}
})
.startDownload(newDownloadListener() {
@OverridepublicvoidonDownloadComplete(ResponseokHttpRes) {
// download completed
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

Upload a file

KnHttp.upload(url)
.addMultipartFile("avatar", avatarFile)
.build()
.setUploadProgressListener(newUploadProgressListener() {
@OverridepublicvoidonProgress(longbytesUploaded, longtotalBytes) {
// on upload progress
}
})
.getAsJSONObject(newJSONObjectRequestListener() {
@OverridepublicvoidonResponse(JSONObjectobj, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

Download image as bitmap

KnHttp.get(imageUrl)
.setBitmapMaxHeight(100)
.setBitmapMaxWidth(100)
.setBitmapConfig(Bitmap.Config.ARGB_8888)
.build()
.getAsBitmap(newBitmapRequestListener() {
@OverridepublicvoidonResponse(Bitmapbitmap, ResponseokHttpRes) {
// do anything with bitmap
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

Synchronous requests (Do not work on the main thread)

GET

KnRequestrequest = KnHttp.get("https://jsonplaceholder.typicode.com/posts").build();
KnResponse<String> res = request.executeForString();
if (res.isSuccess()) {
Stringstr = res.getResult();
ResponseokHttpRes = res.getOkHttpResponse();
// do anything with response
} else {
KnErrorerr = res.getError();
// Handle Error
}

POST

KnRequestrequest = KnHttp.post("https://jsonplaceholder.typicode.com/posts")
.addBodyParameter("title", "foo")
.addBodyParameter("body", "bar")
.addBodyParameter("userId", "1")
.build();
KnResponse<PostItem> res = request.executeForObject(PostItem.class);
if (res.isSuccess()) {
PostItempost = res.getResult();
ResponseokHttpRes = res.getOkHttpResponse();
// do anything with response
} else {
KnErrorerr = res.getError();
// Handle Error
}

Download

KnRequestrequest = KnHttp.download("https://jsonplaceholder.typicode.com/posts", absoluteDirPath, "posts.json")
.build()
.setDownloadProgressListener(newDownloadProgressListener() {
@OverridepublicvoidonProgress(longbytesDownloaded, longtotalBytes) {
// on download progress
}
});
KnResponseres = request.executeForDownload();
if (res.isSuccess()) {
// download complete
} else {
KnErrorerr = res.getError();
// Handle Error
}

Upload

KnRequestrequest = KnHttp.upload(url)
.addMultipartFile("avatar", avatarFile)
.build()
.setUploadProgressListener(newUploadProgressListener() {
@OverridepublicvoidonProgress(longbytesUploaded, longtotalBytes) {
// on upload progress
}
});
KnResponse<PostItem> res = request.executeForObject(PostItem.class);
if (res.isSuccess()) {
PostItempost = res.getResult();
ResponseokHttpRes = res.getOkHttpResponse();
// do anything with response
} else {
KnErrorerr = res.getError();
// Handle Error
}

Caching (If enabled)

How it's works ?

  • First of all the server must send cache-control in header so that is starts working.
  • Response will be cached on the basis of cache-control max-age, max-stale.
  • If the internet is connected and the age is NOT expired, it will return from cache.
  • If the internet is connected and the age is expired and if server returns 304(NOT MODIFIED), it will return from cache.
  • If the internet is NOT connected and you are using getResponseOnlyIfCached() - it will return from cache even it the date is expired.
  • If the internet is NOT connected, if you are NOT using getResponseOnlyIfCached() - it will NOT return anything.
  • If you are using getResponseOnlyFromNetwork(), it will only return response after validating from the server.
  • If cache-control is set, it will work according to the max-age and the max-stale returned from server.
  • If the internet is NOT connected, only way to get cached response is by using getResponseOnlyIfCached().

Do not cache response

KnHttp.get("https://jsonplaceholder.typicode.com/posts")
.doNotCacheResponse()
.build()
.getAsString(newStringRequestListener() {
@OverridepublicvoidonResponse(Stringstr, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

Get response only if is cached

KnHttp.get("https://jsonplaceholder.typicode.com/posts")
.getResponseOnlyIfCached()
.build()
.getAsString(newStringRequestListener() {
@OverridepublicvoidonResponse(Stringstr, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

Get response only from network(internet)

KnHttp.get("https://jsonplaceholder.typicode.com/posts")
.getResponseOnlyFromNetwork()
.build()
.getAsString(newStringRequestListener() {
@OverridepublicvoidonResponse(Stringstr, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

Set Max Age Cache Control

KnHttp.get("https://jsonplaceholder.typicode.com/posts")
.setMaxAgeCacheControl(0, TimeUnit.SECONDS)
.build()
.getAsString(newStringRequestListener() {
@OverridepublicvoidonResponse(Stringstr, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

Set Max Stale Cache Control

KnHttp.get("https://jsonplaceholder.typicode.com/posts")
.setMaxStaleCacheControl(365, TimeUnit.SECONDS)
.build()
.getAsString(newStringRequestListener() {
@OverridepublicvoidonResponse(Stringstr, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

Others

Error Code Handling

publicvoidonError(KnErrorerr) {
if (err.getErrorCode() != 0) {
// received error from server// err.getErrorCode() - the error code from server// err.getErrorBody() - the error body from server// err.getErrorDetail() - just an error detailLog.d(TAG, "onError errorCode : " + err.getErrorCode());
Log.d(TAG, "onError errorBody : " + err.getErrorBody());
Log.d(TAG, "onError errorDetail : " + err.getErrorDetail());
} else {
// err.getErrorDetail() ==// KnConstants.connectionError// KnConstants.parseError// KnConstants.requestCancelledErrorLog.d(TAG, "onError errorDetail : " + err.getErrorDetail());
}
}

Cancelling a request

KnHttp.cancel("tag"); // All the requests with the given tag will be cancelled.KnHttp.forceCancel("tag"); // All the requests with the given tag will be cancelled , even if any percent threshold is set , it will be cancelled forcefully.KnHttp.cancelAll(); // All the requests will be cancelled.KnHttp.forceCancelAll(); // All the requests will be cancelled , even if any percent threshold is set , it will be cancelled forcefully.

Request priority

KnHttp.get("https://jsonplaceholder.typicode.com/posts")
.setPriority(Priority.LOW)
.build()
.getAsString(newStringRequestListener() {
@OverridepublicvoidonResponse(Stringstr, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

Accessing Headers in Response

@OverridepublicvoidonResponse(Stringstr, ResponseokHttpRes) {
Log.d(TAG, "Headers :" + okHttpRes.headers());
}

Clear Bitmap Cache

KnHttp.evictBitmap(key); // remove a bitmap with key from LruCacheKnHttp.evictAllBitmap(); // clear LruCache

Logging

KnHttp.enableLogging(); // simply enable loggingKnHttp.enableLogging(LEVEL.HEADERS); // enabling logging with level

Custom Executor

KnHttp.get("https://jsonplaceholder.typicode.com/posts")
.setExecutor(Executors.newSingleThreadExecutor()) // setting an executor to get response or completion on that executor thread
.build()
.getAsString(newStringRequestListener() {
@OverridepublicvoidonResponse(Stringstr, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

Setting custom Content-Type

KnHttp.post("https://jsonplaceholder.typicode.com/posts")
.setContentType("application/json+lama; charset=utf-8") // Custom Content-Type
.addJSONObjectBody(json)
.build()
.getAsJSONObject(newJSONObjectRequestListener() {
@OverridepublicvoidonResponse(JSONObjectobj, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

Set global user-agent

KnHttp.setUserAgent("MyApp/" + BuildConfig.VERSION_NAME);

Set per request user-agent

KnHttp.get("https://jsonplaceholder.typicode.com/posts")
.setUserAgent("MyApp/" + BuildConfig.VERSION_NAME)
.build()
.getAsString(newStringRequestListener() {
@OverridepublicvoidonResponse(Stringstr, ResponseokHttpRes) {
// do anything with response
}
@OverridepublicvoidonError(KnErrorerr) {
// handle error
}
});

CREDITS

License

 Copyright (c) 2019-2026 Florent VIALATTE
Copyright (c) 2016-2019 Amit Shekhar
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

About

🚀 Fast Android HTTP Client which supports HTTP/2, TLS 1.3 and Brotli 🚀

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages