kivy 安卓:写入公共文件

2 投票
2 回答
2173 浏览
提问于 2025-04-18 17:29

我正在用Kivy编写一个安卓应用,想让这个应用能够写入安卓的文件系统,具体是一些公共的目录或文件。

目前,如果我的应用写入一个文件(使用Python),这个文件可以被安卓本地的文件管理器读取,但在我的电脑上通过mtp连接时,这些文件却看不到(它们不出现在内部存储中)。不过,adb shell是可以看到这些文件的。

[编辑] 解决办法可能是使用MediaScannerConnection和Pyjnius来扫描这些文件以便在mtp中显示,但正如我在下一个回答中所说的,这对我来说并没有成功。[/编辑]

我觉得我在寻找一个类似于Java中getSharedPreferences的东西,具体可以参考这里:http://developer.android.com/guide/topics/security/permissions.html

我以为在buildozer的配置中有类似的选项:android.private_storage字段,具体描述可以在这里找到:https://raw.githubusercontent.com/kivy/buildozer/master/buildozer/default.spec

但是,我没有成功使用这个选项……也许我没有正确使用buildozer命令:在配置中设置“android.private_storage = False”后,我尝试了几个命令,比如“buildozer android release --dir public my_dir”或者“buildozer android release --public my_dir”等等,但都没有成功。

2 个回答

1

基本上解决了:这似乎是mtp中的一个已知问题:某些文件根据它们的写入方式(我使用的是Python的“open”指令)在设备上不会显示,直到你重启设备。确实,重启设备确实有帮助。

2

我一直在尝试使用Pyjnius中的MediaScannerConnection,让文件在不重启的情况下可见,但一直没有成功。在文件系统中写入文件后,我的目标是扫描这些文件。下面是我运行的代码,但似乎没有任何明显的效果。

from jnius import autoclass , cast
from jnius import PythonJavaClass, java_method

PythonActivity = autoclass('org.renpy.android.PythonActivity')
activity = cast('android.app.Activity', PythonActivity.mActivity)
context = activity.getApplicationContext()

MediaScannerConnection = autoclass('android.media.MediaScannerConnection')
MediaScannerConnection.scanFile(context,successFiles,None,None)   #successFiles is a list of absolute paths of files on Android

我也尝试使用scanFile方法的其他重载形式,但我无法正确定义所需的接口:

class OnScanCompletedListener(PythonJavaClass):
    __javainterfaces__ = ['android.media.MediaScannerConnection$OnScanCompletedListener']


    @java_method('(Ljava.lang.String;Landroid.net.Uri;)V')
    def onScanCompleted(self, path, uri):
        pass

    @java_method('()V')
    def onMediaScannerConnected(self):
        pass


MediaScannerConnection = autoclass('android.media.MediaScannerConnection')
mediaScannerConnectionListener = OnScanCompletedListener()
mScanner = MediaScannerConnection(context,mediaScannerConnectionListener)
mScanner.connect()
for thefile in successFiles:
    mScanner.scanFile(thefile,None) 

撰写回答