Python 中的存储访问框架 [英] Storage Access Framework in Python

查看:8

问题描述

我有 这个小应用程序,我想要重写它以使用对隐私更友好的最佳实践,例如存储访问框架.

I have this small application and I'd like to rewrite it to use more privacy-friendly best practices, such as the Storage Access Framework.

如何在 Python (Kivy) 中做到这一点?我在网上搜索并没有找到任何使用 Python 的教程或示例.我对 JavaKotlin 知之甚少.所以,我想阅读 Python 中的示例.

How to do it in Python (Kivy)? I searched the web and haven't found any tutorial or examples with Python. I know only very little Java and Kotlin at all. So, I would like to read the examples in Python.

我想替换这段代码:

request_permissions([Permission.WRITE_EXTERNAL_STORAGE,
                             Permission.READ_EXTERNAL_STORAGE])
        try:
            if autoclass('android.os.Build$VERSION').SDK_INT >= 29:
                Context = autoclass('android.content.Context')
                self.working_directory = os.path.join(Context.getExternalFilesDir(None).getAbsolutePath(), "tdg_articles")
                self.data_dir = os.path.join(Context.getExternalFilesDir(None).getAbsolutePath(), "nltk")
            else:
                Environment = autoclass('android.os.Environment')
                self.working_directory = os.path.join(Environment.getExternalStorageDirectory().getAbsolutePath(), "tdg_articles")
                self.data_dir = os.path.join(Environment.getExternalStorageDirectory().getAbsolutePath(), "nltk")
        except:
            self.working_directory = os.path.join(App.get_running_app().user_data_dir, "tdg_articles")
            self.data_dir = os.path.join(App.get_running_app().user_data_dir, "nltk")
        
        if not os.path.exists(self.working_directory):
            os.makedirs(self.working_directory)
        
        if not os.path.exists(self.data_dir):
            os.makedirs(self.data_dir)
        
        os.chdir(self.working_directory)

推荐答案

Scoped Storage带来两大变化:

  1. 首先,您不再可以通过文件的路径访问文件.相反,您需要使用它的 Uri.
  2. 其次,如果你想修改一个不是你的应用创建的文件,你需要征求用户的许可.

默认情况下,您有权访问其他应用无法访问的特定应用文件夹.但是,如果您需要在另一个位置读取/写入文件,则必须明确要求它们.范围存储类似于访问数据库.您请求 Android API 执行操作,系统会为您执行.

By default, you are given access to an app-specific folder that can't be accessed by others apps. However, if you need to read/write the files in another location you have to explicitly ask for them. The scoped storage is similar to accessing a database. You request the Android API to perform the action and the system does it for you.

类似问题:

Github 中有一个类似情况的未解决问题.

There's an open issue in Github that resembles a similar situation.

https://github.com/kivy/buildozer/issues/1304

有用的资源:

我找不到任何官方文档,但 Robert Flatt 有一个使用范围存储的实验性存储库.

I couldn't find any official documentation, but there's an experimental repository by Robert Flatt that uses the scope storage.

https://github.com/Android-for-Python/Storage-Example

他提供了 storage.py 实现用于访问此应用程序公共存储的数据库的 API 的类.提供的共享存储操作是 insert()delete()recieve(),这些在此应用的私有存储和共享存储之间复制文件.

He provided the storage.py class that implements an API for database access of this app's public storage. The shared storage operations provided are insert(), delete(), and recieve(), these copy files between this app's private and shared storage.

代码重构建议:

Scoped Storage 不仅限于询问文件权限,因此您需要以这种方式迁移所有文件操作.

Scoped Storage isn't limited to asking the file permission only, hence you need to migrate all of your file operations this way.

  1. 来自 Android API 29+ WRITE_EXTERNAL_STORAGE"许可是多余的.由于您将通过 MediaStore/SAF 使用存储,因此您不再需要此权限.
  2. 每当您执行文件操作时,请检查 Android 版本,如果低于 29,请继续使用现有代码.否则,使用 storage.py 类读取/写入文件.
  3. 如果您已经将数据存储在应用目录之外,则还需要将它们移动到应用目录内的文件夹中.

使用 storage.py 类的示例:

#######################
    #
    # Examples:
    # Where txt_file could be PrivateStorage().getFilesDir() + 'text.txt'
    # and so on.
    # All methods take a required file name, and optional directory parameters.
    #
    #   Insert:
    #   SharedStorage().insert(txt_file, 'Documents')
    #   SharedStorage().insert(txt_file, sub_dir= 'a/b')
    #   SharedStorage().insert(txt_file, 'Downloads')
    #   SharedStorage().insert(jpg_file, 'Pictures')
    #   SharedStorage().insert(mp3_file)
    #   SharedStorage().insert(ogg_file, 'Music')
    #
    #   Retrieve:
    #   path = SharedStorage().retrieve('test.txt')
    #   path = SharedStorage().retrieve('test.txt', 'Documents', 'a/b')
    #
    #   Delete:
    #   SharedStorage().delete('test.mp3', 'Music')
    #
    #   Retrieve from another app's storage (requires READ_EXTERNAL_STORAGE) :
    #   SharedStorage().retrieve('10_28_14.jpg', 'DCIM', '2021_03_12',
    #                            'CameraXF')
    #   SharedStorage().retrieve('10_33_48.mp4', 'DCIM', '2021_03_12',
    #                            'CameraXF')
    #
    #######################

详细说明在这里.

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆