Compare commits
2 Commits
fa0905486a
...
e6d8a5b7aa
Author | SHA1 | Date | |
---|---|---|---|
e6d8a5b7aa | |||
821162964b |
1
.idea/gradle.xml
generated
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
|
@ -56,4 +56,10 @@ dependencies {
|
|||||||
androidTestImplementation(libs.androidx.ui.test.junit4)
|
androidTestImplementation(libs.androidx.ui.test.junit4)
|
||||||
debugImplementation(libs.androidx.ui.tooling)
|
debugImplementation(libs.androidx.ui.tooling)
|
||||||
debugImplementation(libs.androidx.ui.test.manifest)
|
debugImplementation(libs.androidx.ui.test.manifest)
|
||||||
|
|
||||||
|
implementation(libs.retrofit)
|
||||||
|
implementation(libs.converter.gson)
|
||||||
|
implementation(libs.kotlinx.coroutines.android)
|
||||||
|
implementation(libs.kotlinx.coroutines.core)
|
||||||
|
|
||||||
}
|
}
|
BIN
app/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 36 KiB |
@ -0,0 +1,22 @@
|
|||||||
|
package ru.vendetti.bitcoin_summarizer
|
||||||
|
|
||||||
|
import retrofit2.Response
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Query
|
||||||
|
|
||||||
|
// Retrofit-API-интерфейс
|
||||||
|
interface CryptoApiService {
|
||||||
|
// Получение индекса страха и жадности (по умолчанию за 30 дней)
|
||||||
|
@GET("fng/")
|
||||||
|
suspend fun getFearAndGreedIndex(
|
||||||
|
@Query("limit") limit: Int = 30
|
||||||
|
): Response<FearAndGreedResponse>
|
||||||
|
|
||||||
|
// Получение глобальной информации
|
||||||
|
@GET("v1/global/")
|
||||||
|
suspend fun getGlobalData(): Response<GlobalResponse>
|
||||||
|
|
||||||
|
// Получение данных Bitcoin
|
||||||
|
@GET("v1/ticker/bitcoin/")
|
||||||
|
suspend fun getBitcoinTicker(): Response<TickerResponse>
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package ru.vendetti.bitcoin_summarizer
|
||||||
|
|
||||||
|
//Репозиторий для обработки запросов
|
||||||
|
class CryptoRepository(private val apiService: CryptoApiService) {
|
||||||
|
/**
|
||||||
|
* Запрашивает данные для Bitcoin-тикера
|
||||||
|
*/
|
||||||
|
suspend fun fetchBitcoinTicker(): TickerResponse? {
|
||||||
|
return try {
|
||||||
|
val response = apiService.getBitcoinTicker()
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
response.body()
|
||||||
|
} else {
|
||||||
|
println("Ошибка запроса Bitcoin Ticker: ${response.code()}")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println("Exception при получении Bitcoin Ticker: ${e.localizedMessage}")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запрашивает глобальные данные крипторынка
|
||||||
|
*/
|
||||||
|
suspend fun fetchGlobalData(): GlobalResponse? {
|
||||||
|
return try {
|
||||||
|
val response = apiService.getGlobalData()
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
response.body()
|
||||||
|
} else {
|
||||||
|
println("Ошибка запроса Global Data: ${response.code()}")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println("Exception при получении Global Data: ${e.localizedMessage}")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запрашивает индекс страха и жадности за указанный период (по умолчанию 30 дней)
|
||||||
|
*/
|
||||||
|
suspend fun fetchFearAndGreedData(limit: Int = 30): FearAndGreedResponse? {
|
||||||
|
return try {
|
||||||
|
val response = apiService.getFearAndGreedIndex(limit)
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
response.body()
|
||||||
|
} else {
|
||||||
|
println("Ошибка запроса Fear & Greed Index: ${response.code()}")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println("Exception при получении Fear & Greed Index: ${e.localizedMessage}")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package ru.vendetti.bitcoin_summarizer
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
// Обёртка для данных (тут вложенность есть и это API v2, а не v1, поэтому чуть сложнее структура, чем в GlobalResponse.kt)
|
||||||
|
data class FearAndGreedResponse(
|
||||||
|
@SerializedName("name")
|
||||||
|
val name: String,
|
||||||
|
@SerializedName("data")
|
||||||
|
val dataList: List<FearAndGreedData>
|
||||||
|
)
|
||||||
|
|
||||||
|
// Сами данные
|
||||||
|
data class FearAndGreedData(
|
||||||
|
@SerializedName("value")
|
||||||
|
val value: String,
|
||||||
|
@SerializedName("value_classification")
|
||||||
|
val valueClassification: String,
|
||||||
|
@SerializedName("timestamp")
|
||||||
|
val timestamp: String,
|
||||||
|
@SerializedName("time_until_update")
|
||||||
|
val timeUntilUpdate: String
|
||||||
|
)
|
@ -0,0 +1,15 @@
|
|||||||
|
package ru.vendetti.bitcoin_summarizer
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
// Обёртка для данных
|
||||||
|
data class GlobalResponse(
|
||||||
|
val data: GlobalData
|
||||||
|
)
|
||||||
|
|
||||||
|
// Сами данные
|
||||||
|
data class GlobalData(
|
||||||
|
@SerializedName("active_cryptocurrencies") val activeCryptocurrencies: String,
|
||||||
|
@SerializedName("total_market_cap_usd") val totalMarketCapUsd: String,
|
||||||
|
@SerializedName("total_24h_volume_usd") val total24hVolumeUsd: String
|
||||||
|
)
|
@ -0,0 +1,16 @@
|
|||||||
|
package ru.vendetti.bitcoin_summarizer
|
||||||
|
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
|
object RetrofitClient {
|
||||||
|
private const val BASE_URL = "https://api.alternative.me/"
|
||||||
|
|
||||||
|
val apiService: CryptoApiService by lazy {
|
||||||
|
Retrofit.Builder()
|
||||||
|
.baseUrl(BASE_URL)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build()
|
||||||
|
.create(CryptoApiService::class.java)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package ru.vendetti.bitcoin_summarizer
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
// Обёртка для данных (тут json-массив с одним элементом, поэтому выглядит так)
|
||||||
|
typealias TickerResponse = List<TickerData>
|
||||||
|
|
||||||
|
// Сами данные
|
||||||
|
data class TickerData(
|
||||||
|
val id: String,
|
||||||
|
val name: String,
|
||||||
|
val symbol: String,
|
||||||
|
val rank: String,
|
||||||
|
@SerializedName("price_usd") val priceUsd: String,
|
||||||
|
@SerializedName("price_btc") val priceBtc: String,
|
||||||
|
@SerializedName("24h_volume_usd") val volume24hUsd: String,
|
||||||
|
@SerializedName("market_cap_usd") val marketCapUsd: String,
|
||||||
|
@SerializedName("available_supply") val availableSupply: String,
|
||||||
|
@SerializedName("total_supply") val totalSupply: String,
|
||||||
|
@SerializedName("max_supply") val maxSupply: String?,
|
||||||
|
@SerializedName("percent_change_1h") val percentChange1h: String,
|
||||||
|
@SerializedName("percent_change_24h") val percentChange24h: String,
|
||||||
|
@SerializedName("percent_change_7d") val percentChange7d: String,
|
||||||
|
@SerializedName("last_updated") val lastUpdated: String
|
||||||
|
)
|
6
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
<monochrome android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
6
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
<monochrome android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp
Normal file
After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 982 B After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp
Normal file
After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 3.0 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp
Normal file
After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.6 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp
Normal file
After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 6.1 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
Normal file
After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 11 KiB |
4
app/src/main/res/values/ic_launcher_background.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="ic_launcher_background">#FFFFFF</color>
|
||||||
|
</resources>
|
@ -1,16 +1,21 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.8.1"
|
agp = "8.8.1"
|
||||||
|
converterGson = "2.9.0"
|
||||||
kotlin = "2.0.0"
|
kotlin = "2.0.0"
|
||||||
coreKtx = "1.10.1"
|
coreKtx = "1.10.1"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
junitVersion = "1.1.5"
|
junitVersion = "1.1.5"
|
||||||
espressoCore = "3.5.1"
|
espressoCore = "3.5.1"
|
||||||
|
kotlinxCoroutinesAndroid = "1.7.1"
|
||||||
|
kotlinxCoroutinesCore = "1.7.1"
|
||||||
lifecycleRuntimeKtx = "2.6.1"
|
lifecycleRuntimeKtx = "2.6.1"
|
||||||
activityCompose = "1.8.0"
|
activityCompose = "1.8.0"
|
||||||
composeBom = "2024.04.01"
|
composeBom = "2024.04.01"
|
||||||
|
retrofit = "2.9.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
|
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" }
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||||
@ -24,6 +29,9 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin
|
|||||||
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
||||||
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
|
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||||
|
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesAndroid" }
|
||||||
|
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutinesCore" }
|
||||||
|
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|