Ich versuche eine einfache Anwendung zu schreiben, die aktualisiert wird. Dazu benötige ich eine einfache Funktion, die eine Datei herunterladen und den aktuellen Fortschritt in a anzeigen kannProgressDialog
. Ich weiß, wie das ProgressDialog
geht, bin mir aber nicht sicher, wie ich den aktuellen Fortschritt anzeigen und wie ich die Datei überhaupt herunterladen soll.
java
android
download
android-asynctask
Tom Leese
quelle
quelle
Antworten:
Es gibt viele Möglichkeiten, Dateien herunterzuladen. Im Folgenden werde ich die häufigsten Wege veröffentlichen. Es liegt an Ihnen, zu entscheiden, welche Methode für Ihre App besser ist.
1. Verwenden Sie
AsyncTask
den Download-Fortschritt und zeigen Sie ihn in einem Dialogfeld anMit dieser Methode können Sie einige Hintergrundprozesse ausführen und gleichzeitig die Benutzeroberfläche aktualisieren (in diesem Fall aktualisieren wir einen Fortschrittsbalken).
Importe:
Dies ist ein Beispielcode:
Das
AsyncTask
wird so aussehen:Die Methode oben (
doInBackground
) wird immer in einem Hintergrundthread ausgeführt. Sie sollten dort keine UI-Aufgaben ausführen. Auf der anderen Seite wird dasonProgressUpdate
undonPreExecute
auf dem UI-Thread ausgeführt, sodass Sie dort den Fortschrittsbalken ändern können:Damit dies ausgeführt werden kann, benötigen Sie die Berechtigung WAKE_LOCK.
2. Vom Service herunterladen
Die große Frage hier ist: Wie aktualisiere ich meine Aktivität von einem Dienst aus? . Im nächsten Beispiel werden wir zwei Klassen verwenden, die Ihnen möglicherweise nicht bekannt sind:
ResultReceiver
undIntentService
.ResultReceiver
ist derjenige, der es uns ermöglicht, unseren Thread von einem Dienst aus zu aktualisieren;IntentService
ist eine Unterklasse,Service
die einen Thread erzeugt, um von dort aus Hintergrundarbeiten auszuführen (Sie sollten wissen, dass einService
Thread tatsächlich im selben Thread Ihrer App ausgeführt wird; wenn Sie ihn erweiternService
, müssen Sie manuell neue Threads erzeugen, um CPU-Blockierungsvorgänge auszuführen).Der Download-Service kann folgendermaßen aussehen:
Fügen Sie den Service Ihrem Manifest hinzu:
Und die Aktivität wird so aussehen:
Hier ist wo
ResultReceiver
kommt zu spielen:2.1 Verwenden Sie die Groundy-Bibliothek
Groundy ist eine Bibliothek, mit der Sie im Wesentlichen Codeteile in einem Hintergrunddienst ausführen können. Sie basiert auf dem
ResultReceiver
oben gezeigten Konzept. Diese Bibliothek istderzeit veraltet . Sowürdeder gesamte Code aussehen:Die Aktivität, in der Sie den Dialog anzeigen ...
Eine
GroundyTask
Implementierung, mit der Groundy die Datei herunterlädt und den Fortschritt anzeigt :Und fügen Sie dies einfach dem Manifest hinzu:
Einfacher geht es nicht, denke ich. Nehmen Sie einfach das neueste Glas von Github und schon kann es losgehen. Beachten Sie, dass der Hauptzweck von Groundy darin besteht, externe REST-APIs in einem Hintergrunddienst aufzurufen und die Ergebnisse problemlos an die Benutzeroberfläche zu senden. Wenn Sie so etwas in Ihrer App tun, kann dies sehr nützlich sein.
2.2 Verwenden Sie https://github.com/koush/ion
3. Verwenden Sie
DownloadManager
class (GingerBread
und nur neuere)GingerBread brachte eine neue Funktion mit,
DownloadManager
mit der Sie Dateien einfach herunterladen und die harte Arbeit des Umgangs mit Threads, Streams usw. an das System delegieren können.Schauen wir uns zunächst eine Dienstprogrammmethode an:
Der Name der Methode erklärt alles. Sobald Sie sicher sind, dass
DownloadManager
es verfügbar ist, können Sie Folgendes tun:Der Download-Fortschritt wird in der Benachrichtigungsleiste angezeigt.
Abschließende Gedanken
Erste und zweite Methode sind nur die Spitze des Eisbergs. Es gibt viele Dinge, die Sie beachten müssen, wenn Ihre App robust sein soll. Hier ist eine kurze Liste:
INTERNET
undWRITE_EXTERNAL_STORAGE
) verfügen . auchACCESS_NETWORK_STATE
wenn Sie die Internetverfügbarkeit überprüfen möchten.Wenn Sie keine detaillierte Kontrolle über den Download-Prozess benötigen, sollten Sie
DownloadManager
(3) verwenden, da die meisten der oben aufgeführten Elemente bereits verarbeitet werden.Bedenken Sie aber auch, dass sich Ihre Bedürfnisse ändern können. Zum Beispiel
DownloadManager
wird keine Antwort zwischengespeichert . Es wird dieselbe große Datei mehrmals blind heruntergeladen. Es gibt keine einfache Möglichkeit, das Problem nachträglich zu beheben. Wenn Sie mit einem BasicHttpURLConnection
(1, 2) beginnen, müssen Sie lediglich ein hinzufügenHttpResponseCache
. Die anfängliche Anstrengung, die grundlegenden Standardwerkzeuge zu erlernen, kann daher eine gute Investition sein.quelle
close()
die Ströme (input
undoutput
) infinally
statttry
, andernfalls , wenn eine Ausnahme vor geworfen wirdclose()
, haben Sie nicht geschlossene Ströme rumhängen.sdcard/
Verwenden SieEnvironment.getExternalStorageDirectory()
stattdessen keinen Hardcode .Vergessen Sie nicht, Ihrer Manifestdatei Berechtigungen hinzuzufügen, wenn Sie Inhalte aus dem Internet herunterladen möchten!
quelle
Ja, der obige Code funktioniert. Wenn Sie jedoch Ihr
progressbar
InonProgressUpdate
of aktualisierenAsynctask
und die Zurück-Taste drücken oder Ihre Aktivität beenden,AsyncTask
verliert dies den Überblick über Ihre Benutzeroberfläche. Und wenn Sie zu Ihrer Aktivität zurückkehren, wird dies angezeigt, auch wenn der Download im Hintergrund ausgeführt wird Kein Update in der Fortschrittsanzeige. Also aufOnResume()
Versuch einen Thread wie läuftrunOnUIThread
mit einer Timer - Aufgabe , dass Updates urprogressbar
mit Werten aus der Aktualisierung imAsyncTask
Hintergrund laufenden.Vergiss nicht, den Thread zu zerstören, wenn deine Aktivität nicht sichtbar ist.
quelle
Ich würde Ihnen empfehlen, mein Project Netroid zu verwenden . Es basiert auf Volley . Ich habe einige Funktionen hinzugefügt, wie z. B. Rückruf für mehrere Ereignisse und Verwaltung des Dateidownloads. Dies könnte hilfreich sein.
quelle
SSLSocketFactory
, ein eigenes Hinzufügen von A festzulegen,HostnameVerifier
und ich einen solchen Verifizierer benötige. Hat diesbezüglich ein Problem aufgeworfen.Ich habe die
AsyncTask
Klasse geändert , um die ErstellungprogressDialog
im selben Kontext zu handhaben. Ich denke, der folgende Code ist wiederverwendbarer. (Es kann von jeder Aktivität aus aufgerufen werden, indem nur der Kontext, die Zieldatei oder die Dialognachricht übergeben werden.)quelle
Vergessen Sie nicht, "/ sdcard ..." durch eine neue Datei ("/ mnt / sdcard / ...") zu ersetzen, da Sie sonst eine FileNotFoundException erhalten
quelle
Environment.getExternalStorageDirectory().getAbsolutePath()
einen Pfad zur SD-Karte. Vergessen Sie auch nicht zu überprüfen, ob der externe Speicher gemountet ist -Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
( Mannaz )Ich fand diesen Blog-Beitrag sehr hilfreich. Es verwendet loopJ zum Herunterladen von Dateien. Es hat nur eine einfache Funktion und wird einigen neuen Android-Leuten helfen.
quelle
Während ich anfing, Android-Entwicklung zu lernen, hatte ich gelernt, dass dies
ProgressDialog
der richtige Weg ist. Es gibt einesetProgress
Methode, mit derProgressDialog
die Fortschrittsstufe beim Herunterladen der Datei aktualisiert werden kann.Das Beste, was ich in vielen Apps gesehen habe, ist, dass sie die Attribute dieses Fortschrittsdialogs anpassen, um dem Fortschrittsdialog ein besseres Erscheinungsbild zu verleihen als der Standardversion. Gut, um den Benutzer mit Animationen wie Frosch, Elefant oder niedlichen Katzen / Welpen zu beschäftigen. Jede Animation im Fortschrittsdialog zieht Benutzer an und sie haben nicht das Gefühl, lange warten zu müssen.
quelle
Mein persönlicher Rat ist, den Fortschrittsdialog zu verwenden und vor der Ausführung aufzubauen oder den
OnPreExecute()
Fortschritt häufig zu veröffentlichen, wenn Sie den horizontalen Fortschrittsbalken des Fortschrittsdialogs verwenden. Der verbleibende Teil ist die Optimierung des Algorithmus vondoInBackground
.quelle
Verwenden Sie die Android Query-Bibliothek, die in der Tat sehr cool ist. Sie können sie so ändern,
ProgressDialog
wie Sie es in anderen Beispielen sehen. Diese zeigt die Fortschrittsansicht Ihres Layouts an und blendet sie nach Abschluss aus.quelle
Ich füge eine weitere Antwort für eine andere Lösung hinzu, die ich jetzt verwende, weil Android Query so groß und nicht gewartet ist, um gesund zu bleiben. Also bin ich zu diesem https://github.com/amitshekhariitbhu/Fast-Android-Networking gewechselt .
quelle
Berechtigungen
Verwenden von HttpURLConnection
quelle
Sie können den Fortschritt des Download-Managers mithilfe von LiveData und Coroutinen beobachten ( siehe unten)
https://gist.github.com/FhdAlotaibi/678eb1f4fa94475daf74ac491874fc0e
quelle
Wichtig
AsyncTask ist in Android 11 veraltet.
Weitere Informationen finden Sie in den folgenden Beiträgen
Sollte wahrscheinlich zu Concorency Framework wechseln, wie von Google vorgeschlagen
quelle
Wir können die Coroutine und den Arbeitsmanager zum Herunterladen von Dateien in Kotlin verwenden.
Fügen Sie eine Abhängigkeit in build.gradle hinzu
WorkManager-Klasse
Starten Sie den Download über den Arbeitsmanager in der Aktivitätsklasse
quelle