A few more notes:
If I update the button text to thevar's value, the button text shows the value properly, without mangling it. It appears that the value is not being mangled on the android end - it's only mangled when the text is output on the server computer.
I originally thought that kb.iskey(thevar) was returning false and kb.stroke(thevar) didn't work for strings like "comma" "rightbracket" and "dot" because the string value was being mangled before it hit the iskey() function. But apparently the two problems are separate - I think those key names are being passed to the kb functions properly, but are not valid for some reason, despite being listed on the "keys" documentation page.
I think the mangling problem probably lies within kb.text(). kb.stroke seems to be working ok except for the unrecognized key names. for example, the following code works as expected (ie: prints the string value of thevar on the server computer):
actions.stroker = function ()
thevar = "comma"
for i = 1, #thevar do
local c = thevar:sub(i,i)
Using the key names that are output by xev on the server computer (eg: "period" instead of "dot") doesn't seem to work either, but using the UTF-8 keycode (eg: 0x2c for a comma) seems to get kb.stroke() to work as expected. (kb.stroke("shift", 0x2c) outputs a "<").
Also, there appears to be a pretty significant delay between pressing the button and the text being printed on the server computer when using the kb.text(string) function. When using kb.stroke(0x2c) there is no significant delay.
Typing using the keyboard that can be accessed from the bottom row of icons in UR works fine - text is not mangled, and the letters appear without significant delay.