我有一个小应用程序,我想重写它以使用更隐私友好的最佳做法,如存储访问框架。
如何在Python
(Kivy(中进行?我在网上搜索了一下,没有找到任何关于Python
的教程或例子。我只知道很少的Java
和Kotlin
。因此,我想阅读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)
作用域存储带来两个主要变化:
- 首先,您不再可以通过文件路径访问该文件。相反,您需要使用它的Uri
- 其次,如果你想修改一个不是由你的应用程序创建的文件,你需要征求用户的许可
默认情况下,您可以访问其他应用程序无法访问的应用程序特定文件夹。但是,如果您需要在另一个位置读取/写入文件,则必须明确要求它们。作用域存储类似于访问数据库。您请求Android API执行该操作,系统将为您执行该操作。
类似问题:
Github中有一个悬而未决的问题类似于类似的情况。
https://github.com/kivy/buildozer/issues/1304
有用资源:
我找不到任何官方文档,但有一个Robert Flatt的实验存储库,它使用范围存储。
https://github.com/Android-for-Python/Storage-Example
他提供了storage.py类,该类实现了一个API,用于访问该应用程序的公共存储的数据库。提供的共享存储操作为insert()
、delete()
和recieve()
,这些操作在该应用程序的专用存储和共享存储之间复制文件。
代码重构建议:
作用域存储不仅限于请求文件权限,因此您需要以这种方式迁移所有文件操作。
- 来自Android API 29+";EXTERNAL_STORAGE";权限是多余的。由于您将通过MediaStore/SAF使用存储,因此不再需要此权限
- 每当你在做文件操作时,请检查Android版本,如果低于29,请继续使用现有代码。否则,请使用storage.py类来读取/写入文件
- 如果你已经将数据存储在应用程序目录之外,你还需要将它们移动到应用程序目录内的文件夹中
使用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')
#
#######################
此处给出了详细说明。
经过我的研究,您应该使用Pyjnius并直接从Python访问SAF类。Kivy也有一些相关文件:https://kivy.org/doc/stable/guide/android.html#pyjnius.
因此,如果您想访问kivy中的权限,最简单的方法是将权限放在buildozer.spec文件的权限字段中。您只需要在buildozer文件中放置权限WRITE_EEXTERNAL_STORAGE和READ_EXTERNAL_TORAGE。请参阅kivy和buildozer文档。或者,如果你想从应用程序中调用请求权限,你也可以使用pyjnius库。