英文:
Getting [Errno 1] Operation is not permitted error when trying to write to /storage/emulated/0 with Kivy and Python on Android
问题
I have been around the mulberry bush for a few weeks now trying to implement the writing of a file on an android phone. My development setup is on a Windows PC with Anaconda and Pycharm. I am using kivy and buildozer to create the android app. My test app is simply trying to write a file (test.txt) to the root directory of the SD card on the phone.
The directory is: /storage/emulated/0
The error I am getting is: [Errno 1] Operation is not permitted: '/storage/emulated/0/test.txt'
I ask for permissions in the code, but the permissions are not prompted at application startup or installation.
Here is the code;
import kivy
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.utils import platform
import os
class MyGridLayout(GridLayout):
def __init__(self, **kwargs):
super(MyGridLayout, self).__init__(**kwargs)
self.cols = 1
self.dir_button = Button(text="Show Directory")
self.dir_button.bind(on_press=self.press_dir)
self.add_widget(self.dir_button)
self.write_button = Button(text="Write File")
self.write_button.bind(on_press=self.press_write)
self.add_widget(self.write_button)
self.text_field = TextInput(multiline=True)
self.add_widget(self.text_field)
def press_dir(self, instance):
if platform == 'android':
from android.storage import primary_external_storage_path
self.file_dir = primary_external_storage_path()
else:
self.file_dir = App.get_running_app().user_data_dir
if not os.path.exists(self.file_dir):
os.mkdir(self.file_dir)
self.text_field.text = self.file_dir
def press_write(self, instance):
self.file_name = "test.txt"
self.full_name = os.path.join(self.file_dir, self.file_name)
try:
with open(self.full_name, "w") as outfile:
outfile.write("Hello World")
except Exception as e:
self.text_field.text = str(e)
class TestWriteApp(App):
def build(self):
return MyGridLayout()
if platform == 'android':
from android.permissions import request_permissions, Permission
request_permissions([Permission.WRITE_EXTERNAL_STORAGE,
Permission.READ_EXTERNAL_STORAGE])
testwriteapp = TestWriteApp()
testwriteapp.run()
Here are the screenshots during testing;
Show Directory button
enter image description here
Write File button
enter image description here
Thanks for your help.
I tried a number of things...adding permissions in the buildozer.spec file, changing the output location to the internal user_data_dir (which worked, I think, but I need the user to be able to use the Files app to get the generated file)
英文:
I have been around the mulberry bush for a few weeks now trying to implement the writing of a file on an android phone. My development setup is on a Windows PC with Anaconda and Pycharm. I am using kivy and buildozer to create the android app. My test app is simply trying to write a file (test.txt) to the root directory of the SD card on the phone.
The directory is: /storage/emulated/0
The error I am getting is: [Errno 1] Operation is not permitted: '/storage/emulated/0/test.txt'
I ask for permissions in the code, but the permissions are not prompted at application startup or installation.
Here is the code;
import kivy
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.utils import platform
import os
class MyGridLayout(GridLayout):
def __init__(self, **kwargs):
super(MyGridLayout, self).__init__(**kwargs)
self.cols = 1
self.dir_button = Button(text="Show Directory")
self.dir_button.bind(on_press=self.press_dir)
self.add_widget(self.dir_button)
self.write_button = Button(text="Write File")
self.write_button.bind(on_press=self.press_write)
self.add_widget(self.write_button)
self.text_field = TextInput(multiline=True)
self.add_widget(self.text_field)
def press_dir(self, instance):
if platform == 'android':
from android.storage import primary_external_storage_path
self.file_dir = primary_external_storage_path()
else:
self.file_dir = App.get_running_app().user_data_dir
if not os.path.exists(self.file_dir):
os.mkdir(self.file_dir)
self.text_field.text = self.file_dir
def press_write(self, instance):
self.file_name = "test.txt"
self.full_name = os.path.join(self.file_dir, self.file_name)
try:
with open(self.full_name, "w") as outfile:
outfile.write("Hello World")
except Exception as e:
self.text_field.text = str(e)
class TestWriteApp(App):
def build(self):
return MyGridLayout()
if platform == 'android':
from android.permissions import request_permissions, Permission
request_permissions([Permission.WRITE_EXTERNAL_STORAGE,
Permission.READ_EXTERNAL_STORAGE])
testwriteapp = TestWriteApp()
testwriteapp.run()
Here are the screenshots during testing;
Show Directory button
enter image description here
Write File button
enter image description here
Thanks for your help.
I tried a number of things...adding permissions in the buildozer.spec file, changing the output location to the internal user_data_dir (which worked, I think, but I need the user to be able to use the Files app to get the generated file)
答案1
得分: 0
在 Android 11+ 设备上,您不能再像您尝试的那样写入外部存储的根目录。
而是请使用已经存在的公共目录,如文档和下载。
在 Android 13 设备上,您无需任何权限来执行此操作。
英文:
On Android 11+ devices you cannot write anymore to root of external storage as you try to do.
Instead use public directories that are already there like Documents and Download.
On Android 13 devices you do not need any permission to do so.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论