Android Question ExternalStorage: Copy to USB with progress on main UI thread

Charlie Burnham

Member
Licensed User
I'm having no luck showing a progress bar or % number in the UI when copying files using ExternalStorage and the following approach:

Sub in ExternalStorage class:
public Sub CopyToUSB(sourceDir As String, sourceFile As String, dest As String) 
    dest = ProcessPath(dest)
        
    Dim inStream As InputStream = File.OpenInput(sourceDir, sourceFile)
    Dim totalSize As Long = File.Size(sourceDir, sourceFile)
    
    Dim outFile As ExternalFile = FindDeepFile(Storage.Root, dest, True)
    Dim outStream As OutputStream = Storage.OpenOutputStream(outFile)
    
    CopyStreams(inStream, outStream, totalSize)
    
    inStream.Close
    outStream.Flush
    outStream.Close
    
    OnCopyComplete(sourceDir & "/" & sourceFile, dest)
End Sub

Private Sub CopyStreams(in As InputStream, out As OutputStream, totalSize As Long)
    Dim buffer(FILE_COPY_BUFFER_SIZE) As Byte
    Dim read As Int = 0
    
    Dim lastProgress As Int = -1
    Dim bytesWritten As Long  = 0
    Do While(True)
        read = in.ReadBytes(buffer, 0, buffer.Length)
            If read = -1 Then
            Exit
        End If       
         out.WriteBytes(buffer, 0, read)
        bytesWritten = bytesWritten + read       
        Dim progress As Int = (bytesWritten / totalSize) * 100
        If progress > lastProgress Then
            lastProgress = progress           
            OnCopyProgress(progress)
        End If       
       Loop   
End Sub

Private Sub OnCopyProgress(progress As Int)    
    CallSub2(module, eventName  & "_CopyProgress", progress)
End Sub

Code in main UI activity:
Sub ES_CopyProgress(progress As Int)
    CallSubDelayed2("Upload","DisplayCopyProgress", progress)
End Sub

Sub DisplayCopyProgress(progress As Int)
    Sleep(0)
    Log("USB Copying " & progress)
    lbl_Process_Status.Text = "Progess: " & progress
End Sub

DisplayCopyProgress does not log until all the writebytes is finished (copy complete) . Then it logs all the progress at once. The UI never updates on progress. This is true in both debug and release. I realize this is likely a threading problem and may not have a solution. The file copying itself works well, however these are ~250MB files, taking up to 45 seconds, with another 15 to allow for safe USB removal from the OTG. That is a lot of time for the user to just watch the circular/indeterminate progress bar. Perhaps the whole project would benefit from moving to B4X Pages, however it is large and elderly (like me) and if there is a simple/safe/fast way to get progress from the ExternalStorage lib, I would love to hear it.

Kind regards to all.
 

Charlie Burnham

Member
Licensed User
Thanks Erel. That allows the UI to be unblocked during the transfer, but to get incremental file copy progress, I had to use a timer and poll the size of the file on the USB. I do this at 1500ms intervals. It works, but I wonder if there is another way to get progress from File.Copy2Async
 
Upvote 0
Top