├── app
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── dimens.xml
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── layout
│ │ │ ├── activity_main.xml
│ │ │ └── fragment_main.xml
│ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ └── drawable
│ │ │ └── ic_launcher_background.xml
│ │ ├── java
│ │ └── com
│ │ │ └── kine
│ │ │ └── test
│ │ │ ├── ConfigUtils.kt
│ │ │ ├── model
│ │ │ ├── Post.kt
│ │ │ ├── CreateUserResponse.kt
│ │ │ ├── User.kt
│ │ │ └── UserListResponse.kt
│ │ │ ├── MainActivity.kt
│ │ │ └── TestFragment.kt
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle
├── kine
├── .gitignore
├── gradle.properties
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── kine
│ │ ├── request
│ │ ├── SimpleRequestBody.kt
│ │ ├── MultiPartBody.kt
│ │ ├── MultiPartStringBody.kt
│ │ ├── MultiPartFileBody.kt
│ │ ├── RequestDataFields.kt
│ │ ├── StringRequestBody.kt
│ │ ├── ContentType.kt
│ │ ├── RequestBody.kt
│ │ ├── RequestFields.kt
│ │ ├── UploadRequestFields.kt
│ │ ├── DownloadRequestFields.kt
│ │ ├── EncodedRequestBody.kt
│ │ └── MultiPartRequestBody.kt
│ │ ├── connections
│ │ └── ConnectionChecker.kt
│ │ ├── interceptors
│ │ ├── PreNetworkKineInterceptor.kt
│ │ └── KineInterceptor.kt
│ │ ├── cache
│ │ ├── KineCache.kt
│ │ └── KineCacheControl.kt
│ │ ├── timer
│ │ ├── Timer.kt
│ │ ├── TimerManager.kt
│ │ └── SimpleTimer.kt
│ │ ├── exceptions
│ │ ├── NoInternetException.kt
│ │ ├── TimeoutException.kt
│ │ ├── UnknownException.kt
│ │ ├── NoClientFoundException.kt
│ │ ├── NoConverterFoundException.kt
│ │ ├── NullResponseException.kt
│ │ ├── NullResponseBodyException.kt
│ │ ├── OfflineException.kt
│ │ ├── UrlMalformedException.kt
│ │ ├── HttpStatusCodeException.kt
│ │ ├── MisMatchClientException.kt
│ │ ├── MisMatchConverterException.kt
│ │ └── ParseException.kt
│ │ ├── response
│ │ ├── KineResponseListener.kt
│ │ ├── KineError.kt
│ │ └── KineResponse.kt
│ │ ├── executor
│ │ ├── CallbackExecutor.kt
│ │ ├── PriorityRunnable.kt
│ │ ├── PriorityThreadFactory.kt
│ │ ├── KineExecutorManager.kt
│ │ ├── ExecutorSupplier.kt
│ │ ├── PriorityThreadPoolExecutor.kt
│ │ └── DefaultPriorityExecutorSupplier.kt
│ │ ├── extensions
│ │ ├── File.kt
│ │ ├── Any.kt
│ │ ├── List.kt
│ │ ├── Class.kt
│ │ └── Url.kt
│ │ ├── internal
│ │ ├── DefaultKineClass.kt
│ │ ├── IRequestManager.kt
│ │ └── KineClass.kt
│ │ ├── converters
│ │ ├── Converter.kt
│ │ ├── FileDownloadConverter.kt
│ │ └── RawResponseConverter.kt
│ │ ├── client
│ │ └── KineClient.kt
│ │ ├── log
│ │ ├── JavaLog.kt
│ │ ├── Log.kt
│ │ ├── LogLevel.kt
│ │ └── Logger.kt
│ │ ├── policies
│ │ ├── Priority.kt
│ │ ├── RetryPolicy.kt
│ │ └── DefaultRetryPolicy.kt
│ │ └── Kine.kt
└── build.gradle
├── kine-gson
├── .gitignore
├── gradle.properties
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── kine
│ │ └── converters
│ │ ├── GsonConverter.kt
│ │ └── extensions
│ │ └── Gson.kt
└── build.gradle
├── kine-json
├── .gitignore
├── build.gradle
└── src
│ ├── main
│ └── java
│ │ └── com
│ │ └── kine
│ │ ├── converters
│ │ └── JsonConverter.kt
│ │ └── extensions
│ │ └── Url.kt
│ └── test
│ └── java
│ └── com
│ └── kine
│ └── JsonApiTest.kt
├── kine-moshi
├── .gitignore
├── gradle.properties
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── kine
│ │ └── converters
│ │ ├── extensions
│ │ └── Moshi.kt
│ │ └── MoshiConverter.kt
└── build.gradle
├── kine-okhttp
├── .gitignore
├── gradle.properties
├── src
│ ├── main
│ │ └── java
│ │ │ └── com
│ │ │ └── kine
│ │ │ ├── converters
│ │ │ └── OkioConverter.kt
│ │ │ └── client
│ │ │ ├── FileProgressRequestBody.kt
│ │ │ └── extensions
│ │ │ └── Extensions.kt
│ └── test
│ │ └── java
│ │ └── com
│ │ └── kine
│ │ └── client
│ │ ├── OkHttpGetTest.kt
│ │ ├── OkHttpHeadTest.kt
│ │ ├── OkHttpPutTest.kt
│ │ ├── OkHttpPostTest.kt
│ │ ├── OkHttpPatchTest.kt
│ │ └── OkHttpDeleteTest.kt
└── build.gradle
├── kine-android
├── .gitignore
├── consumer-rules.pro
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── kine
│ │ └── android
│ │ ├── request
│ │ └── JsonRequestBody.kt
│ │ ├── connections
│ │ ├── SimpleConnectionChecker.kt
│ │ └── Utils.kt
│ │ ├── timer
│ │ └── AndroidTimer.kt
│ │ ├── executor
│ │ ├── PriorityThreadFactory.kt
│ │ ├── MainThreadExecutor.kt
│ │ └── AndroidPriorityExecutorSupplier.kt
│ │ ├── log
│ │ └── Log.kt
│ │ ├── converters
│ │ └── JsonConverter.kt
│ │ ├── cache
│ │ └── Cache.kt
│ │ └── extensions
│ │ └── Url.kt
├── proguard-rules.pro
└── build.gradle
├── kine-coroutine
├── .gitignore
├── gradle.properties
├── build.gradle
└── src
│ └── main
│ └── java
│ └── com
│ └── kine
│ └── coroutine
│ └── Coroutine.kt
├── kine-imageloader
├── .gitignore
├── consumer-rules.pro
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── kine
│ │ └── imageloader
│ │ ├── interceptors
│ │ └── BitmapCacheInterceptor.kt
│ │ ├── BitmapKineClass.kt
│ │ ├── converter
│ │ └── BitmapConverter.kt
│ │ ├── policies
│ │ └── MemoryPolicy.kt
│ │ ├── cache
│ │ └── MemoryCache.kt
│ │ └── extensions
│ │ └── Imageloader.kt
├── proguard-rules.pro
└── build.gradle
├── kine-livedata
├── .gitignore
├── consumer-rules.pro
├── gradle.properties
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── kine
│ │ └── android
│ │ └── LiveData.kt
├── proguard-rules.pro
└── build.gradle
├── kine-rxjava2
├── .gitignore
├── consumer-rules.pro
├── gradle.properties
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── kine
│ │ └── rxnetworking
│ │ └── RxJava2.kt
├── build.gradle
└── proguard-rules.pro
├── kine-rxjava3
├── .gitignore
├── gradle.properties
├── build.gradle
└── src
│ └── main
│ └── java
│ └── com
│ └── kine
│ └── rxjava3
│ └── RxJava3.kt
├── kine-okhttplegacy
├── .gitignore
├── gradle.properties
├── src
│ ├── main
│ │ └── java
│ │ │ └── com
│ │ │ └── kine
│ │ │ ├── converters
│ │ │ └── OkioConverter.kt
│ │ │ └── client
│ │ │ ├── FileProgressRequestBody.kt
│ │ │ └── extensions
│ │ │ └── Extensions.kt
│ └── test
│ │ └── java
│ │ └── com
│ │ └── kine
│ │ └── client
│ │ ├── OkHttpGetTest.kt
│ │ ├── OkHttpHeadTest.kt
│ │ ├── OkHttpPutTest.kt
│ │ ├── OkHttpPostTest.kt
│ │ ├── OkHttpPatchTest.kt
│ │ └── OkHttpDeleteTest.kt
└── build.gradle
├── logo.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── settings.gradle
├── .github
└── workflows
│ └── main_release.yml
├── bintray.gradle
├── gradle.properties
├── CODE_OF_CONDUCT.md
├── publish.gradle
└── publish1.gradle
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine-gson/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine-json/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine-moshi/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine-okhttp/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine/gradle.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/kine-android/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine-android/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/kine-coroutine/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine-imageloader/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine-livedata/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine-livedata/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/kine-rxjava2/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine-rxjava2/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/kine-rxjava3/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine-imageloader/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/kine-okhttplegacy/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kine-gson/gradle.properties:
--------------------------------------------------------------------------------
1 | libraryVersion=2.8.6.0
2 |
--------------------------------------------------------------------------------
/kine-livedata/gradle.properties:
--------------------------------------------------------------------------------
1 | libraryVersion=2.2.0.0
2 |
--------------------------------------------------------------------------------
/kine-moshi/gradle.properties:
--------------------------------------------------------------------------------
1 | libraryVersion=1.9.3.0
2 |
--------------------------------------------------------------------------------
/kine-okhttp/gradle.properties:
--------------------------------------------------------------------------------
1 | libraryVersion=4.8.1.0
2 |
--------------------------------------------------------------------------------
/kine-rxjava2/gradle.properties:
--------------------------------------------------------------------------------
1 | libraryVersion=2.2.19.0
2 |
--------------------------------------------------------------------------------
/kine-rxjava3/gradle.properties:
--------------------------------------------------------------------------------
1 | libraryVersion=3.0.6.0
2 |
--------------------------------------------------------------------------------
/kine-coroutine/gradle.properties:
--------------------------------------------------------------------------------
1 | libraryVersion=1.3.8.0
2 |
--------------------------------------------------------------------------------
/kine-okhttplegacy/gradle.properties:
--------------------------------------------------------------------------------
1 | libraryVersion=3.12.12.0
2 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TechDev009/Kine/HEAD/logo.png
--------------------------------------------------------------------------------
/kine-livedata/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Kine
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TechDev009/Kine/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/SimpleRequestBody.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 | class SimpleRequestBody:RequestBody()
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TechDev009/Kine/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TechDev009/Kine/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TechDev009/Kine/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TechDev009/Kine/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TechDev009/Kine/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TechDev009/Kine/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TechDev009/Kine/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TechDev009/Kine/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/MultiPartBody.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 | open class MultiPartBody (val value:T,val contentType:String?)
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TechDev009/Kine/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TechDev009/Kine/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/java/com/kine/test/ConfigUtils.kt:
--------------------------------------------------------------------------------
1 | package com.kine.test
2 |
3 | object ConfigUtils {
4 | const val dummyBaseUrl = "https://reqres.in/api/"
5 | }
--------------------------------------------------------------------------------
/kine-android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/connections/ConnectionChecker.kt:
--------------------------------------------------------------------------------
1 | package com.kine.connections
2 |
3 | interface ConnectionChecker {
4 | fun isConnected(): Boolean
5 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/interceptors/PreNetworkKineInterceptor.kt:
--------------------------------------------------------------------------------
1 | package com.kine.interceptors
2 |
3 | abstract class PreNetworkKineInterceptor:KineInterceptor()
--------------------------------------------------------------------------------
/kine-imageloader/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/kine-imageloader/src/main/java/com/kine/imageloader/interceptors/BitmapCacheInterceptor.kt:
--------------------------------------------------------------------------------
1 | package com.kine.imageloader.interceptors
2 |
3 | class BitmapCacheInterceptor {
4 | }
--------------------------------------------------------------------------------
/kine-rxjava2/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 | /
5 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/MultiPartStringBody.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 | class MultiPartStringBody(value:String, contentType:String?=null): MultiPartBody(value, contentType)
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/cache/KineCache.kt:
--------------------------------------------------------------------------------
1 | package com.kine.cache
2 |
3 | import java.io.File
4 |
5 | /**
6 | * interface for caching response.
7 | */
8 | class KineCache (val file: File, val cacheSize:Long)
9 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/MultiPartFileBody.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 | import java.io.File
4 |
5 | class MultiPartFileBody(value: File, contentType:String?=null): MultiPartBody(value, contentType)
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/timer/Timer.kt:
--------------------------------------------------------------------------------
1 | package com.kine.timer
2 |
3 | interface Timer {
4 |
5 | fun clone():Timer
6 |
7 | fun start()
8 |
9 | fun stop():Long
10 |
11 | fun time():Long
12 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 10dp
4 | 10dp
5 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/NoInternetException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | import java.lang.Exception
4 |
5 | class NoInternetException(msg: String?="Please check your internet connection"):Exception(msg)
6 | {
7 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/response/KineResponseListener.kt:
--------------------------------------------------------------------------------
1 | @file:JvmName("ResponseListenerKt")
2 |
3 | package com.kine.response
4 |
5 |
6 | typealias OnSuccess = ((KineResponse) -> Unit)
7 |
8 | typealias OnError = ((KineError) -> Unit)
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #6200EE
4 | #3700B3
5 | #03DAC5
6 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/executor/CallbackExecutor.kt:
--------------------------------------------------------------------------------
1 | package com.kine.executor
2 |
3 | import java.util.concurrent.Executor
4 |
5 | class CallbackExecutor:Executor {
6 | override fun execute(command: Runnable) {
7 | command.run()
8 | }
9 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/extensions/File.kt:
--------------------------------------------------------------------------------
1 | package com.kine.extensions
2 |
3 | import java.net.URLConnection
4 |
5 | fun String.getMimeType(): String {
6 | return URLConnection.getFileNameMap().getContentTypeFor(this)?:"application/octet-stream"
7 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/TimeoutException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | import java.lang.Exception
4 |
5 | class TimeoutException (msg: String?="timeout error"): Exception(msg) {
6 | constructor(e: Exception):this(e.localizedMessage?:e.message)
7 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/UnknownException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | import java.lang.Exception
4 |
5 | class UnknownException(msg: String?="unknown error"): Exception(msg) {
6 | constructor(e: Exception):this(e.localizedMessage?:e.message)
7 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/NoClientFoundException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | class NoClientFoundException(msg: String?= "no kineClient found" +
4 | "please set at least one client through Kine class or individual request") : IllegalStateException(msg)
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Aug 19 00:29:13 IST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/NoConverterFoundException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | class NoConverterFoundException(msg: String?="no converter specified, please set at least one converter"
4 | + "through Kine class or through individual request") : IllegalStateException(msg)
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/extensions/Any.kt:
--------------------------------------------------------------------------------
1 | package com.kine.extensions
2 |
3 | import com.kine.executor.KineExecutorManager
4 |
5 |
6 | fun Any.onCallbackThread(action: () -> Unit) {
7 | KineExecutorManager.executorSupplier.forCallbackTasks().execute {
8 | action()
9 | }
10 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/internal/DefaultKineClass.kt:
--------------------------------------------------------------------------------
1 | package com.kine.internal
2 |
3 | class DefaultKineClass(clazz: Class) : KineClass(clazz) {
4 |
5 | override fun isAssignableFrom(t: Class<*>): Boolean {
6 | return clazz.isAssignableFrom(t).apply {
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/NullResponseException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | import java.lang.Exception
4 |
5 | class NullResponseException(msg: String?="null response from client"): NullPointerException(msg) {
6 | constructor(e: Exception):this(e.localizedMessage?:e.message)
7 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/converters/Converter.kt:
--------------------------------------------------------------------------------
1 | package com.kine.converters
2 |
3 | import com.kine.request.RequestFields
4 | import kotlin.jvm.Throws
5 |
6 | interface Converter {
7 | @Throws(Throwable::class)
8 | fun convert(response: Any, requestFields: RequestFields, clazz: Class): J?
9 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/NullResponseBodyException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | import java.lang.Exception
4 |
5 | class NullResponseBodyException(msg: String?="null response from server"): NullPointerException(msg) {
6 | constructor(e: Exception):this(e.localizedMessage?:e.message)
7 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/OfflineException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | import java.lang.Exception
4 |
5 | class OfflineException(msg: String?="request called with offline only mode but no cached response found"): Exception(msg) {
6 | constructor(e: Exception):this(e.localizedMessage?:e.message)
7 | }
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/UrlMalformedException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | import java.lang.Exception
4 |
5 | class UrlMalformedException(msg: String?="url is not properly formatted or not a url at all"): NullPointerException(msg) {
6 | constructor(e: Exception):this(e.localizedMessage?:e.message)
7 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/timer/TimerManager.kt:
--------------------------------------------------------------------------------
1 | package com.kine.timer
2 |
3 | object TimerManager {
4 | private var timer: Timer = SimpleTimer()
5 |
6 | fun start(): Timer {
7 | return timer.clone().apply { start()}
8 | }
9 |
10 | fun time(): Long {
11 | return timer.time()
12 | }
13 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/HttpStatusCodeException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | import java.lang.Exception
4 |
5 | class HttpStatusCodeException(msg: String?="unsuccessful status code from server ",code:Int): Exception(msg+code) {
6 | constructor(e: Exception,code:Int):this(e.localizedMessage?:e.message,code)
7 | }
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/kine-android/src/main/java/com/kine/android/request/JsonRequestBody.kt:
--------------------------------------------------------------------------------
1 | package com.kine.android.request
2 |
3 | import com.kine.request.ContentType
4 | import com.kine.request.StringRequestBody
5 | import org.json.JSONObject
6 |
7 | class JsonRequestBody(jsonObject: JSONObject?):StringRequestBody(jsonObject?.toString(),ContentType.JSON.toString())
--------------------------------------------------------------------------------
/app/src/main/java/com/kine/test/model/Post.kt:
--------------------------------------------------------------------------------
1 | package com.kine.test.model
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Post (
6 |
7 | @SerializedName("userId") val userId : Int,
8 | @SerializedName("id") val id : Int,
9 | @SerializedName("title") val title : String,
10 | @SerializedName("body") val body : String
11 | )
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/MisMatchClientException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | class MisMatchClientException(msg: String?= "no kineClient found that can handle this type of request, " +
4 | "please set at least one client that can " +
5 | "handle this type of request" + " " + "through Kine class or individual request") : IllegalStateException(msg)
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/executor/PriorityRunnable.kt:
--------------------------------------------------------------------------------
1 | package com.kine.executor
2 |
3 | import com.kine.policies.Priority
4 |
5 | open class PriorityRunnable(private val priority: Priority) : Runnable {
6 | override fun run() {
7 | // nothing to do here.
8 | }
9 |
10 | fun getPriority(): Priority {
11 | return priority
12 | }
13 |
14 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/executor/PriorityThreadFactory.kt:
--------------------------------------------------------------------------------
1 | package com.kine.executor
2 |
3 |
4 | import java.util.concurrent.ThreadFactory
5 |
6 | class PriorityThreadFactory(private val threadPriority: Int) : ThreadFactory {
7 | override fun newThread(runnable: Runnable): Thread {
8 | return Thread(runnable).apply { priority = threadPriority }
9 | }
10 |
11 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/interceptors/KineInterceptor.kt:
--------------------------------------------------------------------------------
1 | package com.kine.interceptors
2 |
3 | import com.kine.request.RequestFields
4 | import com.kine.response.KineResponse
5 | import kotlin.jvm.Throws
6 |
7 | abstract class KineInterceptor {
8 | @Throws(Throwable::class)
9 | abstract fun intercept(requestFields: RequestFields, clazz: Class):KineResponse?
10 |
11 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':kine-json'
2 | include ':kine-livedata'
3 | include ':kine-okhttplegacy'
4 | include ':kine-rxjava3'
5 | include ':kine-coroutine'
6 | include ':kine-rxjava2'
7 | include ':kine-moshi'
8 | include ':kine-okhttp'
9 | include ':kine-imageloader'
10 | include ':kine-android'
11 | include ':kine-gson'
12 | include ':kine'
13 | include ':app'
14 | rootProject.name = "Kine"
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/RequestDataFields.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 |
4 | /**
5 | * An RequestDataFields. This class is used to hold request param information associated with a single HTTP request.
6 | */
7 | data class RequestDataFields(val reqTAG: String, var url: String, val method: Int,
8 | val body : RequestBody, val headers: HashMap?)
--------------------------------------------------------------------------------
/kine-android/src/main/java/com/kine/android/connections/SimpleConnectionChecker.kt:
--------------------------------------------------------------------------------
1 | package com.kine.android.connections
2 |
3 | import android.content.Context
4 | import com.kine.connections.ConnectionChecker
5 |
6 | class SimpleConnectionChecker(private val context: Context) : ConnectionChecker {
7 | override fun isConnected(): Boolean {
8 | return Utils.isConnected(context)
9 | }
10 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/StringRequestBody.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 | open class StringRequestBody(var body:String?=null, mediaType:String = ContentType.JSON.toString()):RequestBody(mediaType) {
4 |
5 | fun setBody(body: String? = null, mediaType: String = ContentType.JSON.toString()) {
6 |
7 | this.body = body
8 | this.mediaType = mediaType
9 | }
10 |
11 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/MisMatchConverterException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | import java.lang.IllegalArgumentException
4 |
5 | class MisMatchConverterException(msg:String= "the converter passed cannot handle " + "this type of response returned by this request" +
6 | ", please set a converter that can " + "handle this type of response" +
7 | " " + "through converter() method"):IllegalArgumentException(msg)
--------------------------------------------------------------------------------
/kine-imageloader/src/main/java/com/kine/imageloader/BitmapKineClass.kt:
--------------------------------------------------------------------------------
1 | package com.kine.imageloader
2 |
3 | import android.graphics.Bitmap
4 | import com.kine.internal.KineClass
5 |
6 | class BitmapKineClass : KineClass(Bitmap::class.java) {
7 | override fun isAssignableFrom(t: Class<*>): Boolean {
8 | return t.isAssignableFrom(ByteArray::class.java) || t.isAssignableFrom(Bitmap::class.java)
9 | }
10 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/extensions/List.kt:
--------------------------------------------------------------------------------
1 | package com.kine.extensions
2 |
3 | /**
4 | * Returns the first element matching the given [predicate], or `null` if element was not found.
5 | */
6 | public inline fun Iterable.firstResultOrNull(predicate: (T) -> F?): F? {
7 | for (element in this) {
8 | (predicate(element))?.apply {
9 | return this
10 | }
11 | }
12 | return null
13 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/kine-moshi/src/main/java/com/kine/converters/extensions/Moshi.kt:
--------------------------------------------------------------------------------
1 | package com.kine.converters.extensions
2 |
3 |
4 | import com.squareup.moshi.Moshi
5 | import java.lang.reflect.Type
6 |
7 | inline fun Moshi.fromJsonArray(response: String,clazz: Class): List? {
8 | val type: Type = com.squareup.moshi.Types.newParameterizedType(MutableList::class.java, clazz)
9 | return this.adapter>(type).fromJson(response)
10 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/exceptions/ParseException.kt:
--------------------------------------------------------------------------------
1 | package com.kine.exceptions
2 |
3 | import java.lang.Exception
4 |
5 | class ParseException(
6 | msg: String? = "Parsing response failed,check if your specified converter can handle" +
7 | "the response type and if not set a converter that can handle the needed response type"
8 | ) : Exception(msg) {
9 | constructor(e: Throwable) : this(e.localizedMessage ?: e.message)
10 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/internal/IRequestManager.kt:
--------------------------------------------------------------------------------
1 |
2 | package com.kine.internal
3 |
4 | import com.kine.request.RequestFields
5 | import com.kine.response.KineResponse
6 |
7 | /**
8 | * abstract internal class that takes care of caching , parsing and check other params for a request
9 | */
10 | internal interface IRequestManager {
11 |
12 | fun executeRequest(requestFields: RequestFields, clazz: KineClass):KineResponse?
13 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/ContentType.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 | /**
4 | * Helper class for content-type(media-type).
5 | */
6 |
7 | enum class ContentType(private val value:String) {
8 | JSON("application/json; charset=utf-8"), STRING("text/plain; charset=utf-8"),
9 | ENCODED("application/x-www-form-urlencoded"),MULTIPART_FORM("multipart/form-data");
10 |
11 | override fun toString(): String {
12 | return value
13 | }
14 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/extensions/Class.kt:
--------------------------------------------------------------------------------
1 | package com.kine.extensions
2 |
3 | internal fun String.getClassInstance(default:F): T {
4 | return this.getClassInstanceOrNull()?:default
5 | }
6 | @Suppress("UNCHECKED_CAST")
7 | internal fun String.getClassInstanceOrNull(): T? {
8 | return try {
9 | Class.forName(this).newInstance() as T
10 | }catch (exception: ClassNotFoundException) {
11 | // exception.printStackTrace()
12 | null
13 | }
14 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/timer/SimpleTimer.kt:
--------------------------------------------------------------------------------
1 | package com.kine.timer
2 |
3 | class SimpleTimer:Timer {
4 | var time:Long=0
5 | override fun clone(): Timer {
6 | return SimpleTimer()
7 | }
8 |
9 | override fun start() {
10 | time = System.currentTimeMillis()
11 | }
12 |
13 | override fun stop(): Long {
14 | return System.currentTimeMillis() - time
15 | }
16 |
17 | override fun time(): Long {
18 | return System.currentTimeMillis()
19 | }
20 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/cache/KineCacheControl.kt:
--------------------------------------------------------------------------------
1 | package com.kine.cache
2 |
3 | import java.util.concurrent.TimeUnit
4 |
5 | class KineCacheControl(var networkPolicy:Int = NO_CACHE_CONTROL, val cacheMaxAge:Int=0, val timeUnit: TimeUnit){
6 | companion object{
7 | const val NO_CACHE_CONTROL = 0
8 | const val FORCE_CACHE = 1
9 | const val FORCE_NETWORK = 2
10 | const val NO_CACHE = 3
11 | const val NO_STORE = 4
12 | const val CACHE_FOR_TIME =5
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/converters/FileDownloadConverter.kt:
--------------------------------------------------------------------------------
1 | package com.kine.converters
2 |
3 | import com.kine.request.RequestFields
4 | import java.io.File
5 |
6 |
7 | class FileDownloadConverter : Converter {
8 | @Suppress("UNCHECKED_CAST")
9 | override fun convert(response: Any, requestFields: RequestFields, clazz: Class): J? {
10 | if (clazz.isAssignableFrom(File::class.java) && response is File) {
11 | return response as J
12 | }
13 | return null
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kine/test/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.kine.test
2 |
3 | import android.os.Bundle
4 | import androidx.appcompat.app.AppCompatActivity
5 |
6 | class MainActivity : AppCompatActivity() {
7 | override fun onCreate(savedInstanceState: Bundle?) {
8 | super.onCreate(savedInstanceState)
9 | setContentView(R.layout.activity_main)
10 | supportFragmentManager.beginTransaction().replace(
11 | R.id.container,
12 | TestFragment()
13 | ).commit()
14 |
15 | }
16 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/executor/KineExecutorManager.kt:
--------------------------------------------------------------------------------
1 | package com.kine.executor
2 |
3 | import com.kine.extensions.getClassInstance
4 |
5 |
6 | object KineExecutorManager {
7 | val executorSupplier: ExecutorSupplier = getDefaultExecutorSupplier()
8 | private const val androidExecutorClass = "com.kine.android.executor.AndroidPriorityExecutorSupplier"
9 | private fun getDefaultExecutorSupplier(): ExecutorSupplier {
10 | return androidExecutorClass.getClassInstance(DefaultPriorityExecutorSupplier())
11 | }
12 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/client/KineClient.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.request.RequestFields
4 | import com.kine.response.KineResponse
5 |
6 | /**
7 | * kineClient for making the actual HTTP request to server.
8 | */
9 | abstract class KineClient constructor(){
10 |
11 | abstract fun canHandleRequest(url: String, method: Int): Boolean
12 |
13 | @Throws(Throwable::class)
14 | abstract fun execute(requestFields: RequestFields, clazz: Class): KineResponse
15 |
16 | abstract fun cancelAllRequests(tag: String?=null)
17 |
18 | }
--------------------------------------------------------------------------------
/kine-gson/src/main/java/com/kine/converters/GsonConverter.kt:
--------------------------------------------------------------------------------
1 | package com.kine.converters
2 |
3 | import com.google.gson.Gson
4 | import com.kine.request.RequestFields
5 |
6 | class GsonConverter(private var gson: Gson = Gson()) : Converter {
7 | override fun convert(response: Any, requestFields: RequestFields, clazz: Class): J? {
8 | return when (response) {
9 | is String -> {
10 | gson.fromJson(response, clazz)
11 | }
12 | else -> {
13 | null
14 | }
15 | }
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/kine/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java-library'
2 | apply plugin: 'kotlin'
3 | ext {
4 | PUBLISH_GROUP_ID = 'com.kine'
5 | PUBLISH_ARTIFACT_ID = 'kine'
6 | PUBLISH_VERSION = '1.0.0'
7 | }
8 | tasks.withType(Javadoc).all {
9 | enabled = false
10 | }
11 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/publish.gradle'
12 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/bintray.gradle'
13 | dependencies {
14 | implementation fileTree(dir: "libs", include: ["*.jar"])
15 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
16 | }
17 |
--------------------------------------------------------------------------------
/kine-android/src/main/java/com/kine/android/timer/AndroidTimer.kt:
--------------------------------------------------------------------------------
1 | package com.kine.android.timer
2 |
3 | import android.os.SystemClock
4 | import com.kine.timer.Timer
5 |
6 | class AndroidTimer :Timer{
7 | var time:Long=0
8 | override fun clone(): Timer {
9 | return AndroidTimer()
10 | }
11 |
12 | override fun start() {
13 | time = SystemClock.elapsedRealtime()
14 | }
15 |
16 | override fun stop(): Long {
17 | return SystemClock.elapsedRealtime() - time
18 | }
19 |
20 | override fun time(): Long {
21 | return SystemClock.elapsedRealtime()
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/kine-moshi/src/main/java/com/kine/converters/MoshiConverter.kt:
--------------------------------------------------------------------------------
1 | package com.kine.converters
2 |
3 | import com.kine.request.RequestFields
4 | import com.squareup.moshi.Moshi
5 |
6 |
7 | class MoshiConverter(private var moshi: Moshi = Moshi.Builder().build()) : Converter {
8 | override fun convert(response: Any, requestFields: RequestFields, clazz: Class): J? {
9 |
10 | return when (response) {
11 | is String -> {
12 | moshi.adapter(clazz).fromJson(response)
13 | }
14 | else -> {
15 | null
16 | }
17 | }
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/kine-gson/src/main/java/com/kine/converters/extensions/Gson.kt:
--------------------------------------------------------------------------------
1 | package com.kine.converters.extensions
2 |
3 | import com.google.gson.Gson
4 | import com.google.gson.reflect.TypeToken
5 | import java.lang.reflect.Type
6 | import java.util.ArrayList
7 |
8 | inline fun Gson.fromJsonArray(response: String):ArrayList{
9 | val listType = object : TypeToken?>() {}.type
10 | return this.fromJson(response, listType)
11 | }
12 | fun Gson.getArrayType(): Type {
13 | return object : TypeToken>() {}.type
14 | }
15 | fun J.getGsonArrayType(): Type {
16 | return object : TypeToken>() {}.type
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kine/test/model/CreateUserResponse.kt:
--------------------------------------------------------------------------------
1 | package com.kine.test.model
2 |
3 | import com.google.gson.annotations.Expose
4 | import com.google.gson.annotations.SerializedName
5 | import com.squareup.moshi.JsonClass
6 |
7 | @JsonClass(generateAdapter = true)
8 | class CreateUserResponse {
9 | @SerializedName("name")
10 | @Expose
11 | var name: String? = null
12 |
13 | @SerializedName("job")
14 | @Expose
15 | var job: String? = null
16 |
17 | @SerializedName("id")
18 | @Expose
19 | var id: String? = null
20 |
21 | @SerializedName("createdAt")
22 | @Expose
23 | var createdAt: String? = null
24 |
25 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/internal/KineClass.kt:
--------------------------------------------------------------------------------
1 | package com.kine.internal
2 |
3 |
4 | /**
5 | * Helper class for checking generic instance type .
6 | */
7 | open class KineClass(val clazz: Class) {
8 | companion object {
9 | inline operator fun invoke() =
10 | KineClass(T::class.java)
11 | }
12 |
13 | open fun isAssignableFrom(t: Any): Boolean {
14 | return isAssignableFrom(t.javaClass)
15 | }
16 | open fun isAssignableFrom(t: Class<*>): Boolean {
17 | return clazz.isAssignableFrom(t).apply {
18 | println(if (this) "Correct type" else "Wrong type")
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/kine-livedata/src/main/java/com/kine/android/LiveData.kt:
--------------------------------------------------------------------------------
1 | package com.kine.android
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import com.kine.KineRequest
5 |
6 |
7 | fun KineRequest.RequestOptionsBuilder.responseAs(clazz: Class, liveData:MutableLiveData) {
8 | return build().execute(clazz,onSuccess = { response->
9 | liveData.value = response.body
10 | },onError = {e->})
11 | }
12 |
13 | fun KineRequest.RequestOptionsBuilder.responseBackgroundAs(clazz: Class, liveData:MutableLiveData) {
14 | val response = build().execute(clazz)
15 | if(response?.body!=null) {
16 | liveData.postValue(response.body)
17 | }
18 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/executor/ExecutorSupplier.kt:
--------------------------------------------------------------------------------
1 | package com.kine.executor
2 |
3 | import java.util.concurrent.Executor
4 | import java.util.concurrent.ThreadPoolExecutor
5 |
6 | interface ExecutorSupplier {
7 | /*
8 | * returns the thread pool executor for networking task
9 | */
10 | fun forNetworkTasks(): ThreadPoolExecutor
11 |
12 | /*
13 | * returns the thread pool executor for light weight background task like parsing
14 | */
15 | fun forParsingTasks(): ThreadPoolExecutor
16 |
17 | /*
18 | * returns the thread pool executor for executing callback on (Main Thread in Android case)
19 | */
20 | fun forCallbackTasks(): Executor
21 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/RequestBody.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 |
4 | /**
5 | * This class is used to hold requestBody information associated with a single HTTP request.
6 | *
7 | */
8 | abstract class RequestBody(var mediaType: String = ContentType.JSON.toString()) {
9 |
10 |
11 | fun setContentType(mediaType: String = ContentType.JSON.toString()) {
12 | /* if(bodyParams!=null || encodedBodyParams!=null){
13 | throw IllegalArgumentException("Only one type of params is allowed either params String with contentType or hashMap")
14 | }*/
15 | this.mediaType = mediaType
16 | }
17 |
18 | /* abstract fun toRequestBody(): T*/
19 |
20 | }
--------------------------------------------------------------------------------
/kine-android/src/main/java/com/kine/android/executor/PriorityThreadFactory.kt:
--------------------------------------------------------------------------------
1 | package com.kine.android.executor
2 |
3 |
4 | import android.os.Process
5 | import android.util.Log
6 | import java.util.concurrent.ThreadFactory
7 |
8 | class PriorityThreadFactory(private val threadPriority: Int) : ThreadFactory {
9 | override fun newThread(runnable: Runnable): Thread {
10 | Log.e("called","android")
11 | val wrapperRunnable = Runnable {
12 | try {
13 | Process.setThreadPriority(threadPriority)
14 | } catch (t: Throwable) {
15 | }
16 | runnable.run()
17 | }
18 | return Thread(wrapperRunnable)
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kine/test/model/User.kt:
--------------------------------------------------------------------------------
1 | package com.kine.test.model
2 |
3 | import com.google.gson.annotations.Expose
4 | import com.google.gson.annotations.SerializedName
5 | import com.squareup.moshi.JsonClass
6 | @JsonClass(generateAdapter = true)
7 | class User {
8 | @SerializedName("id")
9 | @Expose
10 | var id: Int? = null
11 |
12 | @SerializedName("email")
13 | @Expose
14 | var email: String? = null
15 |
16 | @SerializedName("first_name")
17 | @Expose
18 | var firstName: String? = null
19 |
20 | @SerializedName("last_name")
21 | @Expose
22 | var lastName: String? = null
23 |
24 | @SerializedName("avatar")
25 | @Expose
26 | var avatar: String? = null
27 |
28 | }
--------------------------------------------------------------------------------
/kine-moshi/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java-library'
2 | apply plugin: 'kotlin'
3 | ext {
4 | PUBLISH_GROUP_ID = 'com.kine'
5 | PUBLISH_ARTIFACT_ID = 'kine-moshi'
6 | PUBLISH_VERSION = '1.9.3.0'
7 | }
8 | tasks.withType(Javadoc).all {
9 | enabled = false
10 | }
11 |
12 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/publish.gradle'
13 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/bintray.gradle'
14 |
15 | dependencies {
16 | implementation fileTree(dir: "libs", include: ["*.jar"])
17 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
18 | implementation("com.squareup.moshi:moshi:1.9.3")
19 | implementation project(':kine')
20 | }
--------------------------------------------------------------------------------
/kine-rxjava3/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java-library'
2 | apply plugin: 'kotlin'
3 | ext {
4 | PUBLISH_GROUP_ID = 'com.kine'
5 | PUBLISH_ARTIFACT_ID = 'kine-rxjava3'
6 | PUBLISH_VERSION = '3.0.6.0'
7 | }
8 | tasks.withType(Javadoc).all {
9 | enabled = false
10 | }
11 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/publish.gradle'
12 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/bintray.gradle'
13 |
14 | dependencies {
15 | implementation fileTree(dir: "libs", include: ["*.jar"])
16 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
17 | implementation 'io.reactivex.rxjava3:rxjava:3.0.6'
18 | implementation project(':kine')
19 | }
--------------------------------------------------------------------------------
/kine-rxjava2/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java-library'
2 | apply plugin: 'kotlin'
3 | ext {
4 | PUBLISH_GROUP_ID = 'com.kine'
5 | PUBLISH_ARTIFACT_ID = 'kine-rxjava2'
6 | PUBLISH_VERSION = '2.2.19.0'
7 | }
8 | tasks.withType(Javadoc).all {
9 | enabled = false
10 | }
11 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/publish.gradle'
12 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/bintray.gradle'
13 |
14 | dependencies {
15 | implementation fileTree(dir: "libs", include: ["*.jar"])
16 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
17 | implementation "io.reactivex.rxjava2:rxjava:2.2.19"
18 | implementation project(':kine')
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kine/test/model/UserListResponse.kt:
--------------------------------------------------------------------------------
1 | package com.kine.test.model
2 |
3 | import com.google.gson.annotations.Expose
4 | import com.google.gson.annotations.SerializedName
5 | import com.squareup.moshi.JsonClass
6 |
7 | @JsonClass(generateAdapter = true)
8 | class UserListResponse {
9 | @SerializedName("page")
10 | @Expose
11 | var page: Int? = null
12 |
13 | @SerializedName("per_page")
14 | @Expose
15 | var perPage: Int? = null
16 |
17 | @SerializedName("total")
18 | @Expose
19 | var total: Int? = null
20 |
21 | @SerializedName("total_pages")
22 | @Expose
23 | var totalPages: Int? = null
24 |
25 | @SerializedName("data")
26 | @Expose
27 | var users: List? = null
28 |
29 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
--------------------------------------------------------------------------------
/kine-android/src/main/java/com/kine/android/executor/MainThreadExecutor.kt:
--------------------------------------------------------------------------------
1 | package com.kine.android.executor
2 |
3 | import android.os.Build
4 | import android.os.Handler
5 | import android.os.Looper
6 | import java.util.concurrent.Executor
7 |
8 |
9 | class MainThreadExecutor : Executor {
10 | private val handler: Handler = Handler(Looper.getMainLooper())
11 | override fun execute(runnable: Runnable) {
12 | val isUiThread = if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
13 | Looper.getMainLooper().isCurrentThread
14 | else Thread.currentThread() == Looper.getMainLooper().thread
15 | if(isUiThread){
16 | runnable.run()
17 | }else {
18 | handler.post(runnable)
19 | }
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/kine-gson/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java-library'
2 | apply plugin: 'kotlin'
3 | apply plugin: 'kotlin-kapt'
4 | ext {
5 | PUBLISH_GROUP_ID = 'com.kine'
6 | PUBLISH_ARTIFACT_ID = 'kine-gson'
7 | PUBLISH_VERSION = '2.8.6.0'
8 | }
9 | tasks.withType(Javadoc).all {
10 | enabled = false
11 | }
12 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/publish.gradle'
13 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/bintray.gradle'
14 |
15 | dependencies {
16 | implementation fileTree(dir: "libs", include: ["*.jar"])
17 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
18 | implementation 'com.google.code.gson:gson:2.8.6'
19 | implementation project(':kine')
20 |
21 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/RequestFields.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 | import com.kine.cache.KineCacheControl
4 | import com.kine.client.KineClient
5 | import com.kine.converters.Converter
6 | import com.kine.policies.Priority
7 | import com.kine.policies.RetryPolicy
8 | import java.util.concurrent.Executor
9 |
10 |
11 | /**`
12 | * An RequestFields. This class is used to store all information associated with a single HTTP request.
13 | */
14 | open class RequestFields(val kineClient: KineClient?, val converter: Converter?,
15 | val dataFields: RequestDataFields, var priority: Priority, var retryPolicy: RetryPolicy?,
16 | val kineCacheControl: KineCacheControl, val logLevel: Int, var executor: Executor)
--------------------------------------------------------------------------------
/kine-android/src/main/java/com/kine/android/connections/Utils.kt:
--------------------------------------------------------------------------------
1 | package com.kine.android.connections
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.net.ConnectivityManager
6 |
7 | object Utils {
8 | /**
9 | * checks Network connectivity
10 | *
11 | * @param context the context to check
12 | * @return true/false
13 | */
14 | @Suppress("DEPRECATION")
15 | fun isConnected(context: Context?): Boolean {
16 | context ?: return true
17 | val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
18 | @SuppressLint("MissingPermission") val netInfo = cm.activeNetworkInfo
19 | return netInfo != null && netInfo.isConnected
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/kine-coroutine/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java-library'
2 | apply plugin: 'kotlin'
3 |
4 | ext {
5 | PUBLISH_GROUP_ID = 'com.kine'
6 | PUBLISH_ARTIFACT_ID = 'kine-coroutine'
7 | PUBLISH_VERSION = '1.3.8.0'
8 | }
9 | tasks.withType(Javadoc).all {
10 | enabled = false
11 | }
12 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/publish.gradle'
13 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/bintray.gradle'
14 |
15 |
16 | dependencies {
17 | implementation fileTree(dir: 'libs', include: ['*.jar'])
18 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
19 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8"
20 | implementation project(':kine')
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/log/JavaLog.kt:
--------------------------------------------------------------------------------
1 | package com.kine.log
2 |
3 | class JavaLog :Log{
4 | override fun e(tag: String?, message: String, exception: java.lang.Exception?) {
5 | println("$tag $message "+exception?.localizedMessage)
6 | }
7 |
8 | override fun v(tag: String?, message: String) {
9 | println("$tag $message")
10 | }
11 |
12 | override fun wtf(tag: String?, message: String) {
13 | println("$tag $message")
14 | }
15 |
16 | override fun d(tag: String?, message: String) {
17 | println("$tag $message")
18 | }
19 |
20 | override fun i(tag: String?, message: String) {
21 | println("$tag $message")
22 | }
23 |
24 | override fun w(tag: String?, message: String) {
25 | println("$tag $message")
26 | }
27 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/policies/Priority.kt:
--------------------------------------------------------------------------------
1 | package com.kine.policies
2 |
3 | /**
4 | * Priority levels
5 | */
6 | enum class Priority {
7 | /**
8 | * NOTE: DO NOT CHANGE ORDERING OF THOSE CONSTANTS UNDER ANY CIRCUMSTANCES.
9 | * Doing so will make ordering incorrect.
10 | */
11 | /**
12 | * Lowest priority level. Used for prefetches of data.
13 | */
14 | LOW,
15 |
16 | /**
17 | * Medium priority level. Used for warming of data that might soon get visible.
18 | */
19 | MEDIUM,
20 |
21 | /**
22 | * Highest priority level. Used for data that are currently visible on screen.
23 | */
24 | HIGH,
25 |
26 | /**
27 | * Highest priority level. Used for data that are required instantly(mainly for emergency).
28 | */
29 | IMMEDIATE
30 | }
--------------------------------------------------------------------------------
/kine-coroutine/src/main/java/com/kine/coroutine/Coroutine.kt:
--------------------------------------------------------------------------------
1 | package com.kine.coroutine
2 |
3 | import com.kine.KineRequest
4 | import com.kine.internal.DefaultKineClass
5 | import com.kine.response.KineResponse
6 | import kotlinx.coroutines.*
7 | import kotlin.coroutines.CoroutineContext
8 |
9 | suspend fun KineRequest.RequestOptionsBuilder.responseAsCoroutine(clazz: Class, scope: CoroutineContext = Dispatchers.IO): KineResponse? {
10 | return build().responseAsCoroutine(clazz, scope)
11 | }
12 |
13 | suspend fun KineRequest.responseAsCoroutine(
14 | clazz: Class,
15 | scope: CoroutineContext = Dispatchers.IO
16 | ): KineResponse? {
17 | val response: KineResponse?
18 | withContext(scope) {
19 | response = execute(DefaultKineClass(clazz))
20 | }
21 | return response
22 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/UploadRequestFields.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 | import com.kine.cache.KineCacheControl
4 | import com.kine.client.KineClient
5 | import com.kine.converters.Converter
6 | import com.kine.extensions.ProgressListener
7 | import com.kine.policies.Priority
8 | import com.kine.policies.RetryPolicy
9 | import java.util.concurrent.Executor
10 |
11 | class UploadRequestFields(val progressListener:ProgressListener?, kineClient: KineClient?, converter: Converter?,
12 | requestDataFields: RequestDataFields, priority: Priority, retryPolicy: RetryPolicy?,
13 | kineCacheControl: KineCacheControl, logLevel: Int, executor: Executor
14 | )
15 | :RequestFields(kineClient, converter, requestDataFields, priority, retryPolicy, kineCacheControl, logLevel,executor){
16 |
17 | }
--------------------------------------------------------------------------------
/kine-android/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/kine-android/src/main/java/com/kine/android/log/Log.kt:
--------------------------------------------------------------------------------
1 | package com.kine.android.log
2 |
3 | import android.util.Log
4 |
5 | class Log:com.kine.log.Log {
6 | override fun e(tag: String?, message: String, exception: java.lang.Exception?) {
7 | Log.e(tag, message, exception)
8 | }
9 |
10 | override fun v(tag: String?, message: String) {
11 | Log.v(tag, message)
12 |
13 | }
14 |
15 | override fun wtf(tag: String?, message: String) {
16 | Log.wtf(tag, message)
17 |
18 | }
19 |
20 | override fun d(tag: String?, message: String) {
21 | Log.d(tag, message)
22 |
23 | }
24 |
25 | override fun i(tag: String?, message: String) {
26 | Log.i(tag, message)
27 |
28 | }
29 |
30 | override fun w(tag: String?, message: String) {
31 | Log.w(tag, message)
32 |
33 | }
34 | }
--------------------------------------------------------------------------------
/kine-livedata/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/kine-rxjava2/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/kine-imageloader/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/kine-okhttp/src/main/java/com/kine/converters/OkioConverter.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNCHECKED_CAST")
2 |
3 | package com.kine.converters
4 |
5 | import com.kine.request.RequestFields
6 | import okio.BufferedSource
7 | import okio.ByteString
8 |
9 |
10 | class OkioConverter : RawResponseConverter() {
11 | override fun convert(response: Any, requestFields: RequestFields, clazz: Class): J? {
12 | return when {
13 | response is ByteString && clazz.isAssignableFrom(ByteString::class.java) -> {
14 | response as J
15 | }
16 | response is BufferedSource && clazz.isAssignableFrom(BufferedSource::class.java) -> {
17 | response as J
18 | }
19 | else -> {
20 | super.convert(response, requestFields, clazz)
21 | }
22 | }
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/kine-okhttplegacy/src/main/java/com/kine/converters/OkioConverter.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNCHECKED_CAST")
2 |
3 | package com.kine.converters
4 |
5 | import com.kine.request.RequestFields
6 | import okio.BufferedSource
7 | import okio.ByteString
8 |
9 |
10 | class OkioConverter : RawResponseConverter() {
11 | override fun convert(response: Any, requestFields: RequestFields, clazz: Class): J? {
12 | return when {
13 | response is ByteString && clazz.isAssignableFrom(ByteString::class.java) -> {
14 | response as J
15 | }
16 | response is BufferedSource && clazz.isAssignableFrom(BufferedSource::class.java) -> {
17 | response as J
18 | }
19 | else -> {
20 | super.convert(response, requestFields, clazz)
21 | }
22 | }
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/DownloadRequestFields.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 | import com.kine.cache.KineCacheControl
4 | import com.kine.client.KineClient
5 | import com.kine.converters.Converter
6 | import com.kine.extensions.ProgressListener
7 | import com.kine.policies.Priority
8 | import com.kine.policies.RetryPolicy
9 | import java.io.File
10 | import java.util.concurrent.Executor
11 |
12 | class DownloadRequestFields(val file: File, val progressListener:ProgressListener, kineClient: KineClient?,
13 | converter: Converter?, requestDataFields: RequestDataFields, priority: Priority, retryPolicy: RetryPolicy?,
14 | kineCacheControl: KineCacheControl, logLevel: Int, executor: Executor)
15 | :RequestFields(kineClient, converter, requestDataFields, priority, retryPolicy, kineCacheControl, logLevel,executor){
16 |
17 | }
--------------------------------------------------------------------------------
/kine-imageloader/src/main/java/com/kine/imageloader/converter/BitmapConverter.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNCHECKED_CAST")
2 |
3 | package com.kine.imageloader.converter
4 |
5 | import android.graphics.Bitmap
6 | import android.graphics.BitmapFactory
7 | import com.kine.converters.Converter
8 | import com.kine.request.RequestFields
9 |
10 | class BitmapConverter :Converter{
11 | override fun convert(response: Any, requestFields: RequestFields, clazz: Class): J? {
12 | if(clazz.isAssignableFrom(Bitmap::class.java)){
13 | return when (response) {
14 | is ByteArray -> {
15 | BitmapFactory.decodeByteArray(response, 0, response.size) as J
16 | }
17 | else -> {
18 | null
19 | }
20 | }
21 | }
22 | return null
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/log/Log.kt:
--------------------------------------------------------------------------------
1 | package com.kine.log
2 |
3 | interface Log {
4 | fun e(tag: String?, message: String, exception: java.lang.Exception? = null) {
5 | if(exception!=null) {
6 | exception.printStackTrace()
7 | println("$tag $message " + exception.localizedMessage)
8 | }else{
9 | println("$tag $message ")
10 | }
11 | }
12 |
13 | fun v(tag: String?, message: String) {
14 | println("$tag $message")
15 | }
16 |
17 | fun wtf(tag: String?, message: String) {
18 | println("$tag $message")
19 | }
20 |
21 | fun d(tag: String?, message: String) {
22 | println("$tag $message")
23 | }
24 |
25 | fun i(tag: String?, message: String) {
26 | println("$tag $message")
27 | }
28 |
29 | fun w(tag: String?, message: String) {
30 | println("$tag $message")
31 | }
32 | }
--------------------------------------------------------------------------------
/kine-imageloader/src/main/java/com/kine/imageloader/policies/MemoryPolicy.kt:
--------------------------------------------------------------------------------
1 | package com.kine.imageloader.policies
2 |
3 | /** Designates the policy to use when dealing with memory cache. */
4 | enum class MemoryPolicy(val index: Int) {
5 | /** Skips memory cache lookup when processing a request. */
6 | CACHE(1 shl 0),
7 |
8 | /**
9 | * Skips storing the final result into memory cache. Useful for one-off requests
10 | * to avoid evicting other bitmaps from the cache.
11 | */
12 | STORE(1 shl 1);
13 |
14 | companion object {
15 | @JvmStatic
16 | fun shouldReadFromMemoryCache(memoryPolicy: Int): Boolean {
17 | return memoryPolicy and CACHE.index != 0
18 | }
19 |
20 | @JvmStatic
21 | fun shouldWriteToMemoryCache(memoryPolicy: Int): Boolean {
22 | return memoryPolicy and STORE.index != 0
23 | }
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/kine-okhttp/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java-library'
2 | apply plugin: 'kotlin'
3 | ext {
4 | PUBLISH_GROUP_ID = 'com.kine'
5 | PUBLISH_ARTIFACT_ID = 'kine-okhttp'
6 | PUBLISH_VERSION = '4.8.1.0'
7 | }
8 | tasks.withType(Javadoc).all {
9 | enabled = false
10 | }
11 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/publish.gradle'
12 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/bintray.gradle'
13 | dependencies {
14 | implementation fileTree(dir: "libs", include: ["*.jar"])
15 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
16 | implementation project(':kine')
17 | implementation("com.squareup.okhttp3:okhttp:4.9.0")
18 | implementation("com.squareup.okio:okio:2.8.0")
19 | testImplementation("com.squareup.okhttp3:mockwebserver:4.8.1")
20 | testImplementation 'junit:junit:4.13'
21 |
22 | }
--------------------------------------------------------------------------------
/kine-okhttplegacy/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java-library'
2 | apply plugin: 'kotlin'
3 | ext {
4 | PUBLISH_GROUP_ID = 'com.kine'
5 | PUBLISH_ARTIFACT_ID = 'kine-okhttplegacy'
6 | PUBLISH_VERSION = '3.12.12.0'
7 | }
8 | tasks.withType(Javadoc).all {
9 | enabled = false
10 | }
11 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/publish.gradle'
12 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/bintray.gradle'
13 | dependencies {
14 | implementation fileTree(dir: "libs", include: ["*.jar"])
15 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
16 | implementation("com.squareup.okhttp3:okhttp:3.12.12")
17 | implementation("com.squareup.okio:okio:1.17.5")
18 | implementation project(':kine')
19 |
20 | testImplementation("com.squareup.okhttp3:mockwebserver:3.12.12")
21 | testImplementation 'junit:junit:4.13'
22 | }
--------------------------------------------------------------------------------
/kine-json/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java-library'
2 | apply plugin: 'kotlin'
3 | ext {
4 | PUBLISH_GROUP_ID = 'com.kine'
5 | PUBLISH_ARTIFACT_ID = 'kine-json'
6 | PUBLISH_VERSION = '1.0.0.0'
7 | }
8 | tasks.withType(Javadoc).all {
9 | enabled = false
10 | }
11 |
12 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/publish.gradle'
13 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/bintray.gradle'
14 |
15 | dependencies {
16 | implementation fileTree(dir: "libs", include: ["*.jar"])
17 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
18 | implementation 'org.json:json:20200518'
19 | implementation project(':kine')
20 | testImplementation("com.squareup.okhttp3:mockwebserver:4.8.1")
21 | testImplementation 'junit:junit:4.13'
22 | testImplementation 'org.json:json:20200518'
23 | testImplementation project(':kine-okhttp')
24 | }
25 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/policies/RetryPolicy.kt:
--------------------------------------------------------------------------------
1 | package com.kine.policies
2 |
3 | /**
4 | * Retry policy for a request.
5 | */
6 | interface RetryPolicy {
7 |
8 |
9 | /**
10 | * Returns the current timeout (used for logging).
11 | */
12 | fun getCurrentTimeout(): Int
13 |
14 | /**
15 | * Returns the total retry count (used for logging).
16 | */
17 | fun getRetryCount(): Int
18 |
19 | /**
20 | * Returns the total retry count (used for logging).
21 | */
22 | fun setCurrentTimeout(timeOut: Int)
23 |
24 | /**
25 | * Returns the backoff multiplier for the policy.
26 | */
27 | fun getBackoffMultiplier(): Float
28 |
29 | fun isSame(retryPolicy: RetryPolicy): Boolean {
30 | return (getCurrentTimeout() == retryPolicy.getCurrentTimeout() && getRetryCount() == retryPolicy.getRetryCount() &&
31 | getBackoffMultiplier() == retryPolicy.getBackoffMultiplier())
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/response/KineError.kt:
--------------------------------------------------------------------------------
1 | package com.kine.response
2 |
3 | import com.kine.exceptions.NoInternetException
4 | import com.kine.exceptions.NullResponseBodyException
5 | import com.kine.exceptions.NullResponseException
6 | import com.kine.exceptions.ParseException
7 |
8 | class KineError(val exception:Throwable) {
9 | fun printStackTrace() {
10 | exception.printStackTrace()
11 | }
12 |
13 | fun message(): String? {
14 | return exception.localizedMessage?:exception.message
15 | }
16 | fun isNoInternetError(): Boolean {
17 | return exception is NoInternetException
18 | }
19 | fun isNullResponseError(): Boolean {
20 | return exception is NullResponseException
21 | }
22 | fun isNullResponseBodyError(): Boolean {
23 | return exception is NullResponseBodyException
24 | }
25 | fun isParsingError(): Boolean {
26 | return exception is ParseException
27 | }
28 | fun isHttpStatusCodeError(): Boolean {
29 | return exception is Exception
30 | }
31 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/converters/RawResponseConverter.kt:
--------------------------------------------------------------------------------
1 | package com.kine.converters
2 |
3 | import com.kine.request.RequestFields
4 | import java.io.InputStream
5 | import java.io.Reader
6 |
7 | open class RawResponseConverter:Converter {
8 | @Suppress("UNCHECKED_CAST")
9 | override fun convert(response: Any, requestFields: RequestFields, clazz: Class): J? {
10 | return when {
11 | response is String && clazz.isAssignableFrom(String::class.java) -> {
12 | response as J
13 | }
14 | response is ByteArray && clazz.isAssignableFrom(ByteArray::class.java) -> {
15 | response as J
16 | }
17 | response is InputStream && clazz.isAssignableFrom(InputStream::class.java) -> {
18 | response as J
19 | }
20 | response is Reader && clazz.isAssignableFrom(Reader::class.java) -> {
21 | response as J
22 | }
23 | else -> {
24 | null
25 | }
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/kine-json/src/main/java/com/kine/converters/JsonConverter.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNCHECKED_CAST")
2 |
3 | package com.kine.converters
4 |
5 | import com.kine.request.RequestFields
6 | import org.json.JSONArray
7 | import org.json.JSONObject
8 |
9 |
10 | class JsonConverter : RawResponseConverter() {
11 | override fun convert(response: Any, requestFields: RequestFields, clazz: Class): J? {
12 | if (response is String) {
13 | return when {
14 | clazz.isAssignableFrom(String::class.java) -> {
15 | response as J
16 | }
17 | clazz.isAssignableFrom(JSONObject::class.java) -> {
18 | JSONObject(response) as J
19 | }
20 | clazz.isAssignableFrom(JSONArray::class.java) -> {
21 | JSONArray(response) as J
22 | }
23 | else -> {
24 | null
25 | }
26 | }
27 | } else {
28 | return super.convert(response, requestFields, clazz)
29 | }
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/kine-android/src/main/java/com/kine/android/converters/JsonConverter.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNCHECKED_CAST")
2 |
3 | package com.kine.android.converters
4 |
5 | import com.kine.converters.RawResponseConverter
6 | import com.kine.request.RequestFields
7 | import org.json.JSONArray
8 | import org.json.JSONObject
9 |
10 |
11 | class JsonConverter : RawResponseConverter() {
12 | override fun convert(response: Any, requestFields: RequestFields, clazz: Class): J? {
13 | if (response is String) {
14 | return when {
15 | clazz.isAssignableFrom(String::class.java) -> {
16 | response as J
17 | }
18 | clazz.isAssignableFrom(JSONObject::class.java) -> {
19 | JSONObject(response) as J
20 | }
21 | clazz.isAssignableFrom(JSONArray::class.java) -> {
22 | JSONArray(response) as J
23 | }
24 | else -> {
25 | null
26 | }
27 | }
28 | } else {
29 | return super.convert(response, requestFields, clazz)
30 | }
31 | }
32 |
33 | }
--------------------------------------------------------------------------------
/.github/workflows/main_release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v*'
7 |
8 | jobs:
9 |
10 | release:
11 | name: Create Release
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - name: Checkout code
16 | uses: actions/checkout@v2
17 |
18 | - name: Set release name
19 | run: echo ::set-env name=RELEASE_NAME::$(echo ${GITHUB_REF:11})
20 |
21 | - name: Create release
22 | id: create_release
23 | uses: actions/create-release@v1
24 | env:
25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26 | with:
27 | tag_name: ${{ github.ref }}
28 | release_name: ${{ env.RELEASE_NAME }}
29 | draft: false
30 | prerelease: false
31 |
32 | publish:
33 | name: Publish Build
34 | runs-on: ubuntu-latest
35 |
36 | steps:
37 | - name: Checkout code
38 | uses: actions/checkout@v2
39 |
40 | - name: Configure JDK
41 | uses: actions/setup-java@v1
42 | with:
43 | java-version: 1.8
44 |
45 | - name: Publish library
46 | env:
47 | bintrayUser: ${{ secrets.BINTRAYUSERNAME }}
48 | bintrayApiKey: ${{ secrets.BINTRAYAPIKEY }}
49 | run: gradle install bintrayUpload
50 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/EncodedRequestBody.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 | import java.util.*
4 |
5 | class EncodedRequestBody(var bodyParams: HashMap = hashMapOf(), var encodedBodyParams: HashMap = hashMapOf())
6 | :RequestBody(ContentType.ENCODED.toString()) {
7 |
8 |
9 | fun setBody(bodyParams: HashMap? = null) {
10 |
11 | this.mediaType = ContentType.ENCODED.toString()
12 | this.bodyParams = bodyParams?: hashMapOf()
13 | }
14 | fun setBodyEncoded(encodedBodyParams: HashMap? = null) {
15 |
16 | this.mediaType = ContentType.ENCODED.toString()
17 | this.encodedBodyParams = encodedBodyParams?: hashMapOf()
18 | }
19 | fun setBody(bodyParams: HashMap? = null,
20 | encodedBodyParams: HashMap? = null) {
21 |
22 | this.mediaType = ContentType.ENCODED.toString()
23 | this.bodyParams = bodyParams?: hashMapOf()
24 | this.encodedBodyParams = encodedBodyParams?: hashMapOf()
25 | }
26 |
27 | fun addBodyParam(key: String, value: String) {
28 | bodyParams[key] = value
29 | }
30 | fun addBodyParamEncoded(key: String, value: String) {
31 | encodedBodyParams[key] = value
32 | }
33 | }
--------------------------------------------------------------------------------
/kine-rxjava2/src/main/java/com/kine/rxnetworking/RxJava2.kt:
--------------------------------------------------------------------------------
1 | package com.kine.rxnetworking
2 |
3 | import com.kine.KineRequest
4 | import com.kine.internal.DefaultKineClass
5 | import com.kine.response.KineResponse
6 | import io.reactivex.Flowable
7 | import io.reactivex.Observable
8 | import io.reactivex.Single
9 |
10 |
11 | fun KineRequest.RequestOptionsBuilder.toSingle(callback:Class): Single?> {
12 | return build().toSingle(callback)
13 | }
14 | fun KineRequest.toSingle(callback:Class): Single?> {
15 | return Single.fromCallable {
16 | this.execute(DefaultKineClass(callback))
17 | }
18 | }
19 | fun KineRequest.RequestOptionsBuilder.toFlowable(callback:Class): Flowable?> {
20 | return build().toFlowable(callback)
21 | }
22 | fun KineRequest.toFlowable(callback:Class): Flowable?> {
23 | return Flowable.fromCallable {
24 | this.execute(DefaultKineClass(callback))
25 | }
26 | }
27 | fun KineRequest.RequestOptionsBuilder.toObservable(callback:Class): Observable?> {
28 | return build().toObservable(callback)
29 | }
30 | fun KineRequest.toObservable(callback:Class): Observable?> {
31 | return Observable.fromCallable {
32 | this.execute(DefaultKineClass(callback))
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/log/LogLevel.kt:
--------------------------------------------------------------------------------
1 | package com.kine.log
2 | /**
3 | * This class is used to filter responses for logging.
4 | */
5 | object LogLevel {
6 | const val NO_LEVEL = -2
7 | const val NO_LOGS = -1
8 | const val INFO = 0
9 | const val VERBOSE = 1
10 | const val DEBUG = 2
11 | const val WARNING = 3
12 | const val ERROR = 4
13 | fun isVerbose(logLevel: Int, localLevel: Int): Boolean {
14 | return if (localLevel == NO_LEVEL) {
15 | logLevel >= VERBOSE
16 | } else localLevel >= VERBOSE
17 | }
18 |
19 | fun isInfo(logLevel: Int, localLevel: Int): Boolean {
20 | return if (localLevel == NO_LEVEL) {
21 | logLevel >= INFO
22 | } else localLevel >= INFO
23 | }
24 |
25 | fun isDebug(logLevel: Int, localLevel: Int): Boolean {
26 | return if (localLevel == NO_LEVEL) {
27 | logLevel >= DEBUG
28 | } else localLevel >= DEBUG
29 | }
30 |
31 | fun isWarning(logLevel: Int, localLevel: Int): Boolean {
32 | return if (localLevel == NO_LEVEL) {
33 | logLevel >= WARNING
34 | } else localLevel >= WARNING
35 | }
36 |
37 | fun isError(logLevel: Int, localLevel: Int): Boolean {
38 | return if (localLevel == NO_LEVEL) {
39 | logLevel >= ERROR
40 | } else localLevel >= ERROR
41 | }
42 | }
--------------------------------------------------------------------------------
/kine-livedata/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 | ext {
5 | PUBLISH_GROUP_ID = 'com.kine'
6 | PUBLISH_ARTIFACT_ID = 'kine-livedata'
7 | PUBLISH_VERSION = '2.2.0.0'
8 | }
9 | android {
10 | compileSdkVersion 30
11 | buildToolsVersion "29.0.3"
12 |
13 | defaultConfig {
14 | minSdkVersion 16
15 | versionCode 1
16 | versionName "1.0"
17 |
18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
19 | consumerProguardFiles "consumer-rules.pro"
20 | }
21 |
22 | buildTypes {
23 | release {
24 | minifyEnabled false
25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
26 | }
27 | }
28 | tasks.withType(Javadoc).all {
29 | enabled = false
30 | }
31 | }
32 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/publish.gradle'
33 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/bintray.gradle'
34 | dependencies {
35 | implementation fileTree(dir: "libs", include: ["*.jar"])
36 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
37 | implementation project(':kine')
38 | implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
39 |
40 | }
--------------------------------------------------------------------------------
/kine-rxjava3/src/main/java/com/kine/rxjava3/RxJava3.kt:
--------------------------------------------------------------------------------
1 | package com.kine.rxjava3
2 |
3 | import com.kine.KineRequest
4 | import com.kine.internal.DefaultKineClass
5 | import com.kine.response.KineResponse
6 | import io.reactivex.rxjava3.core.Flowable
7 | import io.reactivex.rxjava3.core.Observable
8 | import io.reactivex.rxjava3.core.Single
9 |
10 | fun KineRequest.RequestOptionsBuilder.toSingle(callback:Class): Single?> {
11 | return build().toSingle(callback)
12 | }
13 | fun KineRequest.toSingle(callback:Class): Single?> {
14 | return Single.fromCallable {
15 | this.execute(DefaultKineClass(callback))
16 | }
17 | }
18 | fun KineRequest.RequestOptionsBuilder.toFlowable(callback:Class): Flowable?> {
19 | return build().toFlowable(callback)
20 | }
21 | fun KineRequest.toFlowable(callback:Class): Flowable?> {
22 | return Flowable.fromCallable {
23 | this.execute(DefaultKineClass(callback))
24 | }
25 | }
26 | fun KineRequest.RequestOptionsBuilder.toObservable(callback:Class): Observable?> {
27 | return build().toObservable(callback)
28 | }
29 | fun KineRequest.toObservable(callback:Class): Observable?> {
30 | return Observable.fromCallable {
31 | this.execute(DefaultKineClass(callback))
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/kine-imageloader/src/main/java/com/kine/imageloader/cache/MemoryCache.kt:
--------------------------------------------------------------------------------
1 | package com.kine.imageloader.cache
2 |
3 | import android.graphics.Bitmap
4 | import java.util.*
5 |
6 | /** caching class
7 | */
8 | class MemoryCache {
9 | private var maxSize = DEFAULT_CACHE_SIZE
10 | private var entries: HashMap = HashMap()
11 |
12 | fun get(key: String): Bitmap? {
13 | if (entries.containsKey(key)) {
14 | return entries[key]
15 | }
16 | return null
17 | }
18 |
19 | fun put(key: String, cacheEntry: Bitmap) {
20 |
21 | synchronized(entries) { entries.put(key, cacheEntry) }
22 | }
23 |
24 |
25 | fun remove(key: String) {
26 | synchronized(entries) {
27 | if (entries.containsKey(key)) {
28 | entries.remove(key)
29 | }
30 | }
31 | }
32 |
33 | fun clear() {
34 | entries.clear()
35 | }
36 |
37 | private val currentSize: Int
38 | get() {
39 | return entries.size
40 | }
41 |
42 | companion object {
43 | private val TAG = MemoryCache::class.java.name
44 |
45 | /*
46 | * Get max available VM memory, exceeding this amount will throw an OutOfMemory exception.
47 | * and use 1/30th of the available memory for this memory cache.
48 | */
49 | val DEFAULT_CACHE_SIZE = (Runtime.getRuntime().maxMemory() / 30).toInt()
50 | }
51 |
52 | }
--------------------------------------------------------------------------------
/kine-imageloader/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 | ext {
5 | PUBLISH_GROUP_ID = 'com.kine'
6 | PUBLISH_ARTIFACT_ID = 'kine-imageloader'
7 | PUBLISH_VERSION = '1.0.0.0'
8 | }
9 | android {
10 | compileSdkVersion 29
11 | buildToolsVersion "29.0.3"
12 |
13 | defaultConfig {
14 | minSdkVersion 16
15 | targetSdkVersion 29
16 | versionCode 1
17 | versionName "1.0"
18 |
19 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
20 | consumerProguardFiles "consumer-rules.pro"
21 | }
22 |
23 | buildTypes {
24 | release {
25 | minifyEnabled false
26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
27 | }
28 | }
29 | tasks.withType(Javadoc).all {
30 | enabled = false
31 | }
32 | }
33 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/publish.gradle'
34 | apply from: 'https://raw.githubusercontent.com/AnkitAgrawal967/Kine/master/bintray.gradle'
35 |
36 | dependencies {
37 | implementation fileTree(dir: "libs", include: ["*.jar"])
38 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
39 | implementation 'androidx.core:core-ktx:1.3.2'
40 | implementation project(':kine')
41 | implementation project(':kine-android')
42 | }
--------------------------------------------------------------------------------
/bintray.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.jfrog.bintray'
2 |
3 | if (project.hasProperty("android")) {
4 | apply plugin: 'com.github.dcendents.android-maven'
5 | }
6 |
7 | group = publishedGroupId
8 | def bintrayUser = ''
9 | def bintrayApiKey = ''
10 | def bintrayPassword = ''
11 | // Bintray
12 | if (project.rootProject.file('local.properties').exists()) {
13 | Properties properties = new Properties()
14 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
15 | bintrayUser = properties.getProperty("bintray.user")
16 | bintrayApiKey = properties.getProperty("bintray.apikey")
17 | bintrayPassword = properties.getProperty("bintray.gpg.password")
18 | } else {
19 | bintrayUser = System.getenv("bintrayUser")
20 | bintrayApiKey = System.getenv("bintrayApiKey")
21 | bintrayPassword = System.getenv("bintrayApiKey")
22 | }
23 |
24 | bintray {
25 | user = bintrayUser
26 | key = bintrayApiKey
27 | publications = ['MyPublication']
28 | configurations = ['archives']
29 | pkg {
30 | repo = bintrayRepo
31 | name = bintrayName
32 | desc = libraryDescription
33 | websiteUrl = siteUrl
34 | vcsUrl = gitUrl
35 | licenses = allLicenses
36 | publish = true
37 | publicDownloadNumbers = true
38 | version {
39 | desc = libraryDescription
40 | gpg {
41 | sign = true //Determines whether to GPG sign the files. The default is false
42 | passphrase = bintrayPassword
43 | //Optional. The passphrase for GPG signing'
44 | }
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/kine-android/src/main/java/com/kine/android/cache/Cache.kt:
--------------------------------------------------------------------------------
1 | package com.kine.android.cache
2 |
3 | import com.kine.response.KineResponse
4 |
5 | /**
6 | * interface for caching response.
7 | */
8 | interface Cache {
9 | operator fun get(key: String): CacheEntry?
10 | fun remove(key: String)
11 | fun clear()
12 | fun put(key: String, cacheEntry: CacheEntry?)
13 |
14 | class CacheEntry(kineResponse: KineResponse, cacheTime: Long, reqTAG: String, timeStampMillis: Long) {
15 |
16 | val cacheDuration: Long
17 |
18 | val url: String
19 |
20 | val timeStampMillis: Long
21 |
22 | /**
23 | * data from this kineResponse.
24 | */
25 | val data: String?
26 |
27 | /**
28 | * The HTTP status code.
29 | */
30 | @JvmField
31 | val statusCode: Int
32 |
33 | /**
34 | * KineResponse headers.
35 | */
36 | val headers: Map
37 |
38 | /**
39 | * Network roundtrip time in milliseconds.
40 | */
41 | @JvmField
42 | val networkTimeMs: Long
43 |
44 | /**
45 | * Network roundtrip time in milliseconds.
46 | */
47 | val loadedFrom: Int
48 |
49 | init {
50 | data = kineResponse.body
51 | headers = kineResponse.headers
52 | networkTimeMs = kineResponse.networkTimeMs
53 | loadedFrom = kineResponse.loadedFrom
54 | statusCode = kineResponse.statusCode
55 | cacheDuration = cacheTime
56 | url = reqTAG
57 | this.timeStampMillis = timeStampMillis
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/kine-okhttp/src/main/java/com/kine/client/FileProgressRequestBody.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 |
4 | import com.kine.extensions.ProgressListener
5 | import okhttp3.MediaType
6 | import okhttp3.RequestBody
7 | import okio.*
8 | import java.io.IOException
9 |
10 | internal class FileProgressRequestBody(
11 | private val requestBody: RequestBody,
12 | private val progressListener: ProgressListener?
13 | ) : RequestBody() {
14 |
15 | override fun contentType(): MediaType? {
16 | return requestBody.contentType()
17 | }
18 |
19 | @Throws(IOException::class)
20 | override fun contentLength(): Long {
21 | return requestBody.contentLength()
22 | }
23 |
24 | @Throws(IOException::class)
25 | override fun writeTo(sink: BufferedSink) {
26 | if (progressListener == null) {
27 | requestBody.writeTo(sink)
28 | return
29 | }
30 | val progressSink = wrapSink(sink).buffer()
31 | requestBody.writeTo(progressSink)
32 | progressSink.flush()
33 | }
34 |
35 | private fun wrapSink(sink: Sink): Sink {
36 | return object : ForwardingSink(sink) {
37 | var bytesWritten = 0L
38 | var contentLength = 0L
39 |
40 | @Throws(IOException::class)
41 | override fun write(source: Buffer, byteCount: Long) {
42 | super.write(source, byteCount)
43 | if (contentLength == 0L) {
44 | contentLength = contentLength()
45 | }
46 | bytesWritten += byteCount
47 | progressListener?.invoke(bytesWritten, contentLength)
48 |
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/kine-okhttplegacy/src/main/java/com/kine/client/FileProgressRequestBody.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 |
4 | import com.kine.extensions.ProgressListener
5 | import okhttp3.MediaType
6 | import okhttp3.RequestBody
7 | import okio.*
8 | import java.io.IOException
9 |
10 | internal class FileProgressRequestBody(
11 | private val requestBody: RequestBody,
12 | private val progressListener: ProgressListener?
13 | ) : RequestBody() {
14 |
15 | override fun contentType(): MediaType? {
16 | return requestBody.contentType()
17 | }
18 |
19 | @Throws(IOException::class)
20 | override fun contentLength(): Long {
21 | return requestBody.contentLength()
22 | }
23 |
24 | @Throws(IOException::class)
25 | override fun writeTo(sink: BufferedSink) {
26 | if (progressListener == null) {
27 | requestBody.writeTo(sink)
28 | return
29 | }
30 | val progressSink = Okio.buffer(wrapSink(sink))
31 | requestBody.writeTo(progressSink)
32 | progressSink.flush()
33 | }
34 |
35 | private fun wrapSink(sink: Sink): Sink {
36 | return object : ForwardingSink(sink) {
37 | var bytesWritten = 0L
38 | var contentLength = 0L
39 |
40 | @Throws(IOException::class)
41 | override fun write(source: Buffer, byteCount: Long) {
42 | super.write(source, byteCount)
43 | if (contentLength == 0L) {
44 | contentLength = contentLength()
45 | }
46 | bytesWritten += byteCount
47 | progressListener?.invoke(bytesWritten, contentLength)
48 |
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/executor/PriorityThreadPoolExecutor.kt:
--------------------------------------------------------------------------------
1 | package com.kine.executor
2 |
3 | import com.kine.policies.Priority
4 | import java.util.concurrent.*
5 |
6 |
7 | class PriorityThreadPoolExecutor(
8 | corePoolSize: Int, maximumPoolSize: Int, keepAliveTime: Long,
9 | unit: TimeUnit?, threadFactory: ThreadFactory?
10 | ) :
11 | ThreadPoolExecutor(
12 | corePoolSize,
13 | maximumPoolSize,
14 | keepAliveTime,
15 | unit,
16 | PriorityBlockingQueue(),
17 | threadFactory
18 | ) {
19 | override fun submit(task: Runnable): Future<*> {
20 | val futureTask = PriorityFutureTask(task as PriorityRunnable)
21 | execute(futureTask)
22 | return futureTask
23 | }
24 |
25 | private class PriorityFutureTask(private val priorityRunnable: PriorityRunnable) :
26 | FutureTask(priorityRunnable, null),
27 | Comparable {
28 |
29 | /*
30 | * compareTo() method is defined in interface java.lang.Comparable and it is used
31 | * to implement natural sorting on java classes. natural sorting means the the sort
32 | * order which naturally applies on object e.g. lexical order for String, numeric
33 | * order for Integer or Sorting employee by there ID etc. most of the java core
34 | * classes including String and Integer implements CompareTo() method and provide
35 | * natural sorting.
36 | */
37 | override operator fun compareTo(other: PriorityFutureTask): Int {
38 | val p1: Priority = priorityRunnable.getPriority()
39 | val p2: Priority = other.priorityRunnable.getPriority()
40 | return p2.ordinal - p1.ordinal
41 | }
42 |
43 | }
44 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
22 |
23 | libraryVersion=1.0.0.0
24 | libraryName=Kine
25 | libraryDescription=A simple and powerful HTTP networking lib for kotlin/Android.
26 | publishedGroupId=com.kine
27 | artifact=Kine
28 | bintrayRepo=Kine
29 | bintrayName=kine
30 | siteUrl=https://github.com/AnkitAgrawal967/Kine
31 | gitUrl=https://github.com/AnkitAgrawal967/Kine.git
32 | developerId=AnkitAgrawal967
33 | developerName=Ankit Agrawal
34 | developerEmail=xyz@mail.com
35 | licenseName=The Apache Software License, Version 2.0
36 | licenseUrl=http://www.apache.org/licenses/LICENSE-2.0.txt
37 | allLicenses=["Apache-2.0"]
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 | apply plugin: 'kotlin-kapt'
5 |
6 | android {
7 | compileSdkVersion 29
8 | buildToolsVersion "29.0.3"
9 |
10 | defaultConfig {
11 | applicationId "com.kine.test"
12 | minSdkVersion 16
13 | targetSdkVersion 22
14 | versionCode 1
15 | versionName "1.0"
16 |
17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
18 | }
19 |
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
24 | }
25 | }
26 | }
27 |
28 | dependencies {
29 | implementation fileTree(dir: "libs", include: ["*.jar"])
30 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
31 | implementation 'androidx.core:core-ktx:1.3.2'
32 | implementation 'androidx.appcompat:appcompat:1.2.0'
33 | implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
34 | implementation project(':kine')
35 | implementation project(':kine-android')
36 | implementation project(':kine-okhttp')
37 | implementation project(':kine-moshi')
38 | implementation project(':kine-gson')
39 | implementation project(':kine-imageloader')
40 | implementation project(':kine-rxjava2')
41 | implementation project(':kine-coroutine')
42 | kapt("com.squareup.moshi:moshi-kotlin-codegen:1.9.3")
43 | implementation 'com.google.code.gson:gson:2.8.6'
44 | implementation("com.squareup.moshi:moshi:1.9.3")
45 | implementation 'com.squareup.picasso:picasso:2.71828'
46 | implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
47 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8"
48 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8"
49 |
50 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/response/KineResponse.kt:
--------------------------------------------------------------------------------
1 | package com.kine.response
2 |
3 | import java.util.*
4 |
5 | /**
6 | * This class is used to store the response from the server.
7 | */
8 | class KineResponse {
9 | /** data from this response. */
10 | @JvmField
11 | val body: T?
12 |
13 | /** The HTTP status code. */
14 | @JvmField
15 | val statusCode: Int
16 |
17 | /** KineResponse headers. */
18 | @JvmField
19 | val headers: Map
20 |
21 | /** Network roundtrip time in milliseconds. */
22 | @JvmField
23 | val networkTimeMs: Long
24 |
25 | /** source from which response is loaded from. */
26 | @JvmField
27 | val loadedFrom: Int
28 |
29 | /** Parse time in milliseconds. */
30 | @JvmField
31 | var parseTime: Long
32 |
33 | constructor(
34 | response: T,
35 | headers: Map,
36 | statusCode: Int,
37 | networkTimeMs: Long,
38 | loadedFrom: Int
39 | ) {
40 | this.body = response
41 | this.headers = headers
42 | this.statusCode = statusCode
43 | this.networkTimeMs = networkTimeMs
44 | this.loadedFrom = loadedFrom
45 | parseTime = 0
46 | }
47 |
48 | constructor(response: T, loadedFrom: Int) {
49 | this.body = response
50 | headers = HashMap()
51 | statusCode = 200
52 | networkTimeMs = 0
53 | this.loadedFrom = loadedFrom
54 | parseTime = 0
55 | }
56 |
57 | constructor(loadedFrom: Int) {
58 | body = null
59 | headers = HashMap()
60 | statusCode = 200
61 | networkTimeMs = 0
62 | this.loadedFrom = loadedFrom
63 | parseTime = 0
64 | }
65 | fun map(t:T):KineResponse{
66 | return KineResponse(t,headers,statusCode,networkTimeMs,loadedFrom).apply { parseTime = this@KineResponse.parseTime }
67 | }
68 | object LoadedFrom {
69 | const val DISK = 1
70 | const val NETWORK = 2
71 | }
72 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/policies/DefaultRetryPolicy.kt:
--------------------------------------------------------------------------------
1 | package com.kine.policies
2 |
3 | /**
4 | * Default retry policy for requests.
5 | */
6 | class DefaultRetryPolicy
7 | /**
8 | * Constructs a new retry policy using the default timeouts.
9 | */ @JvmOverloads constructor(
10 | /** The current timeout in milliseconds. */
11 | private var mCurrentTimeoutMs: Int = DEFAULT_TIMEOUT_MS,
12 | /** The maximum number of attempts. */
13 | private val mMaxNumRetries: Int = DEFAULT_MAX_RETRIES,
14 | /** The backoff multiplier for the policy. */
15 | private val mBackoffMultiplier: Float = DEFAULT_BACKOFF_MULT
16 | ) : RetryPolicy {
17 |
18 | /**
19 | * Returns the current timeout.
20 | */
21 | override fun getCurrentTimeout(): Int {
22 | return mCurrentTimeoutMs
23 | }
24 |
25 | /**
26 | * Returns the current retry count.
27 | */
28 | override fun getRetryCount(): Int {
29 | return mMaxNumRetries
30 | }
31 |
32 | /**
33 | * Returns the total retry count (used for logging).
34 | *
35 | * @param timeOut
36 | */
37 | override fun setCurrentTimeout(timeOut: Int) {
38 | mCurrentTimeoutMs = timeOut
39 | }
40 |
41 | /**
42 | * Returns the backoff multiplier for the policy.
43 | */
44 | override fun getBackoffMultiplier(): Float {
45 | return mBackoffMultiplier
46 | }
47 |
48 | companion object {
49 | /** The default socket timeout in milliseconds */
50 | const val DEFAULT_TIMEOUT_MS = 12500
51 |
52 | /** The default number of retries */
53 | const val DEFAULT_MAX_RETRIES = 1
54 |
55 | /** The default backoff multiplier */
56 | const val DEFAULT_BACKOFF_MULT = 1f
57 | }
58 | /**
59 | * Constructs a new retry policy.
60 | * @param mCurrentTimeoutMs The initial timeout for the policy.
61 | * @param mMaxNumRetries The maximum number of retries.
62 | * @param mBackoffMultiplier Backoff multiplier for the policy.
63 | */
64 | }
--------------------------------------------------------------------------------
/kine-android/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | ext {
6 | bintrayRepo = 'Kine'
7 | bintrayName = 'kine'
8 |
9 | publishedGroupId = 'com.kine'
10 | libraryName = 'Kine'
11 | artifact = 'kine-android'
12 | libraryDescription = 'A simple and powerful HTTP networking lib for kotlin/Android..'
13 | libraryVersion = '1.0.0.0'
14 |
15 | siteUrl = 'https://github.com/AnkitAgrawal967/Kine'
16 | gitUrl = 'https://github.com/AnkitAgrawal967/Kine.git'
17 | githubRepository= 'AnkitAgrawal967/Kine'
18 |
19 | developerId = 'AnkitAgrawal967'
20 | developerName = 'Ankit Agrawal'
21 | developerEmail = 'xyz@mail.com'
22 |
23 | licenseName = 'The Apache Software License, Version 2.0'
24 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
25 | allLicenses = ["Apache-2.0"]
26 | }
27 |
28 | apply from: 'https://raw.githubusercontent.com/ktvipin27/RoomInspector/master/library/publish.gradle'
29 |
30 | android {
31 | compileSdkVersion 29
32 | buildToolsVersion "29.0.3"
33 |
34 | defaultConfig {
35 | minSdkVersion 16
36 | targetSdkVersion 29
37 | versionCode 1
38 | versionName "1.0"
39 |
40 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
41 | consumerProguardFiles "consumer-rules.pro"
42 | }
43 |
44 | buildTypes {
45 | release {
46 | minifyEnabled false
47 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
48 | }
49 | }
50 | tasks.withType(Javadoc).all {
51 | enabled = false
52 | }
53 | testOptions {
54 | unitTests.returnDefaultValues = true
55 | }
56 | }
57 | dependencies {
58 | implementation fileTree(dir: "libs", include: ["*.jar"])
59 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
60 | implementation project(':kine')
61 | implementation "androidx.preference:preference-ktx:1.1.1"
62 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/request/MultiPartRequestBody.kt:
--------------------------------------------------------------------------------
1 | package com.kine.request
2 |
3 | import java.io.File
4 | import java.util.*
5 |
6 | class MultiPartRequestBody(
7 | var multiPartParams: HashMap = hashMapOf(),
8 | var multiPartFileParams: HashMap> = hashMapOf()
9 | ) : RequestBody() {
10 |
11 | fun addMultiPartFileParam(key: String, value: File, contentType: String? = null) {
12 | multiPartFileParams[key] = multiPartFileParams[key]?.apply {add(
13 | MultiPartFileBody(
14 | value,
15 | contentType
16 | )
17 | )}
18 | ?:arrayListOf(MultiPartFileBody(value, contentType))
19 | }
20 |
21 | fun addMultiPartParam(key: String, value: String, contentType: String? = null) {
22 | multiPartParams[key] = MultiPartStringBody(value, contentType)
23 | }
24 | fun addMultiPartFileParams(parts: HashMap, contentType: String? = null) {
25 |
26 | for ((key, file) in parts.entries) {
27 | val fileBodies: MutableList? = multiPartFileParams[key]?:ArrayList()
28 | fileBodies!!.add(MultiPartFileBody(file, contentType))
29 | multiPartFileParams[key] = fileBodies
30 | }
31 | }
32 | fun addMultiPartFileListParams(parts: HashMap>, contentType: String? = null) {
33 | for ((key, fileList) in parts.entries) {
34 | val fileBodies: MutableList = multiPartFileParams[key] ?: ArrayList()
35 | for (file in fileList) {
36 | fileBodies.add(MultiPartFileBody(file, contentType))
37 | }
38 | multiPartFileParams[key] = fileBodies
39 | }
40 | }
41 | fun addMultiPartParams(parts: HashMap, contentType: String? = null) {
42 | parts.apply {
43 | for ((key, stringBody) in this.entries) {
44 | multiPartParams[key] = MultiPartStringBody(stringBody, contentType)
45 | }
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/log/Logger.kt:
--------------------------------------------------------------------------------
1 | package com.kine.log
2 |
3 | import com.kine.extensions.getClassInstance
4 |
5 |
6 | /**
7 | * Helper class for logging.
8 | */
9 | object Logger {
10 | private var level = LogLevel.NO_LOGS
11 | private var disabledLogs = false
12 | private var localLevel = LogLevel.NO_LEVEL
13 | private var log:Log= getDefaultLogger()
14 |
15 | private const val androidLoggerClass = "com.kine.android.log.Log"
16 | private fun getDefaultLogger(): Log {
17 | return androidLoggerClass.getClassInstance(JavaLog())
18 | }
19 | fun setLevel(level: Int) {
20 | if (level != LogLevel.NO_LEVEL) {
21 | Logger.level = level
22 | }
23 | }
24 |
25 | fun setLocalLevel(level: Int) {
26 | if (level != LogLevel.NO_LEVEL) {
27 | localLevel = level
28 | }
29 | }
30 |
31 | fun e(tag: String?, message: String,exception: java.lang.Exception?=null) {
32 | if (LogLevel.isError(level, localLevel) && !disabledLogs) {
33 | log.e(tag, message,exception)
34 | }
35 | }
36 |
37 | fun v(tag: String?, message: String) {
38 | if (LogLevel.isVerbose(level, localLevel) && !disabledLogs) {
39 | log.v(tag, message)
40 | }
41 | }
42 |
43 | fun wtf(tag: String?, message: String) {
44 | if (!disabledLogs) {
45 | log.wtf(tag, message)
46 | }
47 | }
48 |
49 | fun d(tag: String?, message: String) {
50 | if (LogLevel.isDebug(level, localLevel) && !disabledLogs) {
51 | log.d(tag, message)
52 | }
53 | }
54 |
55 | fun i(tag: String?, message: String) {
56 | if (LogLevel.isInfo(level, localLevel) && !disabledLogs) {
57 | log.i(tag, message)
58 | }
59 | }
60 |
61 | fun w(tag: String?, message: String) {
62 | if (LogLevel.isWarning(level, localLevel) && !disabledLogs) {
63 | log.w(tag, message)
64 | }
65 | }
66 |
67 | fun printStackTrace(e: Exception) {
68 | if (!disabledLogs) {
69 | e.printStackTrace()
70 | }
71 | }
72 |
73 | fun setDisabledLogs(disabledLogs: Boolean) {
74 | Logger.disabledLogs = disabledLogs
75 | }
76 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
17 |
18 |
23 |
24 |
31 |
32 |
38 |
39 |
46 |
47 |
54 |
55 |
--------------------------------------------------------------------------------
/kine-json/src/main/java/com/kine/extensions/Url.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress1("unused")
2 |
3 | package com.kine.extensions
4 |
5 |
6 | import com.kine.KineRequest
7 | import com.kine.converters.JsonConverter
8 | import com.kine.response.KineResponse
9 | import com.kine.response.OnError
10 | import com.kine.response.OnSuccess
11 | import org.json.JSONArray
12 | import org.json.JSONObject
13 | import kotlin.Suppress as Suppress1
14 |
15 |
16 | fun Map<*,*>.toJsonObject(): JSONObject {
17 | return JSONObject(this)
18 | }
19 |
20 | fun KineRequest.RequestBodyBuilder.bodyParams(jsonObject : JSONObject?): KineRequest.RequestBodyBuilder {
21 | return bodyParams(jsonObject?.toString())
22 | }
23 | fun KineRequest.RequestBodyBuilder.bodyParams(jsonObject : JSONArray?): KineRequest.RequestBodyBuilder {
24 | return bodyParams(jsonObject?.toString())
25 | }
26 |
27 | fun String.httpPost(jsonObject : JSONObject?): KineRequest.RequestBodyBuilder {
28 | return KineRequest.post(this).bodyParams(jsonObject?.toString())
29 | }
30 | fun String.httpDelete(jsonObject : JSONObject?): KineRequest.RequestBodyBuilder {
31 | return KineRequest.delete(this).bodyParams(jsonObject?.toString())
32 | }
33 | fun String.httpPut(jsonObject : JSONObject?): KineRequest.RequestBodyBuilder {
34 | return KineRequest.put(this).bodyParams(jsonObject?.toString())
35 | }
36 | fun String.httpPatch(jsonObject : JSONObject?): KineRequest.RequestBodyBuilder {
37 | return KineRequest.patch(this).bodyParams(jsonObject?.toString())
38 | }
39 | fun String.httpPostAs(jsonObject : JSONObject?, clazz: Class, onSuccess: OnSuccess, onError: OnError){
40 | return this.httpPost(jsonObject).responseAs(clazz,onSuccess, onError)
41 | }
42 | fun KineRequest.RequestOptionsBuilder.responseAsJson(onSuccess: OnSuccess, onError: OnError){
43 | return this.converter(JsonConverter()).responseAs(JSONObject::class.java,onSuccess, onError)
44 | }
45 | fun KineRequest.RequestOptionsBuilder.responseAsJsonArray(onSuccess: OnSuccess, onError: OnError){
46 | return this.converter(JsonConverter()).responseAs(JSONArray::class.java,onSuccess, onError)
47 | }
48 | fun KineRequest.RequestOptionsBuilder.responseAsJson(): KineResponse? {
49 | return this.converter(JsonConverter()).responseAs(JSONObject::class.java)
50 | }
51 | fun KineRequest.RequestOptionsBuilder.responseAsJsonArray(): KineResponse? {
52 | return this.converter(JsonConverter()).responseAs(JSONArray::class.java)
53 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/executor/DefaultPriorityExecutorSupplier.kt:
--------------------------------------------------------------------------------
1 | package com.kine.executor
2 |
3 | import java.util.concurrent.*
4 |
5 | class DefaultPriorityExecutorSupplier():ExecutorSupplier {
6 | /*
7 | * Number of cores to decide the number of threads
8 | */
9 | private val NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors()
10 |
11 | /*
12 | * thread pool executor for background tasks
13 | */
14 | private var forBackgroundTasks: PriorityThreadPoolExecutor
15 |
16 | /*
17 | * thread pool executor for light weight background tasks
18 | */
19 | private var forLightWeightBackgroundTasks: ThreadPoolExecutor
20 |
21 | /*
22 | * thread pool executor for main thread tasks
23 | */
24 | private var callbackExecutor: Executor
25 |
26 |
27 | init {
28 | // setting the thread factory
29 | val backgroundPriorityThreadFactory: ThreadFactory = createThreadFactory()
30 |
31 | // setting the thread pool executor for mForBackgroundTasks;
32 |
33 | forBackgroundTasks = PriorityThreadPoolExecutor(
34 | NUMBER_OF_CORES * 2,
35 | NUMBER_OF_CORES * 2,
36 | 60L,
37 | TimeUnit.SECONDS,
38 | backgroundPriorityThreadFactory
39 | )
40 |
41 | // setting the thread pool executor for mForLightWeightBackgroundTasks;
42 | forLightWeightBackgroundTasks = ThreadPoolExecutor(
43 | NUMBER_OF_CORES * 2,
44 | NUMBER_OF_CORES * 2,
45 | 60L,
46 | TimeUnit.SECONDS,
47 | LinkedBlockingQueue(),
48 | backgroundPriorityThreadFactory
49 | )
50 |
51 | // setting the thread pool executor for mMainThreadExecutor;
52 | callbackExecutor = createCallbackExecutor()
53 | }
54 |
55 | private fun createCallbackExecutor(): Executor = CallbackExecutor()
56 |
57 | private fun createThreadFactory(): ThreadFactory = PriorityThreadFactory(Thread.NORM_PRIORITY)
58 |
59 | /*
60 | * returns the thread pool executor for background task
61 | */
62 | override fun forNetworkTasks(): ThreadPoolExecutor {
63 | return forBackgroundTasks
64 | }
65 |
66 | /*
67 | * returns the thread pool executor for light weight background task
68 | */
69 | override fun forParsingTasks(): ThreadPoolExecutor {
70 | return forLightWeightBackgroundTasks
71 | }
72 |
73 | /*
74 | * returns the thread pool executor for main thread task
75 | */
76 | override fun forCallbackTasks(): Executor {
77 | return callbackExecutor
78 | }
79 | }
--------------------------------------------------------------------------------
/kine-android/src/main/java/com/kine/android/executor/AndroidPriorityExecutorSupplier.kt:
--------------------------------------------------------------------------------
1 | package com.kine.android.executor
2 |
3 | import android.os.Process
4 | import com.kine.executor.ExecutorSupplier
5 | import com.kine.executor.PriorityThreadPoolExecutor
6 | import java.util.concurrent.*
7 |
8 | class AndroidPriorityExecutorSupplier: ExecutorSupplier {
9 | /*
10 | * Number of cores to decide the number of threads
11 | */
12 | private val NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors()
13 |
14 | /*
15 | * thread pool executor for background tasks
16 | */
17 | private var forBackgroundTasks: PriorityThreadPoolExecutor
18 |
19 | /*
20 | * thread pool executor for light weight background tasks
21 | */
22 | private var forLightWeightBackgroundTasks: ThreadPoolExecutor
23 |
24 | /*
25 | * thread pool executor for main thread tasks
26 | */
27 | private var callbackExecutor: Executor
28 |
29 | init {
30 | // setting the thread factory
31 | val backgroundPriorityThreadFactory: ThreadFactory = createThreadFactory()
32 |
33 | // setting the thread pool executor for mForBackgroundTasks;
34 |
35 | forBackgroundTasks = PriorityThreadPoolExecutor(
36 | NUMBER_OF_CORES * 2,
37 | NUMBER_OF_CORES * 2,
38 | 60L,
39 | TimeUnit.SECONDS,
40 | backgroundPriorityThreadFactory
41 | )
42 |
43 | // setting the thread pool executor for mForLightWeightBackgroundTasks;
44 | forLightWeightBackgroundTasks = ThreadPoolExecutor(
45 | NUMBER_OF_CORES * 2,
46 | NUMBER_OF_CORES * 2,
47 | 60L,
48 | TimeUnit.SECONDS,
49 | LinkedBlockingQueue(),
50 | backgroundPriorityThreadFactory
51 | )
52 |
53 | // setting the thread pool executor for mMainThreadExecutor;
54 | callbackExecutor = createCallbackExecutor()
55 | }
56 |
57 | private fun createCallbackExecutor(): Executor = MainThreadExecutor()
58 |
59 | private fun createThreadFactory(): ThreadFactory = PriorityThreadFactory(Process.THREAD_PRIORITY_BACKGROUND)
60 |
61 | /*
62 | * returns the thread pool executor for background task
63 | */
64 | override fun forNetworkTasks(): ThreadPoolExecutor {
65 | return forBackgroundTasks
66 | }
67 |
68 | /*
69 | * returns the thread pool executor for light weight background task
70 | */
71 | override fun forParsingTasks(): ThreadPoolExecutor {
72 | return forLightWeightBackgroundTasks
73 | }
74 |
75 | /*
76 | * returns the thread pool executor for main thread task
77 | */
78 | override fun forCallbackTasks(): Executor {
79 | return callbackExecutor
80 | }
81 | }
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/extensions/Url.kt:
--------------------------------------------------------------------------------
1 | package com.kine.extensions
2 |
3 | import com.kine.KineRequest
4 | import com.kine.request.ContentType
5 | import com.kine.response.KineResponse
6 | import com.kine.response.OnError
7 | import com.kine.response.OnSuccess
8 | import java.io.File
9 |
10 | /**
11 | * extensions function for making a request.
12 | */
13 | typealias ProgressListener = (Long,Long)->Unit
14 |
15 | fun String.httpGet(): KineRequest.RequestOptionsBuilder {
16 | return KineRequest.get(this)
17 | }
18 | fun String.httpHead(): KineRequest.RequestOptionsBuilder {
19 | return KineRequest.head(this)
20 | }
21 | fun String.httpPost(params : String?=null,contentType: String=ContentType.JSON.toString()): KineRequest.RequestBodyBuilder {
22 | return KineRequest.post(this).bodyParams(params,contentType)
23 | }
24 | fun String.httpDelete(params : String?=null,contentType: String=ContentType.JSON.toString()): KineRequest.RequestBodyBuilder {
25 | return KineRequest.delete(this).bodyParams(params,contentType)
26 | }
27 | fun String.httpPut(params : String?=null,contentType: String= ContentType.JSON.toString()): KineRequest.RequestBodyBuilder {
28 | return KineRequest.put(this).bodyParams(params,contentType)
29 | }
30 | fun String.httpPatch(params : String?=null,contentType: String=ContentType.JSON.toString()): KineRequest.RequestBodyBuilder {
31 | return KineRequest.patch(this).bodyParams(params,contentType)
32 | }
33 | fun String.httpMethod(method : Int): KineRequest.RequestOptionsBuilder {
34 | return KineRequest.method(this,method)
35 | }
36 | fun String.httpGetAs(clazz: Class, onSuccess: OnSuccess, onError: OnError) {
37 | return this.httpGet().responseAs(clazz,onSuccess, onError)
38 | }
39 | fun String.httpGetAs(clazz: Class): KineResponse? {
40 | return this.httpGet().responseAs(clazz)
41 | }
42 | fun String.httpPostAs(params : String?,clazz: Class): KineResponse? {
43 | return this.httpPost(params).responseAs(clazz)
44 | }
45 | fun String.httpPostAs(params : String?,clazz: Class, onSuccess: OnSuccess, onError: OnError){
46 | return this.httpPost(params).responseAs(clazz,onSuccess, onError)
47 | }
48 | fun KineRequest.RequestOptionsBuilder.httpGetAsString(onSuccess: OnSuccess, onError: OnError){
49 | return responseAs(String::class.java,onSuccess, onError)
50 | }
51 |
52 | fun String.formatUrl(vararg values:Any): String {
53 | return String.format(this,values)
54 | }
55 |
56 | fun File.downloadFrom(url:String, progressListener: ProgressListener,onSuccess: OnSuccess?=null, onError: OnError?=null) {
57 | url.httpGet().downloadFile(this,progressListener, { response ->
58 | onSuccess?.invoke(response)
59 | }, onError = {kineError ->
60 | kineError.exception.printStackTrace()
61 | onError?.invoke(kineError)
62 | })
63 | }
64 | fun String.downloadTo(file:File, progressListener: ProgressListener,onSuccess: OnSuccess?=null, onError: OnError?=null) {
65 | file.downloadFrom(this,progressListener, onSuccess, onError)
66 | }
67 |
68 |
69 |
--------------------------------------------------------------------------------
/kine-android/src/main/java/com/kine/android/extensions/Url.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress1("unused")
2 |
3 | package com.kine.android.extensions
4 |
5 |
6 | import android.net.Uri
7 | import com.kine.KineRequest
8 | import com.kine.android.converters.JsonConverter
9 | import com.kine.android.request.JsonRequestBody
10 | import com.kine.response.OnError
11 | import com.kine.response.OnSuccess
12 | import org.json.JSONArray
13 | import org.json.JSONObject
14 | import kotlin.Suppress as Suppress1
15 |
16 | fun String.buildUrl(pathParams:List?=null,queryParams:HashMap?=null,
17 | encodedPathParams:List?=null): String {
18 | val builder = Uri.parse(this)
19 | .buildUpon()
20 | pathParams?.apply {
21 | for (value in this) {
22 | builder.appendPath(value)
23 | }
24 | }
25 | encodedPathParams?.apply {
26 | for (value in this) {
27 | builder.appendEncodedPath(value)
28 | }
29 | }
30 | queryParams?.apply {
31 | val entries: Set> = this.entries
32 | for ((name, value) in entries) {
33 | builder.appendQueryParameter(name, value)
34 | }
35 | }
36 | return builder.build().toString()
37 | }
38 | fun Map<*,*>.toJsonObject(): JSONObject {
39 | return JSONObject(this)
40 | }
41 |
42 | fun KineRequest.RequestBodyBuilder.bodyParams(jsonObject : JSONObject?): KineRequest.RequestBodyBuilder {
43 | return bodyParams(jsonObject?.toString())
44 | }
45 | fun KineRequest.RequestBodyBuilder.bodyParams(jsonObject : JSONArray?): KineRequest.RequestBodyBuilder {
46 | return bodyParams(jsonObject?.toString())
47 | }
48 | fun KineRequest.RequestBodyBuilder.bodyParams(jsonObject : JsonRequestBody): KineRequest.RequestBodyBuilder {
49 | return bodyParams(jsonObject.body,jsonObject.mediaType)
50 | }
51 | fun String.httpPost(jsonObject : JSONObject?): KineRequest.RequestBodyBuilder {
52 | return KineRequest.post(this).bodyParams(jsonObject?.toString())
53 | }
54 | fun String.httpDelete(jsonObject : JSONObject?): KineRequest.RequestBodyBuilder {
55 | return KineRequest.delete(this).bodyParams(jsonObject?.toString())
56 | }
57 | fun String.httpPut(jsonObject : JSONObject?): KineRequest.RequestBodyBuilder {
58 | return KineRequest.put(this).bodyParams(jsonObject?.toString())
59 | }
60 | fun String.httpPatch(jsonObject : JSONObject?): KineRequest.RequestBodyBuilder {
61 | return KineRequest.patch(this).bodyParams(jsonObject?.toString())
62 | }
63 | fun String.httpPostAs(jsonObject : JSONObject?, clazz: Class, onSuccess: OnSuccess, onError: OnError){
64 | return this.httpPost(jsonObject).responseAs(clazz,onSuccess, onError)
65 | }
66 | fun KineRequest.RequestOptionsBuilder.responseAsJson(onSuccess: OnSuccess, onError: OnError){
67 | return this.converter(JsonConverter()).responseAs(JSONObject::class.java,onSuccess, onError)
68 | }
69 | fun KineRequest.RequestOptionsBuilder.responseAsJsonArray(onSuccess: OnSuccess, onError: OnError){
70 | return this.converter(JsonConverter()).responseAs(JSONArray::class.java,onSuccess, onError)
71 | }
--------------------------------------------------------------------------------
/kine-okhttp/src/test/java/com/kine/client/OkHttpGetTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.Kine
4 | import com.kine.KineRequest
5 | import com.kine.exceptions.HttpStatusCodeException
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import org.junit.Assert.assertEquals
9 | import org.junit.Assert.assertTrue
10 | import okhttp3.mockwebserver.MockResponse
11 | import okhttp3.mockwebserver.MockWebServer
12 | import org.junit.Before
13 | import org.junit.Test
14 | import java.util.concurrent.CountDownLatch
15 | import java.util.concurrent.TimeUnit
16 | import java.util.concurrent.atomic.AtomicReference
17 |
18 | class OkHttpGetTest {
19 |
20 | private val mockServer = MockWebServer()
21 | private val testStringResponse = "testing okhttpresponse"
22 | @Before
23 | fun init() {
24 | mockServer.start()
25 | Kine.Builder()
26 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
27 | .logLevel(LogLevel.ERROR)
28 | .build()
29 | }
30 |
31 | @Test
32 | fun httpResponseSuccessTest() {
33 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
34 | val responseRef = AtomicReference()
35 | val countDownLatch = CountDownLatch(1)
36 |
37 | KineRequest.get(mockServer.url("/").toString())
38 | .responseAs(String::class.java, { response ->
39 | responseRef.set(response.body)
40 | countDownLatch.countDown()
41 | }, {
42 | assertTrue(false)
43 | })
44 | assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
45 | assertEquals(testStringResponse, responseRef.get())
46 |
47 | }
48 | @Test
49 | fun httpResponseFailedTest() {
50 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
51 | val errorDetailRef = AtomicReference()
52 | val countDownLatch = CountDownLatch(1)
53 | KineRequest.get(mockServer.url("/").toString())
54 | .responseAs(String::class.java, {
55 | assertTrue(false)
56 | }, {e->
57 | errorDetailRef.set(e.exception)
58 | countDownLatch.countDown()
59 | })
60 |
61 | assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
62 | assertTrue(errorDetailRef.get() is HttpStatusCodeException)
63 | }
64 | @Test
65 | fun httpResponseSuccessSyncTest() {
66 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
67 | val response = KineRequest.get(mockServer.url("/").toString())
68 | .responseAs(String::class.java)
69 | assertEquals(testStringResponse, response?.body)
70 | assertEquals(200, response?.statusCode)
71 | }
72 | @Test
73 | fun httpResponseFailedSyncTest() {
74 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
75 | try {
76 | KineRequest.get(mockServer.url("/").toString()).responseAs(String::class.java)
77 | assertTrue(false)
78 | }catch (e:Throwable){
79 | assertTrue(e is HttpStatusCodeException)
80 | }
81 | }
82 |
83 | }
--------------------------------------------------------------------------------
/kine-okhttplegacy/src/test/java/com/kine/client/OkHttpGetTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.Kine
4 | import com.kine.KineRequest
5 | import com.kine.exceptions.HttpStatusCodeException
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import org.junit.Assert.assertEquals
9 | import org.junit.Assert.assertTrue
10 | import okhttp3.mockwebserver.MockResponse
11 | import okhttp3.mockwebserver.MockWebServer
12 | import org.junit.Before
13 | import org.junit.Test
14 | import java.util.concurrent.CountDownLatch
15 | import java.util.concurrent.TimeUnit
16 | import java.util.concurrent.atomic.AtomicReference
17 |
18 | class OkHttpGetTest {
19 |
20 | private val mockServer = MockWebServer()
21 | private val testStringResponse = "testing okhttpresponse"
22 | @Before
23 | fun init() {
24 | mockServer.start()
25 | Kine.Builder()
26 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
27 | .logLevel(LogLevel.ERROR)
28 | .build()
29 | }
30 |
31 | @Test
32 | fun httpResponseSuccessTest() {
33 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
34 | val responseRef = AtomicReference()
35 | val countDownLatch = CountDownLatch(1)
36 |
37 | KineRequest.get(mockServer.url("/").toString())
38 | .responseAs(String::class.java, { response ->
39 | responseRef.set(response.body)
40 | countDownLatch.countDown()
41 | }, {
42 | assertTrue(false)
43 | })
44 | assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
45 | assertEquals(testStringResponse, responseRef.get())
46 |
47 | }
48 | @Test
49 | fun httpResponseFailedTest() {
50 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
51 | val errorDetailRef = AtomicReference()
52 | val countDownLatch = CountDownLatch(1)
53 | KineRequest.get(mockServer.url("/").toString())
54 | .responseAs(String::class.java, {
55 | assertTrue(false)
56 | }, {e->
57 | errorDetailRef.set(e.exception)
58 | countDownLatch.countDown()
59 | })
60 |
61 | assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
62 | assertTrue(errorDetailRef.get() is HttpStatusCodeException)
63 | }
64 | @Test
65 | fun httpResponseSuccessSyncTest() {
66 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
67 | val response = KineRequest.get(mockServer.url("/").toString())
68 | .responseAs(String::class.java)
69 | assertEquals(testStringResponse, response?.body)
70 | assertEquals(200, response?.statusCode)
71 | }
72 | @Test
73 | fun httpResponseFailedSyncTest() {
74 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
75 | try {
76 | KineRequest.get(mockServer.url("/").toString()).responseAs(String::class.java)
77 | assertTrue(false)
78 | }catch (e:Throwable){
79 | assertTrue(e is HttpStatusCodeException)
80 | }
81 | }
82 |
83 | }
--------------------------------------------------------------------------------
/kine-imageloader/src/main/java/com/kine/imageloader/extensions/Imageloader.kt:
--------------------------------------------------------------------------------
1 | @file:JvmName("ImageLoader")
2 |
3 | package com.kine.imageloader.extensions
4 |
5 | import android.graphics.Bitmap
6 | import android.widget.ImageView
7 | import androidx.annotation.DrawableRes
8 | import com.kine.KineRequest
9 | import com.kine.exceptions.NullResponseException
10 | import com.kine.extensions.httpGet
11 | import com.kine.imageloader.BitmapKineClass
12 | import com.kine.imageloader.converter.BitmapConverter
13 | import com.kine.response.KineError
14 | import com.kine.response.KineResponse
15 | import com.kine.response.OnError
16 | import com.kine.response.OnSuccess
17 |
18 | inline fun ImageView.loadImage(url: String, @DrawableRes placeHolder: Int? = null,crossinline onSuccess: OnSuccess,
19 | crossinline onError: OnError = { _ -> }) {
20 | placeHolder?.let {
21 | setImageResource(it)
22 | }
23 | url.httpGet().converter(BitmapConverter())
24 | .responseAs(BitmapKineClass(), { response ->
25 | setImageBitmap(response.body)
26 | onSuccess.invoke(response)
27 | }, onError = { error ->
28 | error.printStackTrace()
29 | onError.invoke(error)
30 | })
31 | }
32 |
33 | fun ImageView.loadImage(url: String, @DrawableRes placeHolder: Int? = null) {
34 | placeHolder?.let {
35 | setImageResource(it)
36 | }
37 | val response = url.httpGet().converter(BitmapConverter())
38 | .responseAs(BitmapKineClass())
39 | if (response?.body != null) {
40 | setImageBitmap(response.body)
41 | }
42 | }
43 |
44 | inline fun String.loadBitmapFromUrl(
45 | crossinline onSuccess: (Bitmap) -> Unit,
46 | crossinline onError: OnError = { _ -> }
47 | ) {
48 | this.httpGet().converter(BitmapConverter())
49 | .responseAs(BitmapKineClass(), { response ->
50 | response.body?:onError(KineError(NullResponseException("null bitmap")))
51 | response.body?.apply {
52 | onSuccess(this)
53 | }
54 | }, onError = { error ->
55 | error.printStackTrace()
56 | onError(error)
57 | })
58 | }
59 |
60 | inline fun String.loadBitmapResponseFromUrl(crossinline onSuccess: OnSuccess, crossinline onError: OnError = { _ -> }
61 | ) {
62 | this.httpGet().converter(BitmapConverter())
63 | .responseAs(BitmapKineClass(), { response ->
64 | onSuccess(response)
65 | }, onError = { error ->
66 | error.printStackTrace()
67 | onError(error)
68 | })
69 | }
70 |
71 | inline fun KineRequest.RequestOptionsBuilder.loadBitmap(crossinline onSuccess: OnSuccess, crossinline onError: OnError = { _ -> }) {
72 | return converter(BitmapConverter()).responseAs(BitmapKineClass(), { response ->
73 | response.body?:onError(KineError(NullResponseException("null bitmap")))
74 | response.body?.apply {
75 | onSuccess(response)
76 | }
77 | }, onError = { error ->
78 | error.printStackTrace()
79 | onError(error)
80 | })
81 | }
82 | fun KineRequest.RequestOptionsBuilder.loadBitmap(): KineResponse? {
83 | return converter(BitmapConverter()).responseAs(BitmapKineClass())
84 | }
85 |
--------------------------------------------------------------------------------
/kine-okhttp/src/test/java/com/kine/client/OkHttpHeadTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.Kine
4 | import com.kine.KineRequest
5 | import com.kine.exceptions.HttpStatusCodeException
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import okhttp3.mockwebserver.MockResponse
9 | import okhttp3.mockwebserver.MockWebServer
10 | import org.junit.Assert
11 | import org.junit.Before
12 | import org.junit.Test
13 | import java.util.concurrent.CountDownLatch
14 | import java.util.concurrent.TimeUnit
15 | import java.util.concurrent.atomic.AtomicReference
16 |
17 | class OkHttpHeadTest {
18 | private val mockServer = MockWebServer()
19 | private val testStringResponse = "testing_okhttp_response"
20 | @Before
21 | fun init() {
22 | mockServer.start()
23 | Kine.Builder()
24 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
25 | .logLevel(LogLevel.ERROR)
26 | .build()
27 | }
28 |
29 | @Test
30 | fun httpResponseSuccessTest() {
31 | mockServer.enqueue(MockResponse().setResponseCode(200).setHeader(testStringResponse,testStringResponse))
32 | val responseRef = AtomicReference()
33 | val countDownLatch = CountDownLatch(1)
34 |
35 | KineRequest.head(mockServer.url("/").toString())
36 | .responseAs(String::class.java, { response ->
37 | responseRef.set(response.headers[testStringResponse])
38 | countDownLatch.countDown()
39 | }, {
40 | Assert.assertTrue(false)
41 | })
42 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
43 | Assert.assertEquals(testStringResponse, responseRef.get())
44 |
45 | }
46 | @Test
47 | fun httpResponseFailedTest() {
48 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
49 | val errorDetailRef = AtomicReference()
50 | val countDownLatch = CountDownLatch(1)
51 | KineRequest.head(mockServer.url("/").toString())
52 | .responseAs(String::class.java, {
53 | Assert.assertTrue(false)
54 | }, {e->
55 | errorDetailRef.set(e.exception)
56 | countDownLatch.countDown()
57 | })
58 |
59 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
60 | Assert.assertTrue(errorDetailRef.get() is HttpStatusCodeException)
61 | }
62 | @Test
63 | fun httpResponseSuccessSyncTest() {
64 | mockServer.enqueue(MockResponse().setResponseCode(200).setHeader(testStringResponse,testStringResponse))
65 | val response = KineRequest.head(mockServer.url("/").toString())
66 | .responseAs(String::class.java)
67 | Assert.assertEquals(testStringResponse, response?.headers?.get(testStringResponse))
68 | Assert.assertEquals(200, response?.statusCode)
69 | }
70 | @Test
71 | fun httpResponseFailedSyncTest() {
72 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
73 | try {
74 | KineRequest.head(mockServer.url("/").toString()).responseAs(String::class.java)
75 | Assert.assertTrue(false)
76 | }catch (e:Throwable){
77 | Assert.assertTrue(e is HttpStatusCodeException)
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/kine-okhttplegacy/src/test/java/com/kine/client/OkHttpHeadTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.Kine
4 | import com.kine.KineRequest
5 | import com.kine.exceptions.HttpStatusCodeException
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import okhttp3.mockwebserver.MockResponse
9 | import okhttp3.mockwebserver.MockWebServer
10 | import org.junit.Assert
11 | import org.junit.Before
12 | import org.junit.Test
13 | import java.util.concurrent.CountDownLatch
14 | import java.util.concurrent.TimeUnit
15 | import java.util.concurrent.atomic.AtomicReference
16 |
17 | class OkHttpHeadTest {
18 | private val mockServer = MockWebServer()
19 | private val testStringResponse = "testing_okhttp_response"
20 | @Before
21 | fun init() {
22 | mockServer.start()
23 | Kine.Builder()
24 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
25 | .logLevel(LogLevel.ERROR)
26 | .build()
27 | }
28 |
29 | @Test
30 | fun httpResponseSuccessTest() {
31 | mockServer.enqueue(MockResponse().setResponseCode(200).setHeader(testStringResponse,testStringResponse))
32 | val responseRef = AtomicReference()
33 | val countDownLatch = CountDownLatch(1)
34 |
35 | KineRequest.head(mockServer.url("/").toString())
36 | .responseAs(String::class.java, { response ->
37 | responseRef.set(response.headers[testStringResponse])
38 | countDownLatch.countDown()
39 | }, {
40 | Assert.assertTrue(false)
41 | })
42 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
43 | Assert.assertEquals(testStringResponse, responseRef.get())
44 |
45 | }
46 | @Test
47 | fun httpResponseFailedTest() {
48 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
49 | val errorDetailRef = AtomicReference()
50 | val countDownLatch = CountDownLatch(1)
51 | KineRequest.head(mockServer.url("/").toString())
52 | .responseAs(String::class.java, {
53 | Assert.assertTrue(false)
54 | }, {e->
55 | errorDetailRef.set(e.exception)
56 | countDownLatch.countDown()
57 | })
58 |
59 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
60 | Assert.assertTrue(errorDetailRef.get() is HttpStatusCodeException)
61 | }
62 | @Test
63 | fun httpResponseSuccessSyncTest() {
64 | mockServer.enqueue(MockResponse().setResponseCode(200).setHeader(testStringResponse,testStringResponse))
65 | val response = KineRequest.head(mockServer.url("/").toString())
66 | .responseAs(String::class.java)
67 | Assert.assertEquals(testStringResponse, response?.headers?.get(testStringResponse))
68 | Assert.assertEquals(200, response?.statusCode)
69 | }
70 | @Test
71 | fun httpResponseFailedSyncTest() {
72 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
73 | try {
74 | KineRequest.head(mockServer.url("/").toString()).responseAs(String::class.java)
75 | Assert.assertTrue(false)
76 | }catch (e:Throwable){
77 | Assert.assertTrue(e is HttpStatusCodeException)
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/kine-okhttp/src/test/java/com/kine/client/OkHttpPutTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.Kine
4 | import com.kine.KineRequest
5 | import com.kine.exceptions.HttpStatusCodeException
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import com.kine.request.ContentType
9 | import okhttp3.mockwebserver.MockResponse
10 | import okhttp3.mockwebserver.MockWebServer
11 | import org.junit.Assert
12 | import org.junit.Before
13 | import org.junit.Test
14 | import java.util.concurrent.CountDownLatch
15 | import java.util.concurrent.TimeUnit
16 | import java.util.concurrent.atomic.AtomicReference
17 |
18 | class OkHttpPutTest {
19 | private val mockServer = MockWebServer()
20 | private val testStringResponse = "testing okhttpresponse"
21 | @Before
22 | fun init() {
23 | mockServer.start()
24 | Kine.Builder()
25 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
26 | .logLevel(LogLevel.ERROR)
27 | .build()
28 | }
29 |
30 | @Test
31 | fun httpResponseSuccessTest() {
32 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
33 | val responseRef = AtomicReference()
34 | val countDownLatch = CountDownLatch(1)
35 |
36 | KineRequest.put(mockServer.url("/").toString())
37 | .bodyParams(testStringResponse,ContentType.STRING.toString())
38 | .responseAs(String::class.java, { response ->
39 | responseRef.set(response.body)
40 | countDownLatch.countDown()
41 | }, {
42 | Assert.assertTrue(false)
43 | })
44 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
45 | Assert.assertEquals(testStringResponse, responseRef.get())
46 |
47 | }
48 | @Test
49 | fun httpResponseFailedTest() {
50 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
51 | val errorDetailRef = AtomicReference()
52 | val countDownLatch = CountDownLatch(1)
53 | KineRequest.put(mockServer.url("/").toString())
54 | .responseAs(String::class.java, {
55 | Assert.assertTrue(false)
56 | }, {e->
57 | errorDetailRef.set(e.exception)
58 | countDownLatch.countDown()
59 | })
60 |
61 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
62 | Assert.assertTrue(errorDetailRef.get() is HttpStatusCodeException)
63 | }
64 | @Test
65 | fun httpResponseSuccessSyncTest() {
66 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
67 | val response = KineRequest.put(mockServer.url("/").toString())
68 | .responseAs(String::class.java)
69 | Assert.assertEquals(testStringResponse, response?.body)
70 | Assert.assertEquals(200, response?.statusCode)
71 | }
72 | @Test
73 | fun httpResponseFailedSyncTest() {
74 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
75 | try {
76 | KineRequest.put(mockServer.url("/").toString()).responseAs(String::class.java)
77 | Assert.assertTrue(false)
78 | }catch (e:Throwable){
79 | Assert.assertTrue(e is HttpStatusCodeException)
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/kine-okhttp/src/test/java/com/kine/client/OkHttpPostTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.Kine
4 | import com.kine.KineRequest
5 | import com.kine.exceptions.HttpStatusCodeException
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import com.kine.request.ContentType
9 | import okhttp3.mockwebserver.MockResponse
10 | import okhttp3.mockwebserver.MockWebServer
11 | import org.junit.Assert
12 | import org.junit.Before
13 | import org.junit.Test
14 | import java.util.concurrent.CountDownLatch
15 | import java.util.concurrent.TimeUnit
16 | import java.util.concurrent.atomic.AtomicReference
17 |
18 | class OkHttpPostTest {
19 | private val mockServer = MockWebServer()
20 | private val testStringResponse = "testing okhttpresponse"
21 | @Before
22 | fun init() {
23 | mockServer.start()
24 | Kine.Builder()
25 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
26 | .logLevel(LogLevel.ERROR)
27 | .build()
28 | }
29 |
30 | @Test
31 | fun httpResponseSuccessTest() {
32 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
33 | val responseRef = AtomicReference()
34 | val countDownLatch = CountDownLatch(1)
35 |
36 | KineRequest.post(mockServer.url("/").toString())
37 | .bodyParams(testStringResponse,ContentType.STRING.toString())
38 | .responseAs(String::class.java, { response ->
39 | responseRef.set(response.body)
40 | countDownLatch.countDown()
41 | }, {
42 | Assert.assertTrue(false)
43 | })
44 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
45 | Assert.assertEquals(testStringResponse, responseRef.get())
46 |
47 | }
48 | @Test
49 | fun httpResponseFailedTest() {
50 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
51 | val errorDetailRef = AtomicReference()
52 | val countDownLatch = CountDownLatch(1)
53 | KineRequest.post(mockServer.url("/").toString())
54 | .responseAs(String::class.java, {
55 | Assert.assertTrue(false)
56 | }, {e->
57 | errorDetailRef.set(e.exception)
58 | countDownLatch.countDown()
59 | })
60 |
61 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
62 | Assert.assertTrue(errorDetailRef.get() is HttpStatusCodeException)
63 | }
64 | @Test
65 | fun httpResponseSuccessSyncTest() {
66 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
67 | val response = KineRequest.post(mockServer.url("/").toString())
68 | .responseAs(String::class.java)
69 | Assert.assertEquals(testStringResponse, response?.body)
70 | Assert.assertEquals(200, response?.statusCode)
71 | }
72 | @Test
73 | fun httpResponseFailedSyncTest() {
74 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
75 | try {
76 | KineRequest.post(mockServer.url("/").toString()).responseAs(String::class.java)
77 | Assert.assertTrue(false)
78 | }catch (e:Throwable){
79 | Assert.assertTrue(e is HttpStatusCodeException)
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/kine-okhttplegacy/src/test/java/com/kine/client/OkHttpPutTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.Kine
4 | import com.kine.KineRequest
5 | import com.kine.exceptions.HttpStatusCodeException
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import com.kine.request.ContentType
9 | import okhttp3.mockwebserver.MockResponse
10 | import okhttp3.mockwebserver.MockWebServer
11 | import org.junit.Assert
12 | import org.junit.Before
13 | import org.junit.Test
14 | import java.util.concurrent.CountDownLatch
15 | import java.util.concurrent.TimeUnit
16 | import java.util.concurrent.atomic.AtomicReference
17 |
18 | class OkHttpPutTest {
19 | private val mockServer = MockWebServer()
20 | private val testStringResponse = "testing okhttpresponse"
21 | @Before
22 | fun init() {
23 | mockServer.start()
24 | Kine.Builder()
25 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
26 | .logLevel(LogLevel.ERROR)
27 | .build()
28 | }
29 |
30 | @Test
31 | fun httpResponseSuccessTest() {
32 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
33 | val responseRef = AtomicReference()
34 | val countDownLatch = CountDownLatch(1)
35 |
36 | KineRequest.put(mockServer.url("/").toString())
37 | .bodyParams(testStringResponse,ContentType.STRING.toString())
38 | .responseAs(String::class.java, { response ->
39 | responseRef.set(response.body)
40 | countDownLatch.countDown()
41 | }, {
42 | Assert.assertTrue(false)
43 | })
44 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
45 | Assert.assertEquals(testStringResponse, responseRef.get())
46 |
47 | }
48 | @Test
49 | fun httpResponseFailedTest() {
50 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
51 | val errorDetailRef = AtomicReference()
52 | val countDownLatch = CountDownLatch(1)
53 | KineRequest.put(mockServer.url("/").toString())
54 | .responseAs(String::class.java, {
55 | Assert.assertTrue(false)
56 | }, {e->
57 | errorDetailRef.set(e.exception)
58 | countDownLatch.countDown()
59 | })
60 |
61 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
62 | Assert.assertTrue(errorDetailRef.get() is HttpStatusCodeException)
63 | }
64 | @Test
65 | fun httpResponseSuccessSyncTest() {
66 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
67 | val response = KineRequest.put(mockServer.url("/").toString())
68 | .responseAs(String::class.java)
69 | Assert.assertEquals(testStringResponse, response?.body)
70 | Assert.assertEquals(200, response?.statusCode)
71 | }
72 | @Test
73 | fun httpResponseFailedSyncTest() {
74 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
75 | try {
76 | KineRequest.put(mockServer.url("/").toString()).responseAs(String::class.java)
77 | Assert.assertTrue(false)
78 | }catch (e:Throwable){
79 | Assert.assertTrue(e is HttpStatusCodeException)
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/kine-okhttp/src/test/java/com/kine/client/OkHttpPatchTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.Kine
4 | import com.kine.KineRequest
5 | import com.kine.exceptions.HttpStatusCodeException
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import com.kine.request.ContentType
9 | import okhttp3.mockwebserver.MockResponse
10 | import okhttp3.mockwebserver.MockWebServer
11 | import org.junit.Assert
12 | import org.junit.Before
13 | import org.junit.Test
14 | import java.util.concurrent.CountDownLatch
15 | import java.util.concurrent.TimeUnit
16 | import java.util.concurrent.atomic.AtomicReference
17 |
18 | class OkHttpPatchTest {
19 | private val mockServer = MockWebServer()
20 | private val testStringResponse = "testing okhttpresponse"
21 | @Before
22 | fun init() {
23 | mockServer.start()
24 | Kine.Builder()
25 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
26 | .logLevel(LogLevel.ERROR)
27 | .build()
28 | }
29 |
30 | @Test
31 | fun httpResponseSuccessTest() {
32 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
33 | val responseRef = AtomicReference()
34 | val countDownLatch = CountDownLatch(1)
35 |
36 | KineRequest.patch(mockServer.url("/").toString())
37 | .bodyParams(testStringResponse,ContentType.STRING.toString())
38 | .responseAs(String::class.java, { response ->
39 | responseRef.set(response.body)
40 | countDownLatch.countDown()
41 | }, {
42 | Assert.assertTrue(false)
43 | })
44 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
45 | Assert.assertEquals(testStringResponse, responseRef.get())
46 |
47 | }
48 | @Test
49 | fun httpResponseFailedTest() {
50 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
51 | val errorDetailRef = AtomicReference()
52 | val countDownLatch = CountDownLatch(1)
53 | KineRequest.patch(mockServer.url("/").toString())
54 | .responseAs(String::class.java, {
55 | Assert.assertTrue(false)
56 | }, {e->
57 | errorDetailRef.set(e.exception)
58 | countDownLatch.countDown()
59 | })
60 |
61 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
62 | Assert.assertTrue(errorDetailRef.get() is HttpStatusCodeException)
63 | }
64 | @Test
65 | fun httpResponseSuccessSyncTest() {
66 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
67 | val response = KineRequest.patch(mockServer.url("/").toString())
68 | .responseAs(String::class.java)
69 | Assert.assertEquals(testStringResponse, response?.body)
70 | Assert.assertEquals(200, response?.statusCode)
71 | }
72 | @Test
73 | fun httpResponseFailedSyncTest() {
74 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
75 | try {
76 | KineRequest.patch(mockServer.url("/").toString()).responseAs(String::class.java)
77 | Assert.assertTrue(false)
78 | }catch (e:Throwable){
79 | Assert.assertTrue(e is HttpStatusCodeException)
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/kine-okhttplegacy/src/test/java/com/kine/client/OkHttpPostTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.Kine
4 | import com.kine.KineRequest
5 | import com.kine.exceptions.HttpStatusCodeException
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import com.kine.request.ContentType
9 | import okhttp3.mockwebserver.MockResponse
10 | import okhttp3.mockwebserver.MockWebServer
11 | import org.junit.Assert
12 | import org.junit.Before
13 | import org.junit.Test
14 | import java.util.concurrent.CountDownLatch
15 | import java.util.concurrent.TimeUnit
16 | import java.util.concurrent.atomic.AtomicReference
17 |
18 | class OkHttpPostTest {
19 | private val mockServer = MockWebServer()
20 | private val testStringResponse = "testing okhttpresponse"
21 | @Before
22 | fun init() {
23 | mockServer.start()
24 | Kine.Builder()
25 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
26 | .logLevel(LogLevel.ERROR)
27 | .build()
28 | }
29 |
30 | @Test
31 | fun httpResponseSuccessTest() {
32 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
33 | val responseRef = AtomicReference()
34 | val countDownLatch = CountDownLatch(1)
35 |
36 | KineRequest.post(mockServer.url("/").toString())
37 | .bodyParams(testStringResponse,ContentType.STRING.toString())
38 | .responseAs(String::class.java, { response ->
39 | responseRef.set(response.body)
40 | countDownLatch.countDown()
41 | }, {
42 | Assert.assertTrue(false)
43 | })
44 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
45 | Assert.assertEquals(testStringResponse, responseRef.get())
46 |
47 | }
48 | @Test
49 | fun httpResponseFailedTest() {
50 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
51 | val errorDetailRef = AtomicReference()
52 | val countDownLatch = CountDownLatch(1)
53 | KineRequest.post(mockServer.url("/").toString())
54 | .responseAs(String::class.java, {
55 | Assert.assertTrue(false)
56 | }, {e->
57 | errorDetailRef.set(e.exception)
58 | countDownLatch.countDown()
59 | })
60 |
61 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
62 | Assert.assertTrue(errorDetailRef.get() is HttpStatusCodeException)
63 | }
64 | @Test
65 | fun httpResponseSuccessSyncTest() {
66 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
67 | val response = KineRequest.post(mockServer.url("/").toString())
68 | .responseAs(String::class.java)
69 | Assert.assertEquals(testStringResponse, response?.body)
70 | Assert.assertEquals(200, response?.statusCode)
71 | }
72 | @Test
73 | fun httpResponseFailedSyncTest() {
74 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
75 | try {
76 | KineRequest.post(mockServer.url("/").toString()).responseAs(String::class.java)
77 | Assert.assertTrue(false)
78 | }catch (e:Throwable){
79 | Assert.assertTrue(e is HttpStatusCodeException)
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/kine-okhttp/src/test/java/com/kine/client/OkHttpDeleteTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.Kine
4 | import com.kine.KineRequest
5 | import com.kine.exceptions.HttpStatusCodeException
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import com.kine.request.ContentType
9 | import okhttp3.mockwebserver.MockResponse
10 | import okhttp3.mockwebserver.MockWebServer
11 | import org.junit.Assert
12 | import org.junit.Before
13 | import org.junit.Test
14 | import java.util.concurrent.CountDownLatch
15 | import java.util.concurrent.TimeUnit
16 | import java.util.concurrent.atomic.AtomicReference
17 |
18 | class OkHttpDeleteTest {
19 | private val mockServer = MockWebServer()
20 | private val testStringResponse = "testing okhttpresponse"
21 | @Before
22 | fun init() {
23 | mockServer.start()
24 | Kine.Builder()
25 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
26 | .logLevel(LogLevel.ERROR)
27 | .build()
28 | }
29 |
30 | @Test
31 | fun httpResponseSuccessTest() {
32 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
33 | val responseRef = AtomicReference()
34 | val countDownLatch = CountDownLatch(1)
35 |
36 | KineRequest.delete(mockServer.url("/").toString())
37 | .bodyParams(testStringResponse,ContentType.STRING.toString())
38 | .responseAs(String::class.java, { response ->
39 | responseRef.set(response.body)
40 | countDownLatch.countDown()
41 | }, {
42 | Assert.assertTrue(false)
43 | })
44 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
45 | Assert.assertEquals(testStringResponse, responseRef.get())
46 |
47 | }
48 | @Test
49 | fun httpResponseFailedTest() {
50 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
51 | val errorDetailRef = AtomicReference()
52 | val countDownLatch = CountDownLatch(1)
53 | KineRequest.delete(mockServer.url("/").toString())
54 | .responseAs(String::class.java, {
55 | Assert.assertTrue(false)
56 | }, {e->
57 | errorDetailRef.set(e.exception)
58 | countDownLatch.countDown()
59 | })
60 |
61 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
62 | Assert.assertTrue(errorDetailRef.get() is HttpStatusCodeException)
63 | }
64 | @Test
65 | fun httpResponseSuccessSyncTest() {
66 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
67 | val response = KineRequest.delete(mockServer.url("/").toString())
68 | .responseAs(String::class.java)
69 | Assert.assertEquals(testStringResponse, response?.body)
70 | Assert.assertEquals(200, response?.statusCode)
71 | }
72 | @Test
73 | fun httpResponseFailedSyncTest() {
74 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
75 | try {
76 | KineRequest.delete(mockServer.url("/").toString()).responseAs(String::class.java)
77 | Assert.assertTrue(false)
78 | }catch (e:Throwable){
79 | Assert.assertTrue(e is HttpStatusCodeException)
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/kine-okhttplegacy/src/test/java/com/kine/client/OkHttpPatchTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.Kine
4 | import com.kine.KineRequest
5 | import com.kine.exceptions.HttpStatusCodeException
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import com.kine.request.ContentType
9 | import okhttp3.mockwebserver.MockResponse
10 | import okhttp3.mockwebserver.MockWebServer
11 | import org.junit.Assert
12 | import org.junit.Before
13 | import org.junit.Test
14 | import java.util.concurrent.CountDownLatch
15 | import java.util.concurrent.TimeUnit
16 | import java.util.concurrent.atomic.AtomicReference
17 |
18 | class OkHttpPatchTest {
19 | private val mockServer = MockWebServer()
20 | private val testStringResponse = "testing okhttpresponse"
21 | @Before
22 | fun init() {
23 | mockServer.start()
24 | Kine.Builder()
25 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
26 | .logLevel(LogLevel.ERROR)
27 | .build()
28 | }
29 |
30 | @Test
31 | fun httpResponseSuccessTest() {
32 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
33 | val responseRef = AtomicReference()
34 | val countDownLatch = CountDownLatch(1)
35 |
36 | KineRequest.patch(mockServer.url("/").toString())
37 | .bodyParams(testStringResponse,ContentType.STRING.toString())
38 | .responseAs(String::class.java, { response ->
39 | responseRef.set(response.body)
40 | countDownLatch.countDown()
41 | }, {
42 | Assert.assertTrue(false)
43 | })
44 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
45 | Assert.assertEquals(testStringResponse, responseRef.get())
46 |
47 | }
48 | @Test
49 | fun httpResponseFailedTest() {
50 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
51 | val errorDetailRef = AtomicReference()
52 | val countDownLatch = CountDownLatch(1)
53 | KineRequest.patch(mockServer.url("/").toString())
54 | .responseAs(String::class.java, {
55 | Assert.assertTrue(false)
56 | }, {e->
57 | errorDetailRef.set(e.exception)
58 | countDownLatch.countDown()
59 | })
60 |
61 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
62 | Assert.assertTrue(errorDetailRef.get() is HttpStatusCodeException)
63 | }
64 | @Test
65 | fun httpResponseSuccessSyncTest() {
66 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
67 | val response = KineRequest.patch(mockServer.url("/").toString())
68 | .responseAs(String::class.java)
69 | Assert.assertEquals(testStringResponse, response?.body)
70 | Assert.assertEquals(200, response?.statusCode)
71 | }
72 | @Test
73 | fun httpResponseFailedSyncTest() {
74 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
75 | try {
76 | KineRequest.patch(mockServer.url("/").toString()).responseAs(String::class.java)
77 | Assert.assertTrue(false)
78 | }catch (e:Throwable){
79 | Assert.assertTrue(e is HttpStatusCodeException)
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/kine-okhttplegacy/src/test/java/com/kine/client/OkHttpDeleteTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client
2 |
3 | import com.kine.Kine
4 | import com.kine.KineRequest
5 | import com.kine.exceptions.HttpStatusCodeException
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import com.kine.request.ContentType
9 | import okhttp3.mockwebserver.MockResponse
10 | import okhttp3.mockwebserver.MockWebServer
11 | import org.junit.Assert
12 | import org.junit.Before
13 | import org.junit.Test
14 | import java.util.concurrent.CountDownLatch
15 | import java.util.concurrent.TimeUnit
16 | import java.util.concurrent.atomic.AtomicReference
17 |
18 | class OkHttpDeleteTest {
19 | private val mockServer = MockWebServer()
20 | private val testStringResponse = "testing okhttpresponse"
21 | @Before
22 | fun init() {
23 | mockServer.start()
24 | Kine.Builder()
25 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
26 | .logLevel(LogLevel.ERROR)
27 | .build()
28 | }
29 |
30 | @Test
31 | fun httpResponseSuccessTest() {
32 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
33 | val responseRef = AtomicReference()
34 | val countDownLatch = CountDownLatch(1)
35 |
36 | KineRequest.delete(mockServer.url("/").toString())
37 | .bodyParams(testStringResponse,ContentType.STRING.toString())
38 | .responseAs(String::class.java, { response ->
39 | responseRef.set(response.body)
40 | countDownLatch.countDown()
41 | }, {
42 | Assert.assertTrue(false)
43 | })
44 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
45 | Assert.assertEquals(testStringResponse, responseRef.get())
46 |
47 | }
48 | @Test
49 | fun httpResponseFailedTest() {
50 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
51 | val errorDetailRef = AtomicReference()
52 | val countDownLatch = CountDownLatch(1)
53 | KineRequest.delete(mockServer.url("/").toString())
54 | .responseAs(String::class.java, {
55 | Assert.assertTrue(false)
56 | }, {e->
57 | errorDetailRef.set(e.exception)
58 | countDownLatch.countDown()
59 | })
60 |
61 | Assert.assertTrue(countDownLatch.await(3, TimeUnit.SECONDS))
62 | Assert.assertTrue(errorDetailRef.get() is HttpStatusCodeException)
63 | }
64 | @Test
65 | fun httpResponseSuccessSyncTest() {
66 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
67 | val response = KineRequest.delete(mockServer.url("/").toString())
68 | .responseAs(String::class.java)
69 | Assert.assertEquals(testStringResponse, response?.body)
70 | Assert.assertEquals(200, response?.statusCode)
71 | }
72 | @Test
73 | fun httpResponseFailedSyncTest() {
74 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
75 | try {
76 | KineRequest.delete(mockServer.url("/").toString()).responseAs(String::class.java)
77 | Assert.assertTrue(false)
78 | }catch (e:Throwable){
79 | Assert.assertTrue(e is HttpStatusCodeException)
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at . All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/kine-okhttplegacy/src/main/java/com/kine/client/extensions/Extensions.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client.extensions
2 |
3 |
4 | import com.kine.KineRequest
5 | import com.kine.client.OkHttpKineClient
6 | import com.kine.extensions.ProgressListener
7 | import okhttp3.HttpUrl
8 | import okhttp3.OkHttpClient
9 | import okhttp3.ResponseBody
10 | import okio.*
11 | import okio.Okio.sink
12 | import java.io.File
13 | import java.io.FileDescriptor
14 | import java.io.FileOutputStream
15 |
16 | fun String.buildUrl(
17 | pathParams: List? = null,
18 | queryParams: HashMap? = null,
19 | encodedPathParams: List? = null,
20 | encodedQueryParams: HashMap? = null
21 | ): String {
22 | val urlBuilder = HttpUrl.parse(this)?.newBuilder() ?: throw IllegalArgumentException("not a valid url")
23 | pathParams?.apply {
24 | for (value in this) {
25 | urlBuilder.addEncodedPathSegment(value)
26 | }
27 | }
28 | encodedPathParams?.apply {
29 | for (value in this) {
30 | urlBuilder.addEncodedPathSegment(value)
31 | }
32 | }
33 | queryParams?.apply {
34 | val entries: Set> = this.entries
35 | for ((name, value) in entries) {
36 | urlBuilder.addQueryParameter(name, value)
37 | }
38 | }
39 | encodedQueryParams?.apply {
40 | val entries: Set> = this.entries
41 | for ((name, value) in entries) {
42 | urlBuilder.addEncodedQueryParameter(name, value)
43 | }
44 | }
45 | return urlBuilder.build().toString()
46 | }
47 |
48 | const val DOWNLOAD_CHUNK_SIZE = 2048L
49 | internal inline fun File.download(
50 | body: ResponseBody,
51 | crossinline progressListener: ProgressListener
52 | ): File {
53 | val contentLength: Long = body.contentLength()
54 | val source: BufferedSource = body.source()
55 | val sink: BufferedSink = Okio.buffer(sink(this))
56 | sink.use {
57 | var totalRead: Long = 0
58 | var read: Long
59 | val buffer = Buffer()
60 | while (source.read(buffer, DOWNLOAD_CHUNK_SIZE).also { read = it } != -1L) {
61 | sink.write(buffer, read)
62 | totalRead += read
63 | progressListener(totalRead, contentLength)
64 | }
65 | sink.flush()
66 | sink.close()
67 | source.close()
68 | progressListener(contentLength, contentLength)
69 | }
70 | return this
71 | }
72 |
73 | internal inline fun FileDescriptor.download(
74 | body: ResponseBody,
75 | crossinline progressListener: ProgressListener
76 | ) {
77 | FileOutputStream(this).download(body, progressListener)
78 | }
79 |
80 | internal inline fun FileOutputStream.download(
81 | body: ResponseBody,
82 | crossinline progressListener: ProgressListener
83 | ) {
84 | use {
85 | val contentLength: Long = body.contentLength()
86 | val source: BufferedSource = body.source()
87 | val sink: BufferedSink = Okio.buffer(sink(this))
88 | var totalRead: Long = 0
89 | var read: Long
90 | val buffer = Buffer()
91 | while (source.read(buffer, DOWNLOAD_CHUNK_SIZE).also { read = it } != -1L) {
92 | sink.write(buffer, read)
93 | totalRead += read
94 | progressListener(totalRead, contentLength)
95 | }
96 | sink.flush()
97 | sink.close()
98 | source.close()
99 | close()
100 | progressListener(contentLength, contentLength)
101 | }
102 | }
103 | fun KineRequest.RequestOptionsBuilder.client(okHttpClient: OkHttpClient): KineRequest.RequestOptionsBuilder {
104 | return client(okHttpClient.toKineClient())
105 | }
106 | fun OkHttpClient.toKineClient(): OkHttpKineClient {
107 | return OkHttpKineClient(this)
108 | }
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/kine-okhttp/src/main/java/com/kine/client/extensions/Extensions.kt:
--------------------------------------------------------------------------------
1 | package com.kine.client.extensions
2 |
3 |
4 | import com.kine.KineRequest
5 | import com.kine.client.OkHttpKineClient
6 | import com.kine.extensions.ProgressListener
7 | import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
8 | import okhttp3.OkHttpClient
9 | import okhttp3.ResponseBody
10 | import okio.*
11 | import java.io.File
12 | import java.io.FileDescriptor
13 | import java.io.FileOutputStream
14 |
15 | fun String.buildUrl(
16 | pathParams: List? = null,
17 | queryParams: HashMap? = null,
18 | encodedPathParams: List? = null,
19 | encodedQueryParams: HashMap? = null
20 | ): String {
21 | val urlBuilder =
22 | this.toHttpUrlOrNull()?.newBuilder() ?: throw IllegalArgumentException("not a valid url")
23 | pathParams?.apply {
24 | for (value in this) {
25 | urlBuilder.addEncodedPathSegment(value)
26 | }
27 | }
28 | encodedPathParams?.apply {
29 | for (value in this) {
30 | urlBuilder.addEncodedPathSegment(value)
31 | }
32 | }
33 | queryParams?.apply {
34 | val entries: Set> = this.entries
35 | for ((name, value) in entries) {
36 | urlBuilder.addQueryParameter(name, value)
37 | }
38 | }
39 | encodedQueryParams?.apply {
40 | val entries: Set> = this.entries
41 | for ((name, value) in entries) {
42 | urlBuilder.addEncodedQueryParameter(name, value)
43 | }
44 | }
45 | return urlBuilder.build().toString()
46 | }
47 |
48 | const val DOWNLOAD_CHUNK_SIZE = 2048L
49 | internal inline fun File.download(
50 | body: ResponseBody,
51 | crossinline progressListener: ProgressListener
52 | ): File {
53 | val contentLength: Long = body.contentLength()
54 | val source: BufferedSource = body.source()
55 | val sink: BufferedSink = this.sink().buffer()
56 | sink.use {
57 | var totalRead: Long = 0
58 | var read: Long
59 | val buffer = Buffer()
60 | while (source.read(buffer, DOWNLOAD_CHUNK_SIZE).also { read = it } != -1L) {
61 | sink.write(buffer, read)
62 | totalRead += read
63 | progressListener(totalRead, contentLength)
64 | }
65 | sink.flush()
66 | sink.close()
67 | source.close()
68 | progressListener(contentLength, contentLength)
69 | }
70 | return this
71 | }
72 |
73 | internal inline fun FileDescriptor.download(
74 | body: ResponseBody,
75 | crossinline progressListener: ProgressListener
76 | ) {
77 | FileOutputStream(this).download(body, progressListener)
78 | }
79 |
80 | internal inline fun FileOutputStream.download(
81 | body: ResponseBody,
82 | crossinline progressListener: ProgressListener
83 | ) {
84 | use {
85 | val contentLength: Long = body.contentLength()
86 | val source: BufferedSource = body.source()
87 | val sink: BufferedSink = this.sink().buffer()
88 | var totalRead: Long = 0
89 | var read: Long
90 | val buffer = Buffer()
91 | while (source.read(buffer, DOWNLOAD_CHUNK_SIZE).also { read = it } != -1L) {
92 | sink.write(buffer, read)
93 | totalRead += read
94 | progressListener(totalRead, contentLength)
95 | }
96 | sink.flush()
97 | sink.close()
98 | source.close()
99 | close()
100 | progressListener(contentLength, contentLength)
101 | }
102 | }
103 | fun KineRequest.RequestOptionsBuilder.client(okHttpClient: OkHttpClient): KineRequest.RequestOptionsBuilder {
104 | return client(okHttpClient.toKineClient())
105 | }
106 | fun OkHttpClient.toKineClient(): OkHttpKineClient {
107 | return OkHttpKineClient(this)
108 | }
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/kine-json/src/test/java/com/kine/JsonApiTest.kt:
--------------------------------------------------------------------------------
1 | package com.kine
2 |
3 | import com.kine.exceptions.HttpStatusCodeException
4 | import com.kine.extensions.responseAsJson
5 | import com.kine.extensions.responseAsJsonArray
6 | import com.kine.log.LogLevel
7 | import com.kine.policies.DefaultRetryPolicy
8 | import okhttp3.mockwebserver.MockResponse
9 | import okhttp3.mockwebserver.MockWebServer
10 | import org.json.JSONArray
11 | import org.json.JSONObject
12 | import org.junit.Assert
13 | import org.junit.Before
14 | import org.junit.Test
15 | import java.util.concurrent.CountDownLatch
16 | import java.util.concurrent.TimeUnit
17 | import java.util.concurrent.atomic.AtomicReference
18 |
19 |
20 | class JsonApiTest {
21 |
22 | private val mockServer = MockWebServer()
23 | private val testStringResponse = JSONObject(HashMap().apply{put("test","response")}).toString()
24 |
25 | private val testJsonArrayResponse = JSONArray(arrayListOf().apply{add("test")
26 | add("response")}).toString()
27 | @Before
28 | fun init() {
29 | mockServer.start()
30 | Kine.Builder()
31 |
32 | .retryPolicy(DefaultRetryPolicy(12500,0,0f))
33 | .logLevel(LogLevel.ERROR)
34 | .build()
35 | }
36 |
37 | @Test
38 | fun httpResponseSuccessTest() {
39 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
40 | val responseRef = AtomicReference()
41 | val countDownLatch = CountDownLatch(1)
42 |
43 | KineRequest.get(mockServer.url("/").toString())
44 | .responseAsJson({ response ->
45 | responseRef.set(response.body)
46 | countDownLatch.countDown()
47 | }, {
48 | Assert.assertTrue(false)
49 | })
50 | Assert.assertTrue(countDownLatch.await(5, TimeUnit.SECONDS))
51 | Assert.assertEquals(testStringResponse, responseRef.get().toString())
52 |
53 | }
54 | @Test
55 | fun httpResponseFailedTest() {
56 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
57 | val errorDetailRef = AtomicReference()
58 | val countDownLatch = CountDownLatch(1)
59 | KineRequest.get(mockServer.url("/").toString())
60 | .responseAsJson({
61 | Assert.assertTrue(false)
62 | }, {e->
63 | errorDetailRef.set(e.exception)
64 | countDownLatch.countDown()
65 | })
66 |
67 | Assert.assertTrue(countDownLatch.await(5, TimeUnit.SECONDS))
68 | Assert.assertTrue(errorDetailRef.get() is HttpStatusCodeException)
69 | }
70 | @Test
71 | fun httpResponseSuccessSyncTest() {
72 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testStringResponse))
73 | val response = KineRequest.get(mockServer.url("/").toString()).responseAsJson()
74 | Assert.assertEquals(testStringResponse, response?.body.toString())
75 | Assert.assertEquals(200, response?.statusCode)
76 | }
77 | @Test
78 | fun httpResponseFailedSyncTest() {
79 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testStringResponse))
80 | try {
81 | KineRequest.get(mockServer.url("/").toString()).responseAsJson()
82 | Assert.assertTrue(false)
83 | }catch (e:Throwable){
84 | Assert.assertTrue(e is HttpStatusCodeException)
85 | }
86 | }
87 | @Test
88 | fun httpResponseSuccessSyncArrayTest() {
89 | mockServer.enqueue(MockResponse().setResponseCode(200).setBody(testJsonArrayResponse))
90 | val response = KineRequest.get(mockServer.url("/").toString()).responseAsJsonArray()
91 | Assert.assertEquals(testJsonArrayResponse, response?.body.toString())
92 | Assert.assertEquals(200, response?.statusCode)
93 | }
94 | @Test
95 | fun httpResponseFailedSyncArrayTest() {
96 | mockServer.enqueue(MockResponse().setResponseCode(402).setBody(testJsonArrayResponse))
97 | try {
98 | KineRequest.get(mockServer.url("/").toString()).responseAsJsonArray()
99 | Assert.assertTrue(false)
100 | }catch (e:Throwable){
101 | Assert.assertTrue(e is HttpStatusCodeException)
102 | }
103 | }
104 | }
--------------------------------------------------------------------------------
/publish.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven'
2 | apply plugin: 'maven-publish'
3 |
4 | version = libraryVersion
5 |
6 |
7 | if (project.hasProperty("android")) {
8 | // Android libraries
9 | task sourcesJar(type: Jar) {
10 | classifier = 'sources'
11 | from android.sourceSets.main.java.srcDirs
12 | }
13 |
14 | task javadoc(type: Javadoc) {
15 | source = android.sourceSets.main.java.srcDirs
16 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
17 | }
18 | } else {
19 | // Java libraries
20 | task sourcesJar(type: Jar, dependsOn: classes) {
21 | classifier = 'sources'
22 | from sourceSets.main.allSource
23 | }
24 | }
25 |
26 | // Generate javador
27 | task javadocJar(type: Jar, dependsOn: javadoc) {
28 | classifier = 'javadoc'
29 | from javadoc.destinationDir
30 | }
31 |
32 | // Create the pom configuration with maven-publish plugin.
33 | def pomConfig = {
34 | licenses {
35 | license {
36 | name licenseName
37 | url licenseUrl
38 | distribution "repo"
39 | }
40 | }
41 | developers {
42 | developer {
43 | id developerId
44 | name developerName
45 | email developerEmail
46 | }
47 | }
48 | scm {
49 | url gitUrl
50 | }
51 | }
52 |
53 | // Get the artifacts
54 | artifacts {
55 | archives javadocJar
56 | archives sourcesJar
57 | }
58 |
59 | // Create the publication with the pom configuration:
60 | publishing {
61 | publications {
62 | MyPublication(MavenPublication) {
63 | artifact sourcesJar
64 | artifact javadocJar
65 | if (project.hasProperty("android")) {
66 | artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
67 | }else{
68 | artifact("$buildDir/libs/${project.getName()}-${libraryVersion}.jar")
69 | }
70 | groupId publishedGroupId
71 | artifactId artifact
72 | version libraryVersion
73 | pom.withXml {
74 | def dependenciesNode = asNode().appendNode('dependencies')
75 | getDependencies(configurations.compile, dependenciesNode)
76 | getDependencies(configurations.api, dependenciesNode)
77 | getDependencies(configurations.implementation, dependenciesNode)
78 | if (project.hasProperty("android")) {
79 | getDependencies(configurations.releaseImplementation, dependenciesNode)
80 | getDependencies(configurations.debugImplementation, dependenciesNode)
81 | getDependencies(configurations.androidTestAnnotationProcessor, dependenciesNode)
82 | getDependencies(configurations.annotationProcessor, dependenciesNode)
83 | }
84 | def root = asNode()
85 | root.appendNode('description', libraryDescription)
86 | root.appendNode('name', libraryName)
87 | root.appendNode('url', siteUrl)
88 | root.children().last() + pomConfig
89 | }
90 | }
91 | }
92 | }
93 |
94 | def getDependencies(config, dependenciesNode) {
95 | config.allDependencies.each {
96 | if (it.group != null && it.name != null) {
97 | if (!hasExistingNode(dependenciesNode, it)) {
98 | def dependencyNode = dependenciesNode.appendNode('dependency')
99 | dependencyNode.appendNode('groupId', it.group)
100 | dependencyNode.appendNode('artifactId', it.name)
101 | dependencyNode.appendNode('version', it.version)
102 | printAdd(it)
103 | if (it.excludeRules.size() > 0) {
104 | def exclusionsNode = dependencyNode.appendNode('exclusions')
105 | printAddExclusions(it)
106 | it.excludeRules.each { rule ->
107 | def exclusionNode = exclusionsNode.appendNode('exclusion')
108 | exclusionNode.appendNode('groupId', rule.group)
109 | if (rule.module != null) {
110 | exclusionNode.appendNode('artifactId', rule.module)
111 | }
112 | }
113 | }
114 | }
115 | }
116 | }
117 | def dependenciesSize = config.allDependencies.size()
118 | if (dependenciesSize > 0) {
119 | println "Added Dependencies for configuration: ${config.getName()}"
120 | println "Dependencies size: ${dependenciesNode.children().size()}"
121 | } else {
122 | println "No dependencies found for configuration: ${config.getName()}"
123 | }
124 | }
125 |
126 | boolean hasExistingNode(dependenciesNode, it) {
127 | for (def item : dependenciesNode.children()) {
128 | def itemGroupId = item.groupId[0].value()
129 | def itemArtifactId = item.artifactId[0].value()
130 | def itemVersion = item.version[0].value()
131 | if (it.group == itemGroupId
132 | && it.name == itemArtifactId
133 | && it.version == itemVersion) {
134 | return true
135 | }
136 | }
137 |
138 | return false
139 | }
140 |
141 | def printAdd(it) {
142 | println "Added dependency: '${it.group}:${it.name}:${it.version}'"
143 | }
144 |
145 | def printAddExclusions(it) {
146 | println "Added exclusions for: '${it.group}:${it.name}:${it.version}'"
147 | }
148 |
--------------------------------------------------------------------------------
/publish1.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven'
2 | apply plugin: 'maven-publish'
3 |
4 | version = libraryVersion
5 |
6 |
7 | if (project.hasProperty("android")) {
8 | // Android libraries
9 | task sourcesJar(type: Jar) {
10 | classifier = 'sources'
11 | from android.sourceSets.main.java.srcDirs
12 | }
13 |
14 | task javadoc(type: Javadoc) {
15 | source = android.sourceSets.main.java.srcDirs
16 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
17 | }
18 | } else {
19 | // Java libraries
20 | task sourcesJar(type: Jar, dependsOn: classes) {
21 | classifier = 'sources'
22 | from sourceSets.main.allSource
23 | }
24 | }
25 |
26 | // Generate javador
27 | task javadocJar(type: Jar, dependsOn: javadoc) {
28 | classifier = 'javadoc'
29 | from javadoc.destinationDir
30 | }
31 |
32 | // Create the pom configuration with maven-publish plugin.
33 | def pomConfig = {
34 | licenses {
35 | license {
36 | name licenseName
37 | url licenseUrl
38 | distribution "repo"
39 | }
40 | }
41 | developers {
42 | developer {
43 | id developerId
44 | name developerName
45 | email developerEmail
46 | }
47 | }
48 | scm {
49 | url gitUrl
50 | }
51 | }
52 |
53 | // Get the artifacts
54 | artifacts {
55 | archives javadocJar
56 | archives sourcesJar
57 | }
58 |
59 | // Create the publication with the pom configuration:
60 | publishing {
61 | publications {
62 | MyPublication(MavenPublication) {
63 | artifact sourcesJar
64 | artifact javadocJar
65 | if (project.hasProperty("android")) {
66 | artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
67 | }else{
68 | artifact("$buildDir/libs/${project.getName()}-${libraryVersion}.jar")
69 | }
70 | groupId publishedGroupId
71 | artifactId artifact
72 | version libraryVersion
73 | pom.withXml {
74 | def dependenciesNode = asNode().appendNode('dependencies')
75 | getDependencies(configurations.compile, dependenciesNode)
76 | getDependencies(configurations.api, dependenciesNode)
77 | getDependencies(configurations.implementation, dependenciesNode)
78 | if (project.hasProperty("android")) {
79 | getDependencies(configurations.releaseImplementation, dependenciesNode)
80 | getDependencies(configurations.debugImplementation, dependenciesNode)
81 | getDependencies(configurations.androidTestAnnotationProcessor, dependenciesNode)
82 | getDependencies(configurations.annotationProcessor, dependenciesNode)
83 | }
84 | def root = asNode()
85 | root.appendNode('description', libraryDescription)
86 | root.appendNode('name', libraryName)
87 | root.appendNode('url', siteUrl)
88 | root.children().last() + pomConfig
89 | }
90 | }
91 | }
92 | }
93 |
94 | def getDependencies(config, dependenciesNode) {
95 | config.allDependencies.each {
96 | if (it.group != null && it.name != null) {
97 | if (!hasExistingNode(dependenciesNode, it)) {
98 | def dependencyNode = dependenciesNode.appendNode('dependency')
99 | dependencyNode.appendNode('groupId', it.group)
100 | dependencyNode.appendNode('artifactId', it.name)
101 | dependencyNode.appendNode('version', it.version)
102 | printAdd(it)
103 | if (it.excludeRules.size() > 0) {
104 | def exclusionsNode = dependencyNode.appendNode('exclusions')
105 | printAddExclusions(it)
106 | it.excludeRules.each { rule ->
107 | def exclusionNode = exclusionsNode.appendNode('exclusion')
108 | exclusionNode.appendNode('groupId', rule.group)
109 | if (rule.module != null) {
110 | exclusionNode.appendNode('artifactId', rule.module)
111 | }
112 | }
113 | }
114 | }
115 | }
116 | }
117 | def dependenciesSize = config.allDependencies.size()
118 | if (dependenciesSize > 0) {
119 | println "Added Dependencies for configuration: ${config.getName()}"
120 | println "Dependencies size: ${dependenciesNode.children().size()}"
121 | } else {
122 | println "No dependencies found for configuration: ${config.getName()}"
123 | }
124 | }
125 |
126 | boolean hasExistingNode(dependenciesNode, it) {
127 | for (def item : dependenciesNode.children()) {
128 | def itemGroupId = item.groupId[0].value()
129 | def itemArtifactId = item.artifactId[0].value()
130 | def itemVersion = item.version[0].value()
131 | if (it.group == itemGroupId
132 | && it.name == itemArtifactId
133 | && it.version == itemVersion) {
134 | return true
135 | }
136 | }
137 |
138 | return false
139 | }
140 |
141 | def printAdd(it) {
142 | println "Added dependency: '${it.group}:${it.name}:${it.version}'"
143 | }
144 |
145 | def printAddExclusions(it) {
146 | println "Added exclusions for: '${it.group}:${it.name}:${it.version}'"
147 | }
148 |
--------------------------------------------------------------------------------
/kine/src/main/java/com/kine/Kine.kt:
--------------------------------------------------------------------------------
1 | package com.kine
2 |
3 | import com.kine.client.KineClient
4 | import com.kine.connections.ConnectionChecker
5 | import com.kine.converters.Converter
6 | import com.kine.internal.RequestManager
7 | import com.kine.log.LogLevel
8 | import com.kine.log.Logger.setDisabledLogs
9 | import com.kine.log.Logger.setLevel
10 | import com.kine.policies.RetryPolicy
11 | import java.util.*
12 |
13 |
14 | /**
15 | * Global class for setting config for all request.
16 | */
17 |
18 | @Suppress("unused")
19 | class Kine private constructor(builder: Builder) {
20 | /**
21 | * `Kine` builder static inner class.
22 | */
23 | class Builder {
24 | internal var kineClients: ArrayList? = null
25 | internal var converters: ArrayList? = null
26 | internal var headers: HashMap? = null
27 | internal var baseUrl: String? = null
28 | internal var retryPolicy: RetryPolicy? = null
29 | internal var networkPolicy = 0
30 | internal var connectionChecker: ConnectionChecker? = null
31 | internal var logLevel = LogLevel.NO_LEVEL
32 | internal var disableAllLogs = false
33 |
34 | fun baseUrl(url: String): Builder {
35 | baseUrl = url
36 | return this
37 | }
38 |
39 | fun addHeader(key: String, value: String): Builder {
40 | if (headers == null) {
41 | headers = HashMap()
42 | }
43 | headers!![key] = value
44 | return this
45 | }
46 |
47 | /**
48 | * Sets the `requestHeader` and returns a reference to `IRetryPolicy`
49 | *
50 | * @param params the `requestHeader` to set
51 | * @return a reference to this RequestBuilder
52 | */
53 | fun headers(params : HashMap?): Builder {
54 | headers = params
55 | return this
56 | }
57 |
58 | fun logLevel(level: Int): Builder {
59 | logLevel = level
60 | return this
61 | }
62 |
63 | fun connectionChecker(connectionChecker: ConnectionChecker?): Builder {
64 | this.connectionChecker = connectionChecker
65 | return this
66 | }
67 |
68 | fun disableAllLogs(disableAllLogs: Boolean): Builder {
69 | this.disableAllLogs = disableAllLogs
70 | return this
71 | }
72 |
73 | /**
74 | * Sets the `retryPolicy` and returns a reference to `IReqTAG`
75 | *
76 | * @param retryPolicy the `retryPolicy` to set
77 | * @return a reference to this RequestBuilder
78 | */
79 | fun retryPolicy(retryPolicy: RetryPolicy?): Builder {
80 | this.retryPolicy = retryPolicy
81 | return this
82 | }
83 |
84 | /**
85 | * Specifies the [CacheControl] to use for this request. You may specify additional policy
86 | * options using the varargs parameter.
87 | */
88 | fun cacheControl(networkPolicy: Int): Builder {
89 | this.networkPolicy = networkPolicy
90 | return this
91 | }
92 |
93 | /**
94 | * Sets the `KineClient` and returns a reference to this RequestBuilder so that the methods can be chained together.
95 | *
96 | * @param `kineClient` the `KineClient` to set
97 | * @return a reference to this RequestBuilder
98 | */
99 | fun client(kineClient: KineClient): Builder {
100 | this.kineClients= arrayListOf(kineClient)
101 | return this
102 | }
103 | fun clients(kineClient: ArrayList?): Builder {
104 | this.kineClients = kineClient
105 | return this
106 | }
107 | fun addClient(kineClient: KineClient): Builder {
108 | if (this.kineClients == null) {
109 | this.kineClients = ArrayList(2)
110 | }
111 | this.kineClients!!.add(kineClient)
112 | return this
113 | }
114 | fun converters(converters: ArrayList?): Builder {
115 | this.converters = converters
116 | return this
117 | }
118 |
119 | fun converter(converter: Converter): Builder {
120 | this.converters = arrayListOf(converter)
121 | return this
122 | }
123 |
124 | fun addConverter(converters: Converter): Builder {
125 | this.converters = this.converters?: arrayListOf()
126 | this.converters!!.add(converters)
127 | return this
128 | }
129 |
130 |
131 |
132 | /**
133 | * Returns a `GlobalRequestBuilder` built from the parameters previously set.
134 | *
135 | * @return a `GlobalRequestBuilder` built with parameters of this `GlobalRequestBuilder.RequestBuilder`
136 | */
137 | fun build(): Kine {
138 | return Kine(this)
139 | }
140 | }
141 |
142 | companion object {
143 | fun newBuilder(): Builder {
144 | return Builder()
145 | }
146 | fun cancelAllRequests(tag: String?=null) {
147 | RequestManager.cancelAllRequests(tag)
148 | }
149 | }
150 |
151 | init {
152 | RequestManager.setRetryPolicy(builder.retryPolicy)
153 | RequestManager.setNetworkPolicy(builder.networkPolicy)
154 | RequestManager.setHeaders(builder.headers)
155 | RequestManager.setClients(builder.kineClients)
156 | RequestManager.setConverters(builder.converters)
157 | RequestManager.setConnectionChecker(builder.connectionChecker)
158 | RequestManager.setBaseUrl(builder.baseUrl)
159 | setLevel(builder.logLevel)
160 | setDisabledLogs(builder.disableAllLogs)
161 | }
162 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kine/test/TestFragment.kt:
--------------------------------------------------------------------------------
1 | package com.kine.test
2 |
3 | import android.os.Bundle
4 | import android.os.Environment
5 | import android.util.Log
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import android.widget.AdapterView
10 | import android.widget.AdapterView.OnItemSelectedListener
11 | import android.widget.ArrayAdapter
12 | import androidx.fragment.app.Fragment
13 | import com.kine.Kine
14 | import com.kine.converters.GsonConverter
15 | import com.kine.converters.MoshiConverter
16 | import com.kine.extensions.downloadTo
17 | import com.kine.imageloader.extensions.loadBitmapResponseFromUrl
18 | import com.kine.log.LogLevel
19 | import com.kine.test.model.CreateUserResponse
20 | import com.kine.test.model.UserListResponse
21 | import kotlinx.android.synthetic.main.fragment_main.*
22 | import org.json.JSONObject
23 | import java.io.File
24 |
25 |
26 | /**
27 | * A placeholder fragment containing a simple view.
28 | */
29 | class TestFragment : Fragment() {
30 | var pos = 0
31 | override fun onCreateView(
32 | inflater: LayoutInflater,
33 | container: ViewGroup?,
34 | savedInstanceState: Bundle?
35 | ): View {
36 | return inflater.inflate(R.layout.fragment_main, container, false)
37 | }
38 |
39 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
40 | super.onViewCreated(view, savedInstanceState)
41 |
42 | Kine.Builder()
43 | .baseUrl(ConfigUtils.dummyBaseUrl)
44 | .logLevel(LogLevel.ERROR)
45 | .build()
46 | send.setOnClickListener {
47 | when (pos) {
48 | 0 -> {
49 | NetworkUtils.getRequest(UserListResponse::class.java, parseTime, resp){
50 | it.converter(GsonConverter())
51 | }
52 | }
53 | 1 -> {
54 | NetworkUtils.postRequest(CreateUserResponse::class.java, parseTime, resp)
55 | { it.converter(GsonConverter())}
56 | }
57 | 2 -> {
58 | NetworkUtils.getRequest(UserListResponse::class.java, parseTime, resp)
59 | {it.converter(MoshiConverter()) }
60 | }
61 | 3 -> {
62 | NetworkUtils.postRequest(CreateUserResponse::class.java, parseTime, resp)
63 | {it.converter(MoshiConverter()) }
64 | }
65 | 4 -> {
66 | NetworkUtils.getRequest(JSONObject::class.java, parseTime, resp)
67 | }
68 | 5 -> {
69 | NetworkUtils.postRequest(JSONObject::class.java, parseTime, resp)
70 | { it -> it }
71 | }
72 | 6 -> {
73 | NetworkUtils.getRequest(String::class.java, parseTime, resp)
74 | }
75 | 7 -> {
76 | NetworkUtils.postRequest(String::class.java, parseTime, resp)
77 | { it -> it }
78 | }
79 | 8 -> {
80 | testRequest()
81 | }
82 | 9 -> {
83 | downloadImage()
84 | }
85 | 10 -> {
86 | NetworkUtils.getRxRequest(UserListResponse::class.java, parseTime, resp)
87 | }
88 | 11 -> {
89 | NetworkUtils.getRxFRequest(UserListResponse::class.java, parseTime, resp)
90 | }
91 | 12 -> {
92 | NetworkUtils.getRxORequest(UserListResponse::class.java, parseTime, resp)
93 | }
94 | 13 -> {
95 | NetworkUtils.getCoroutineRequest(UserListResponse::class.java, parseTime, resp)
96 | }
97 | 14 -> {
98 | NetworkUtils.getJsonArrayRequest( parseTime, resp)
99 | }
100 | else->{
101 |
102 | }
103 | }
104 | }
105 | val array: MutableList = ArrayList()
106 | array.add("Gson Get Request")
107 | array.add("Gson Post Request")
108 | array.add("Moshi Get Request")
109 | array.add("Moshi Post Request")
110 | array.add("Json Get Request")
111 | array.add("Json Post Request")
112 | array.add("String Get Request")
113 | array.add("String Post Request")
114 | array.add("Image Loading")
115 | array.add("Download File")
116 | array.add("RX Single Request")
117 | array.add("RX Flowable Request")
118 | array.add("RX Observable Request")
119 | array.add("Coroutine Request")
120 | array.add("JsonArray Get Request")
121 | spinner.adapter = ArrayAdapter(requireActivity(), android.R.layout.simple_list_item_1, array)
122 | spinner.onItemSelectedListener = object : OnItemSelectedListener {
123 | override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
124 | Log.e("pos", "pos is$position")
125 | this@TestFragment.pos = position
126 |
127 | }
128 |
129 | override fun onNothingSelected(parent: AdapterView<*>?) {
130 |
131 | }
132 | }
133 |
134 | }
135 |
136 | private fun downloadImage() {
137 |
138 | val time = System.currentTimeMillis()
139 | "http://speedtest.ftp.otenet.gr/files/test10Mb.db".downloadTo(
140 | File(Environment.getExternalStorageDirectory(),"test10Mb.db"),{downloaded,total->
141 | Log.e("progress", (downloaded*100/total).toString())
142 | activity?.runOnUiThread {
143 | resp!!.text = "progress ${((downloaded*100)/total)}"
144 | }
145 | }, { response ->
146 | Log.e("response1", response.networkTimeMs.toString() + " " + response.parseTime)
147 | parseTime!!.text = ("time:${response.networkTimeMs} parse time:${response.parseTime}" +
148 | " total time:${System.currentTimeMillis() - time}").trimIndent()
149 | resp!!.text ="saved as "+ response.body?.path?:"null"
150 | }, { e ->
151 | e.printStackTrace()
152 | activity?.runOnUiThread {
153 | resp.text = e.message()
154 | }
155 | })
156 | }
157 |
158 | private fun testRequest() {
159 | val time = System.currentTimeMillis()
160 | "http://i.imgur.com/2M7Hasn.png".loadBitmapResponseFromUrl( { response ->
161 | Log.e("response1", response.networkTimeMs.toString() + " " + response.parseTime)
162 | parseTime!!.text = ("time:${response.networkTimeMs} parse time:${response.parseTime}" +
163 | " total time:${System.currentTimeMillis() - time}").trimIndent()
164 | resp!!.text = response.body.toString()
165 | image!!.setImageBitmap(response.body)
166 | }, { e ->
167 | resp.text = e.message()
168 | })
169 | }
170 |
171 | }
172 |
--------------------------------------------------------------------------------