Android Kotlin 应用未根据接收到的蓝牙数据显示或隐藏图像
Android Kotlin app not displaying or hiding an image based on received bluetooth data
我的应用程序通过蓝牙连接到 Arduino,板上有一个由按钮控制的 LED。 LED 打开或关闭。当状态发生变化时,Arduino 将传输 1(开)或 0(关)。
我的 app/phone 连接正常。我可以在应用程序的日志中看到这些 LED 状态变化。
LOGCAT
2019-12-04 09:36:41.271 30645-32215/com.example.pigcatcher I/MainActivity: 1
2019-12-04 09:36:42.288 30645-32215/com.example.pigcatcher I/MainActivity: 0
2019-12-04 09:36:43.395 30645-32215/com.example.pigcatcher I/MainActivity: 1
2019-12-04 09:36:44.207 30645-32215/com.example.pigcatcher I/MainActivity: 0
此函数侦听那些 LED 状态更改消息:
private fun readBlueToothDataFromMothership(bluetoothSocket: android.bluetooth.BluetoothSocket) {
val bluetoothSocketInputStream = bluetoothSocket.inputStream
val buffer = ByteArray(256)
var bytes: Int
while (true) {
try {
bytes = bluetoothSocketInputStream.read(buffer)
val readMessage = String(buffer, 0, bytes)
Log.i(LOGTAG, readMessage)
if (readMessage.equals(1)) {
imageView_mothership_LED_state.showOrHideImage(true)
} else {
imageView_mothership_LED_state.showOrHideImage(false)
}
} catch (e: IOException) {
e.printStackTrace()
break
}
}
}
此函数是从上面的 while 循环中调用的。
private fun View.showOrHideImage(imageShow: Boolean) {
visibility = if (imageShow) {
View.VISIBLE
} else {
View.INVISIBLE
}
}
这是来自 .xml 文件的相关图像。
<ImageView
android:id="@+id/imageView_mothership_button_pushed"
android:layout_width="228dp"
android:layout_height="204dp"
android:layout_marginStart="16dp"
android:layout_marginTop="75dp"
android:contentDescription="Star"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button_led_off"
app:srcCompat="@android:drawable/btn_star_big_on" />
这就是我的 question/problem 发挥作用的地方。这不会发生。如上面的日志所示,应用程序正在查看那些 LED 状态更改消息。但是应用程序中没有任何反应。我敢肯定,我设置不正确,但我无法弄清楚我做错了什么。
编辑
我忘记包含以下内部 class,其中调用了 "readBlueToothDataFromMothership" 函数。
private inner class ConnectThread(device: BluetoothDevice): Thread() {
private var newSocket = device.createRfcommSocketToServiceRecord(uuid)
override fun run() {
try {
Log.d(LOGTAG, "Connecting bluetoothSocket")
handler.post {
connectedOrNotTextView.text = getString(R.string.connecting)
connectToDeviceButton.isEnabled = false
}
bluetoothSocket = newSocket
bluetoothSocket.connect()
Log.d(LOGTAG, "Socket connected")
handler.post {
connectedOrNotTextView.text = getString(R.string.connected)
connectToDeviceButton.isEnabled = false; disconnectButton.isEnabled = true
}
}catch (e1: Exception){
Log.e(LOGTAG, "Error connecting bluetoothSocket, $e1")
handler.post {
connectedOrNotTextView.text = getString(R.string.connection_failed)
connectToDeviceButton.isEnabled = true; disconnectButton.isEnabled = false
}
}
readBlueToothDataFromMothership(bluetoothSocket)
}
}
编辑 2
正如评论中所指出的,readMessage 是一个字符串而不是一个整数。
所以,我改变了:
if (readMessage.equals(1) {
至:
如果 (readMessage == "1") {
不,它似乎实际上是在点击 View.showOrHideImage() 函数。但是,该应用程序现在崩溃并显示以下内容:
2019-12-04 12:49:53.983 19718-19987/com.example.pigcatcher I/MainActivity: 1
2019-12-04 12:49:54.018 19718-19987/com.example.pigcatcher E/AndroidRuntime: FATAL EXCEPTION: Thread-6
Process: com.example.pigcatcher, PID: 19718
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at com.example.pigcatcher.MainActivity.showOrHideImage(MainActivity.kt:102)
at com.example.pigcatcher.MainActivity.readBlueToothDataFromMothership(MainActivity.kt:89)
at com.example.pigcatcher.MainActivity.access$readBlueToothDataFromMothership(MainActivity.kt:31)
at com.example.pigcatcher.MainActivity$ConnectThread.run(MainActivity.kt:173)
第 102 行指向以下内容:
visibility = if (imageShow) {
第 173 行是:
readBlueToothDataFromMothership(bluetoothSocket)
来自 ConnectThread() 内部 class。
我想,我从错误的地方调用了那个函数?
因为 readMessage 是一个 String按照下面的代码
val readMessage = String(buffer, 0, bytes)
您的情况
if (readMessage.equals(1)) {
imageView_mothership_LED_state.showOrHideImage(true)
} else {
imageView_mothership_LED_state.showOrHideImage(false)
}
应该是
imageView_mothership_LED_state.showOrHideImage(readMessage == "1")
OR(对于 UI/Main 线程以外的线程)
imageView_mothership_LED_state.post {
imageView_mothership_LED_state.showOrHideImage(readMessage == "1")
}
val readMessage = "1"
if(readMessage.equals(1)) System.out.println("true")
else System.out.println("false")
O/P -> false
如果我从你的代码中了解到你得到的 String 为 1 并且你正在将它与 Int 1 进行比较,因为它返回 false 并且你的条件没有得到执行
尝试在readMessage中写一个日志并打印值,这将有助于解决您的问题
我的应用程序通过蓝牙连接到 Arduino,板上有一个由按钮控制的 LED。 LED 打开或关闭。当状态发生变化时,Arduino 将传输 1(开)或 0(关)。
我的 app/phone 连接正常。我可以在应用程序的日志中看到这些 LED 状态变化。
LOGCAT
2019-12-04 09:36:41.271 30645-32215/com.example.pigcatcher I/MainActivity: 1
2019-12-04 09:36:42.288 30645-32215/com.example.pigcatcher I/MainActivity: 0
2019-12-04 09:36:43.395 30645-32215/com.example.pigcatcher I/MainActivity: 1
2019-12-04 09:36:44.207 30645-32215/com.example.pigcatcher I/MainActivity: 0
此函数侦听那些 LED 状态更改消息:
private fun readBlueToothDataFromMothership(bluetoothSocket: android.bluetooth.BluetoothSocket) {
val bluetoothSocketInputStream = bluetoothSocket.inputStream
val buffer = ByteArray(256)
var bytes: Int
while (true) {
try {
bytes = bluetoothSocketInputStream.read(buffer)
val readMessage = String(buffer, 0, bytes)
Log.i(LOGTAG, readMessage)
if (readMessage.equals(1)) {
imageView_mothership_LED_state.showOrHideImage(true)
} else {
imageView_mothership_LED_state.showOrHideImage(false)
}
} catch (e: IOException) {
e.printStackTrace()
break
}
}
}
此函数是从上面的 while 循环中调用的。
private fun View.showOrHideImage(imageShow: Boolean) {
visibility = if (imageShow) {
View.VISIBLE
} else {
View.INVISIBLE
}
}
这是来自 .xml 文件的相关图像。
<ImageView
android:id="@+id/imageView_mothership_button_pushed"
android:layout_width="228dp"
android:layout_height="204dp"
android:layout_marginStart="16dp"
android:layout_marginTop="75dp"
android:contentDescription="Star"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button_led_off"
app:srcCompat="@android:drawable/btn_star_big_on" />
这就是我的 question/problem 发挥作用的地方。这不会发生。如上面的日志所示,应用程序正在查看那些 LED 状态更改消息。但是应用程序中没有任何反应。我敢肯定,我设置不正确,但我无法弄清楚我做错了什么。
编辑
我忘记包含以下内部 class,其中调用了 "readBlueToothDataFromMothership" 函数。
private inner class ConnectThread(device: BluetoothDevice): Thread() {
private var newSocket = device.createRfcommSocketToServiceRecord(uuid)
override fun run() {
try {
Log.d(LOGTAG, "Connecting bluetoothSocket")
handler.post {
connectedOrNotTextView.text = getString(R.string.connecting)
connectToDeviceButton.isEnabled = false
}
bluetoothSocket = newSocket
bluetoothSocket.connect()
Log.d(LOGTAG, "Socket connected")
handler.post {
connectedOrNotTextView.text = getString(R.string.connected)
connectToDeviceButton.isEnabled = false; disconnectButton.isEnabled = true
}
}catch (e1: Exception){
Log.e(LOGTAG, "Error connecting bluetoothSocket, $e1")
handler.post {
connectedOrNotTextView.text = getString(R.string.connection_failed)
connectToDeviceButton.isEnabled = true; disconnectButton.isEnabled = false
}
}
readBlueToothDataFromMothership(bluetoothSocket)
}
}
编辑 2
正如评论中所指出的,readMessage 是一个字符串而不是一个整数。
所以,我改变了:
if (readMessage.equals(1) {
至: 如果 (readMessage == "1") {
不,它似乎实际上是在点击 View.showOrHideImage() 函数。但是,该应用程序现在崩溃并显示以下内容:
2019-12-04 12:49:53.983 19718-19987/com.example.pigcatcher I/MainActivity: 1
2019-12-04 12:49:54.018 19718-19987/com.example.pigcatcher E/AndroidRuntime: FATAL EXCEPTION: Thread-6 Process: com.example.pigcatcher, PID: 19718 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at com.example.pigcatcher.MainActivity.showOrHideImage(MainActivity.kt:102)
at com.example.pigcatcher.MainActivity.readBlueToothDataFromMothership(MainActivity.kt:89)
at com.example.pigcatcher.MainActivity.access$readBlueToothDataFromMothership(MainActivity.kt:31)
at com.example.pigcatcher.MainActivity$ConnectThread.run(MainActivity.kt:173)
第 102 行指向以下内容:
visibility = if (imageShow) {
第 173 行是:
readBlueToothDataFromMothership(bluetoothSocket)
来自 ConnectThread() 内部 class。
我想,我从错误的地方调用了那个函数?
因为 readMessage 是一个 String按照下面的代码
val readMessage = String(buffer, 0, bytes)
您的情况
if (readMessage.equals(1)) {
imageView_mothership_LED_state.showOrHideImage(true)
} else {
imageView_mothership_LED_state.showOrHideImage(false)
}
应该是
imageView_mothership_LED_state.showOrHideImage(readMessage == "1")
OR(对于 UI/Main 线程以外的线程)
imageView_mothership_LED_state.post {
imageView_mothership_LED_state.showOrHideImage(readMessage == "1")
}
val readMessage = "1"
if(readMessage.equals(1)) System.out.println("true")
else System.out.println("false")
O/P -> false
如果我从你的代码中了解到你得到的 String 为 1 并且你正在将它与 Int 1 进行比较,因为它返回 false 并且你的条件没有得到执行
尝试在readMessage中写一个日志并打印值,这将有助于解决您的问题