Android Question StringUtils.SaveCSV - get actual saved filename changed by user

Mark Stuart

Active Member
Licensed User
Longtime User
Hi all,
This code is using the FileHandler class added to the project, for the purposes of allowing the user to choose the folder.
I allow the user to "export" SQLite table data to a CSV file, as a backup data feature.
The user selects the folder and saves the file. The file name can be changed by the user.
I need to capture that user changed filename after the OS save file returns back to my app code.
That actual filename will be added to a SQLite backup table for history viewing reasons.
The HandleLoadResult function - If Result.Success Then - is always false.

So this function never is able to get to the code line:
s = File.ReadString(Result.Dir, Result.FileName)
Therefore, I'm unable to get the actual filename (Result.FileName) used in the saving of the file.

How can I get the actual user filename that is saved?

My code:
button code to save the file::
Private Sub btnBackup_Click
    Dim Filename As String = "persons.csv"
    Dim data As List = DBModule.GetAllPersons2
    Dim count As Int = data.Size
    
    If data.Size > 0 Then
        'save as CSV file format
        su.SaveCSV(Folder,Filename,",",data)
        'now read the CSV file bytes
        Dim b() As Byte = File.ReadBytes(Folder,Filename)                  '<==== this is the "default" Filename from line #2
        Dim inp As InputStream
        inp.InitializeFromBytesArray(b,0,b.Length)
        'save to where the user wants to save the file
        Wait For (fh.SaveAs(inp,"text/plain",Filename)) Complete (Success As Boolean)     '<==== this is the "default" Filename from line #2
        If Success Then
            HandleLoadResult(fh.CheckForReceivedFiles)
            DBModule.AddEventHistory("BACKUP",data.Size)
            LoadEventHistory
            MsgboxAsync(count & " Person records backed up." & CRLF & "Backup File: " & Filename,"Attention")
            IME.HideKeyboard
        Else
            'ToastMessageShow("File not saved.", False)
        End If
    Else
        MsgboxAsync("No Person records to backup.","Attention")
    End If
End Sub
The code line: If Result.Success is always False, so it can't read the real user changed filename.
HandleLoadResult:
Private Sub HandleLoadResult(Result As LoadResult)
    If Result.Success Then
        Dim s As String
        Try
            s = File.ReadString(Result.Dir, Result.FileName)
            Log("Result.FileName: " & Result.FileName)
            ToastMessageShow($"File '${Result.RealName}' loaded"$, False)
        Catch
            s = "Error loading file"
            Log(LastException)
        End Try
        xui.MsgboxAsync(s,"Attention")
    End If
End Sub
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Your code is based on https://www.b4x.com/android/forum/t...-save-and-load-external-files.132731/#content

FileHandler.CheckForReceivedFiles is not relevant for your use case. This is used when another app sends an intent to your app with the file:


Attached is an updated FileHandler that will return information about the saved file. SaveAs now returns a LoadResult and it has a DocumentId field that includes the path, though you can't access it directly:


[Dir=, DocumentId=primary:Documents/NewFile (1).txt, FileName=
, IsInitialized=true, MimeType=text/plain, Modified=1759308195163
, RealName=NewFile (1).txt, Size=0, Success=true
]


Make sure to call it correctly:
B4X:
Wait For (FileHandler1.SaveAs(in, "text/plain", "NewFile.txt")) Complete (res As LoadResult)

Tested in B4A only.
 

Attachments

  • FileHandler.bas
    5.1 KB · Views: 6
Upvote 0

Mark Stuart

Active Member
Licensed User
Longtime User
Tested your new FileHandler.bas. Working great. Thankyou.
If others are to want to get the actual file name if the user changes the default filename, then use the class file as instructed by @Erel above.
My changes:
B4X:
Private Sub btnBackup_Click
    Dim Filename As String = "persons.csv"
    Dim data As List = DBModule.GetAllPersons2
    Dim count As Int = data.Size
    
    If count > 0 Then
        'save as CSV file format
        su.SaveCSV(Folder,Filename,",",data)
        'now read the CSV file bytes
        Dim b() As Byte = File.ReadBytes(Folder,Filename)
        
        Dim inp As InputStream
        inp.InitializeFromBytesArray(b,0,b.Length)
        'save to where the user wants to save the file
        'Wait For (fh.SaveAs(inp,"text/csv",Filename)) Complete (Success As Boolean)    '<=== old code line
        Wait For (fh.SaveAs(inp,"text/csv",Filename)) Complete (res As LoadResult)      '<=== new code line
        If res.Success Then            '<=== changed
            Dim resRealname As String = res.RealName     '<=== new code line to get the actual filename
            'Log("resRealname: " & resRealname)
            DBModule.AddEventHistory("BACKUP",count,resRealname)
            MsgboxAsync(count & " Person records backed up." & CRLF & "Backup File: " & resRealname,"Attention")
            IME.HideKeyboard
        'Else
            'ToastMessageShow("File not saved.", False)
        End If
    Else
        MsgboxAsync("No Person records to backup.","Attention")
    End If
End Sub
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…