Cannot format given Object as a Number in Kotlin - kotlin

An error occurred while using the ConverPrice function as follows for information about the price.
The price of the item in the recycler view adapter onBindViewHolder.
As a result of debugging, the error occurs in the following code.
priceText =
"${dec.format(priceMin)} ~ ${dec.format(priceMax)}"
Please check my code and answer.
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is DataViewHolder -> {
val item = dataList[position]
item.price.let {
holder.price.text = ConvertPrice(item, holder.price)
}
}
}
}
fun ConvertPrice(productDetail: ProductDetail?, tv: TextView? = null, setPrice: Boolean = false): String {
val disableColor = Color.parseColor("#aaaaaa")
val enableColor = Color.parseColor("#3692ff")
tv?.setTextColor(disableColor)
if (ProductDetail != null) {
val priceMin = productDetail.priceMin
val priceMax = productDetail.priceMax
var priceText = ""
val dec = DecimalFormat("##,###")
productDetail.enabledRetail?.let {
if (productDetail.enabledRetail == true) {
if (setPrice) {
priceText = if (priceMin == null || priceMax == null) {
"No pricing information"
} else {
"${dec.format(priceMin)} ~ ${dec.format(priceMax)}"
}
tv?.setTextColor(disableColor)
}
else {
priceText = dec.format(wineDetail.price).toString()
tv?.setTextColor(enableColor)
}
return priceText
} else if (productDetail.cntRating!! > 0) {
if ((priceMin == null && priceMax == null) || (priceMin == 0 && priceMax == 0)) {
priceText = "No pricing information"
} else {
priceText =
"${dec.format(priceMin)} ~ ${dec.format(priceMax)}"
tv?.setTextColor(disableColor)
}
return priceText
}
}
}
return "No pricing information"
}

DecimalFormat.format() only works fine with long or double. You should convert "priceMin" and "priceMax" to Long.
val priceMin = productDetail.priceMin.toLong()
val priceMax = productDetail.priceMax.toLong()
I recommend to use NumberFormat instead of DecimalFormat because it is locale-sensitive
val decFormat = NumberFormat.getInstance() // or getCurrencyInstance()
decFormat.maximumFractionDigits = 3
decFormat.format(priceMin)
decFormat.format(priceMax)

Related

Get Address from current location Kotlin

I get the current location like this:
val fusedLocationClient: FusedLocationProviderClient =
LocationServices.getFusedLocationProviderClient(LocalContext.current)
fun getLastKnownLocation() {
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
if (location != null) {
longitude.value = location.longitude
latitude.value = location.latitude
}
}
}
How I can get the Address from it?
Update
I implemented like this:
fun getLastKnownLocation() {
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
if (location != null) {
longitude.value = location.longitude
latitude.value = location.latitude
val geocoder = Geocoder(app)
if (Build.VERSION.SDK_INT >= 33) {
geocoder.getFromLocation(
location.latitude, location.longitude, 1
) { addresses ->
address.value = addresses.first().toString()
}
}
else {
try {
val addresses = geocoder.getFromLocation(location.latitude, location.longitude, 1
)?.firstOrNull()
address.value = addresses.toString()
} catch (Exp: Exception) {
address.value = "No Address found"
println("$Exp")
}
}
}
}
}
But got this exception: java.io.IOException: eccc: DEADLINE_EXCEEDED: deadline exceeded after 4.907678698s
val geocoder = Geocoder(this, Locale.getDefault())
val addresses = geocoder.getFromLocation(location.latitude, location.longitude, 1)
https://developer.android.com/reference/kotlin/android/location/Geocoder

I tried to run this code and every time I run it shows this result

private fun moveMarkerAnimation(key: String, newData: AnimationModel, marker: Marker?, from: String, to: String) {
if (!newData.isRun)
{
compositeDisposable.add(
iGoogleAPI.getDirections(
"driving",
"less_driving",
from, to,
getString(R.string.google_api_key1)
)!!.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { returnResult ->
Log.d("API_RETURN",returnResult,)
try {
val jsonObject = JSONObject(returnResult)
val jsonArray = jsonObject.getJSONArray("routes")
for ( i in 0 until jsonArray.length())
{
val route = jsonArray.getJSONObject(i)
val poly = route.getJSONObject("overview_polyLine")
val polyLine = poly.getString("points")
polylineList = Common.decodePoly(polyLine) as java.util.ArrayList<LatLng?>
}
handler = Handler()
index = -1
next = 1
val runnable = object :Runnable{
override fun run() {
if (polylineList!!.size > 1)
{
if (index< polylineList!!.size)
{
index ++
next = index+1
start = polylineList!![index] !!
end = polylineList!![next]!!
}
val valueAnimator = ValueAnimator.ofInt(0,1)
valueAnimator.duration = 3000
valueAnimator.interpolator = LinearInterpolator()
valueAnimator.addUpdateListener { value ->
v = value.animatedFraction
lat = v*end !!.latitude + (1-v) * start!!.latitude
lng = v*end !!.longitude+ (1-v) * start!!.longitude
val newPos = LatLng(lat,lng)
marker!!.position = newPos
marker!!.setAnchor(0.5f,0.5f)
marker!!.rotation = Common.getBearing(start!!,newPos)
}
valueAnimator.start()
if (index < polylineList!!.size-2)
{
handler!!.postDelayed(this,1500)
}else if (index < polylineList!!.size-1)
{
newData.isRun = false
Common.driversSubscrib.put(key,newData)
}
}
}
}
handler!!.postDelayed(runnable,1500)
}
catch (e:java.lang.Exception){
Snackbar.make(requireView(),e.message!!,Snackbar.LENGTH_LONG).show()
}
When the site changes from from firebase this result appears
022-04-26 13:19:30.912 23482-23482/com.example.bustrackerriderapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.bustrackerriderapp, PID: 23482
io.reactivex.exceptions.OnErrorNotImplementedException: The exception was not handled due to missing onError handler in the subscribe() method call. Further reading
what should I do to fix this problem

State flow Android Kotlin

I have a god view model for every thing I know this is wrong
but I am just experimenting with Flow
I have these two State flow variables in view model
private val _currentRestroMenu = MutableStateFlow<State<Menu>>(State.loading())
private val _userCart = MutableStateFlow(CustomerCart())
val currentRestroMenu: StateFlow<State<Menu>> = _currentRestroMenu
val userCart: StateFlow<CustomerCart> = _userCart
Below functions get data from server and update above state flow
private fun getRestroMenuFromCloudAndUpdateData(restroId: String) = viewModelScope.launch {
fireStoreRepository.getRestroMenu(restroId).collect { state ->
when (state) {
is State.Success -> {
_currentRestroMenu.value = State.success(state.data)
dataHolderMenuOnSearch = state.data
if (!viewedRestroMenu.contains(state.data)) {
viewedRestroMenu.add(state.data)
}
}
is State.Failed -> {
_currentRestroMenu.value = State.failed(state.message)
}
is State.Loading -> {
_currentRestroMenu.value = State.loading()
}
}
}
}
private fun getCart() = viewModelScope.launch(Dispatchers.IO) {
if (currentCart.cartEmpty) {
fireStoreRepository.getUserCartInfoFromCloud(dataStoreRepository.readFileDataStoreValue.first().savedUserId)
.collect { cartState ->
when (cartState) {
is State.Success -> {
_userCart.update {
it.copy(
cartId = cartState.data.cartId,
cartEmpty = cartState.data.cartEmpty,
cartItem = cartState.data.getCartItem(),
restroId = cartState.data.restroId,
cartTotalAmount = cartState.data.cartTotalAmount,
cartAddressId = cartState.data.cartAddressId,
cartDeliveryTime = cartState.data.cartDeliveryTime,
cartCookingInstructions = cartState.data.cartCookingInstructions,
cartAppliedOfferId = cartState.data.cartAppliedOfferId,
deliveryPartnerTipAmount = cartState.data.deliveryPartnerTipAmount,
cartDeliveryCharge = cartState.data.cartDeliveryCharge,
cartTax = cartState.data.cartTax,
deliveryInstructionId = cartState.data.deliveryInstructionId,
foodHandlingCharge = cartState.data.foodHandlingCharge,
cartNumberOfItems = cartState.data.cartNumberOfItems,
cartRestroName = cartState.data.cartRestroName
)
}
currentCart = cartState.data
}
is State.Failed -> {
if (cartState.message == "Result null") {
Log.d(
ContentValues.TAG,
"getCartFromCloud: No cart details found in cloud creating new cart"
)
_userCart.update {
it.copy(
cartId = dataStoreRepository.readFileDataStoreValue.first().savedUserId,
cartEmpty = true
)
}
currentCart = CustomerCart(
cartId = dataStoreRepository.readFileDataStoreValue.first().savedUserId,
cartEmpty = true
)
}
}
is State.Loading -> {
Log.d(ContentValues.TAG, "getCartFromCloud: Loading")
}
}
}
} else {
_userCart.value = currentCart
Log.d(ContentValues.TAG, "getCart: $currentCart ")
}
}
I am collecting these state flow from different fragments
every thing works fine except one fragment
here is the code
in on create method
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
godCustomerViewModel.currentRestroMenu.collectLatest { menuState ->
Log.d(TAG, "currentRestroMenu ::: mENUSELECT FIRED: ")
when (menuState) {
is State.Success -> {
restroMenu = menuState.data
binding.recyclerView2.hideShimmer()
getCartDetails(restroMenu)
}
is State.Failed -> {
Log.d(TAG, "currentRestroMenu: ")
}
is State.Loading -> {
binding.recyclerView2.showShimmer()
}
}
}
}
}
private fun getCartDetails(restroMenu: Menu) = viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
godCustomerViewModel.userCart.collectLatest {
if (it.restroId == restroMenu.restroId) {
categoryAdapterRestroDetails.setData(
restroMenu.menuCategories,
it.getCartItem()
)
} else {
categoryAdapterRestroDetails.setData(
restroMenu.menuCategories,
ArrayList()
)
}
}
}
}
I am passing the two collected values to adapter (retro menu and item in cart )
when the fragment is loaded for the first time everything works fine
I have add dish to cart function which updates the value of user cart
fun addDishToCart(dish: Dish) = viewModelScope.launch {
Log.d(ContentValues.TAG, "addDishToCart: view model invoked")
if (currentCart.checkIfCartBelongsToThisRestro(dish.dishRestroId)) {
currentCart.addDishToCart(dish).collect {
Log.d(ContentValues.TAG, "addDishToCartcollect: $currentCart")
_userCart.update {
it.copy(
cartEmpty = currentCart.cartEmpty,
cartItem = currentCart.getCartItem(),
restroId = currentCart.restroId,
cartTotalAmount = currentCart.cartTotalAmount,
cartNumberOfItems = currentCart.cartNumberOfItems,
)
}
}
} else {
// restro Conflict
Log.d(ContentValues.TAG, "addDishToCart: $currentCart")
_restroConflict.value = CartConflict(true, currentCart.cartRestroName, dish)
}
Log.d(ContentValues.TAG, "addDishToCart current cart: ${currentCart.getCartItem()}")
Log.d(ContentValues.TAG, "addDishToCart: user Cart : ${_userCart.value.getCartItem()} ")
}
Which also work fine initially
I also have a button to filter menu to veg non veg
fun filterMenuForVeg(value: Boolean, showAll: Boolean) = viewModelScope.launch {
if (!showAll) {
Log.d(ContentValues.TAG, "filterMenuForVeg: Entered veg :$value")
var filteredMenu = Menu()
filteredMenu.restroId = dataHolderMenuOnSearch.restroId
for (menuCategory in dataHolderMenuOnSearch.menuCategories) {
Log.d(ContentValues.TAG, "filterMenuForVeg: $dataHolderMenuOnSearch ")
for (dish in menuCategory.dishes) {
if (dish.dishVeg == value) {
Log.d(ContentValues.TAG, "found dish with veg $value: ")
var categoryAlreadySaved = false
filteredMenu.menuCategories.filter {
categoryAlreadySaved = it.categoryId == menuCategory.categoryId
true
}
if (!categoryAlreadySaved) {
Log.d(ContentValues.TAG, "menu category not found in filtered list ")
val menuCategoryToAdd = MenuCategories()
menuCategoryToAdd.menuCategoryName = menuCategory.menuCategoryName
menuCategoryToAdd.categoryId = menuCategory.categoryId
menuCategoryToAdd.restroId = menuCategory.restroId
menuCategoryToAdd.dishes.add(dish)
filteredMenu.menuCategories.add(menuCategoryToAdd)
} else {
Log.d(ContentValues.TAG, "menu category found in filtered list ")
filteredMenu.menuCategories.find {
if (it.categoryId == menuCategory.categoryId) {
it.restroId = menuCategory.restroId
it.dishes.add(dish)
}
true
}
}
}
}
}
Log.d(ContentValues.TAG, "filterMenuForVeg : $filteredMenu ")
_currentRestroMenu.value = State.success(filteredMenu)
} else {
// set to all data
_currentRestroMenu.value = State.success(dataHolderMenuOnSearch)
}
When I filter dish for veg or non veg then add dish to cart (Which only changes userCart State flow) the place where I am collecting these state flow
get fired twice
so set data to adapter is getting called twice
What Iam doing wrong
Could you collect the items with onEach instead of collectLatest? It would solve your problem probably.

Setting local variables inside a function for unit testing kotlin

I'm trying to testing a function in android.For the function to be tested ,have to set local variable inside the function. Heres the code:
fun needToBeTested(serviceContext: Context):Int
{
val manager = serviceContext.getSystemService(Context.USB_SERVICE) as UsbManager
val deviceList = manager.deviceList
if(deviceList.size != 0){
val deviceIterator = deviceList.values.iterator()
while (deviceIterator.hasNext()) {
val device = deviceIterator.next()
if ((device != null)&&(device.deviceClass == 255)) { // USB_CLASS_VENDOR_SPEC - HUB
val permitToRead:Boolean = manager.hasPermission(device)
if(permitToRead){
setUpConnection(device,serviceContext)
} else{
manager.requestPermission(device, permissionIntent)
}
deviceConnectionStatus = 1
} else if((device != null) &&(device.deviceClass == 0)){ // USB_CLASS_PER_INTERFACE - USB STICK
}
}
} else (deviceList.size == 0){
connectionStatus = 0
}
}
Test class
class Test {
val mockContext = ApplicationProvider.getApplicationContext<Context>()
#Test
fun needTobeTested_returnOne(){
asserThat(sample.needToBeTested(mockContext)==1) //successcase
}
}
For testing this class,need to set the value of deviceList.Is there any way to set the value of 'x' from the test class for testing this function. Im new to android and testing.Any help would be really helpful.

kotlin Exception in thread "main" java.lang.IndexOutOfBoundsException

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index:
62, Size: 62
I can't fix this annoying error. I use indexes = size of List but have this exception
import java.io.File
fun main(args: Array<String>) {
fun markdownToHtmlSimple(inputName: String) {
val writer = File("out.txt").bufferedWriter()
val str = File(inputName).readLines()
var countTagI = 0
var countTagB = 0
var countTagS = 0
var openedTagI = false
var openedTagB = false
var openedTagS = false
writer.write("<html>\n\t<body>\n\t\t<p>")
for (i in 0..str.size) {
if (str[i] == "") writer.newLine()
else {
Regex("""\*\*""").replace(str[i], "☺") //временная замена для облегчения поиcка
Regex("""\~\~""").replace(str[i], "☻") //аналогично
val currentStr = str[i].toList()
for (j in 0..currentStr.size) {
when {
currentStr[j] == '*' -> countTagI++
currentStr[j] == '☺' -> countTagB++
currentStr[j] == '☻' -> countTagS++
}
}
if ((countTagB % 2 == 0) && (countTagI % 2 == 0) && (countTagS % 2 == 0)) for (j in 0..currentStr.size) {
when {
(currentStr[j] == '*') && !openedTagI -> {
writer.write("<i>")
openedTagI = true
}
(currentStr[j] == '*') && openedTagI -> {
writer.write("</i>")
openedTagI = false
}
(currentStr[j] == '☺') && !openedTagB -> {
writer.write("<b>")
openedTagI = true
}
(currentStr[j] == '☺') && openedTagB -> {
writer.write("</b>")
openedTagI = false
}
(currentStr[j] == '☻') && !openedTagS -> {
writer.write("<s>")
openedTagS = true
}
(currentStr[j] == '☻') && openedTagS -> {
writer.write("</s>")
openedTagS = false
}
else -> writer.write(currentStr[j].toString())
}
}
}
}
}
markdownToHtmlSimple("input.txt")
}
I use only three constructions for and they are limited with size of Arrays
Please help where is my error?
Replace
0..str.size
with
0 until str.size