Android Tutorial Download huge files with HttpUtils2

Status
Not open for further replies.

Erel

Administrator
Staff member
Licensed User
The attached project includes a slightly modified version of HttpUtils2 and a new service named DownloadService. The purpose of DownloadService is to make it simple to download files of any size.



It is very simple to use this service.

Start a download:
B4X:
Sub btnDownload_Click
   Dim dd As DownloadData
   dd.url = link1 '<--- download link
   dd.EventName = "dd"
   dd.Target = Me
   CallSubDelayed2(DownloadService, "StartDownload", dd)
End Sub
Handle the events:
B4X:
Sub dd_Progress(Progress As Long, Total As Long)
   ProgressBar1.Progress = Progress / Total * 100
   Label1.Text = NumberFormat(Progress / 1024, 0, 0) & "KB / " & _
      NumberFormat(Total / 1024, 0, 0) & "KB"
End Sub

Sub dd_Complete(Job As HttpJob)
   Log("Job completed: " & Job.Success)
   Job.Release
End Sub
Cancel a download:
B4X:
Sub btnCancel_Click
   CallSubDelayed2(DownloadService, "CancelDownload", link1)
End Sub
DownloadService allows you to download multiple files at once and track the progress of each one of them.

The following libraries are required:
OkHttp
StringUtils
Phone (required in order to acquire a partial lock during the download)
RandomAccessFile

As this is a modified version of OkHttpUtils2 you should not reference OkHttpUtils2 library. You should instead add the three modules from the attached project. Note that the modified code is in Sub hc_ResponseSuccess.
 

Attachments

Last edited:

Jaames

Active Member
Licensed User
If use this modules instead of regular HttpUtils2Service and httpjob

I get this error "java.lang.ClassCastException: java.lang.Object cannot be cast to b4a.example.downloadservice$_jobtag
"

Does this mean that we cannot use modules from this example instead of modules from httputils2 example described in this thread?
 

Erel

Administrator
Staff member
Licensed User
You should change the code in hc_ResponseSuccess (HttpUtils2Service) to:
B4X:
Sub hc_ResponseSuccess (Response As HttpResponse, TaskId As Int)
   ' ********** Modified code *************
   Dim cs As CountingOutputStream
   cs.Initialize(File.OpenOutput(TempFolder, TaskId, False))
   Dim j As HttpJob = TaskIdToJob.Get(TaskId)
   If j.Tag Is JobTag Then
      Dim jt As JobTag = j.Tag
      jt.CountingStream = cs
      jt.Total = Response.ContentLength
      If jt.Data.url = "" Then
         Log("Job cancelled before downloaded started")
         cs.Close
      End If
   End If
   Response.GetAsynchronously("response", cs , _
      True, TaskId)
   '**************************************
End Sub
 

Jaames

Active Member
Licensed User
You should change the code in hc_ResponseSuccess (HttpUtils2Service) to:
B4X:
Sub hc_ResponseSuccess (Response As HttpResponse, TaskId As Int)
   ' ********** Modified code *************
   Dim cs As CountingOutputStream
   cs.Initialize(File.OpenOutput(TempFolder, TaskId, False))
   Dim j As HttpJob = TaskIdToJob.Get(TaskId)
   If j.Tag Is JobTag Then
      Dim jt As JobTag = j.Tag
      jt.CountingStream = cs
      jt.Total = Response.ContentLength
      If jt.Data.url = "" Then
         Log("Job cancelled before downloaded started")
         cs.Close
      End If
   End If
   Response.GetAsynchronously("response", cs , _
      True, TaskId)
   '**************************************
End Sub
Thank you Erel. It is working now.
 

yuhong

Member
Licensed User
How Get Download file?

B4X:
Sub dd_Complete(Successful As Boolean)
    Log("Job completed: " & Successful)
End Sub
I can't use job,Get download file. help me!

why not use job in Complete event.
B4X:
Sub JobDone(job As HttpJob)
   jobs.Remove(job.JobName)
   Dim jt As JobTag = job.Tag
   If jobs.Size = 0 Then EndTimer
   If job.Success Then
      CallSubDelayed3(jt.Data.Target, jt.Data.EventName & "_Progress", _
            jt.CountingStream.Count, jt.Total)
      CallSubDelayed2(jt.Data.Target, jt.Data.EventName & "_Complete", _
            True)
   Else
      Log(job.ErrorMessage)
      CallSubDelayed2(jt.Data.Target, jt.Data.EventName & "_Complete", _
            False)
   End If
End Sub
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I modity the code and OK:

B4X:
Sub JobDone(job As HttpJob)
   jobs.Remove(job.JobName)
   Dim jt As JobTag = job.Tag
   If jobs.Size = 0 Then EndTimer
   If job.Success Then
      CallSubDelayed3(jt.Data.Target, jt.Data.EventName & "_Progress", _
            jt.CountingStream.Count, jt.Total)
      CallSubDelayed2(jt.Data.Target, jt.Data.EventName & "_Complete", _
            Job)
   Else
      Log(job.ErrorMessage)
      CallSubDelayed2(jt.Data.Target, jt.Data.EventName & "_Complete", _
            Job)
   End If
End Sub
 
Last edited:

texwillerx

Member
Licensed User
problems with this code

I used your sample code in my program. Unfortunately, from time to time, the services does not start and callsubdelayed2 module returns immediately.

1. Do I have to set some parameters in my program to make this code work?

2. I tried your project, same thing happens. Some times it works, and some time it does not.

3. Is callsubdelayed2 synchronuos or async?

4. Is it permissible to change the file name in the service?

5. When I compile my programs, some time it is installed to the device, some times nothing happens, I have to run it again

Thanks and regards
 

texwillerx

Member
Licensed User
I put a breakpoint in dd_Progress, but the program never stops at that point.

Even I have put a breakpoint in Startdownload procedure, again it didnot stop.

What about callsubdelayed2? Is it Asynch also?

If so, how shall I know when the download is complete?

Thanks
 

texwillerx

Member
Licensed User
Here is my code.

Nothing is downloaded (DownloadService does not start at all)

Please help me.

Thanks

Sub downloadsystemdb_click
Dim httpdd As DownloadData
httpdd.url = ilink
httpdd.EventName = "httpdd"
httpdd.Target = Me
CallSubDelayed2(DownloadService, "StartDownload", httpdd)
End Sub
Sub httpdd_Progress(Progress As Long, Total As Long)
progressbar1.Visible=True
lblprogress.Visible=True
progressbar1.Progress = Progress / Total * 100
lblprogress.Text = NumberFormat(Progress / 1024, 0, 0) & "KB / " & _
NumberFormat(Total / 1024, 0, 0) & "KB"
End Sub

Sub httpdd_Complete(Successful As Boolean)
progressbar1.Visible=False
lblprogress.Visible=False
Log("Job completed: " & Successful)
End Sub
 

texwillerx

Member
Licensed User
Sorry for bothering you.

After restructuring the code bearing in mind that callsubdelayed is async, everything worked fine.

Thanks for everything.

P.S.: I have changed the followings:

Type DownloadData (url As String, Target As Object, EventName As String,jobname As String,taskid As Int,count As Long,total As Long,retval As Boolean) '*****changed

Sub JobDone(job As HttpJob)
jobs.Remove(job.JobName)
Dim jt As JobTag = job.Tag
If jobs.Size = 0 Then EndTimer
If job.Success Then
jt.Data.count=jt.CountingStream.Count '****added
jt.Data.total=jt.Total '****added
jt.Data.retval=True '****added
CallSubDelayed2(jt.Data.Target, jt.Data.EventName & "_Progress", _
jt.data) '*****changed
CallSubDelayed2(jt.Data.Target, jt.Data.EventName & "_Complete", _
jt.Data) '*****changed
Else
jt.Data.retval=False '****added
Log(job.ErrorMessage)
CallSubDelayed2(jt.Data.Target, jt.Data.EventName & "_Complete", _
jt.Data) '*****changed
End If
End Sub


Sub timer1_tick
For Each job As HttpJob In jobs.Values
Dim jt As JobTag = job.Tag
If jt.CountingStream.IsInitialized Then
jt.Data.count=jt.CountingStream.Count '****added
jt.Data.total=jt.Total '****added
jt.Data.retval=True '****added
CallSub2(jt.Data.Target, jt.Data.EventName & "_Progress", _
jt.data) '*****changed
End If
Next
End Sub

Sub hc_ResponseSuccess (Response As HttpResponse, TaskId As Int)
' ********** Modified code *************
Dim cs As CountingOutputStream
cs.Initialize(File.OpenOutput(TempFolder, TaskId, False))
Dim j As HttpJob = TaskIdToJob.Get(TaskId)
Dim jt As JobTag = j.Tag
jt.CountingStream = cs
jt.Total = Response.ContentLength
jt.Data.taskid=TaskId '*****changed
If jt.Data.url = "" Then
Log("Job cancelled before downloaded started")
cs.Close
End If
Response.GetAsynchronously("response", cs , _
True, TaskId)
'**************************************
End Sub
 

hanyelmehy

Active Member
Licensed User
I think file (which was downloaded from url) is saved to TempFolder using TaskId as file name ,how to copy this file to other folder with different name in this sub
B4X:
Sub dd_Complete(Successful As Boolean)
    Log("Job completed: " & Successful)
End Sub
 
Status
Not open for further replies.
Top