You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kivy应用打包安卓后点击TextInput控件立即崩溃

问题描述

开发Kivy框架问答游戏应用时,VSCode本地运行所有功能正常,通过搭载Ubuntu 20.04系统的DigitalOcean服务器打包为安卓应用后,点击TextInput输入框应用会立即崩溃。此前尝试移除kv文件顶部的BoxLayoutExample声明,问题未解决。

相关代码

mynew.kv

<BoxLayoutExample>:
    orientation:"vertical"
    Label:
        size_hint:1,.5
        text:"Enter private IP address of host:"
        id:label1
    TextInput: 
        size_hint:1,.5
        id:input_ip
        multiline:False
    Label:
        size_hint:1,.5
        text:"Enter port number (10000-65535):"
        id:label2
    TextInput: 
        size_hint:1,.5
        id:input_port
        multiline:False
    Label:
        size_hint:1,.5
        text:"Enter team name:"
        id:label3        
    TextInput: 
        size_hint:1,.5
        id:input_team_name
        multiline:False

    Label:
        size_hint:1,.5
        text:"Your score is: 0"
        id:label_score
    Button:
        text:"connect"
        id:button
        on_press: root.click()
        #size:"40dp","40dp"
        size_hint:1,4.5
        pos_hint:{"center_x":0.5}

main.py

import socket,threading
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput



class BoxLayoutExample(BoxLayout):
    score = 0
    pos = 0
    i = 0
    name = 0
    TCP_IP = ""
    BUFFER_SIZE = 1024
    TCP_PORT = 0
    s=0

    def click(self):
        if self.ids.button.text == "Raise hand":
            self.s.send(self.name.encode("ascii"))

        elif self.name != "":
            self.name = self.ids.input_team_name.text
            self.TCP_PORT = int(self.ids.input_port.text)
            self.TCP_IP = self.ids.input_ip.text
            self.ids.input_ip.size_hint = (0, 0)
            self.ids.input_team_name.size_hint = (0, 0)
            self.ids.input_port.size_hint = (0, 0)
            self.ids.label1.size_hint = (0, 0)
            self.ids.label2.size_hint = (0, 0)
            self.ids.label3.size_hint = (0, 0)
            self.ids.button.text = "Raise hand"
            self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.s.connect((self.TCP_IP, self.TCP_PORT))
            self.s.send(self.name.encode("ascii"))
            thread2=threading.Thread(target=receive,args=(self,))
            thread2.start()


class mynewApp(App):  # App should be at end of class
    def build(self):
        return BoxLayoutExample()
    
def receive(other):
    while 1:
        BoxLayoutExample.score = other.s.recv(
            BoxLayoutExample.BUFFER_SIZE).decode("ascii")
        BoxLayoutExample.pos = other.s.recv(
            BoxLayoutExample.BUFFER_SIZE).decode("ascii")
        other.ids.label_score.text = f"Your score is: {other.score} and you are on {other.pos}. position"




mynewApp().run()
崩溃日志

Android Studio logcat 最后输出内容如下:

2022-06-06 10:41:37.640 24504-24533/org.test.myapp I/python: [INFO   ] [Base        ] Leaving application in progress...
2022-06-06 10:41:37.640 24504-24533/org.test.myapp I/python:  Traceback (most recent call last):
2022-06-06 10:41:37.640 24504-24533/org.test.myapp I/python:    File "/root/enviroments/kivy_lab/.buildozer/android/app/main.py", line 58, in <module>
2022-06-06 10:41:37.640 24504-24533/org.test.myapp I/python:    File "/root/enviroments/kivy_lab/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/python-installs/myapp/arm64-v8a/kivy/app.py", line 955, in run
2022-06-06 10:41:37.641 24504-24533/org.test.myapp I/python:    File "/root/enviroments/kivy_lab/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/python-installs/myapp/arm64-v8a/kivy/base.py", line 574, in runTouchApp
2022-06-06 10:41:37.641 24504-24533/org.test.myapp I/python:    File "/root/enviroments/kivy_lab/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/python-installs/myapp/arm64-v8a/kivy/base.py", line 339, in mainloop
2022-06-06 10:41:37.642 24504-24533/org.test.myapp I/python:    File "/root/enviroments/kivy_lab/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/python-installs/myapp/arm64-v8a/kivy/base.py", line 383, in idle
2022-06-06 10:41:37.642 24504-24533/org.test.myapp I/python:    File "/root/enviroments/kivy_lab/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/python-installs/myapp/arm64-v8a/kivy/base.py", line 334, in dispatch_input
2022-06-06 10:41:37.642 24504-24533/org.test.myapp I/python:    File "/root/enviroments/kivy_lab/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/python-installs/myapp/arm64-v8a/kivy/base.py", line 302, in post_dispatch_input
2022-06-06 10:41:37.642 24504-24533/org.test.myapp I/python:    File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
2022-06-06 10:41:37.642 24504-24533/org.test.myapp I/python:    File "/root/enviroments/kivy_lab/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/python-installs/myapp/arm64-v8a/kivy/uix/textinput.py", line 1674, in on_touch_up
2022-06-06 10:41:37.642 24504-24533/org.test.myapp I/python:    File "/root/enviroments/kivy_lab/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/python-installs/myapp/arm64-v8a/kivy/uix/textinput.py", line 249, in __init__
2022-06-06 10:41:37.643 24504-24533/org.test.myapp I/python:    File "/root/enviroments/kivy_lab/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/python-installs/myapp/arm64-v8a/kivy/uix/widget.py", line 1167, in get_window_matrix
2022-06-06 10:41:37.643 24504-24533/org.test.myapp I/python:    File "/root/enviroments/kivy_lab/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/python-installs/myapp/arm64-v8a/kivy/uix/widget.py", line 1152, in _apply_transform
2022-06-06 10:41:37.643 24504-24533/org.test.myapp I/python:    File "/root/enviroments/kivy_lab/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/python-installs/myapp/arm64-v8a/kivy/uix/widget.py", line 1150, in _apply_transform
2022-06-06 10:41:37.643 24504-24533/org.test.myapp I/python:  TypeError: to_window() argument after * must be an iterable, not int
2022-06-06 10:41:37.643 24504-24533/org.test.myapp I/python: Python for android ended.
2022-06-06 10:41:37.676 24504-24520/org.test.myapp W/System: A resource failed to call close. 
2022-06-06 10:41:37.698 24504-24538/org.test.myapp A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xf1fe4a3a48 in tid 24538 (InsetsAnimation), pid 24504 (org.test.myapp)
故障原因

核心触发点是日志最后抛出的TypeError: to_window() argument after * must be an iterable, not int,属于自定义变量覆盖框架原生属性导致的兼容问题:

  • Kivy所有UI组件自带pos属性,存储控件的窗口坐标,是(x, y)格式的二元元组,属于可迭代对象。安卓端点击TextInput弹出软键盘时,框架会调用坐标转换方法计算输入框位置,需要传入可迭代的pos值做参数。
  • 代码中BoxLayoutExample类内定义了类属性pos = 0,直接把框架原生的pos元组覆盖成了整数0,整数不可迭代,直接触发类型错误。
  • 本地桌面端运行不会触发安卓软键盘弹出时的坐标适配逻辑,所以不会复现崩溃,只有打包到安卓端点击输入框唤起软键盘时才会触发报错。
修复方法
  1. 重命名和框架原生属性重名的自定义变量:把类内的pos = 0改为其他名称,比如rank_pos = 0,后续代码中所有存储排名位置的调用点同步替换为新变量名,不要占用Kivy组件原生的pos属性名。
  2. 修正其他逻辑隐患:
    • 类内name = 0初始值设置错误,name是存储队伍名的字符串,初始值应设为空字符串"",否则原有elif self.name != ""的判断逻辑第一次点击会直接跳过连接流程。
    • 网络接收线程直接修改UI控件文本不符合Kivy线程安全规则,建议用Clock.schedule_once把UI更新操作切回主线程执行,避免后续出现随机崩溃。
    • socket连接等耗时网络操作不要直接写在按钮点击回调里,会阻塞主线程导致应用无响应。

修复后的类属性定义参考:

class BoxLayoutExample(BoxLayout):
    score = 0
    rank_pos = 0 # 原pos=0改名,避免覆盖原生属性
    i = 0
    name = "" # 初始值改为空字符串
    TCP_IP = ""
    BUFFER_SIZE = 1024
    TCP_PORT = 0
    s=0

receive函数对应修改:

def receive(other):
    while 1:
        BoxLayoutExample.score = other.s.recv(
            BoxLayoutExample.BUFFER_SIZE).decode("ascii")
        BoxLayoutExample.rank_pos = other.s.recv(
            BoxLayoutExample.BUFFER_SIZE).decode("ascii")
        other.ids.label_score.text = f"Your score is: {other.score} and you are on {other.rank_pos}. position"

内容的提问来源于stack exchange,提问作者steve p.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 17:06:29