I have an application in which I can receive bluetooth messages, but whenever I write a message it will still remember data from the previous message. How do I clear this? Underneath is my code for sending the message:
private fun sendMessage(message: String) {
messages.add(message)
val time = SimpleDateFormat("HH:mm:ss").format(Date())
messageAdapter?.add(
"$message\n\t${bluetoothAdapter?.name} $time"
)
messageAdapter?.notifyDataSetChanged()
launchAsync {
asyncAwait {
try {
outputStream?.write(message.toByteArray(Charset.forName("UTF-8")))
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
Related
I have a file containing 14 million records each with 2 fields. I had indexed the documents with below config:
private fun getIndexWriter(directory: String): IndexWriter = try {
val indexWriterConfig = IndexWriterConfig(KeywordAnalyzer())
indexWriterConfig.ramBufferSizeMB = 2048.0
indexWriterConfig.openMode = IndexWriterConfig.OpenMode.CREATE_OR_APPEND
IndexWriter(FSDirectory.open(Paths.get(directory)), indexWriterConfig)
} catch (exception: Exception) {
logger.error("File missing: {} ", exception.message)
throw Exception("File missing: ${exception.message}")
}
fun indexDocs(documents: List<Document>)= mutex.withLock {
coroutineScope {
val indexedDocs = getIndexWriter("directory_path").use { indexWriter ->
try {
documents.forEach { document ->
try {
indexWriter.addDocument(document)
} catch (exception: IOException) {
logger.error("Failed to add document: {} to passive index", document)
}
}
indexWriter.flush()
indexWriter.commit()
} catch (exception: IOException) {
logger.error("Failed to commit")
}
indexWriter.docStats.numDocs
}
}
}
It takes 5 minutes around to complete the index and to start the application, however I wanted to check if there can be some optimization done to reduce the time taken for indexing.
Thanks for the help in advance!
I am trying to make a ProgressDialog show up while the application is looking for an IP Address in the network. In my present codes, even though the initialization of the ProgressDialog is at the beginning, it shows after what I am waiting for finishes.
Here is my code:
val clickListener = View.OnClickListener { view ->
when(view.id) {
R.id.button_upload -> {
progressDialog = ProgressDialog(activity)
progressDialog!!.setMessage("Looking for the server. Please wait...")
progressDialog!!.setCancelable(false)
progressDialog!!.show()
if(findServer()) {
Log.i("TAG", "FOUND")
} else {
Log.i("TAG", "NOT FOUND")
}
}
}
}
private fun findServer(): Boolean {
if(canPingServer()) {
Toast.makeText(context, "We are connected to the server server", Toast.LENGTH_LONG).show()
gView.button_upload.setText("Upload")
gView.button_upload.isEnabled = true
progressDialog!!.dismiss()
return true
} else {
Toast.makeText(context, "We cannot connect to the server.", Toast.LENGTH_LONG).show()
gView.button_upload.setText("Server not found")
gView.button_upload.isEnabled = false
progressDialog!!.dismiss()
return false
}
}
private fun canPingServer(): Boolean {
val runtime = Runtime.getRuntime()
try {
val mIpAddrProcess = runtime.exec("/system/bin/ping -c 1 192.168.1.4")
val mExitValue = mIpAddrProcess.waitFor()
Log.i("TAG","mExitValue $mExitValue")
return mExitValue == 0
} catch (ignore: InterruptedException) {
ignore.printStackTrace()
Log.i("TAG"," Exception:$ignore")
} catch (e: IOException) {
e.printStackTrace()
Log.i("TAG"," Exception:$e")
}
return false
}
I believe that I have to create the AsyncTask<Void, Void, String> for this, but the thing is, this fragment have inherited from another class already like so
class UploadFragment : BaseFragment() {.....}
It's showing because you findServer() function needs to execute on a different thread.
val clickListener = View.OnClickListener { view ->
when(view.id) {
R.id.button_upload -> {
progressDialog = ProgressDialog(activity)
progressDialog!!.setMessage("Looking for the server. Please wait...")
progressDialog!!.setCancelable(false)
progressDialog!!.show()
Thread(Runnable {
if(findServer()) {
Log.i("TAG", "FOUND")
} else {
Log.i("TAG", "NOT FOUND")
}
}).start()
}
}
}
AsyncTask<Void, Void, String> is another way to multi thread in java but I believe the way I showed above would suit your needs better. You need to be careful though because anything that has to run on the main thread I.e. your toasts or where you are setting the text of your elements still needs to happen on the main thread. You can accomplish this by surrounding anything that requires being run on the main thread with
activity.runOnUiThread(java.lang.Runnable {
//put code here that needs to be run on the ui thread
})
In you case an example would be
private fun findServer(): Boolean {
if(canPingServer()) {
activity.runOnUiThread(java.lang.Runnable {
Toast.makeText(context, "We are connected to the server server", Toast.LENGTH_LONG).show()
gView.button_upload.setText("Upload")
gView.button_upload.isEnabled = true
progressDialog!!.dismiss()
})
return true
} else {
activity.runOnUiThread(java.lang.Runnable {
Toast.makeText(context, "We cannot connect to the server.", Toast.LENGTH_LONG).show()
gView.button_upload.setText("Server not found")
gView.button_upload.isEnabled = false
progressDialog!!.dismiss()
})
return false
}
}
I have the following snippet for testing purposes;
fun main() {
val myScope = CoroutineScope(Dispatchers.Default) + Job()
myScope.launch {
val job = async {
delay(1000)
throw RuntimeException("shiiiet")
}
try {
job.await()
} catch (ret: RuntimeException){
throw RuntimeException("yooo!")
}
}
try {
Thread.sleep(5000)
} catch(e: Exception){
}
println("wohoooo!")
}
I thought the flow would never reach the last "wohooo!" line but I was wrong. I see it's printed on the screen. The reason I had in my mind that launch would propagate the exception to the parent scope and since the parent scope does not handle it, it would crash the JVM by the time it reaches the print statement.
Is this because the parent scope got cancelled once it's child failed, received a CancellationException and it was ignored?
You tried multiple throwand catch approaches in your example.
async works as expected - when you await for it, you can catch the exception. But if you launch a co-routine, the default Thread.uncaughtExceptionHandler just prints the result to console.
Even if you do
myScope.launch {
....
}.invokeOnCompletion { e -> println("Exception: $e") }
you still get the result additionally on console.
The propagation rules and the different types of calls to handle the exceptions are explained here.
An example on how to catch an exception in the "main" co-routine:
fun main() = runBlocking {
try {
GlobalScope.launch {
delay(10)
throw Exception("You don't catch me in main.")
}
launch {
delay(10)
throw Exception("You catch me in main.")
}
delay(100)
println("Never reached.")
} catch(e: Exception) {
println("Caught in main: ${e.cause}")
}
println("The end")
}
Say I need to wrap BroadcastReceiver with Flowable:
Flowable
.create<Boolean>({ emitter ->
val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
throw RuntimeException("Test exception")
}
}
application.registerReceiver(broadcastReceiver, IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION))
}, BackpressureStrategy.MISSING)
.onErrorReturn { false }
Then I need to catch any exceptions thrown inside Flowable in one single place.
I supposed onErrorReturn should be able to catch that throw RuntimeException("Test exception") inside broadcastReceiver but it doesn't catch that exception and app crashes.
Certainly, I can wrap anything inside BroadcastReceiver with try/catch. But actually, I have a lot of source code there so that adding try/catch makes source code quite messy.
Is there any way to catch all the exceptions thrown in any line inside Flowable in one single place?
In case of Flowable#create() to follow contract of Flowable if you have error and want to pass it through stream, you need to catch it and call emitter.onError(). If you do that, Flowable.onErrorReturn() starts work as expected.
To properly register/unregister BroadcastReceiver and handle exceptions you can use that approach
Flowable
.create<Boolean>({ emitter ->
val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
try {
throw RuntimeException("Test exception")
} catch(e: Throwable) {
emitter.tryOnError(e)
}
}
}
try {
application.registerReceiver(broadcastReceiver, IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION))
emitter.setCancellable {
application.unregisterReceiver(broadcastReceiver)
}
} catch (e: Throwable) {
emitter.tryOnError(e)
}
}, BackpressureStrategy.MISSING)
.onErrorReturn { false }
I'm starting in kotlin and if anyone can help me, I've had a question about how I can return the http status, when my true if it returns 200 Ok and when it's any other way, return 404 NotFound.
I tried to do according to the code below, but it is only returning status 200 Ok, in all situations
#DeleteMapping("{id}")
fun delete(#PathVariable id: Long): ResponseEntity<Unit> {
try {
if (dogRepository.exists(id)) {
dogRepository.delete(id)
}
return ResponseEntity.ok().build()
} catch (e: Exception) {
return ResponseEntity.notFound().build()
}
}
I think an else block can do that
#DeleteMapping("{id}") fun delete(#PathVariable id: Long): ResponseEntity<Unit> {
try {
if (dogRepository.exists(id)) {
dogRepository.delete(id)
return ResponseEntity.ok().build()
} else {
return ResponseEntity.notFound().build()
}
} catch (e: Exception) { return ResponseEntity.notFound().build() }
}
You are not throwing an exception anywhere, hence catch block is not getting executed. Here is updated code.
#DeleteMapping("{id}")
fun delete(#PathVariable id: Long): ResponseEntity {
try {
if (dogRepository.exists(id)) {
dogRepository.delete(id)
return ResponseEntity.ok().build()
}
return ResponseEntity.notFound().build()
} catch (e: Exception) {
return ResponseEntity.notFound().build()
}
}
You can check the response header via curl . E.g.
curl -v -X DELETE http://YOUR_API_URL