Android Things Uart 中的 Uart 回调问题
Problem in Uart callback in Android Things Uart
我正在使用 Odroid N2+ 板从 UART 发送和接收数据以及打开和关闭 GPIO。 GPIO 部分工作正常。当我只输入传输代码时,没有问题。但是,当我将代码用于接收时,应用程序崩溃了。
我得到的 logcat 错误说
2021-04-14 15:50:47.623 5127-5127/com.example.androidthings E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.androidthings, PID: 5127
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.androidthings/com.example.androidthings.MainActivity}: java.io.IOException: Uart Callback feature is not implemented
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2951)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3086)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6718)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.io.IOException: Uart Callback feature is not implemented
at com.google.android.things.pio.impl.UartImpl.registerUartDeviceCallback(UartImpl.java:261)
at com.example.androidthings.MainActivity.onCreate(MainActivity.kt:85)
at android.app.Activity.performCreate(Activity.java:7144)
at android.app.Activity.performCreate(Activity.java:7135)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2931)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3086)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6718)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
我查看了 Uart 回调实现、Handler 实现和 HandlerThread 实现,它们看起来都很好,但我看不出问题的根源。
是否有一些实现或我在这里缺少的东西?看起来 UartDeviceCallback 无法识别。
我的实现如下:
class MainActivity : AppCompatActivity()
{
val TAG = "PeripActivity"
private lateinit var bind: ActivityMainBinding
private lateinit var gpio: Gpio
private lateinit var gpioList: List<String>
private lateinit var uart: UartDevice
lateinit var inputThread: HandlerThread
lateinit var handler: Handler
private lateinit var pManager: PeripheralManager
val maxCount = 128
private val uartDeviceCallback: UartDeviceCallback = object: UartDeviceCallback {
override fun onUartDeviceDataAvailable(uart: UartDevice): Boolean {
// Loop until there is no more data in the RX buffer.
transferUartData()
// Continue listening for more interrupts
return true
}
override fun onUartDeviceError(uart: UartDevice?, error: Int) {
Log.w(TAG, "$uart: Error event $error")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bind = ActivityMainBinding.inflate(layoutInflater)
setContentView(bind.root)
pManager = PeripheralManager.getInstance()
gpioList = pManager.gpioList
gpio = pManager.openGpio(gpioList[0]).apply {
setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW)
}
var uartlist = pManager.uartDeviceList
for(item in uartlist)
Log.d(TAG, "Uarts: $item\n")
inputThread = HandlerThread("InputThread")
inputThread.start()
handler = Handler(inputThread.looper)
uart = openUart(uartlist[0], 115200)
uart.registerUartDeviceCallback(handler, uartDeviceCallback)
// Read any initially buffered data
handler.post { transferUartData() }
bind.gpioSwitch.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
Toast.makeText(this, "GPIO HIGH", Toast.LENGTH_SHORT).show()
gpio.value = true
}
else {
Toast.makeText(this, "GPIO LOW", Toast.LENGTH_SHORT).show()
gpio.value = false
}
}
bind.btnUart.setOnClickListener {
writeUartData("Odroid says hello\n");
}
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "Loopback Destroyed")
// Terminate the worker thread
inputThread.quitSafely()
// Attempt to close the UART device
uart.unregisterUartDeviceCallback(uartDeviceCallback)
uart.close()
}
private fun writeUartData(str: String){
val bytes = str.toByteArray()
val count = uart.write(bytes, bytes.size)
Log.d(TAG, "Wrote $count bytes to peripheral")
Toast.makeText(this, "message send : $str", Toast.LENGTH_SHORT).show()
}
private fun openUart(name: String, baudRate: Int): UartDevice {
return pManager.openUartDevice(name).apply {
// Configure the UART
setBaudrate(baudRate)
setDataSize(8)
setParity(UartDevice.PARITY_NONE)
setStopBits(1)
}
}
private fun transferUartData() {
// Loop until there is no more data in the RX buffer.
val buffer = ByteArray(maxCount)
do {
val read = uart.read(buffer, buffer.size)
if (read > 0) {
Log.w(TAG, "received data:\n${buffer}")
}
} while (read > 0)
}
}
查看 UartDeviceCallback 的实现后,window 打开并在顶部显示消息。
我选择了下载源,但没有任何反应。
我在这里遗漏了任何 files/libraries ?
我使用 Runnable Interface 读取 Uart 数据解决了这个问题。
private lateinit var handler: Handler
private lateinit var rThread: Thread
private lateinit var eRunnable: ExampleRunnable
inner class ExampleRunnable (pUart: UartDevice): Runnable{
val maxlen = 128
var inneruart = pUart
val TAG = "Uart_Activity"
@Volatile var threadRunning = true;
override fun run(){
Log.d(TAG, "Uart receive start")
while(threadRunning){
readUart()
}
}
private fun readUart() {
// Loop until there is no more data in the RX buffer.
val buffer = ByteArray(maxlen)
do {
val read = inneruart.read(buffer, buffer.size)
if (read > 0) {
val sub = buffer.copyOfRange(0,read)
var readString = String(sub)
Log.w("Uart_Activity", "received data bytes ($read):\n${readString}")
handler.post(object : Runnable{
override fun run() {
var cat:String = bind.peripheralMsg.text.toString() + readString
bind.peripheralMsg.text = cat
}
})
}
} while (read > 0)
}
fun setRunning(state: Boolean){
threadRunning = state
}
}
在上面的代码中,
bind.peripheralMsg.text = cat
在UI中显示接收到的数据。
在主程序的onCreate函数中,我做了如下操作:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Other stuffs
handler = Handler(Looper.getMainLooper())
eRunnable = ExampleRunnable(uart)
rThread = Thread(eRunnable)
rThread.start()
// Other stuffs
}
override fun onStop() {
super.onStop()
eRunnable.setRunning(false)
}
我正在使用 Odroid N2+ 板从 UART 发送和接收数据以及打开和关闭 GPIO。 GPIO 部分工作正常。当我只输入传输代码时,没有问题。但是,当我将代码用于接收时,应用程序崩溃了。
我得到的 logcat 错误说
2021-04-14 15:50:47.623 5127-5127/com.example.androidthings E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.androidthings, PID: 5127
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.androidthings/com.example.androidthings.MainActivity}: java.io.IOException: Uart Callback feature is not implemented
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2951)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3086)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6718)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.io.IOException: Uart Callback feature is not implemented
at com.google.android.things.pio.impl.UartImpl.registerUartDeviceCallback(UartImpl.java:261)
at com.example.androidthings.MainActivity.onCreate(MainActivity.kt:85)
at android.app.Activity.performCreate(Activity.java:7144)
at android.app.Activity.performCreate(Activity.java:7135)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2931)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3086)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6718)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
我查看了 Uart 回调实现、Handler 实现和 HandlerThread 实现,它们看起来都很好,但我看不出问题的根源。
是否有一些实现或我在这里缺少的东西?看起来 UartDeviceCallback 无法识别。
我的实现如下:
class MainActivity : AppCompatActivity()
{
val TAG = "PeripActivity"
private lateinit var bind: ActivityMainBinding
private lateinit var gpio: Gpio
private lateinit var gpioList: List<String>
private lateinit var uart: UartDevice
lateinit var inputThread: HandlerThread
lateinit var handler: Handler
private lateinit var pManager: PeripheralManager
val maxCount = 128
private val uartDeviceCallback: UartDeviceCallback = object: UartDeviceCallback {
override fun onUartDeviceDataAvailable(uart: UartDevice): Boolean {
// Loop until there is no more data in the RX buffer.
transferUartData()
// Continue listening for more interrupts
return true
}
override fun onUartDeviceError(uart: UartDevice?, error: Int) {
Log.w(TAG, "$uart: Error event $error")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bind = ActivityMainBinding.inflate(layoutInflater)
setContentView(bind.root)
pManager = PeripheralManager.getInstance()
gpioList = pManager.gpioList
gpio = pManager.openGpio(gpioList[0]).apply {
setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW)
}
var uartlist = pManager.uartDeviceList
for(item in uartlist)
Log.d(TAG, "Uarts: $item\n")
inputThread = HandlerThread("InputThread")
inputThread.start()
handler = Handler(inputThread.looper)
uart = openUart(uartlist[0], 115200)
uart.registerUartDeviceCallback(handler, uartDeviceCallback)
// Read any initially buffered data
handler.post { transferUartData() }
bind.gpioSwitch.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
Toast.makeText(this, "GPIO HIGH", Toast.LENGTH_SHORT).show()
gpio.value = true
}
else {
Toast.makeText(this, "GPIO LOW", Toast.LENGTH_SHORT).show()
gpio.value = false
}
}
bind.btnUart.setOnClickListener {
writeUartData("Odroid says hello\n");
}
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "Loopback Destroyed")
// Terminate the worker thread
inputThread.quitSafely()
// Attempt to close the UART device
uart.unregisterUartDeviceCallback(uartDeviceCallback)
uart.close()
}
private fun writeUartData(str: String){
val bytes = str.toByteArray()
val count = uart.write(bytes, bytes.size)
Log.d(TAG, "Wrote $count bytes to peripheral")
Toast.makeText(this, "message send : $str", Toast.LENGTH_SHORT).show()
}
private fun openUart(name: String, baudRate: Int): UartDevice {
return pManager.openUartDevice(name).apply {
// Configure the UART
setBaudrate(baudRate)
setDataSize(8)
setParity(UartDevice.PARITY_NONE)
setStopBits(1)
}
}
private fun transferUartData() {
// Loop until there is no more data in the RX buffer.
val buffer = ByteArray(maxCount)
do {
val read = uart.read(buffer, buffer.size)
if (read > 0) {
Log.w(TAG, "received data:\n${buffer}")
}
} while (read > 0)
}
}
查看 UartDeviceCallback 的实现后,window 打开并在顶部显示消息。
我选择了下载源,但没有任何反应。 我在这里遗漏了任何 files/libraries ?
我使用 Runnable Interface 读取 Uart 数据解决了这个问题。
private lateinit var handler: Handler
private lateinit var rThread: Thread
private lateinit var eRunnable: ExampleRunnable
inner class ExampleRunnable (pUart: UartDevice): Runnable{
val maxlen = 128
var inneruart = pUart
val TAG = "Uart_Activity"
@Volatile var threadRunning = true;
override fun run(){
Log.d(TAG, "Uart receive start")
while(threadRunning){
readUart()
}
}
private fun readUart() {
// Loop until there is no more data in the RX buffer.
val buffer = ByteArray(maxlen)
do {
val read = inneruart.read(buffer, buffer.size)
if (read > 0) {
val sub = buffer.copyOfRange(0,read)
var readString = String(sub)
Log.w("Uart_Activity", "received data bytes ($read):\n${readString}")
handler.post(object : Runnable{
override fun run() {
var cat:String = bind.peripheralMsg.text.toString() + readString
bind.peripheralMsg.text = cat
}
})
}
} while (read > 0)
}
fun setRunning(state: Boolean){
threadRunning = state
}
}
在上面的代码中,
bind.peripheralMsg.text = cat
在UI中显示接收到的数据。
在主程序的onCreate函数中,我做了如下操作:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Other stuffs
handler = Handler(Looper.getMainLooper())
eRunnable = ExampleRunnable(uart)
rThread = Thread(eRunnable)
rThread.start()
// Other stuffs
}
override fun onStop() {
super.onStop()
eRunnable.setRunning(false)
}