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)
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.