It is recommended to use HttpUtils2 instead of this code module. HttpUtils2 is more powerful and is easier to work with.
As discussed in the Services tutorial, some tasks are easier to implement with services than with activities.
In this example we will download an image file with a service and use it for the activity background.
This service can be used to download larger files as well.
The advantage of a service over activity in this case is that the service isn't paused when the application is in the background.
The steps required for downloading a file with this service is to first set the URL and the target file (the downloaded file is written to this file) and then call StartService.
The process global variables are used for passing those values to the service.
Process global variables can be accessed from all modules and are always available (even when the component is paused).
The service then downloads the file. When download completes the service uses CallSub to notify the Activity that the download has completed.
It is possible that the activity is not active when download is complete. In this case CallSub will not do anything. Press on Home button after starting the download to pause the activity.
We are handling this case in the activity resume event. When the activity resumes we check if we were in the middle of a download task. If yes, then we check the service JobStatus global variable which tells us whether the task has finished.
In most cases it is better to let the activity pull data from the service than pushing the data to the activity from the service. This way when the activity is ready it can grab the data and work with it.
If we were to download a large file in the background it is possible that the OS will at some point kill our process to free some memory. This will of course break our download.
To avoid this issue the service calls Service.StartForeground while downloading. This call marks our process as a foreground process. Which means that it is important not to kill it. A status bar notification is also displayed when the service is in this state.
You should be careful not to overuse this method and only call it if it is really problematic for your service to be killed.
When download completes we also check if the activity is currently active. If not we show a status bar notification that notifies the user that download has completed. When the user presses on the notification (by first dragging the status bar downwards) our activity is resumed.
The program is attached.
Main activity:
DownloadService service:
As discussed in the Services tutorial, some tasks are easier to implement with services than with activities.
In this example we will download an image file with a service and use it for the activity background.
This service can be used to download larger files as well.
The advantage of a service over activity in this case is that the service isn't paused when the application is in the background.
The steps required for downloading a file with this service is to first set the URL and the target file (the downloaded file is written to this file) and then call StartService.
The process global variables are used for passing those values to the service.
Process global variables can be accessed from all modules and are always available (even when the component is paused).
The service then downloads the file. When download completes the service uses CallSub to notify the Activity that the download has completed.
It is possible that the activity is not active when download is complete. In this case CallSub will not do anything. Press on Home button after starting the download to pause the activity.
We are handling this case in the activity resume event. When the activity resumes we check if we were in the middle of a download task. If yes, then we check the service JobStatus global variable which tells us whether the task has finished.
In most cases it is better to let the activity pull data from the service than pushing the data to the activity from the service. This way when the activity is ready it can grab the data and work with it.
If we were to download a large file in the background it is possible that the OS will at some point kill our process to free some memory. This will of course break our download.
To avoid this issue the service calls Service.StartForeground while downloading. This call marks our process as a foreground process. Which means that it is important not to kill it. A status bar notification is also displayed when the service is in this state.
You should be careful not to overuse this method and only call it if it is really problematic for your service to be killed.
When download completes we also check if the activity is currently active. If not we show a status bar notification that notifies the user that download has completed. When the user presses on the notification (by first dragging the status bar downwards) our activity is resumed.
The program is attached.
Main activity:
B4X:
'Activity module
Sub Process_Globals
Dim image As Bitmap
End Sub
Sub Globals
Dim btnDownload As Button
End Sub
Sub Activity_Create(FirstTime As Boolean)
Activity.LoadLayout("1")
'check if we already loaded the image previously.
If image.IsInitialized Then
Activity.SetBackgroundImage(image)
End If
End Sub
Sub Activity_Resume
'check if download has finished while the activity was paused
If btnDownload.Enabled = False AND DownloadService.JobStatus = DownloadService.STATUS_DONE Then
FinishDownload
End If
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub
Sub btnDownload_Click
Activity.Color = Colors.Black
DownloadService.URL = "http://www.b4x.com/basic4android/images/designer1.png"
DownloadService.Target = File.OpenOutput(File.DirInternalCache, "image.png", False)
StartService(DownloadService)
btnDownload.Enabled = False
End Sub
Sub FinishDownload
'Load the saved image
If DownloadService.DoneSuccessfully = True Then
image = LoadBitmapSample(File.DirInternalCache, "image.png", _
100%x, 100%y)
Activity.SetBackgroundImage(image)
End If
btnDownload.Enabled = True
DownloadService.JobStatus = DownloadService.STATUS_NONE
End Sub
B4X:
'Service module
Sub Process_Globals
Dim HC As HttpClient
'Activity is expected to set URL
Dim URL As String
Dim Target As OutputStream
Dim JobStatus As Int
Dim STATUS_NONE, STATUS_WORKING, STATUS_DONE As Int
STATUS_NONE = 0
STATUS_WORKING = 1
STATUS_DONE = 2
Dim DoneSuccessfully As Boolean
Dim Notification1 As Notification
End Sub
Sub Service_Create
HC.Initialize("HC")
Notification1.Initialize
Notification1.Icon = "icon" 'use the application icon file for the notification
Notification1.Vibrate = False
End Sub
Sub Service_Start
'URL and Target should be set by the calling module
Dim request As HttpRequest
request.InitializeGet(URL)
HC.Execute(request, 1)
JobStatus = STATUS_WORKING
Notification1.SetInfo("Download Service example", "Downloading: " & URL, Main)
Notification1.Sound = False
'Make sure that the process is not killed during the download
'This is important if the download is expected to be long.
'This will also show the status bar notification
Service.StartForeground(1, Notification1)
End Sub
Sub HC_ResponseError (Reason As String, StatusCode As Int, TaskId As Int)
ToastMessageShow("Error downloading file: " & Reason, True)
DoneSuccessfully = False
Finish
End Sub
Sub HC_ResponseSuccess (Response As HttpResponse, TaskId As Int)
'Asynchronously download the stream
Response.GetAsynchronously("Response", Target, True, TaskId)
End Sub
Sub Response_StreamFinish (Success As Boolean, TaskId As Int)
If Success = False Then
ToastMessageShow("Error downloading file: " & LastException.Message, True)
Else
ToastMessageShow("Download successfully.", True)
End If
DoneSuccessfully = Success
Finish
End Sub
Sub Finish
Log("Service finished downloading")
JobStatus = STATUS_DONE
'Notify the activity that the download has finished.
'It will do nothing if the activity is currently paused.
CallSub(Main, "FinishDownload")
Service.StopForeground(1) 'Return the service to the "background" (also removes the ongoing notification)
If IsPaused(Main) Then
'The activity is paused. The user is probably busy with some other activity.
'Notify the user that the download has finished
Notification1.Sound = True
Notification1.SetInfo("Download Service", "Download complete", Main)
Notification1.AutoCancel = True
Notification1.Notify(1)
End If
End Sub
Sub Service_Destroy
End Sub