Send Multi Image with Retrofit - Android Studio - asp.net-core

I am trying to send images to .net core server with retrofit. There is no problem sending a single image with Multipartbody.Part. okay. But I try List or Array , the image array doesn't go to the server.
I've been trying for days, but I can't reach a conclusion, please help me.
.NetCore API
public IActionResult AddPost([FromForm]string title, [FromForm]string description, [FromForm]string[] steps, [FromForm]string[] ingredients, [FromForm]IFormFile[] photos)
{}
Debug note;
title: okey, data exist.
description: okey, data exist.
steps: okey, data exist.
ingredients: okey, data exist.
**photos: COUNT:0, DATA NOT EXIST.*****************
Retrofit method;
#Multipart
#POST("Post/addpost")
fun sendPost(#Part ("title") title: String,
#Part ("description") description: String,
#Part ("steps") steps: Array<String>,
#Part ("ingredients") ingredients: Array<String>,
#Part photos: Array<MultipartBody.Part> ): Call<String>
Use of Method;
viewModel.sendPost(
title = postTitle.text.toString(),
description = postDescription.text.toString(),
steps = steps,
ingredients = ingredients,
photos = photos
)
this method create Array
val photos = Array<MultipartBody.Part>(mediaList.size){MultipartBody.Part.createFormData("", "")}
mediaList.forEachIndexed { index, part ->
photos[index] = part
}
getPostMedia() Method
private fun getPostMedia(): MutableList<MultipartBody.Part> {
var postList = mutableListOf<MultipartBody.Part>()
PostList.instance!!.forEachIndexed { index, post ->
if (!post.isAddPost) {
postList.add(prepareFilePart("post[$index]", post.postUri))
}
}
return postList
}

I solved the problem *
Solution, in getPostMedia() method.
postList.add(prepareFilePart("photos", post.postUri))

Related

How can I loop over an array of sets/maps with varying data types

I want to make it so that I keep my code dry and create 3 (or more, or less) buttons with somewhat the same structure. So I create a list of objects to loop over and put the data inside the object to use in several places in the AppButton.
I might think a bit too Pythonic, because that's my main language and I only recently started using Kotlin. What I normally do in Python:
app_buttons = [
dict(
text="....",
icon="....",
uri_string="....",
),
...
]
I've tried something similar in Kotlin with mapOf:
val appButtons = arrayOf(
mapOf(
"title" to getString(R.string.app_btn_example1),
"icon" to R.drawable.ic_some_icon_1_64,
"uriString" to "myapp://example1",
),
...
)
and then loop over them and getting from the map:
for (entry in appButtons) {
buttons.add(
AppButton(
entry.get("text"),
entry.get("icon"),
) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(entry.get("uriString"))).apply {
val name = getString(R.string.saved_account_key)
putExtra(name, sharedPref.getString(name, null))
}
startActivity(intent)
}
)
}
But then I get Type mismatch. Required String. Found {Comparable & java.io.Serializable}?. I don't know what types to put where...
Ok different approach, using setOf and destructuring:
val appButtons = arrayOf(
setOf(
getString(R.string.app_btn_example1),
R.drawable.ic_some_icon_1_64,
"myapp://example1",
),
...
)
for ((text, icon, uriString) in appButtons) {
buttons.add(
AppButton(
text,
icon
) {
...
}
)
}
But now I get the following:
Destructuring declaration initializer of type Set<{Comparable<*> & java.io.Serializable}> must have a 'component1()' function
Destructuring declaration initializer of type Set<{Comparable<*> & java.io.Serializable}> must have a 'component2()' function
Destructuring declaration initializer of type Set<{Comparable<*> & java.io.Serializable}> must have a 'component3()' function
How do I make this work? How do I create a basic list of objects and loop over them with the correct types? It feels so simple in Python. I'm clearly missing something.
Rather than using maps, you should create a data class. For example:
data class ButtonModel(
val title: String,
val icon: Int,
val uriString: String,
)
You can then create the array like this:
val appButtons = arrayOf(
ButtonModel(
title = getString(R.string.app_btn_example1),
icon = R.drawable.ic_some_icon_1_64,
uriString = "myapp://example1",
),
...
)
Or without the parameter labels if you prefer:
val appButtons = arrayOf(
ButtonModel(
getString(R.string.app_btn_example1),
R.drawable.ic_some_icon_1_64,
"myapp://example1",
),
...
)
Then, rather than getting them with get or [], you can just use the dot syntax:
buttons.add(
AppButton(
entry.text,
entry.icon,
) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(entry.uriString)).apply {
val name = getString(R.string.saved_account_key)
putExtra(name, sharedPref.getString(name, null))
}
startActivity(intent)
}
)

About binarySearch() of Kotlin List

I ran the examples in the official Kotlin documentation in the local Android Studio, and found that the results are different from what I expected, but I don’t know what is causing this?
data class Produce(
val name: String,
val price: Double
)
This is the data class I defined
val list2 = listOf(
Produce("AppCode", 52.0),
Produce("IDEA", 182.0),
Produce("VSCode", 2.75),
Produce("Eclipse", 1.75)
)
this is my source list
println(list2.sortedWith(compareBy<Produce> {
it.price
}.thenBy {
it.name
}))
The output on the console is:
[Produce(name=Eclipse, price=1.75), Produce(name=VSCode, price=2.75), Produce(name=AppCode, price=52.0), Produce(name=IDEA, price=182.0)]
I call binarySearch() like this
println("result: ${
list2.binarySearch(
Produce("AppCode", 52.0), compareBy<Produce> {
it.price
}.thenBy {
it.name
}
)
}")
I think the result should be 2, but it is 0
result: 0
I don't know why it turned out like this. Plase help me . thanks a lot
sortedWith() does not modify the list, it returns a new, sorted collection. When calling list2.binarySearch() you still search through original, unsorted list.
You need to either do something like:
list2.sortedWith().binarySearch()
Or create your list with mutableListOf() and then use sort() which sorts in-place.
Broot is right. You need to pass the sorted list to the binarySearch() function. To clarify in code:
val comparator = compareBy<Produce> { it.price }.thenBy { it.name }
val sorted = list2.sortedWith(comparator)
println(sorted.joinToString("\n"))
val foundIndex = sorted.binarySearch(Produce("AppCode", 52.0), comparator)
println("Found at: $foundIndex")
Result:
Produce(name=Eclipse, price=1.75)
Produce(name=VSCode, price=2.75)
Produce(name=AppCode, price=52.0)
Produce(name=IDEA, price=182.0)
Found at: 2

Parsing a String into List of information KOTLIN

I am an amateur Kotlin programming. And I have one task which I am not sure how to solve.
So any help would come in handy.
More about this task:
I get this message via HTTP post request
AL:OK:XX:XX:XX:XX:XX:YY~~TYPE:3~~FOF:v1.0~~RSSI:-68~~PORT:8215~~TEMP:34.22~~CH1:OK~~CH2:KS~~CH3:PR~~CH4:VL~~CH5:KS~~CH6:OK~~AUX1:OK~~AUX2:KS~~AUX3:OK
And I need to parse this message into following output format.
XX:XX:XX:XX:XX:XY - MAC ADDRESS
3 - Type of device
v1.0 - Version of device
-68 - Signal strenght
8215 - Server Port
34.22 - Processor temperature
I only need to get this output in console
I would be really thankfull for any kind of help or hints about this problem.
Thank you in advance,
You can use regex group for this purpose and get each part with index. also you can Assign name to each group and then select each part you want with name.
import java.util.regex.Pattern
fun main() {
val request = "AL:OK:XX:XX:XX:XX:XX:YY~~TYPE:3~~FOF:v1.0~~RSSI:-68~~PORT:8215~~TEMP:34.22" +
"~~CH1:OK~~CH2:KS~~CH3:PR~~CH4:VL~~CH5:KS~~CH6:OK" +
"~~AUX1:OK~~AUX2:KS~~AUX3:OK"
extractValues(request)
}
fun extractValues(request: String) {
val patternWithName = "AL:OK:(?<macAddress>.+)~~TYPE:(?<type>\\d+)~~FOF:(?<fof>v\\d+.\\d+)~~RSSI:(?<rssi>[-+]\\d+)~~PORT:(?<port>\\d+)~~TEMP:(?<temp>\\d+.\\d+)" +
"~~CH1:(?<ch1>.+)~~CH2:(?<ch2>.+)~~CH3:(?<ch3>.+)~~CH4:(?<ch4>.+)~~CH5:(?<ch5>.+)~~CH6:(?<ch6>.+)" +
"~~AUX1:(?<aux1>.+)~~AUX2:(?<aux2>.+)~~AUX3:(?<aux3>.+)"
val patternWithoutName = "AL:OK:(.+)~~TYPE:(\\d+)~~FOF:(v\\d+.\\d+)~~RSSI:([-+]\\d+)~~PORT:(\\d+)~~TEMP:(\\d+.\\d+)" +
"~~CH1:(.+)~~CH2:(.+)~~CH3:(.+)~~CH4:(.+)~~CH5:(.+)~~CH6:(.+)" +
"~~AUX1:(.+)~~AUX2:(.+)~~AUX3:(.+)"
val matcher = Pattern.compile(patternWithoutName).matcher(request)
if (matcher.find()) {
// get with their name --> use [patternWithName]
// val macAddress = matcher.group("macAddress")
// val type = matcher.group("type")
// val fof = matcher.group("fof")
// or
// get with index -- use [patternWithName] or [patternWithoutName]
for (i in 1..matcher.groupCount()) {
println(matcher.group(i))
}
} else {
error("$request doesn't match.")
}
}

Serializing a Map with custom MapAdapter in moshi

I am trying to write a custom MapAdapter in moshi My requirement is to ignore any bad elements in the map. I have successfully written deserialization method(fromJson()), however, I am facing trouble with toJson. here is my toJson() method.
override fun toJson(writer: JsonWriter, value: Map<Any?, Any?>?) {
if (value == null) {
writer.nullValue()
} else {
writer.beginObject()
value.forEach {
writer.name(elementKeyAdapter.toJsonValue(it.key).toString())
.value(elementValueAdapter.toJson(it.value))
}
writer.endObject()
}
}
problem with this code is that it always is writing values in map as string in final Json. For example consider this code
enum class VehicleType2 {
#Json(name ="type1")
TYPE1,
#Json(name ="type2")
TYPE2,
#Json(name ="type3")
TYPE3,
#Json(name ="type4")
TYPE4,
}
and
val map = mutableMapOf<VehicleType2, Int>()
map[VehicleType2.TYPE1] = 1
map[VehicleType2.TYPE2] = 2
val adapter: JsonAdapter<Map<VehicleType2, Int>> =
moshi.adapter(Types.newParameterizedType(Map::class.java, VehicleType2::class.java, Integer::class.java))
Log.i("test", adapter.toJson(map))
this results in following Json
{"type1":"1","type2":"2"}
notice how 1 and 2 are strings and not integers. I have tried many permutations bit no success so far.
Here is more complete sample which reproduces this issue.
After few more trials and errors I found that this is working fine
writer.name(elementKeyAdapter.toJsonValue(it.key).toString())
elementValueAdapter.toJson(writer, it.value)
instead of
writer.name(elementKeyAdapter.toJsonValue(it.key).toString())
.value(elementValueAdapter.toJson(it.value))
I am still unsure about the reasoning behind it though. Thanks!

Exposed Kotlin. Problem with cyrillic encoding

I tryed to fix a problem with encodings. So, I sent from 'Postman', from web browser request to server, where I search data in database by keys in request. Request can be like this:
http://localhost:8080/books.getBooksByGenre/Документальное/0/10
(in browser).
Server receive string, like
http://localhost:8080/books.getBooksByGenre/%D0%94%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5/0/10
then, takes params from url:
genreName: 'Документальное'
start: 0
count: 10.
Then, this data sends to dao:
override fun findGenreByName(genreName: String): DatabaseGenre {
return transaction(db) { getGenreByName(genreName) }
}
private fun getGenreByName(genreName: String): DatabaseGenre {
return try {
val foundGenre = GenreEntity.find { Genres.genre eq genreName }.single()
DatabaseGenre(foundGenre.id.value, foundGenre.genre, foundGenre.link)
} catch (e: Exception) {
throw NothingFoundInDatabaseException("no one genre found by '$genreName'")
} catch (e: NoSuchElementException) {
val m = "Duplicates of genre with name '$genreName'"
throw DuplicatedDataInDatabaseException(m)
}
}
In log I see, that sql-query for finding genres is correct, but I receive an exception:
java.util.NoSuchElementException: Collection is empty.
The sql-query, as I said, is correct:
SELECT genres.id, genres.genre, genres.link FROM genres WHERE genres.genre = 'Документальное'
Structure of genres table:
genres
id: int(10)
genre: varchar(100)
link: varchar(100
I tryied, to select all genres, and this query executed almost correctly. So, I decided, to check this query with english word, and this query correctly executed:
SELECT genres.id, genres.genre, genres.link FROM genres WHERE genres.genre = 'simpleGenre'
I have not exceptions with this query.
So, what I've done wrong and how to fix problem with collations?
UPD:
As I said at github (issue), I've tryied this query it mysql cli and I receive correct answer.
Also, I've tryed to decode url params (with java URLDecoder class). It doesn't helps too.
Thanks, #madhead.
I tryied an advance of #madhead, and it works. So, from this time my DB connection URL looks like this:
val connect = Database.connect(
url = "jdbc:mysql://localhost:3306/my_database_name?characterEncoding=utf8&useUnicode=true",
driver = "com.mysql.jdbc.Driver",
user = user_name,
password = password
)