Gradle dependencies updates, Api class and handling added.

This commit is contained in:
2020-04-19 12:29:36 +01:00
parent 5b86cc1f8e
commit 96c0b944c1
9 changed files with 228 additions and 6 deletions

View File

@@ -1,6 +1,7 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 29
@@ -36,4 +37,33 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
//Retrofit and GSON
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'
//Kotlin Coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0"
// ViewModel and LiveData
implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"
//New Material Design
implementation 'com.google.android.material:material:1.1.0-alpha10'
//Kodein Dependency Injection
implementation "org.kodein.di:kodein-di-generic-jvm:6.2.1"
implementation "org.kodein.di:kodein-di-framework-android-x:6.2.1"
//Android Room
implementation "androidx.room:room-runtime:2.2.0-rc01"
implementation "androidx.room:room-ktx:2.2.0-rc01"
kapt "androidx.room:room-compiler:2.2.0-rc01"
implementation 'com.xwray:groupie:2.3.0'
implementation 'com.xwray:groupie-kotlin-android-extensions:2.3.0'
implementation 'com.xwray:groupie-databinding:2.3.0'
implementation "androidx.preference:preference-ktx:1.1.0"
}

View File

@@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.h_mal.candyspace">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"

View File

@@ -1,4 +1,37 @@
package com.example.h_mal.candyspace.data.api
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query
interface ApiClass {
@GET("users?")
suspend fun getUsersFromApi(@Query("inname") inname: String): Response<User>
companion object{
operator fun invoke(
networkConnectionInterceptor: NetworkConnectionInterceptor,
queryParamsInterceptor: QueryParamsInterceptor
) : ApiClass{
val okkHttpclient = OkHttpClient.Builder()
.addNetworkInterceptor(networkConnectionInterceptor)
.addInterceptor(queryParamsInterceptor)
.build()
return Retrofit.Builder()
.client(okkHttpclient)
.baseUrl("https://api.stackexchange.com/2.2/")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiClass::class.java)
}
}
}

View File

@@ -0,0 +1,43 @@
package com.example.h_mal.candyspace.data.api
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import okhttp3.Interceptor
import okhttp3.Response
import java.io.IOException
/*
*
*
*/
class NetworkConnectionInterceptor(
context: Context
) : Interceptor {
private val applicationContext = context.applicationContext
override fun intercept(chain: Interceptor.Chain): Response {
if (!isInternetAvailable()){
throw IOException("Make sure you have an active data connection")
}
return chain.proceed(chain.request())
}
private fun isInternetAvailable(): Boolean {
var result = false
val connectivityManager =
applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
connectivityManager?.let {
it.getNetworkCapabilities(connectivityManager.activeNetwork)?.apply {
result = when {
hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
else -> false
}
}
}
return result
}
}

View File

@@ -0,0 +1,29 @@
package com.example.h_mal.candyspace.data.api
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
class QueryParamsInterceptor : Interceptor{
override fun intercept(chain: Interceptor.Chain): Response {
val original = chain.request()
val originalHttpUrl = original.url()
val url = originalHttpUrl.newBuilder()
.addQueryParameter("site", "stackoverflow")
.addQueryParameter("pagesize","20")
.addQueryParameter("order","desc")
.addQueryParameter("sort","reputation")
.build()
// Request customization: add request headers
// Request customization: add request headers
val requestBuilder: Request.Builder = original.newBuilder()
.url(url)
val request: Request = requestBuilder.build()
return chain.proceed(request)
}
}

View File

@@ -0,0 +1,29 @@
package com.example.h_mal.candyspace.data.api
import org.json.JSONException
import org.json.JSONObject
import retrofit2.Response
import java.io.IOException
abstract class ResponseUnwrap {
suspend fun<T: Any> apiRequest(call: suspend () -> Response<T>) : T{
val response = call.invoke()
if(response.isSuccessful){
return response.body()!!
}else{
val error = response.errorBody()?.string()
val message = StringBuilder()
error?.let{
try{
message.append(JSONObject(it).getString("error_message"))
}catch(e: JSONException){ }
message.append("\n")
}
message.append("Error Code: ${response.code()}")
throw IOException(message.toString())
}
}
}

View File

@@ -0,0 +1,38 @@
package com.example.h_mal.candyspace.data.api
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName
class User {
@SerializedName("last_modified_date")
@Expose
var lastModifiedDate: Int? = null
@SerializedName("reputation")
@Expose
var reputation: Int? = null
@SerializedName("creation_date")
@Expose
var creationDate: Int? = null
@SerializedName("user_type")
@Expose
var userType: String? = null
@SerializedName("user_id")
@Expose
var userId: Int? = null
@SerializedName("location")
@Expose
var location: String? = null
@SerializedName("website_url")
@Expose
var websiteUrl: String? = null
@SerializedName("link")
@Expose
var link: String? = null
@SerializedName("profile_image")
@Expose
var profileImage: String? = null
@SerializedName("display_name")
@Expose
var displayName: String? = null
}

View File

@@ -1,5 +1,14 @@
package com.example.h_mal.candyspace.data.repositories
class Repository {
import com.example.h_mal.candyspace.data.api.ApiClass
import com.example.h_mal.candyspace.data.api.ResponseUnwrap
import com.example.h_mal.candyspace.data.api.User
class Repository(
private val api: ApiClass
): ResponseUnwrap() {
suspend fun sdasda(username: String): User {
return apiRequest { api.getUsersFromApi(username) }
}
}

View File

@@ -7,14 +7,24 @@
android:layout_height="match_parent"
tools:context=".ui.main.MainFragment">
<TextView
android:id="@+id/message"
android:layout_width="wrap_content"
<androidx.appcompat.widget.SearchView
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="MainFragment"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<view class="androidx.appcompat.app.AlertController$RecycleListView"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/search_bar"
tools:listitem="@android:layout/simple_list_item_2">
</view>
</androidx.constraintlayout.widget.ConstraintLayout>