Python Forum
Open/save file on Android - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Open/save file on Android (/thread-41489.html)



Open/save file on Android - frohr - Jan-24-2024

Hi all, I have app using Kivy and I need open / save csv files. Under Windows/Linux it works well but not under Android. I see folders but no files. Testing on Android 13 but must works also on 10,11,12.
Any suggestion? Thank you.

Part of open/save code:
# OPEN FILE DOALOG  ==================================================================================================

    def show_load(self):
        self.root.ids.sm.current = 'open_screen'
        open_layout = self.root.ids.open_layout
        open_layout.clear_widgets()
        if platform == 'android':
            default_path = '/storage/emulated/0/'  
        else:
            default_path = '.'
        file_chooser = FileChooserIconView(size_hint=(1, 1), path=default_path)
        file_chooser.filters = ['*.csv']  # Show only CSV files
        open_layout.add_widget(file_chooser)
        status_label = Label(text='', size_hint=(1, None), height=dp(40))
        open_layout.add_widget(status_label)
        open_button = Button(text="Open", size_hint=(1, None), height=dp(40))
        open_button.bind(on_release=lambda instance: self.open_file(file_chooser.selection[0],
                                                                    file_chooser.path, status_label))
        open_layout.add_widget(open_button)
        exit_layout = BoxLayout(orientation='horizontal', size_hint_y=None, height=dp(40))
        exit_button = Button(text="Exit")
        exit_button.bind(on_release=self.switch_to_main)
        exit_layout.add_widget(exit_button)
        open_layout.add_widget(exit_layout)

# OPEN FILE AND LOAD DATA ===================================================================================
        
    def open_file(self, file_name, path, status_label):
        if not file_name:
            status_label.text = "Error: No file selected."
            return

        file_path = os.path.join(path, file_name)
        if not os.path.exists(file_path):
            status_label.text = "Error: File does not exist."
            return

        try:
            with open(file_path, 'r') as file:
                file_content = file.read().replace(';', '')

            file_like_object = StringIO(file_content)

            data = np.loadtxt(file_like_object, dtype="float")

            if len(data) == 0:
                status_label.text = "Error: No data in file."
                return
            self.accel_data = data
            self.SPS = len(self.accel_data)
            data_sps_button = self.root.ids.data_SPS
            data_sps_button.text = f"SPS: {self.SPS}"
            self.switch_to_main(None)  
        except IOError as io_err:
            status_label.text = f"Error opening file: {io_err}"
        except ValueError as val_err:
            status_label.text = f"Error in file format: {val_err}"
        except Exception as e:
            status_label.text = f"An unexpected error occurred: {e}"

# SAVE FILE DIALOG ===================================================================================

    def show_save(self):
        self.root.ids.sm.current = 'save_screen'
        save_layout = self.root.ids.save_layout
        save_layout.clear_widgets()
        file_name_input = TextInput(hint_text="Enter file name (e.g., my_file.csv)",
                                    size_hint=(1, None), height=dp(40))
        save_layout.add_widget(file_name_input)
        if platform == 'android':
            default_path = '/storage/emulated/0/'  
        else:
            default_path = '.'
        file_chooser = FileChooserIconView(size_hint=(1, 1), path=default_path)
        save_layout.add_widget(file_chooser)
        status_label = Label(text='', size_hint=(1, None), height=dp(40))
        save_layout.add_widget(status_label)
        save_button = Button(text="Save", size_hint=(1, None), height=dp(40))
        save_button.bind(on_release=lambda instance: self.save_file(file_name_input.text,
                                                                    file_chooser.path, status_label))
        save_layout.add_widget(save_button)
        exit_layout = BoxLayout(orientation='horizontal', size_hint_y=None, height=dp(40))
        exit_button = Button(text="Exit")
        exit_button.bind(on_release=self.switch_to_main)
        exit_layout.add_widget(exit_button)
        save_layout.add_widget(exit_layout)

# SAVE FILE ==============================================================================================================

    def save_file(self, file_name, path, status_label):
        if path and file_name:
            if not file_name.lower().endswith('.csv'):
                file_name += '.csv'
            file_path = os.path.join(path, file_name)
          
            if not hasattr(self, 'accel_data') or self.accel_data is None:
                status_label.text = "Error: No acceleration data available."
                return
            data = self.accel_data
            if len(data) == 0 or not isinstance(data, np.ndarray):
                status_label.text = "Error: Invalid data. Data must be a non-empty numpy array."
                return
            try:
                np.savetxt(file_path, data, delimiter=',')
                status_label.text = f"File saved as: {file_path}"
            except IOError as io_err:
                status_label.text = f"Error saving file: {io_err}"
            except Exception as e:
                status_label.text = f"An unexpected error occurred: {e}"
        else:
            status_label.text = "Please enter a file name and select a save location."
When I compile to APK, I use this in buildozer.spec:

android.permissions = INTERNET, WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE