首页 > 解决方案 > 为什么 Kivy Plyer Storagepath 不将文件保存到 Android 主目录和应用目录?

问题描述

我用 Kivy 制作了两个简单的应用程序,它将一个带有一个应用程序的 Sqlite3 db 文件和另一个应用程序的 json 文件保存到plyer.storagepath内置目录中。目的首先是为了测试android环境可以接受什么,其次是体验plyer项目的简单性和天才性。

问题是plyer.storagepath不想将文件保存到storagepath.get_home_dir(),storagepath.get_root_dir()storagepath.get_application_dir()android 环境中的目录。我明白为什么文件不会保存到根目录,但为什么不保存主目录和应用程序目录?

试过了

1] 授予应用程序存储权限。

2]使用python的os.path库获取带参数的App目录和带__file__参数的Home目录../../..。这确实有效,但我仍然想知道为什么plyer.storagepath当我尝试保存到主目录和应用程序目录时导致应用程序崩溃?

Sqlite3 文件使用 python os.path 创建代码

import kivy
kivy.require('1.11.0')

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.modalview import ModalView
from kivy.uix.button import Button
import os
from os.path import dirname
import sqlite3 as sl
import datetime
import threading, time
import plyer

Builder.load_string('''
#: import Window kivy.core.window.Window
<theData>:
    color: (0,0,0,1)
    background_normal: ''
    background_color: (0.72,0,0,1)
    on_release: app.root.test_file(self)
<ActionButton>:
    background_normal: ''
<DataLabel>:
    size_hint_x: 0.5
    color: (0,0,0,1)
    text: ''
    on_release: app.root.get_ins(self)
    background_normal: ''
    background_color: (0, 0.89, 0.32, 1)
    size_hint_y: None
    text_size: self.width, None
    height: self.texture_size[1]
<Data_Viewer>:
    id: mod_view
    size_hint: (0.8, 0.9)
    background_normal: ''
    background_color: (1, 1, 1, 0)
    background: 'white.png'
    ScrollView:
        size_hint_y: None
        size: mod_view.width, mod_view.height
        GridLayout:
            id: the_dat
            cols: 1
            size_hint_y: None
            height: self.minimum_height
            space: 5
            padding: [0,7,0,7]

<ActionBar>:
    canvas:
        Color:
            rgba: (0.14,0.5,0.71,1)
        Rectangle:
            pos: self.pos
            size: self.size
<TestAn>:
    canvas.before:
        Color:
            rgba: (1,1,1,1)
        Rectangle:
            pos: self.pos
            size: self.size
    ActionBar:
        pos_hint: {'top': 1, 'right': 1}
        ActionView:
            use_separator: True
            ActionPrevious:
                title: ''
                with_previous: False
                app_icon: ''
            ActionButton:
                text: 'Test'
                color: (0,0,0.56,1)
            ActionButton:
                id: view_gps
                Image:
                    source: 'i_5478.png'
                    center_y: self.parent.center_y
                    center_x: self.parent.center_x
                    size: self.parent.width /1.7, self.parent.height/ 1.7
                    allow_stretch: True
    Button:
        id: one_but
        pos_hint: {'top': 0.9, 'right': 1}
        size_hint: [1,0.2]
        text: 'Hello User. Do you want to create a db file?'
        on_release: app.root.sow_dir()
    GridLayout:
        id: view_data
        cols: 1
        size_hint_x: 1
        size_hint_y: None
        height: Window.height / 4
        spacing: 2
        pos_hint: {'right': 1,'top': 0.7}


''')
class DataLabel(Button):
    pass
class theData(Button):
    pass
class Data_Viewer(ModalView):
    pass
class TestAn(FloatLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.ids.view_data.add_widget(theData(text= str(os.path.dirname(os.path.abspath(__file__)))))
        self.ids.view_data.add_widget(theData(text= str(os.path.abspath(os.path.join(__file__ ,"../..")))))
        self.ids.view_data.add_widget(theData(text= str(os.path.abspath(os.path.join(__file__ ,"../../..")))))
        self.ids.view_data.add_widget(theData(text= str(plyer.storagepath.get_home_dir())))
        self.ids.view_data.add_widget(theData(text= str(plyer.storagepath.get_application_dir())))
        self.ids.view_data.add_widget(theData(text= str(plyer.storagepath.get_root_dir())))
    def sow_dir(self):
        m = Data_Viewer()
        m.ids.the_dat.clear_widgets()
        ff = App._get_user_data_dir
        if os.path.exists(os.path.abspath(__file__)):
            m.ids.the_dat.add_widget(DataLabel(text=str(os.path.basename(__file__))))
            m.ids.the_dat.add_widget(DataLabel(text=str(os.path.dirname(os.path.abspath(__file__)))))
            m.ids.the_dat.add_widget(DataLabel(text=str(os.path.abspath(os.path.join(__file__ ,"../..")))))
            m.ids.the_dat.add_widget(DataLabel(text=str(os.path.abspath(os.path.join(__file__ ,"../../..")))))
            m.ids.the_dat.add_widget(DataLabel(text= str(plyer.storagepath.get_home_dir())))
            m.ids.the_dat.add_widget(DataLabel(text= str(plyer.storagepath.get_application_dir())))
            m.ids.the_dat.add_widget(DataLabel(text= str(plyer.storagepath.get_root_dir())))
        m.open()
    def get_ins(self, instance):
        the_db = my_db()
        conn = the_db.create_db(instance.text)
        cur = conn.cursor()
        the_db.create_log_table(cur)
        the_db.log_data_entry(conn,cur, instance.text)
        cur.close()
        conn.close()
    def test_file(self, instance):
        the_path = (instance.text + '/test_entry.db')

        if os.path.isfile(the_path):
            ntitle = 'File Existence'
            nmessage = 'File Exists!'
            the_app_name = str(App.get_running_app().name)
            plyer.notification.notify(title=ntitle, message=nmessage,app_name=the_app_name,timeout=4,ticker='New Incoming Notification',toast=True)

class my_db():
    sql_err = (sl.IntegrityError, sl.OperationalError, sl.ProgrammingError, sl.InterfaceError)
    def create_db(self, db_dir):
        the_path = (db_dir + '/test_entry.db')
        conn = sl.connect(the_path)
        return conn
    def create_log_table(self, cur):
        cur.execute('CREATE TABLE IF NOT EXISTS test_logs(\
                    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\
                    user_id INTEGER NOT NULL,\
                    test_file BLOB NOT NULL, \
                    date_created TEXT NOT NULL)')
    def log_data_entry(self,conn, cur, ins):
        ur = 1
        dte_created = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
        try:
            cur.execute("INSERT INTO test_logs(user_id, test_file, date_created)\
                        VALUES(?,?, ?)", (ur, ins, dte_created))
            conn.commit()
        except self.sql_err as err:
            cur.close()
class TheAnTestApp(App):
    title = 'The test App'
    def build(self):
        self.icon = 'find_folderpath.png'
        return TestAn()

if __name__ == '__main__':
    TheAnTestApp().run()

Json文件创建代码

import kivy
kivy.require('1.10.0')

from kivy.app import App
import plyer
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty, StringProperty
from kivy.utils import platform

import datetime, json, os

Builder.load_string('''
#: import storagepath plyer.storagepath
<ThePlyThing>:
    Button:
        pos_hint: {'top': 1, 'right': 0.9}
        size_hint: [0.8, 0.05]
        text: 'Get Bluetooth status'
        on_release:
            root.get_info()
    Label:
        pos_hint: {'top': 0.95, 'right': 0.9}
        size_hint: [0.8, 0.04]
        text: str(root.text)
    Label:
        pos_hint: {'top': 0.91, 'right': 0.9}
        size_hint: [0.8, 0.04]
        text: str(root.info)
    TextInput:
        id: tit_notify
        pos_hint: {'top': 0.87, 'x': 0.05}
        size_hint: [0.9, 0.05]
        hint_text: 'Title'
    TextInput:
        id: mess_notify
        pos_hint: {'top': 0.82, 'x': 0.05}
        size_hint: [0.9, 0.05]
        hint_text: 'Message'
    Button:
        pos_hint: {'top': 0.77, 'x': 0.3}
        size_hint: [0.4, 0.08]
        text: 'Get notified true..?'
        on_release: root.get_notified()
    Button:
        pos_hint: {'top': 0.67, 'x': 0.3}
        size_hint: [0.4, 0.04]
        text: 'Home'
        on_press: label.text = str(storagepath.get_home_dir())
    Button:
        pos_hint: {'top': 0.63, 'x': 0.3}
        size_hint: [0.4, 0.04]
        text: 'External Storage'
        on_press:
            label.text = str(storagepath.get_external_storage_dir())
    Button:
        pos_hint: {'top': 0.59, 'x': 0.3}
        size_hint: [0.4, 0.04]
        text: 'Root'
        on_press: label.text = str(storagepath.get_root_dir())
    Button:
        pos_hint: {'top': 0.55, 'x': 0.3}
        size_hint: [0.4, 0.04]
        text: 'Documents'
        on_press: label.text = str(storagepath.get_documents_dir())
    Button:
        pos_hint: {'top': 0.51, 'x': 0.3}
        size_hint: [0.4, 0.04]
        text: 'Downloads'
        on_press: label.text = str(storagepath.get_downloads_dir())
    Button:
        pos_hint: {'top': 0.47, 'x': 0.3}
        size_hint: [0.4, 0.04]
        text: 'Videos'
        on_press: label.text = str(storagepath.get_videos_dir())
    Button:
        pos_hint: {'top': 0.43, 'x': 0.3}
        size_hint: [0.4, 0.04]
        text: 'Music'
        on_press: label.text = str(storagepath.get_music_dir())
    Button:
        pos_hint: {'top': 0.39, 'x': 0.3}
        size_hint: [0.4, 0.04]
        text: 'Pictures'
        on_press: label.text = str(storagepath.get_pictures_dir())
    Button:
        pos_hint: {'top': 0.35, 'x': 0.3}
        size_hint: [0.4, 0.04]
        text: 'Applications'
        on_press: label.text = str(storagepath.get_application_dir())
    Button:
        pos_hint: {'top': 0.67, 'x': 0}
        size_hint: [0.3, 0.04]
        text: 'New File'
        on_press: root.create_file()
    Button:
        pos_hint: {'top': 0.67, 'x': 0.7}
        size_hint: [0.3, 0.04]
        text: 'Existence'
        on_press:
            root.test_file()
    Label:
        canvas.before:
            Color:
                rgba: (0.57,0.57,0.57,1)
            Rectangle:
                pos: self.pos
                size: self.size
        id: label
        pos_hint: {'top': 0.31, 'x': 0}
        size_hint: [1, 0.1]
    Button:
        pos_hint: {'top': 0.20, 'x': 0.05}
        size_hint: [0.4, 0.05]
        text: 'Vibrate'
        on_press: root.get_vibe()
''')
class ThePlyThing(FloatLayout):
    info = ObjectProperty()
    text = StringProperty()
    dte = StringProperty()
    fil = StringProperty()
    text = "Bluetooth: "
    def get_notified(self):
        if self.ids.tit_notify.text != '' and self.ids.mess_notify.text != '':
            ntitle = str(self.ids.tit_notify.text)
            nmessage = str(self.ids.mess_notify.text)
            the_app_name = str(App.get_running_app().name)
            plyer.notification.notify(title=ntitle, message=nmessage,app_name=the_app_name,timeout=4,ticker='New Incoming Notification',toast=True)
    def get_info(self):
        if platform == 'android' or platform == 'ios': 
            self.info = str(plyer.bluetooth.info)
        else:
            self.info = 'Not supported'
    def get_vibe(self):
        if platform == 'android' or platform == 'ios':
            if plyer.vibrator.exists():
                plyer.vibrator.vibrate(4)
            else:
                the_app_name = str(App.get_running_app().name)
                plyer.notification.notify(title='No Vibrator', message='No Vibrator',app_name=the_app_name,timeout=4,ticker='New Incoming Notification',toast=True)
    def create_file(self):
        self.fil = self.ids.label.text
        if self.fil != "":
            self.dte = datetime.datetime.now().strftime('%d/%m/%Y %H:%M:%S')
            dat = {}
            dat['newfile'] = []  
            dat['newfile'].append({  
                'name': 'File Exists!',
                'thedate': self.dte,
                'from': 'Herman'
            })

            with open(self.fil + '/data_file.txt', 'w') as outfile:  
                json.dump(dat, outfile)
    def test_file(self):
        self.fil = self.ids.label.text
        if self.fil != "":
            self.fil = self.fil + '/data_file.txt'
            if os.path.isfile(self.fil):
                the_app_name = str(App.get_running_app().name)
                with open(self.fil) as json_file:
                    rd_dat = json.load(json_file)
                    for p in rd_dat['newfile']:
                        if p['name']:
                            mess = p['name']
                        if p['thedate']:
                            mess = mess + ' ' + p['thedate']
                if mess != "":
                    plyer.notification.notify(title='File Exists', message=mess,app_name=the_app_name,timeout=4,ticker='New Incoming Notification',toast=True)
class AndyApp(App):
    title = 'The Ply Test'
    def build (self):
        self.icon = 'test_all_limits.png'
        return ThePlyThing()
    def on_pause(self):
        return True

AndyApp().run()

预期结果

我想使用开箱即用的 plyer 在主目录和应用程序目录中创建一个文件。

当前为每个 plyer 存储路径返回的目录是:

storagepath.get_home_dir()/data

storagepath.get_root_dir()/system

storagepath.get_application_dir()/data/user/0

标签: androidpythonpython-3.xkivy

解决方案


推荐阅读