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

Python Kivy应用数据库存储问题:APK打包后JsonStorage无法保存

登录/注册页面数据存储问题解决方案

一、修复JsonStorage在Android上的崩溃与存储问题

1. 改用应用专属存储路径

Android系统限制应用只能在专属目录写入文件,直接用相对路径"user_info.json"会触发权限错误。修改为Kivy App提供的user_data_dir路径,这是系统允许应用读写的安全目录:

from kivy.app import App
from kivy.storage.jsonstore import JsonStore
# ... 其他导入代码

class LoginApp(App):
    def build(self):
        # 拼接应用专属路径与存储文件名
        self.stored_data = JsonStore(f"{self.user_data_dir}/user_info.json")
        return login_screen_sign_up(stored_data=self.stored_data)

class login_screen_sign_up(FloatLayout):
    def __init__(self, stored_data, **kwargs):
        super().__init__(**kwargs)
        self.stored_data = stored_data  # 接收存储实例,避免全局变量风险
        # ... 后续控件初始化代码

2. 移除错误代码

  • 删除stored_data.store_load():JsonStore会自动加载文件,手动调用无意义且可能引发异常。
  • 删除Builder.load_file('user_info.json'):Builder用于加载KV语言布局文件,不能加载JSON数据文件,这是导致APK崩溃的直接原因之一。
  • 删除FloatInput类中的your text垃圾代码,修复语法错误:
    class FloatInput(TextInput):
        input_filter = 'float'
    

3. 修复用户名重复判断逻辑

原循环逻辑会覆盖之前的匹配结果,改用JsonStore自带的exists()方法更高效准确:

def click_me(self, instance):
    username = self.login_info_un.text
    password = self.login_info_pass.text
    confirm_pwd = self.login_info_pass_confirm.text

    if not all([username, password, confirm_pwd]):
        print('请填写所有字段')
        return

    if self.stored_data.exists(username):
        print('This username is already taken.')
    elif password != confirm_pwd:
        print('Passwords do not match.')
    else:
        self.stored_data.put(username, password=password)
        self.stored_data.store_sync()
        print('注册成功')

4. 避免初始化时的KeyError

原代码直接取stored_data.get('Beckett')['password'],若该用户不存在会抛出异常,修改为安全取值:

# 安全获取用户密码,不存在则显示默认文本
user_data = self.stored_data.get('Beckett', {})
password_text = user_data.get('password', '暂无用户数据')
self.login_prompt = Label(text=password_text, size_hint=(0.3, 0.1), pos_hint={'x': 0.1, 'y': 0.6})

二、Buildozer配置调整

在buildozer.spec中添加必要权限和配置,确保Android端正常运行:

# 配置兼容的Android API级别(建议30及以上)
android.api = 30
android.ndk = 25b
# 添加存储读写权限
android.permissions = WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE
# 确保依赖版本兼容
requirements = python3,kivy

三、替代方案:使用SQLite存储

如果需要更可靠的结构化存储,推荐使用Python标准库的sqlite3,Android端支持良好:

import sqlite3
from kivy.app import App

class LoginApp(App):
    def build(self):
        db_path = f"{self.user_data_dir}/user_db.db"
        self.conn = sqlite3.connect(db_path)
        cursor = self.conn.cursor()
        # 创建用户表(不存在则创建)
        cursor.execute('CREATE TABLE IF NOT EXISTS users (username TEXT PRIMARY KEY, password TEXT)')
        self.conn.commit()
        return login_screen_sign_up(db_conn=self.conn)

class login_screen_sign_up(FloatLayout):
    def __init__(self, db_conn, **kwargs):
        super().__init__(**kwargs)
        self.db_conn = db_conn
        # ... 控件初始化代码

    def click_me(self, instance):
        username = self.login_info_un.text
        password = self.login_info_pass.text
        confirm_pwd = self.login_info_pass_confirm.text

        if not all([username, password, confirm_pwd]):
            print('请填写所有字段')
            return

        if password != confirm_pwd:
            print('Passwords do not match.')
            return

        try:
            cursor = self.db_conn.cursor()
            cursor.execute('INSERT INTO users VALUES (?, ?)', (username, password))
            self.db_conn.commit()
            print('注册成功')
        except sqlite3.IntegrityError:
            print('This username is already taken.')

内容的提问来源于stack exchange,提问作者Beckett

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 10:12:03