如何在Android设备上将Kivy应用文件保存至Documents文件夹?
解决Kivy Android应用导出文件到公共Documents/Download文件夹的问题
权限说明
- Android 10(API 29)及以上版本:采用Scoped Storage机制,写入公共Documents、Download等目录无需申请
WRITE_EXTERNAL_STORAGE权限,通过系统提供的API访问即可。 - Android 9及以下:仍需在
AndroidManifest.xml中添加WRITE_EXTERNAL_STORAGE权限,但目前主流设备已升级到Android 10+,重点适配新版本即可。
问题原因
直接硬编码绝对路径(如/storage/emulate/0/Download)会报错,原因是:
- 不同设备的公共目录路径可能存在差异;
- Scoped Storage限制应用直接访问根目录下的存储路径,必须通过系统API获取合法的可写路径。
解决方案
推荐两种实现方式,优先选择更简洁的plyer库,或用pyjnius直接调用Android原生API。
方式一:使用plyer库(推荐)
plyer是Kivy生态的跨平台库,提供统一的存储访问接口。
- 配置buildozer.spec:
在requirements中添加plyer:
requirements = python3,kivy,plyer
- 修改Python代码:
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from os.path import join from kivy.properties import StringProperty from plyer import storage class Main(BoxLayout): pass class TestApp(App): path = StringProperty("Path") ToPrint = ["Hello", "World", "This", "Is", "A", "Kivy", "App"] def Export(self): # 获取公共Documents目录路径 docs_dir = storage.get_documents_dir() # 或获取Download目录:storage.get_downloads_dir() self.path = join(docs_dir, "Sentence.txt") # 写入文件 with open(self.path, 'w') as doc: for word in self.ToPrint: doc.write(f"{word}\n") def build(self): return Main() TestApp().run()
方式二:使用pyjnius调用Android原生API
无需额外库,直接通过pyjnius调用Android的Environment类获取路径。
- 配置buildozer.spec:
确保requirements包含pyjnius:
requirements = python3,kivy,pyjnius
- 修改Python代码:
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from os.path import join from kivy.properties import StringProperty from jnius import autoclass class Main(BoxLayout): pass class TestApp(App): path = StringProperty("Path") ToPrint = ["Hello", "World", "This", "Is", "A", "Kivy", "App"] def Export(self): # 获取Android的Environment类 Environment = autoclass('android.os.Environment') # 获取公共Documents目录 docs_dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getPath() # 或获取Download目录:Environment.DIRECTORY_DOWNLOADS self.path = join(docs_dir, "Sentence.txt") # 写入文件 with open(self.path, 'w') as doc: for word in self.ToPrint: doc.write(f"{word}\n") def build(self): return Main() TestApp().run()
注意事项
- 若适配Android 9及以下设备,需在
buildozer.spec的android.permissions中添加:android.permissions = WRITE_EXTERNAL_STORAGE - 写入文件前可先检查目录是否存在,若不存在则创建:
import os if not os.path.exists(docs_dir): os.makedirs(docs_dir)
内容的提问来源于stack exchange,提问作者Eoin Brennan
相关产品推荐
相关产品推荐

