Skip to content

Commit

Permalink
Merge pull request #195 from itachi1706/194-api-handling
Browse files Browse the repository at this point in the history
feat: Implemented a basic API handler with Volley
  • Loading branch information
itachi1706 authored Jan 30, 2024
2 parents 6abd027 + 1346ba3 commit cdc21fa
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 15 deletions.
17 changes: 4 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,11 @@ dependencies {
}
```

## Usage - Artifactory (DEPRECATED)
To use this library in an Android Project, add the following lines into your app-level build.gradle file
Note: If you are using artifactory, Move to GitHub Packages or Maven Central ASAP. This repo will be removed soon
## API Helper Usage
To use the API Helper, you will need to add the following lines into your `AndroidManifest.xml` file

```gradle
repositories {
maven {
url "https://itachi1706.jfrog.io/artifactory/ccn-android-libs/"
}
}
dependencies {
implementation 'com.itachi1706.helpers:helperlib:<latest-version>' // See badge for latest version
}
```xml
<uses-permission android:name="android.permission.INTERNET" />
```

## Helper Classes in the library
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
plugins {
id 'com.android.library' version '8.2.1' apply false
id 'org.jetbrains.kotlin.android' version '1.9.22' apply false
id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.22' apply false
id "org.sonarqube" version "4.4.1.3373"
}

Expand Down
3 changes: 3 additions & 0 deletions helperlib/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
id 'org.jetbrains.kotlin.plugin.serialization'
}

android {
Expand Down Expand Up @@ -61,6 +62,8 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

implementation 'com.google.android.material:material:1.11.0'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2'
implementation 'com.android.volley:volley:1.2.1'
}

apply from: 'publish.gradle'
9 changes: 7 additions & 2 deletions helperlib/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

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

<!-- Remove UnusedAttribute warning when SDK version is 23 or higher -->
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme" />
android:theme="@style/AppTheme"
android:usesCleartextTraffic="false"
tools:ignore="UnusedAttribute" />
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package com.itachi1706.helperlib.helpers

import android.content.Context
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.Response
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import com.itachi1706.helperlib.objects.ApiResponse
import kotlinx.serialization.json.Json

@Suppress("unused")
/**
* API Call Handling class
* @param context Context
* @param baseUrl Base URL to use (Default: https://api.itachi1706.com)
* @param tag Tag to use for Volley Request Queue (Default: DEFAULT)
*/
class ApiCallsHelper(
context: Context,
private val baseUrl: String = DEFAULT_URL,
private val tag: String = "DEFAULT"
) {

/**
* Volley Request Queue
*/
private val queue: RequestQueue = Volley.newRequestQueue(context)

/**
* Cancels all requests with the tag
*/
fun cancelAllRequests() {
queue.cancelAll(tag)
}

/**
* Gets the current sequence number of the request queue
* @return Sequence Number
*/
fun getSequenceNumber(): Int {
return queue.sequenceNumber
}

/**
* Makes a GET Call to the specified path
* @param path Path to call
* @param listener Listener to handle the response on
* @see ApiCallListener
* @see ApiResponse
* @see StringRequest
* @see internalCallHandling
*/
fun makeGetCall(path: String, listener: ApiCallListener) {
internalCallHandling(Request.Method.GET, path, null, listener)
}

/**
* Makes a POST Call to the specified path
* @param path Path to call
* @param data Data to send
* @param listener Listener to handle the response on
* @see ApiCallListener
* @see ApiResponse
* @see StringRequest
* @see internalCallHandling
*/
fun makePostCall(path: String, data: String?, listener: ApiCallListener) {
internalCallHandling(Request.Method.POST, path, data, listener)
}

/**
* Makes a PUT Call to the specified path
* @param path Path to call
* @param data Data to send
* @param listener Listener to handle the response on
* @see ApiCallListener
* @see ApiResponse
* @see StringRequest
* @see internalCallHandling
*/
fun makePutCall(path: String, data: String?, listener: ApiCallListener) {
internalCallHandling(Request.Method.PUT, path, data, listener)
}

/**
* Makes a DELETE Call to the specified path
* @param path Path to call
* @param listener Listener to handle the response on
* @see ApiCallListener
* @see ApiResponse
* @see StringRequest
* @see internalCallHandling
*/
fun makeDeleteCall(path: String, listener: ApiCallListener) {
internalCallHandling(Request.Method.DELETE, path, null, listener)
}

/**
* Makes a HTTP Call to the specified path
* @param method HTTP Method to use
* @param path Path to call
* @param data Data to send if any
* @param listener Listener to handle the response on
* @see ApiCallListener
* @see ApiResponse
* @see StringRequest
* @see internalCallHandling
*/
private fun internalCallHandling(
method: Int,
path: String,
data: String?,
listener: ApiCallListener
) {
// Make a HTTP Call to the URL and path
val url = "$baseUrl/$path"

val successListener = Response.Listener { response: String ->
listener.onApiCallSuccess(serializeResponse(response))
}
val failedListener = Response.ErrorListener { error ->
listener.onApiCallError(
error?.message ?: UNKNOWN_ERROR
)
}

val request: StringRequest = if (data != null) {
object : StringRequest(method, url, successListener, failedListener) {
override fun getBody(): ByteArray {
return data.toByteArray()
}

override fun getBodyContentType(): String {
return "application/json"
}
}
} else {
StringRequest(method, url, successListener, failedListener)
}

request.tag = tag
queue.add(request)
}

/**
* Serializes the response into an ApiResponse object
* @param response Response to serialize
* @return ApiResponse object
*/
private fun serializeResponse(response: String): ApiResponse {
return Json.decodeFromString<ApiResponse>(response)
}

/**
* Interface to handle API Calls
*/
interface ApiCallListener {
/**
* Called when API Call is successful
* @param response ApiResponse object
*/
fun onApiCallSuccess(response: ApiResponse)

/**
* Called when API Call fails
* @param error Error message
*/
fun onApiCallError(error: String)
}

companion object {
private const val LOG_TAG = "ApiCallsHelper"
private const val UNKNOWN_ERROR = "Unknown Error"
private const val DEFAULT_URL = "https://api.itachi1706.com"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.itachi1706.helperlib.objects

import java.io.Serializable
import java.util.Date

/**
* API Response Object
* @constructor Creates an API Response Object
* @since 1.0.0
* @property date Date of the response
* @property status Status Code of the response
* @property message Message of the response
* @property success Success of the response
* @property data Data of the response
* @property error Error of the response
* @see Serializable
* @see Date
*/
data class ApiResponse(
val date: Date,
val status: Int,
val message: String,
val success: Boolean,
val data: Any? = null,
val error: String? = null
) : Serializable

0 comments on commit cdc21fa

Please sign in to comment.