Decode Data Received from Bluetooth device in Android Kotlin? - android

I have configured Bluetooth Device that send data to Android App.
But I am receiving data in unreadable format.
Data I received from Bluetooth is below format.
���
��
���
Here is my android code
private val mmInStream: InputStream?
private val mmOutStream: OutputStream?
init {
var tmpIn: InputStream? = null
var tmpOut: OutputStream? = null
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = mmSocket.inputStream
tmpOut = mmSocket.outputStream
} catch (e: IOException) {
Log.e(TAG, ": " + e.message)
}
mmInStream = tmpIn
mmOutStream = tmpOut
}
override fun run() {
val buffer = ByteArray(1024) // buffer store for the stream
var bytes = 0 // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
bytes = mmInStream?.read(buffer) ?:0
val readMessage = String(buffer, 0, bytes)
Log.e("Arduino Message", readMessage.toString())
handler?.obtainMessage(MESSAGE_READ, readMessage)?.sendToTarget()
} catch (e: IOException) {
handler?.obtainMessage(CONNECTING_STATUS, 0, -1)?.sendToTarget()
e.printStackTrace()
break
}
}
}

Pls convert the received bytes to hex string via bytesToHex extension method and log it
fun ByteArray.bytesToHexString(
spaces: Boolean = false
): String {
val format = if (spaces) "%02x " else "%02x"
val sb = StringBuilder()
for (i in 0 until size) {
sb.append(format.format(this[i]))
}
return sb.toString()
}

Related

Getting very small PCM file from AudioRecord

I am trying to write the audio signal recorded on the phone microphone to PCM file, using Android AudioRecord class. The PCM files I am getting are too small and when I convert them to WAV there is only the click sound(10-20ms). The filesize is roughly couple KB for minute. Please help! Changing the buffer size is not helping.
val SAMPLE_RATE = 44100
val AUDIO_SOURCE = MediaRecorder.AudioSource.MIC
val CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_STEREO
val AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT
val BUFFER_SIZE_RECORDING =
AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT)
fun startRecording(dir: String) {
isRecordingAudio = true
if (ActivityCompat.checkSelfPermission(
fragmentActivitySender,
Manifest.permission.RECORD_AUDIO
) != PackageManager.PERMISSION_GRANTED
) {
return
}
recorder = AudioRecord(
AUDIO_SOURCE, SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT,
BUFFER_SIZE_RECORDING
)
if (this::recorder.isInitialized) {
recorder.startRecording()
recordingThread = thread(true) {
writeAudioDataToFile(dir)
}
}
}
private fun writeAudioDataToFile(dir: String) {
val audioBuffer = ByteArray(BUFFER_SIZE_RECORDING)
val outputStream: FileOutputStream?
try {
outputStream = FileOutputStream(dir)
} catch (e: FileNotFoundException) {
return
}
while (isRecordingAudio) {
val read = recorder.read(audioBuffer,0, BUFFER_SIZE_RECORDING)
try {
outputStream.write(read)
// clean up file writing operations
} catch (e: IOException) {
e.printStackTrace()
}
}
try {
outputStream.flush()
outputStream.close()
} catch (e: IOException) {
Log.e(ContentValues.TAG, "exception while closing output stream $e")
e.printStackTrace()
}
}
First thing: You are flushing the file in the loop, and that is wrong. Move: outputStream.flush() outside of the loop to one line above outputStream.close() read more about it here
Second issue, you need to write the audioBuffer, not the read variable. The read variable is the result of the read method, is it successful or not. The real data is in the read buffer.

How to use okhttp to create a stream of data and write into device in android

What I am doing: I am using a connection to download file from server and write into a storage
What is happening: Code is working
What I am trying to do: How to achieve the same using okhttp
try {
val url = URL(DICTIONARY_FILE_URL)
val conection = url.openConnection()
conection.connect()
// getting file length
// input stream to read file - with 8k buffer
val input = BufferedInputStream(url.openStream(), 8192)
// Output stream to write file
val directoryPathName = Environment.getExternalStorageDirectory().absolutePath.plus("/CNX/dictionary/")
val dictionaryFileName = "DictionaryEN.quickdic"
var f = File(directoryPathName)
if(!f.isDirectory) {
f.mkdirs()
}
val output = FileOutputStream(directoryPathName.plus(dictionaryFileName))
val data = ByteArray(1024)
var count: Int? = 0
while ({ count = input.read(data);count }() != -1) {
output.write(data, 0, count!!)
}
// flushing output
output.flush()
// closing streams
output.close()
input.close()
isJobSuccess = true
//sharedPreferences[IS_DICTIONARY_DOWNLOADED] = true
} catch (e: Exception) {
Log.e("Exception",e.message)
isJobSuccess = false
//sharedPreferences[IS_DICTIONARY_DOWNLOADED] = false
}
Sample for Downloading a file with OkHttp asynchronously
fun downloadFileAsync(downloadUrl: String) {
val client = OkHttpClient();
val request = Request.Builder().url(downloadUrl).build();
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e("fail", e.printStackTrace().toString())
}
override fun onResponse(call: Call, response: Response) {
if (!response.isSuccessful) {
Log.e("fail", "Download error")
}else{
// Output stream to write file
val directoryPathName = Environment.getExternalStorageDirectory().absolutePath.plus("/CNX/dictionary/")
val dictionaryFileName = "DictionaryEN.quickdic"
val f = File(directoryPathName)
if(!f.isDirectory) {
f.mkdirs()
}
val output = FileOutputStream(directoryPathName.plus(dictionaryFileName))
response.body?.let {
output.write(it.bytes())
}
// flushing output
output.flush()
// closing streams
output.close()
}
}
})
}
Sample for Downloading a file with OkHttp synchronously
fun downloadFileSync(downloadUrl: String) {
val client = OkHttpClient();
val request = Request.Builder().url(downloadUrl).build();
val response = client.newCall (request).execute();
if (!response.isSuccessful) {
Log.e("fail", "Failed to download file: " + response)
}else {
val directoryPathName = Environment.getExternalStorageDirectory().absolutePath.plus("/CNX/dictionary/")
val dictionaryFileName = "DictionaryEN.quickdic"
val f = File(directoryPathName)
if (!f.isDirectory) {
f.mkdirs()
}
val output = FileOutputStream(directoryPathName.plus(dictionaryFileName))
response.body?.let {
output.write(it.bytes())
}
// flushing output
output.flush()
// closing streams
output.close()
}
}
build.gradle
implementation("com.squareup.okhttp3:okhttp:4.5.0")

Kotlin compress/deflate string to server not working

Quite a few questions/answers and many I have tried without success. I receive a compressed string that uses a MemoryStream and DeflateStream to do so (c#). The following decompression function works fine
fun decompress(string: String): String? {
var decompressedString: String? = ""
try {
val bytes: ByteArray = Base64.decode(string, Base64.DEFAULT)
val inflater = Inflater(true)
val outputStream = ByteArrayOutputStream()
val buffer = ByteArray(1024)
inflater.setInput(bytes)
while (!inflater.finished()) {
val count = inflater.inflate(buffer)
outputStream.write(buffer, 0, count)
}
inflater.end()
outputStream.close()
decompressedString = outputStream.toString("UTF8")
} catch (e: IOException) {
e.printStackTrace()
}
return decompressedString
}
At a later time I need to compress the data and send it back. Attempts to compress the data have been unsuccessful. The server keeps telling me that the "block length does not match with its complement." I use the following function for compressing
fun compress(string: String): String? {
var compressedString: String? = null
try {
val bytes: ByteArray = string.toByteArray(charset("UTF-8"))
// Compress the bytes
val deflater = Deflater()
//val outputStream = ByteArrayOutputStream()
val buffer = ByteArray(1024)
deflater.setInput(bytes)
deflater.finish()
deflater.deflate(buffer)
deflater.end()
//outputStream.close()
compressedString = Base64.encodeToString(buffer, Base64.DEFAULT)
} catch (e: IOException) {
e.printStackTrace()
}
return compressedString
}
The problem isn't server side as it works fine with an iOS app but not Android. I've tried many variants of this all without success.
Anyone have any suggestions on what it is that I am doing incorrectly and what I need to do to get it to work?
Thanks ^.^
In case anyone else runs into this problem. I was able to solve it by changing the deflate function to
var compressedString: String? = ""
val bytes: ByteArray = string.toByteArray(charset("UTF-8"))
val deflater = Deflater(1, true)
deflater.setInput(bytes)
deflater.finish()
val outputStream = ByteArrayOutputStream(bytes.size)
try {
val bytesCompressed = ByteArray(Short.MAX_VALUE.toInt())
val numberOfBytesAfterCompression = deflater.deflate(bytesCompressed)
val returnValues = ByteArray(numberOfBytesAfterCompression)
System.arraycopy(bytesCompressed, 0, returnValues, 0, numberOfBytesAfterCompression)
compressedString = Base64.encodeToString(returnValues, Base64.DEFAULT)
} catch (e: IOException) {
e.printStackTrace()
} finally {
deflater.end()
outputStream.close()
}
Obtained from here deflater examples site.
Apparently using the prior function adds 2 additional bytes and this is what was causing the issue. After the change, the 2 bytes are not added. I don't quite understand how or why so if someone knows and wishes to share, please do so.

How measure download speed with OkHTTP?

I am downloading the file using OkHttp3, I want to see the downloading speed. but I am confused about how to measure the speed.
I tried getting the current millis before reading the buffer and calculating after it is written, but it always returns a static value.
Following is my download function.
fun download(fileName: String) {
val request = Request.Builder().url(url)
.get().build()
val call = OkHttpClient().newCall(request)
val response = call.execute()
if (response.isSuccessful) {
var inputStream: InputStream? = null
try {
inputStream = response.body()?.byteStream()
val buffer = ByteArray(8192)
val mediaFile = File(downloadDir, fileName)
val output = RandomAccessFile(mediaFile, "rw")
output.seek(0)
while (true) {
val readed = inputStream?.read(buffer)
if (readed == -1 || readed == null) {
break
}
output.write(buffer, 0, readed)
downloaded.append(readed.toLong())
}
output.close()
} catch (e: IOException) {
// TODO: handle IOException
console.log("${e.message}")
} finally {
inputStream?.close()
}
}
}
It's a very simple problem, I got confused by overthinking. Anyway here is the solution.
all I need to do is store the downloaded bytes in a variable after 1s subtract downloaded bytes from newly downloaded bytes, that will give me the downloaded bytes in 1s, then I can use those bytes to convert into speed like kbps or Mbps.
fun getSpeed(callback: (String) -> Unit) {
doAsync {
var prevDownloaded = 0L
while (true) {
if (contentLength != null) {
if (downloaded.get() >= contentLength!!) {
break
}
}
if (prevDownloaded != 0L) {
callback(formatBytes(downloaded.get() - prevDownloaded))
}
prevDownloaded = downloaded.get()
Thread.sleep(1000)
}
}
}

Kotlin write byte array to BufferedWriter socket

What I'm trying to is sending bytes to TCP socket.
Data format is byte array.
But BufferedWrite.write() doesn't have ByteArray. It has int or CharArray or String
Here is my code.
socket = Socket("192.168.9.34", 5000)
networkReader = BufferedReader(InputStreamReader(socket!!.getInputStream()))
networkWriter = BufferedWriter(OutputStreamWriter(socket!!.getOutputStream()))
val json = """
{"type":"REQ","code":"DP1200","key":"e7aa7f5e-15df-4ea1-9e7b-e4f05d2ac288","ip":"192.168.9.33","port":"31147","serviceid":"WINIXRND1D"}
""".trimIndent()
val jsonByte = json.toString().toByteArray()
val header: ByteArray = byteArrayOf(0x76,0x31,0x30,0x30,0x0,0x0,0x0,jsonByte.size.toByte())
val payload: ByteArray = header + jsonByte
try {
networkWriter!!.write(payload) //<== I want to write byte arra here! but write's argument no ByteArray
} catch (e: Exception) {
}
Please, correct give me advices.

Categories

Resources