Currency Conversion Application This application converts US dollars to euros, British pounds, Mexican pesos, Canadian Dollars, or bitcoin. The opening screen requests the amount of US dollars (up to...

1 answer below »
see attached


Currency Conversion Application This application converts US dollars to euros, British pounds, Mexican pesos, Canadian Dollars, or bitcoin. The opening screen requests the amount of US dollars (up to $100,000.00) to be converted. The user selects the currency to convert to. The converted amount is displayed. (You might want to check out NumberFormat to format the converted value properly). The user interface should minimally list the currency to convert to - a better interface would also show the flag (or icon) for the currency conversion). Use https://xe.com (Links to an external site.) for conversion values. In your comments, please include the date of the conversion value. Scoring will be based on the following rubric for each outcome scored: 0 - not demonstrated 1 - minimally attempted, but incomplete or not working 2 - partially attempted, but missing significant part of the outcome 3 - significantly meets the assignment outcome 4 - mastered the assignment outcome, in some cases shows deeper understanding than the assignment Outcomes to be graded: Clear and useful User Interface (pleasing UI) Functional UI layout choices Functional application using Kotlin to interface with Android Widgets
Answered Same DayOct 28, 2021

Answer To: Currency Conversion Application This application converts US dollars to euros, British pounds,...

Gaurav answered on Oct 28 2021
115 Votes
CurrencyConverter-master/.gitignore
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
CurrencyConverter-master/app/.gitignore
/build
CurrencyConverter-master/app/build.gradle
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.plcoding.currencyconverter"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildFeatures {
viewBinding true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.co
nstraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
//Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.28-alpha"
kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02"
kapt "androidx.hilt:hilt-compiler:1.0.0-alpha02"
// Activity KTX for viewModels()
implementation "androidx.activity:activity-ktx:1.1.0"
// Architectural Components
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
// Lifecycle
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation "com.squareup.okhttp3:okhttp:4.9.0"
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
// Coroutine Lifecycle Scopes
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
}
CurrencyConverter-master/app/proguard-rules.pro
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
CurrencyConverter-master/app/src/androidTest/java/com/plcoding/currencyconverter/ExampleInstrumentedTest.kt
package com.plcoding.currencyconverter
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.plcoding.currencyconverter", appContext.packageName)
}
}
CurrencyConverter-master/app/src/main/AndroidManifest.xml








CurrencyConverter-master/app/src/main/java/com/plcoding/currencyconverter/CurrencyApplication.kt
package com.plcoding.currencyconverter
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class CurrencyApplication : Application()
CurrencyConverter-master/app/src/main/java/com/plcoding/currencyconverter/data/CurrencyApi.kt
package com.plcoding.currencyconverter.data
import com.plcoding.currencyconverter.data.models.CurrencyResponse
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Query
interface CurrencyApi {
@GET("/latest?access_key=978a6115d94b1d918f59f66755804089")
suspend fun getRates(
@Query("base") base: String
): Response
}
CurrencyConverter-master/app/src/main/java/com/plcoding/currencyconverter/data/models/CurrencyResponse.kt
package com.plcoding.currencyconverter.data.models
import com.google.gson.annotations.SerializedName
data class CurrencyResponse(
val base: String,
val date: String,
val rates: Rates
)
CurrencyConverter-master/app/src/main/java/com/plcoding/currencyconverter/data/models/Rates.kt
package com.plcoding.currencyconverter.data.models
import com.google.gson.annotations.SerializedName
data class Rates(
@SerializedName("AUD")
val aUD: Double,
@SerializedName("BGN")
val bGN: Double,
@SerializedName("EUR")
val eUR: Double,
@SerializedName("BRL")
val bRL: Double,
@SerializedName("CAD")
val cAD: Double,
@SerializedName("CHF")
val cHF: Double,
@SerializedName("CNY")
val cNY: Double,
@SerializedName("CZK")
val cZK: Double,
@SerializedName("DKK")
val dKK: Double,
@SerializedName("GBP")
val gBP: Double,
@SerializedName("HKD")
val hKD: Double,
@SerializedName("HRK")
val hRK: Double,
@SerializedName("HUF")
val hUF: Double,
@SerializedName("IDR")
val iDR: Double,
@SerializedName("ILS")
val iLS: Double,
@SerializedName("INR")
val iNR: Double,
@SerializedName("ISK")
val iSK: Double,
@SerializedName("JPY")
val jPY: Double,
@SerializedName("KRW")
val kRW: Double,
@SerializedName("MXN")
val mXN: Double,
@SerializedName("MYR")
val mYR: Double,
@SerializedName("NOK")
val nOK: Double,
@SerializedName("NZD")
val nZD: Double,
@SerializedName("PHP")
val pHP: Double,
@SerializedName("PLN")
val pLN: Double,
@SerializedName("RON")
val rON: Double,
@SerializedName("RUB")
val rUB: Double,
@SerializedName("SEK")
val sEK: Double,
@SerializedName("SGD")
val sGD: Double,
@SerializedName("THB")
val tHB: Double,
@SerializedName("TRY")
val tRY: Double,
@SerializedName("USD")
val uSD: Double,
@SerializedName("ZAR")
val zAR: Double
)
CurrencyConverter-master/app/src/main/java/com/plcoding/currencyconverter/di/AppModule.kt
package com.plcoding.currencyconverter.di
import com.plcoding.currencyconverter.data.CurrencyApi
import com.plcoding.currencyconverter.main.DefaultMainRepository
import com.plcoding.currencyconverter.main.MainRepository
import com.plcoding.currencyconverter.util.DispatcherProvider
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ApplicationComponent
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import javax.inject.Singleton
private const val BASE_URL = "http://api.exchangeratesapi.io/v1/"
@Module
@InstallIn(ApplicationComponent::class)
object AppModule {
@Singleton
@Provides
fun provideCurrencyApi(): CurrencyApi = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(CurrencyApi::class.java)
@Singleton
@Provides
fun provideMainRepository(api: CurrencyApi): MainRepository = DefaultMainRepository(api)
@Singleton
@Provides
fun provideDispatchers(): DispatcherProvider = object : DispatcherProvider {
override val main: CoroutineDispatcher
get() = Dispatchers.Main
override val io: CoroutineDispatcher
get() = Dispatchers.IO
override val default: CoroutineDispatcher
get() = Dispatchers.Default
override val unconfined: CoroutineDispatcher
get() = Dispatchers.Unconfined
}
}
CurrencyConverter-master/app/src/main/java/com/plcoding/currencyconverter/main/DefaultMainRepository.kt
package com.plcoding.currencyconverter.main
import com.plcoding.currencyconverter.data.CurrencyApi
import com.plcoding.currencyconverter.data.models.CurrencyResponse
import com.plcoding.currencyconverter.util.Resource
import javax.inject.Inject
class DefaultMainRepository @Inject constructor(
private val api: CurrencyApi
) : MainRepository {
override suspend fun getRates(base: String): Resource {
return try {
val response = api.getRates(base)
val result = response.body()
if(response.isSuccessful && result != null) {
Resource.Success(result)
} else {
Resource.Error(response.message())
}
} catch(e: Exception) {
Resource.Error(e.message ?: "An error occured")
}
}
}
CurrencyConverter-master/app/src/main/java/com/plcoding/currencyconverter/main/MainRepository.kt
package com.plcoding.currencyconverter.main
import com.plcoding.currencyconverter.data.models.CurrencyResponse
import com.plcoding.currencyconverter.util.Resource
interface MainRepository {
suspend fun getRates(base: String): Resource
}
CurrencyConverter-master/app/src/main/java/com/plcoding/currencyconverter/main/MainViewModel.kt
package com.plcoding.currencyconverter.main
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.plcoding.currencyconverter.data.models.Rates
import com.plcoding.currencyconverter.util.DispatcherProvider
import com.plcoding.currencyconverter.util.Resource
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlin.math.round
class MainViewModel @ViewModelInject constructor(
private val repository: MainRepository,
private val dispatchers: DispatcherProvider
): ViewModel() {
sealed class CurrencyEvent {
class Success(val resultText: String): CurrencyEvent()
class Failure(val errorText: String): CurrencyEvent()
object Loading : CurrencyEvent()
object Empty : CurrencyEvent()
}
private val _conversion = MutableStateFlow(CurrencyEvent.Empty)
val conversion: StateFlow = _conversion
fun convert(
amountStr: String,
fromCurrency: String,
toCurrency: String
) {
val fromAmount = amountStr.toFloatOrNull()
if(fromAmount == null) {
_conversion.value = CurrencyEvent.Failure("Not a valid amount")
return
}
viewModelScope.launch(dispatchers.io) {
_conversion.value = CurrencyEvent.Loading
when(val ratesResponse = repository.getRates(fromCurrency)) {
is Resource.Error -> _conversion.value = CurrencyEvent.Failure(ratesResponse.message!!)
is Resource.Success -> {
val rates = ratesResponse.data!!.rates
val rate = getRateForCurrency(toCurrency, rates)
if(rate == null) {
_conversion.value = CurrencyEvent.Failure("Unexpected error")
// Log.d("Errorerer","This is the error")
} else {
val convertedCurrency = round(fromAmount * rate * 100) / 100
_conversion.value = CurrencyEvent.Success(
"$fromAmount $fromCurrency = $convertedCurrency $toCurrency"
)
}
}
}
}
}
private fun getRateForCurrency(currency: String, rates: Rates) = when (currency) {
"CAD" -> rates.cAD
"HKD" -> rates.hKD
"ISK" -> rates.iSK
"EUR" -> rates.eUR
"PHP" -> rates.pHP
"DKK" -> rates.dKK
"HUF" -> rates.hUF
"CZK" -> rates.cZK
"AUD" -> rates.aUD
"RON" -> rates.rON
"SEK" -> rates.sEK
"IDR" -> rates.iDR
"INR" -> rates.iNR
"BRL" -> rates.bRL
"RUB" -> rates.rUB
"HRK" -> rates.hRK
"JPY" -> rates.jPY
"THB" -> rates.tHB
"CHF" -> rates.cHF
"SGD" -> rates.sGD
"PLN" -> rates.pLN
"BGN" -> rates.bGN
"CNY" -> rates.cNY
"NOK" -> rates.nOK
"NZD" -> rates.nZD
"ZAR" -> rates.zAR
"USD" -> rates.uSD
"MXN" -> rates.mXN
"ILS" -> rates.iLS
"GBP" -> rates.gBP
"KRW" -> rates.kRW
"MYR" -> rates.mYR
else -> null
}
}
CurrencyConverter-master/app/src/main/java/com/plcoding/currencyconverter/MainActivity.kt
package com.plcoding.currencyconverter
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.viewModels
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.plcoding.currencyconverter.databinding.ActivityMainBinding
import com.plcoding.currencyconverter.main.MainViewModel
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collect
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btnConvert.setOnClickListener {
viewModel.convert(
binding.etFrom.text.toString(),
binding.spFromCurrency.selectedItem.toString(),
binding.spToCurrency.selectedItem.toString(),
)
}
lifecycleScope.launchWhenStarted {
viewModel.conversion.collect { event ->
...
SOLUTION.PDF

Answer To This Question Is Available To Download

Related Questions & Answers

More Questions »

Submit New Assignment

Copy and Paste Your Assignment Here