commit
271e4011d0
@ -0,0 +1,34 @@
|
|||||||
|
package adaptator
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import api.User
|
||||||
|
import but.androidstudio.tetris.R
|
||||||
|
import javax.xml.xpath.XPath
|
||||||
|
|
||||||
|
class RecyclerViewAdaptator(var userData: List<User>): RecyclerView.Adapter<RecyclerViewAdaptator.ItemViewHolder>(){
|
||||||
|
class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
|
||||||
|
val textViewUsername: TextView = view.findViewById(R.id.item_username)
|
||||||
|
val textViewXp: TextView = view.findViewById(R.id.item_xp)
|
||||||
|
val textViewCountry: TextView = view.findViewById(R.id.item_country)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
|
||||||
|
val adapterLayout = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.item_layout, parent, false)
|
||||||
|
return ItemViewHolder(adapterLayout)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = userData.size
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
|
||||||
|
holder.textViewUsername.text = userData[position].username
|
||||||
|
holder.textViewXp.text = userData[position].xp.toString()
|
||||||
|
holder.textViewCountry.text = userData[position].country
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
class Data(val users: List<User>)
|
@ -0,0 +1,9 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.http.GET
|
||||||
|
|
||||||
|
interface TetrisAPI {
|
||||||
|
@GET("users/lists/xp")
|
||||||
|
fun getAllUsers() : Call<UserResponse>
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.GsonBuilder
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
|
class TetrisClient(okHttpClient: OkHttpClient) {
|
||||||
|
private val api: TetrisAPI
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
// Create Gson object with lenient policy
|
||||||
|
val gson = GsonBuilder()
|
||||||
|
.setLenient()
|
||||||
|
.create()
|
||||||
|
|
||||||
|
// Create Retrofit instance
|
||||||
|
val retrofit = Retrofit.Builder()
|
||||||
|
.baseUrl("https://ch.tetr.io/api/")
|
||||||
|
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||||
|
.client(okHttpClient)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
|
||||||
|
// Create API instance
|
||||||
|
api = retrofit.create(TetrisAPI::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUsers(callback: (List<User>?, Throwable?) -> Unit) {
|
||||||
|
api.getAllUsers().enqueue(object : Callback<UserResponse> {
|
||||||
|
override fun onResponse(call: Call<UserResponse>, response: Response<UserResponse>) {
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
// API call successful, parse response body
|
||||||
|
val users = response.body()?.data?.users
|
||||||
|
callback(users, null)
|
||||||
|
} else {
|
||||||
|
// API call failed, handle error
|
||||||
|
val error = Exception("API call failed with code ${response.code()}")
|
||||||
|
callback(null, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(call: Call<UserResponse>, t: Throwable) {
|
||||||
|
// API call failed, handle error
|
||||||
|
callback(null, t)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
class User(val id: String,
|
||||||
|
val username: String,
|
||||||
|
val role: String,
|
||||||
|
val xp: Double,
|
||||||
|
val supporter: Boolean,
|
||||||
|
val verified: Boolean,
|
||||||
|
val country: String,
|
||||||
|
val timestamp: String,
|
||||||
|
val gamesPlayed: Int,
|
||||||
|
val gamesWon: Int,
|
||||||
|
val gameTime: Int) {
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
class UserResponse(val success: Boolean, val data: Data)
|
@ -0,0 +1,83 @@
|
|||||||
|
package but.androidstudio.tetris
|
||||||
|
|
||||||
|
import adaptator.RecyclerViewAdaptator
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import api.TetrisClient
|
||||||
|
import api.User
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.security.KeyStore
|
||||||
|
import java.security.SecureRandom
|
||||||
|
import java.security.cert.CertificateFactory
|
||||||
|
import javax.net.ssl.SSLContext
|
||||||
|
import javax.net.ssl.TrustManagerFactory
|
||||||
|
import javax.net.ssl.X509TrustManager
|
||||||
|
|
||||||
|
|
||||||
|
class InfoUserFragment : Fragment() {
|
||||||
|
private lateinit var recyclerView: RecyclerView
|
||||||
|
private lateinit var adaptator: RecyclerViewAdaptator
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
// Inflate the layout for this fragment
|
||||||
|
val view = inflater.inflate(R.layout.fragment_info_user, container, false)
|
||||||
|
// Set up RecyclerView
|
||||||
|
recyclerView = view.findViewById<RecyclerView>(R.id.tableUser)
|
||||||
|
recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||||
|
adaptator =RecyclerViewAdaptator(listOf())
|
||||||
|
recyclerView.adapter = adaptator
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
// Read the SSL certificate for the request
|
||||||
|
val certificateStream : InputStream = resources.openRawResource(R.raw.sni_cloudflaressl_com)
|
||||||
|
|
||||||
|
// We create a certificateFactory to extract de data of the certificateInputStream
|
||||||
|
val certificateFactory = CertificateFactory.getInstance("X.509")
|
||||||
|
val certificate = certificateFactory.generateCertificate(certificateStream)
|
||||||
|
|
||||||
|
//To specified the certificate to used
|
||||||
|
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
|
||||||
|
keyStore.load(null, null)
|
||||||
|
keyStore.setCertificateEntry("ca", certificate)
|
||||||
|
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
|
||||||
|
trustManagerFactory.init(keyStore)
|
||||||
|
|
||||||
|
//To create a SSL context
|
||||||
|
val sslContext = SSLContext.getInstance("SSL")
|
||||||
|
sslContext.init(null, trustManagerFactory.trustManagers, SecureRandom())
|
||||||
|
|
||||||
|
// We create a OkHttpClient to use the SSLContext
|
||||||
|
val okHttpClient: OkHttpClient = OkHttpClient.Builder()
|
||||||
|
.sslSocketFactory(sslContext.socketFactory, trustManagerFactory.trustManagers[0] as X509TrustManager)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val client = TetrisClient(okHttpClient)
|
||||||
|
|
||||||
|
client.getUsers { users, error ->
|
||||||
|
if (error != null) {
|
||||||
|
// Handle error
|
||||||
|
println("Error: ${error.message}")
|
||||||
|
} else {
|
||||||
|
// Handle success
|
||||||
|
adaptator.userData = users!!
|
||||||
|
recyclerView.adapter?.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Username"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="XP"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Country"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:id="@+id/tableUser"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
</LinearLayout>
|
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/item_username"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/item_xp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/item_country"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -0,0 +1,30 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFLTCCBNOgAwIBAgIQBVK/egzBVp4B3exMiwpZ0zAKBggqhkjOPQQDAjBKMQsw
|
||||||
|
CQYDVQQGEwJVUzEZMBcGA1UEChMQQ2xvdWRmbGFyZSwgSW5jLjEgMB4GA1UEAxMX
|
||||||
|
Q2xvdWRmbGFyZSBJbmMgRUNDIENBLTMwHhcNMjIwNTIzMDAwMDAwWhcNMjMwNTIz
|
||||||
|
MjM1OTU5WjB1MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQG
|
||||||
|
A1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQQ2xvdWRmbGFyZSwgSW5jLjEe
|
||||||
|
MBwGA1UEAxMVc25pLmNsb3VkZmxhcmVzc2wuY29tMFkwEwYHKoZIzj0CAQYIKoZI
|
||||||
|
zj0DAQcDQgAEtjMD8/gzUYFeKx2j9gc0o3ZHCQH48eYDZmKkiZjB10TyyT4QH2Hn
|
||||||
|
3QfD8eRHKrTU6PlnYol/p2WL/5MnVff9ZKOCA24wggNqMB8GA1UdIwQYMBaAFKXO
|
||||||
|
N+rrsHUOlGeItEX62SQQh5YfMB0GA1UdDgQWBBSUimg81mec3SrIMXpku3tYBLc0
|
||||||
|
qzA0BgNVHREELTArggkqLnRldHIuaW+CB3RldHIuaW+CFXNuaS5jbG91ZGZsYXJl
|
||||||
|
c3NsLmNvbTAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
|
||||||
|
AQUFBwMCMHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNv
|
||||||
|
bS9DbG91ZGZsYXJlSW5jRUNDQ0EtMy5jcmwwN6A1oDOGMWh0dHA6Ly9jcmw0LmRp
|
||||||
|
Z2ljZXJ0LmNvbS9DbG91ZGZsYXJlSW5jRUNDQ0EtMy5jcmwwPgYDVR0gBDcwNTAz
|
||||||
|
BgZngQwBAgIwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20v
|
||||||
|
Q1BTMHYGCCsGAQUFBwEBBGowaDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGln
|
||||||
|
aWNlcnQuY29tMEAGCCsGAQUFBzAChjRodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5j
|
||||||
|
b20vQ2xvdWRmbGFyZUluY0VDQ0NBLTMuY3J0MAwGA1UdEwEB/wQCMAAwggF+Bgor
|
||||||
|
BgEEAdZ5AgQCBIIBbgSCAWoBaAB1AOg+0No+9QY1MudXKLyJa8kD08vREWvs62nh
|
||||||
|
d31tBr1uAAABgO6iKgwAAAQDAEYwRAIgAdeVVw138Q+T/kUu/RdyojBt8cYE3+Ta
|
||||||
|
C8mJjoLZvY4CIDUEiw5lfUGLpXoH8X4HB4zISWVfIpGf2UmBCZ0goKMMAHcANc8Z
|
||||||
|
G7+xbFe/D61MbULLu7YnICZR6j/hKu+oA8M71kwAAAGA7qIqLQAABAMASDBGAiEA
|
||||||
|
lQ2PRS+mQxU0RkZm73SCIUDfLjSMjRFiCXjLJo7FJ78CIQDhgBsqhkZULuN8T0BJ
|
||||||
|
kOSZRde6wJpeD3pFg/qIzgMo6gB2ALc++yTfnE26dfI5xbpY9Gxd/ELPep81xJ4d
|
||||||
|
CYEl7bSZAAABgO6iKh0AAAQDAEcwRQIhAOJMesd21/xYT7JgrgKPGUo4WJqlAsvV
|
||||||
|
HurtPpkBy8cCAiAsSKnLvxW+og6m7YTmKnjEPVWdl2wVejrM2djmJd13JDAKBggq
|
||||||
|
hkjOPQQDAgNIADBFAiBLUqhRLadDrgcbV6AeabEnpLy7LfMj7btLFB3DLLYL0QIh
|
||||||
|
AJg9/jdsmybn7D3mhywg0hAmWWSlqLVp2jp47GU8mJCe
|
||||||
|
-----END CERTIFICATE-----
|
Loading…
Reference in new issue