Android Tutorial Dateien herunterladen mit einem Servicemodul

klaus

Expert
Licensed User
Longtime User
Downloading files using Service module
Dateien herunterladen mit einem Servicemodul

Wie schon in Services tutorial (englisch) und Services Tutorial (deutsch) erläutert, sind einige Aufgaben einfacher mit Dienstleistungen (Service) zu implementieren als mit Activities.
In diesem Beispiel werden wir eine Bilddatei mit einem Service herunterladen und es im Activity Hintergrund verwenden.
Dieser Service kann auch verwendet werden, um größere Dateien herunterzuladen.

Der Vorteil eines Service gegenüber einer Activity ist, in diesem Fall, daß der Service nicht angehalten wird, wenn die Anwendung im Hintergrund ist.

Die Schritte für das Herunterladen einer Datei mit diesem Service sind zunächst den URL und die Ziel-Datei zu setzten (die heruntergeladene Datei wird in diese Datei geschrieben) und dann StartService aufrufen.

Prozess globale Variablen werden benutzt um diese Werte dem Service zu übergeben.
Auf Process globale Variablen kann aus allen Modulen zugegriffen werden und sie sind immer verfügbar (auch wenn die Komponente angehalten ist (paused).

Der Service lädt dann die Datei. Wenn der Download abgeschlossen ist, ruft der Service CallSub auf um die Activity zu benachrichtigen, da
ß der Download abgeschlossen ist.
Es ist möglich, daß die Activity nicht aktiv ist, wenn der Download abgeschlossen ist. In diesem Fall wird CallSub nichts tun. Drücken Sie auf die "Home" Taste nach dem Start von Download um die Activity zu desaktivieren.

Wir behandeln diesen Fall in dem Activity_Resume Event. In Activity_Resume überprüfen wir ob wir in der Mitte des Downloads waren. Wenn ja, dann prüfen wir die Service JobStatus globale Variable, die uns sagt, ob die Aufgabe beendet ist.


In den meisten Fällen ist es besser, die Activity die Daten aus dem Service holen zu lassen als da
ß der Service die Daten an die Activity überträgt. Auf diese Weise, wenn die Activity wieder aktiv ist, kann sie sich die Daten holen und bearbeiten.

Wenn wir eine große Datei im Hintergrund herunterladen ist es möglich, daß das Betriebssystem irgendwann unseren Prozess zerstören will um etwas Speicherplatz freizugeben. Dies wird natürlich unseren Download unterbrechen.

Zur Vermeidung dieses Problems ruft der Service, während des Herunterladens, Service.StartForeground auf. Dieser Aufruf markiert unser Verfahren als Vordergrundprozess. Was bedeutet, daß es wichtig ist, ihn nicht zu zerstören. In der Statusleiste wird eine Meldung angezeigt wenn die Activity in diesem Zustand ist.
Sie sollten darauf achten, nicht zu häufig diese Methode zu benutzen, sondern nur wenn es wirklich problematisch ist daß der Service zerstört würde.


Wenn der Download abgeschlossen ist überprüfen wir noch, ob die Activity gerade aktiv ist oder nicht. Wenn nicht, dann zeigen wir eine Statusleiste Benachrichtigung an, die dem Benutzer meldet daß der Download abgeschlossen ist. Wenn der Benutzer auf die Meldung klickt (durch Ziehen der Statusleiste nach unten) wird unsere Activity wieder aufgenommen.

Das Programm befindet sich im Englischen Originaltext.

Hauptactivity:
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
Der Code zum DownloadService Service:
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
Sourcecode Datei :

zip.gif
DownloadService.zip
 
Top