Overload resolution ambiguity - Kotlin - kotlin

var input = File(response)
try {
var csv = CsvSchema.emptySchema().withHeader();
var csvMapper = CsvMapper();
var mappingIterator: MappingIterator<Map<String, String>> = csvMapper.reader().forType(Map.class).with(csv).readValues(input);
val list: List<Map<String, String>> = mappingIterator.readAll();
println(list);
} catch(Exception e) {
e.printStackTrace()
}
}
Issue is in the fortype() function in the line var mappingIterator: MappingIterator<Map<String, String>> = csvMapper.reader().forType(Map.class).with(csv).readValues(input);

Related

How to save text file in a document directory with Kotlin while using Jetpack with the same format? [duplicate]

I wrote an App, in Kotlin with Android Studio that write some strings to a file.
All work, I can write and read inside the App, but I can't see the file looking in Documents folder.
How can I use the folder Documents as a storage space?
Thank you
These are the function I use:
fun saveTextFile(view: View, nomeFile: String, testo: String, contesto: Context){
var fileStream: FileOutputStream
try {
fileStream = contesto.openFileOutput(nomeFile, MODE_APPEND) // OK esegue append
fileStream.write(testo.toByteArray())
fileStream.close()
}catch (e: Exception){
e.printStackTrace()
}
}
fun readTextFile(view: View, nomeFile: String, contesto: Context): String{
var fileInputStream: FileInputStream? = null
fileInputStream = contesto.openFileInput(nomeFile)
var inputStreamReader: InputStreamReader = InputStreamReader(fileInputStream)
val bufferedReader: BufferedReader = BufferedReader(inputStreamReader)
val stringBuilder: StringBuilder = StringBuilder()
var text: String? = null
while ({ text = bufferedReader.readLine(); text }() != null) {
stringBuilder.append(text)
}
inputStreamReader.close();
return(stringBuilder.toString())
}
Thank you, Livio
For writing in Documents folder of your device , you just need to make use of MediaStore for the same. You can take input for this function anything that you want like String , bitmap , PdfDocument and other's too .
For Your UseCase you can do the following ,
Global Variable :
private var imageUri: Uri? = null
override suspend fun saveDocument(context : Context, text : String) {
withContext(Dispatchers.IO) {
try {
val collection =
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val dirDest = File(
Environment.DIRECTORY_DOCUMENTS,
context.getString(R.string.app_name)
)
val date = System.currentTimeMillis()
val fileName = "$date.txt"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(MediaStore.MediaColumns.RELATIVE_PATH,
"$dirDest${File.separator}")
put(MediaStore.Files.FileColumns.IS_PENDING, 1)
}
}
val imageUri = context.contentResolver.insert(collection, contentValues)
withContext(Dispatchers.IO) {
imageUri?.let { uri ->
context.contentResolver.openOutputStream(uri, "w").use { out -> out?.write(text.toByteArray())
}
contentValues.clear()
contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 0)
context.contentResolver.update(uri, contentValues, null, null)
}
}
} catch (e: FileNotFoundException) {
null
}
}
}
For Updating the already existing file , do the following . After creating file for the first time I have saved the imageUri in a global variable (If you want to store it permanently / or for a while you can use Jetpack Datastore / Shared Preference to save the same ):
suspend fun updateData(context: Context,text : String){
withContext(Dispatchers.IO) {
try {
val collection =
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val dirDest = File(
Environment.DIRECTORY_DOCUMENTS,
context.getString(R.string.app_name)
)
val fileName = "test.txt"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(
MediaStore.MediaColumns.RELATIVE_PATH,
"$dirDest${File.separator}"
)
put(MediaStore.Files.FileColumns.IS_PENDING, 1)
}
withContext(Dispatchers.IO) {
imageUri?.let { uri ->
context.contentResolver.openOutputStream(uri, "wa").use { out ->
out?.write(text.toByteArray())
}
contentValues.clear()
contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 0)
context.contentResolver.update(uri, contentValues, null, null)
}
}
} catch (e: FileNotFoundException) {
null
}
}
}
For Reading the File , Do the following :
suspend fun read(context: Context, source: Uri): String = withContext(Dispatchers.IO) {
val resolver: ContentResolver = context.contentResolver
resolver.openInputStream(source)?.use { stream -> stream.readText() }
?: throw IllegalStateException("could not open $source")
}
private fun InputStream.readText(charset: Charset = Charsets.UTF_8): String =
readBytes().toString(charset)
This is how the final code looks like :
class MainActivity : AppCompatActivity() {
private lateinit var btn: Button
private var imageUri: Uri? = null
private lateinit var btn2: Button
private lateinit var btn3 : Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn = findViewById(R.id.btnAdd)
btn2 = findViewById(R.id.getText)
btn3 = findViewById(R.id.updateText)
btn.setOnClickListener {
lifecycleScope.launch {
saveDocument(applicationContext, "Original ")
}
}
btn3.setOnClickListener {
lifecycleScope.launch {
updateData(applicationContext,"Appended")
}
}
btn2.setOnClickListener {
lifecycleScope.launch {
imageUri?.let { it1 ->
val data = read(applicationContext, it1)
Toast.makeText(applicationContext, "The data is $data ", Toast.LENGTH_LONG)
.show()
}
}
}
}
suspend fun saveDocument(context: Context, text: String) {
withContext(Dispatchers.IO) {
try {
val collection =
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val dirDest = File(
Environment.DIRECTORY_DOCUMENTS,
context.getString(R.string.app_name)
)
val date = System.currentTimeMillis()
val fileName = "test.txt"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(
MediaStore.MediaColumns.RELATIVE_PATH,
"$dirDest${File.separator}"
)
put(MediaStore.Files.FileColumns.IS_PENDING, 1)
}
imageUri = context.contentResolver.insert(collection, contentValues)
withContext(Dispatchers.IO) {
imageUri?.let { uri ->
context.contentResolver.openOutputStream(uri, "w").use { out ->
out?.write(text.toByteArray())
}
contentValues.clear()
contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 0)
context.contentResolver.update(uri, contentValues, null, null)
}
}
} catch (e: FileNotFoundException) {
null
}
}
}
suspend fun updateData(context: Context, text: String) {
withContext(Dispatchers.IO) {
try {
val collection =
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val dirDest = File(
Environment.DIRECTORY_DOCUMENTS,
context.getString(R.string.app_name)
)
val fileName = "test.txt"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(
MediaStore.MediaColumns.RELATIVE_PATH,
"$dirDest${File.separator}"
)
put(MediaStore.Files.FileColumns.IS_PENDING, 1)
}
withContext(Dispatchers.IO) {
imageUri?.let { uri ->
context.contentResolver.openOutputStream(uri, "wa").use { out ->
out?.write(text.toByteArray())
}
contentValues.clear()
contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 0)
context.contentResolver.update(uri, contentValues, null, null)
}
}
} catch (e: FileNotFoundException) {
null
}
}
}
suspend fun read(context: Context, source: Uri): String = withContext(Dispatchers.IO) {
val resolver: ContentResolver = context.contentResolver
resolver.openInputStream(source)?.use { stream -> stream.readText() }
?: throw IllegalStateException("could not open $source")
}
private fun InputStream.readText(charset: Charset = Charsets.UTF_8): String =
readBytes().toString(charset)
I have three buttons . With the first I create a file , then the uri gets stored in the global variable . Then onClick of second button I add to the already existing file and then read the file using the third button using the same imageUri stored in the global variable
This is the demo for the same . Check when the buttons are being pressed and the output in the form of Toast at the bottom .

Unable to get TFlite model working because of wrong inputs

I have a model called RepNet I want to run on TFlite for Kotlin, the interpreter provides the shape and DataType of the data, but I simply could not get the data to work with the interpreter, I have problems getting it to the correct shape.
The data shape is this :
But I simply can't get my list of Images to match the correct shape, I'll include my code down below if someone could help me make the right transformations to get it working and thank you.
class TestActivity2 : AppCompatActivity() {
#RequiresApi(Build.VERSION_CODES.P)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test2)
//val file = File("/assets/repnet.tflite")
//Log.d("Path", file.path)
var file = loadModelFile(assets,"repnet2.5.tflite")
var interpreter = Interpreter(file!!)
var counts = getCount(interpreter)
interpreter.close()
Log.d("Counts", counts.toString())
}
#RequiresApi(Build.VERSION_CODES.P)
private fun getImages(): MutableList<TensorImage> {
val mmd = MediaMetadataRetriever()
val path = "/sdcard/bicycle.mp4"
mmd.setDataSource(path)
var duration = mmd.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT)
var inputImages = mutableListOf<TensorImage>()
Log.d("Duration",duration.toString())
if (duration != null) {
for (i in 0 until 50) {
var bitmap: Bitmap?
Log.d("Frame", i.toString())
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
bitmap = mmd.getFrameAtIndex(i)
if (bitmap != null) {
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
inputImages.add(TensorImage.fromBitmap(bitmap))
}
}
} catch (e: Exception) {
println("Could not convert image to BitMap")
e.printStackTrace()
}
}
}
return inputImages
}
fun preprocessImages(images: List<TensorImage>): List<TensorImage> {
val imageMean = 127.5F
val imageStd = 127.5F
val imageSize = 224
val imageProcessor = ImageProcessor.Builder()
.add(CastOp(DataType.FLOAT32))
.add(NormalizeOp(imageMean,imageStd))
.add(ResizeOp(imageSize,imageSize,ResizeOp.ResizeMethod.BILINEAR))
.build()
val preprocessedImages = mutableListOf<TensorImage>()
for (image in images) {
val processedImage = imageProcessor.process(image)
preprocessedImages.add(processedImage)
}
return preprocessedImages
}
#RequiresApi(Build.VERSION_CODES.P)
fun getCount(interpreter: Interpreter): Int {
var images = getImages()
images = preprocessImages(images as List<TensorImage>).toMutableList()
val batchImages = mutableListOf<TensorBuffer>()
for(img in images) {
batchImages.add(img.tensorBuffer)
}
var inputBuffer = TensorBuffer.createDynamic(DataType.FLOAT32)
var outputBuffer = TensorBuffer.createFixedSize(interpreter.getOutputTensor(0).shape(),interpreter.getOutputTensor(0).dataType())
interpreter.run(images[0].tensorBuffer,outputBuffer.buffer)
Log.d("Result", outputBuffer.floatArray[0].toString())
Log.d("Output", outputBuffer.toString())
return 0
}
#Throws(IOException::class)
private fun loadModelFile(assets: AssetManager, modelFilename: String): MappedByteBuffer? {
val fileDescriptor = assets.openFd(modelFilename)
val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
val fileChannel: FileChannel = inputStream.getChannel()
val startOffset = fileDescriptor.startOffset
val declaredLength = fileDescriptor.declaredLength
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
}

Debug is working but release not - Kotlin receives data via Bluetooth

I am working on Bluetooth receiving and sending data. I can send data via Bluetooth but it doesn't work the receive data. I want to get string data and split it. And the split data will show the list view. Since data import is not working, I created string data and called the split method, but it didn't work here either in a release. Can you help me?
Here are my Activity codes;
var mUUID: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
var mBluetoothSocket: BluetoothSocket? = null
lateinit var mProgress: ProgressDialog
lateinit var mBluetoothAdapter: BluetoothAdapter
var mIsConnected: Boolean = false
lateinit var mAddress: String
lateinit var inputStream: InputStream
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityListBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
mAddress = intent.getStringExtra(MainActivity.EXTRA_ADDRESS).toString()
ConnectToDevice(this).execute()
run()
binding.deneme.setOnClickListener {
sendCommand("denemebeyza")
Log.d("mesajBT", "onCreate: mesaj gonderildi")
}
val string2: String = "deneme, deneme02K, deneme90,klm08B,bitti."
splitList(string2)
}
private fun sendCommand(input: String) {
if (mBluetoothSocket != null) {
try {
mBluetoothSocket!!.outputStream.write(input.toByteArray())
} catch (e: IOException) {
e.printStackTrace()
}
}
}
fun run() {
val LOGTAG: String ="ReadListString"
Log.i(LOGTAG, Thread.currentThread().name)
val buffer = ByteArray(8)
var bytes: Int
val text1: TextView = binding.text2
var readText : String
Log.d("mesajBt", "mesaj metodu")
//Loop to listen for received bluetooth messages
if (mBluetoothSocket != null) {
while (true) {
bytes = try {
bytes = inputStream.read(buffer) ?:0
readText = String(buffer, 0, bytes)
Log.e("Arduino Message", readText)
} catch (e: IOException) {
e.printStackTrace()
Log.d("Else", "message alinamadi.")
break
}
text1.text =readText
}
}
}
fun splitList(output: String) {
val listView : ListView= binding.list1
val textView: TextView= binding.text1
if (mBluetoothSocket != null) {
try {
val list: List<String> = output.split(",").toList()
var arrayAdapter: ArrayAdapter<*>
for (it in list) {
Log.e("TAG", "splitList: $list ")
val list2: ArrayList<String> = ArrayList(list)
textView.text = list2.toString()
}
arrayAdapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, list)
listView.adapter=arrayAdapter
} catch (e: IOException) {
e.printStackTrace()
}
// [A, B, C, D]
}
}
private class ConnectToDevice(c: Context) : AsyncTask<Void, Void, String>() {
private var connectSuccess: Boolean = true
#SuppressLint("StaticFieldLeak")
val context: Context = c
#Deprecated("Deprecated in Java")
override fun onPreExecute() {
super.onPreExecute()
mProgress = ProgressDialog.show(
context,
context.getString(R.string.connecting),
context.getString(R.string.connecting)
)
}
#SuppressLint("MissingPermission")
override fun doInBackground(vararg p0: Void?): String? {
try {
if (mBluetoothSocket == null || !mIsConnected) {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
val device: BluetoothDevice = mBluetoothAdapter.getRemoteDevice(mAddress)
mBluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(mUUID)
BluetoothAdapter.getDefaultAdapter().cancelDiscovery()
mBluetoothSocket!!.connect()
inputStream = mBluetoothSocket!!.inputStream
}
}catch (e: IOException) {
connectSuccess = false
e.printStackTrace()
}
return null
}
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
if (!connectSuccess) {
Log.i("data", "couldn't connect")
} else {
mIsConnected = true
}
mProgress.dismiss()
}
}
}
Here is debugged console log.e output
Thanks, advance :)
I/ReadList-run: main
E/mesajBt: mesaj metodu
W/BluetoothAdapter:getBluetoothService() called with no BluetoothManagerCallback
W/libEGL: EGLNativeWindowType 0xc9a7d808 disconnect failed
W/libEGL:EGLNativeWindowType 0xc95be008 disconnect failed
I/InputMethodManager: startInputInner mService.startInputOrWindowGainedFocus E/ViewRootImpl:sendUserActionEvent() returned.
I/InputMethodManager: startInputInner - mService.startInputOrWindowGainedFocus
Since there will be commas between words in data coming from Bluetooth, I used a comma as a separator in the split method. After some research, I corrected a few mistakes. You can change the value of the bytes as 8-16-32-64 according to the incoming data type and size.
Receive method is here
private fun run() {
//Loop to listen for received bluetooth messages
if (mBluetoothSocket != null) {
val TAG: String = "ReadList-run"
Log.i(TAG, Thread.currentThread().name)
val buffer = ByteArray(1024)
var bytes: Int
var readText: String
Log.e("mesajBt", "mesaj metodu")
while (true) {
try {
bytes = inputStream.read(buffer)
readText = String(buffer, 0, bytes)
Log.e("Arduino Message", readText)
splitlist(readText)
break
} catch (e: IOException) {
e.printStackTrace()
Log.d("Else", "message alinamadi.")
break
}
}
}
}
Here is my split method
fun splitList(output: String) {
if (mBluetoothSocket != null) {
try {
val list: List<String> = output.split(",").toList()
for (it in list) {
Log.e("TAG", "splitList: $list ")
}
} catch (e: IOException) {
e.printStackTrace()
}
// [A, B, C, D]
}
}

Kotlin String url params

I have a string url like this:
exampleUrl = www.example.com/test?item=param1=1&param2=11&param3=111&item=param1=2&param2=22&param3=222
and i want to extract from it a Map of key values using item as key.
I wrote the below function
fun String.getUrlParams(): Map<String, List<String>> {
val params = HashMap<String, List<String>>()
val urlParts = this.split("\\?".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
if (urlParts.size > 1) {
val query = urlParts[1]
for (param in query.split("item=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
System.out.println(param)
val key = "item"
var value = URLDecoder.decode(param, "UTF-8")
var values: MutableList<String>? = params[key] as MutableList<String>?
if (values == null) {
values = ArrayList()
params[key] = values as ArrayList<String>
}
values?.add(value)
}
}
return params
}
But on printed data i am getting this -> {item=[, param1=1&param2=11&param3=111&, param1=2&param2=22&param3=222]}. It has an empty value on start and the & symbol on the end of second value.
The correct one should be -> {item=[param1=1&param2=11&param3=111, param1=2&param2=22&param3=222]}
What am i missing?
Thanks in advance
Splitting on something that appears right at the start or end of a String will give you an empty String at the start or end of the results.
Instead of dropLastWhile you can filter all empty Strings.
You can use "&?item=" to avoid having the trailing & in your first block.
After removing the unnecessary toTypedArray() and Java-specific code you have:
fun String.getUrlParams(): Map<String, List<String>> {
val params = HashMap<String, List<String>>()
val urlParts = split("\\?".toRegex()).filter(String::isNotEmpty)
if (urlParts.size > 1) {
val query = urlParts[1]
for (param in query.split("&?item=".toRegex()).filter(String::isNotEmpty)) {
val key = "item"
val value = URLDecoder.decode(param, "UTF-8")
var values: MutableList<String>? = params[key] as MutableList<String>?
if (values == null) {
values = ArrayList()
params[key] = values
}
values.add(value)
}
}
return params
}
Cleaning it up a bit gives:
fun String.getUrlParams(): Map<String, List<String>> {
val urlParts = split("\\?".toRegex()).filter(String::isNotEmpty)
if (urlParts.size < 2) {
return emptyMap()
}
val query = urlParts[1]
return listOf("item").associateWith { key ->
query.split("&?$key=".toRegex()).filter(String::isNotEmpty)
.map { URLDecoder.decode(it, "UTF-8") }
}
}

Problems adding values to ArrayList

I'm trying to add url values (imgURL variable) taken from JSON into an ArrayList with Kotlin, but somehow when in the scope of the for loop it doesn't seem to work regardless of having my newArrayURLs array declared as a function variable. Any ideas why is this?
private fun getJsonObjectImg(Url: String): ArrayList<String>{
var paths: ArrayList<String> =ArrayList()
val params = HashMap<String, String>()
var newArrayURLs = ArrayList<String>()
val stringRequest = object : StringRequest(Request.Method.POST, Url, Response.Listener { s ->
try {
val array = JSONObject(s)
var imagesArray = array.getJSONArray("images")
for(i in 0..imagesArray.length() -1 ){
var imgURL = imagesArray.getJSONObject(i).getString("fileName")
newArrayURLs.add(imgURL)
paths.add(imgURL)
}
Log.d("pathsin TRY", paths.count().toString())
} catch(e:JSONException){
Log.d("ERROR------", e.toString())
null
}
}, Response.ErrorListener {
error: VolleyError? ->
try {
Log.d("ERROR======","V")
} catch (e: JSONException){
e.printStackTrace()
}
}) {
override fun getParams(): Map<String, String> = mapOf("uploadedBy" to id)
}
val requestQueue = Volley.newRequestQueue(this)
requestQueue.add<String>(stringRequest)
return newArrayURLs
}