Android DownloadManager Tutorial und Beispiele

In dieser Sitzung erforschen wir die Klasse android.app.DownloadManager, wie man sie benutzt und warum sie wichtig ist. Wir werden uns mit Themen wie den Arten von Downloads beschäftigen, die man mit der Klasse DownloadManager machen kann, wie man die eigentlichen Anfragen stellt, wie man den Fortschritt in der Statusleiste über eine Benachrichtigung anzeigt, heruntergeladene Dateien öffnet und sogar entfernt.

Was ist DownloadManager?

Der DownloadManager ist ein Systemdienst, den wir verwenden können, um lang laufende Downloads zu verwalten.

Warum herunterladen?

Unterschätzen Sie nicht die Notwendigkeit von Downloads und wie komplex diese werden können. Der Zustand der Bandbreiten in der heutigen Zeit bedeutet, dass wir, zumindest in vielen Teilen der Welt, immer noch nicht in der Lage sind, Dateien, die wir benötigen, jederzeit auf Abruf zu erhalten. Die Nutzer lassen ihr Internet nicht die ganze Zeit eingeschaltet, da es Geld kostet und den Akku des Geräts belastet.

Festplatte mit Diskpart einrichten

Festplatte mit Diskpart einrichten
Festplatte mit Diskpart einrichten

Daher ist es wichtig, Dateien herunterladen und lokal speichern zu können. Dies ist jedoch keine einfache Aufgabe, die richtig umgesetzt werden muss. Vor allem, wenn man es richtig und effizient macht. Dennoch ist dies eine der Aufgaben, die durchaus auf mehrere Apps verteilt werden können. In den meisten Fällen ist es nicht nötig, das Rad neu zu erfinden, wenn es um http-Downloads geht. Es ist sinnvoll, eine einfach zu verwendende Klasse zu haben, die dies effizient erledigen kann und unsere Anwendung informiert, wenn die Aufgabe abgeschlossen ist.

Die Möglichkeit, Daten herunterzuladen, ist ein mächtiger Weg, unsere Anwendungen zu bereichern, da wir Dateien aus dem Internet beziehen können, die unsere Anwendung dann nutzen kann. Wenn der Benutzer die Datei zufällig entfernt, können wir sie erneut herunterladen.

Allgemeine Fragen

Hier sind einige Fragen, die uns helfen, die Klasse "DownloadManager" zu verstehen.

Welche Arten von Downloads werden von DownloadManager verwaltet?

Normalerweise gibt es mehrere Protokolle für die Kommunikation zwischen Geräten. Und natürlich ist das Herunterladen einer Datei nur eine Form der Kommunikation zwischen mindestens zwei Geräten. Ein Gerät liefert eine Datei, ein anderes empfängt sie. Beachten Sie, dass der DownloadManager nur für HTTP-Downloads verwendet wird.

Der DownloadManager ist besonders nützlich, wenn Ihre Downloads lange dauern.

Wo finden die Downloads statt?

Wo in Bezug auf threads. Nun, die Downloads finden definitiv im Hintergrund-Thread statt.

Warum den DownloadManager verwenden?

Nun, was sind seine Vorteile? Nun, wir haben mehrere. Zum Beispiel

  1. Wie wir schon sagten, finden die Downloads im Hintergrund-Thread statt. In der Tat im Hintergrund in einer System-App. Das bedeutet, dass unsere App die Downloads nicht manuell in unserem Haupt-Thread verarbeiten muss, so dass unsere Benutzeroberfläche immer ansprechbar ist. Diese Tatsache ist sehr wichtig. Das Herunterladen von Daten ist eine der zeit- und ressourcenintensivsten Aufgaben, die persönliche Gadgets erledigen. Dennoch ist dies eine der Aufgaben, die Geräte so leistungsfähig machen, wie sie sind. Wir müssen sie also erledigen. Aber wir müssen sie in einem Hintergrund-Thread erledigen und DownloadManager befolgt das definitiv.
  2. Zweitens sind die HTTP-Interaktionen von uns abstrahiert. Wir müssen uns nicht um die verschiedenen HTTP-Codes und Nachrichten und mögliche Fehlschläge kümmern. Tatsächlich werden sogar Wiederholungsversuche in unserem Namen unternommen. Diese Wiederholungsversuche können jedoch erstaunlicherweise durch Änderungen des Verbindungsstatus und Systemneustarts aufrechterhalten werden. Der Fortschritt kann uns während des Herunterladens angezeigt werden, was ihn sehr benutzerfreundlich macht.

DownloadManager Quick HowTos und Schnipsel

1. Wie man Videos mit der DownloadManager-Klasse herunterlädt

Wir möchten Videos mit der DownloadManager-Klasse in Android herunterladen. Wir wollen ihnen entsprechende Namen geben und sie in einem externen Speicher speichern.

    public void downloadvideo(String videoURL)
    {
        if(videoURL.contains(".mp4"))
        {
            File directory = new File(Environment.getExternalStorageDirectory()+File.separator+"My Videos");
            directory.mkdirs();
            DownloadManager.Request request = new DownloadManager.Request(Uri.parse(videoURL));
            int Number=pref.getFileName();
            request.allowScanningByMediaScanner();
            request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
            File root = new File(Environment.getExternalStorageDirectory() + File.separator+"Facebook Videos");
            Uri path = Uri.withAppendedPath(Uri.fromFile(root), "Video-"+Number+".mp4");
            request.setDestinationUri(path);
            DownloadManager dm = (DownloadManager)getActivity().getSystemService(getActivity().DOWNLOAD_SERVICE);
            if(downloadlist.contains(videoURL))
            {
                Toast.makeText(getActivity().getApplicationContext(),"The Video is Already Downloading",Toast.LENGTH_LONG).show();
            }
            else
            {
                downloadlist.add(videoURL);
                dm.enqueue(request);
                Toast.makeText(getActivity().getApplicationContext(),"Downloading Video-"+Number+".mp4",Toast.LENGTH_LONG).show();
                Number++;
                pref.setFileName(Number);
            }

        }
    }

Zunächst wird uns die Video-Url als Parameter übergeben. Sagen wir, wir wollen nur mp4-Dateien herunterladen, also stellen wir eine einfache boolesche Prüfung bereit, um zu prüfen, ob sie mp4 enthält. Vielleicht können Sie endsWith() anstelle von contains() verwenden, wenn Sie möchten.

DownloadManager Beispiele

Schauen wir uns einige DownloadManager Beispiele an.

Beispiel 1. Datei herunterladen, Alle Downloads anzeigen, Download löschen

In diesem vollständigen Beispiel wollen wir sehen, wie man eine Datei aus dem Internet mit Hilfe der downloadManager-Klasse herunterlädt. Dann können wir den Download öffnen, indem wir auf die Benachrichtigung in der Systemleiste klicken oder von intern in unserer App. Außerdem können wir die Datei löschen, alle Downloads anzeigen usw.

Video-Anleitung

Hier haben wir ein Video-Tutorial für dieses Beispiel.

Demo

Hier ist die Demo der App.

Überblick über die App

  1. Der Benutzer klickt auf die Schaltfläche Download.
  2. Das Herunterladen beginnt.
  3. Währenddessen wird der Fortschritt in der Statusleiste als Benachrichtigung angezeigt. Die Benachrichtigung enthält auch den Titel und die Beschreibung des Downloads.
  4. Der Benutzer wird über den Text in der Systemstatusleiste benachrichtigt, wenn der Download abgeschlossen ist.
  5. Wenn der Benutzer auf die Benachrichtigung klickt, wird die Datei geöffnet. Wird sie nicht gefunden, wird eine Toast-Meldung angezeigt.
  6. Wenn der Benutzer auf die Schaltfläche "Alle anzeigen" klickt, wird die Ansicht für die Anzeige aller Downloads angezeigt. Möglicherweise haben Sie dort noch einige andere Downloads in der Warteschlange, die nicht von Ihrer Anwendung stammen.
  7. Wenn der Benutzer auf die Schaltfläche "Löschen" klickt, wird unser Download, ob teilweise oder vollständig, gelöscht.
(a). MainActivity.java

MainActivity" ist, wie Sie sich vorstellen können, unsere Startaktivität. Sie wird von der "AppCompatActivity" abgeleitet. Hier schreiben wir unseren gesamten Code. Aber zuerst beginnen wir mit mehreren Importen. Diese beinhalten:

  1. DownloadManager" – Die Klasse, die dafür verantwortlich ist, dass wir den Download-Manager des Systems benutzen können.
  2. Intent – Klasse, die dafür verantwortlich ist, dass wir die Ansicht des System-Download-Managers öffnen können.
  3. Uri – Erlaubt es uns, eine String-Url in eine Uri zu parsen, von der unsere Datei heruntergeladen werden kann.
  4. Environment – Erlaubt die Angabe des öffentlichen Verzeichnisses, in dem die heruntergeladene Datei gespeichert wird.
  5. Toast – Ermöglicht die Anzeige von Kurznachrichten.

HowTo’s

Schauen wir uns mehrere HowTos an.

(a). Wie man den DownloadManager initialisiert

Als Systemdienst wird der DownloadManager nicht direkt instanziiert. Stattdessen werden wir ihn mit der Methode getSystemService() initialisieren und das resultierende Objekt in die Klasse DownloadManager casten.

    private void initializeDownloadManager() {
        downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
    }

(b). Wie man eine Download-Anfrage erstellt

Innerhalb der DownloadManager-Klasse gibt es eine innere Klasse, die Request-Klasse. Wir können diese Klasse verwenden, um unsere HTTP-Anfrage zu definieren. Wir tun dies bequem über das Builder-Pattern.

        DownloadManager.Request request=new DownloadManager.Request(Uri.parse("https://raw.githubusercontent.com/Oclemy/SampleJSON/master/spacecrafts/voyager.jpg"));
        request.setTitle("Voyager")
                .setDescription("File is downloading...")
                .setDestinationInExternalFilesDir(this,
                        Environment.DIRECTORY_DOWNLOADS,fileName)
                .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);

Sie können deutlich sehen, dass wir die Uri in unseren Request-Konstruktor eingefügt haben. Dann setzen wir den Titel, die Beschreibung, das Ziel und die Sichtbarkeit der Benachrichtigung.

(c). Wie man einen Download in die Warteschlange stellt

Einen Download in die Warteschlange zu stellen bedeutet, ihn in die Download-Warteschlange des Download-Managers aufzunehmen. Dann wird die Warteschlange automatisch vom System abgearbeitet. Sie stellen einen Download mit der Methode enqueue() in die Warteschlange.

        downLoadId=downloadManager.enqueue(request);

Dies gibt uns eine Download-ID zurück.

(d). Wie kann man eine heruntergeladene Datei entfernen/löschen

Nun, man kann eine heruntergeladene Datei aus dem Download-Manager entfernen, indem man die Methode remove() der Klasse DownloadManager verwendet. Sie übergeben die Download-ID.

    private void deleteDownloadedFile(){
        downloadManager.remove(downLoadId);
    }

Hier ist der vollständige Quellcode.

package info.camposha.mrdownloadmanager;

import android.app.DownloadManager;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

import java.io.FileNotFoundException;

public class MainActivity extends AppCompatActivity {

    private DownloadManager downloadManager;
    private String fileName=null;
    private long downLoadId;

    /**
     * Initialize download manager
     */
    private void initializeDownloadManager() {
        downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        fileName="Voyager";
    }

    /**
     * Set the title and desc of this download, to be displayed in notifications.
     */
    private void downloadFile(){
        DownloadManager.Request request=new DownloadManager.Request(Uri.parse("https://raw.githubusercontent.com/Oclemy/SampleJSON/master/spacecrafts/voyager.jpg"));
        request.setTitle("Voyager")
                .setDescription("File is downloading...")
                .setDestinationInExternalFilesDir(this,
                        Environment.DIRECTORY_DOWNLOADS,fileName)
                .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        //Enqueue the download.The download will start automatically once the download manager is ready
        // to execute it and connectivity is available.
        downLoadId=downloadManager.enqueue(request);
    }

    /**
     * Cancel downloads and remove them from the download manager.
     * If there is a downloaded file, partial or complete, it is deleted.
     */
    private void deleteDownloadedFile(){
        downloadManager.remove(downLoadId);
    }
    private void openOurDownload(){
       //we can open download here
    }

    /**
     * View all downloads in the downloadmanager
     */
    private void viewAllDownloads(){
        Intent intent=new Intent();
        intent.setAction(DownloadManager.ACTION_VIEW_DOWNLOADS);
        startActivity(intent);
    }

    /**
     * Handle button clicks
     * @param view
     */
    public void clickView(View view){
        switch (view.getId()){
            case R.id.downloadBtn:
                downloadFile();
                break;
            case R.id.openDownloadBtn:
                openOurDownload();
                break;
            case R.id.viewDownloadsBtn:
                viewAllDownloads();
                break;
            case R.id.deleteBtn:
                deleteDownloadedFile();
                break;
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initializeDownloadManager();
    }
}
(b). activity_main.xml

Wir brauchen ein Layout für unsere MainActivity. Hier ist der Code.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout

android_layout_width="match_parent"
android_layout_height="match_parent"
    android_orientation="vertical"
android_background="#009688"
tools_context=".MainActivity">

<TextView
    android_id="@+id/headerTxt"
    android_layout_width="match_parent"
    android_layout_height="wrap_content"
    android_text="DownloadManager Example"
    android_textAlignment="center"
    android_fontFamily="casual"
    android_textStyle="bold"
    android_textAppearance="@style/TextAppearance.AppCompat.Large"
    android_textColor="@color/white" />

<ImageView
    android_layout_width="match_parent"
    android_layout_height="300dp"
    android_layout_centerHorizontal="true"
    android_src="@drawable/logo"
    android_contentDescription="@string/app_name"/>

<LinearLayout
    android_id="@+id/button_zone"
    android_layout_width="match_parent"
    android_layout_height="wrap_content"
    android_orientation="horizontal"
    android_layout_centerInParent="true">

    <Button
        android_id="@+id/downloadBtn"
        style="?android:attr/button"
        android_layout_width="0dp"
        android_layout_height="wrap_content"
        android_layout_weight="1"
        android_onClick="clickView"
        android_text="Download" />
    <Button
        android_id="@+id/viewDownloadsBtn"
        style="?android:attr/button"
        android_layout_width="0dp"
        android_layout_height="wrap_content"
        android_layout_weight="1"
        android_onClick="clickView"
        android_text="View All" />
</LinearLayout>

    <LinearLayout
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_orientation="horizontal"
        android_layout_centerInParent="true">
    <Button
        android_id="@+id/openDownloadBtn"
        style="?android:attr/button"
        android_layout_width="0dp"
        android_layout_height="wrap_content"
        android_layout_weight="1"
        android_onClick="clickView"
        android_text="Open" />

        <Button
            android_id="@+id/deleteBtn"
            style="?android:attr/button"
            android_layout_width="0dp"
            android_layout_height="wrap_content"
            android_layout_weight="1"
            android_onClick="clickView"
            android_text="Delete" />

</LinearLayout>

</LinearLayout>
(c). AndroidManifest.xml

In unserem AndroidManifest müssen wir Berechtigungen für die Internetverbindung sowie für das Schreiben auf externen Speicher hinzufügen. Das liegt daran, dass wir unser Bild aus dem Internet herunterladen und auf unseren externen Speicher schreiben.

Hier ist meine vollständige Datei AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest
    package="info.camposha.mrdownloadmanager">

    <uses-permission android_name="android.permission.INTERNET"/>
    <uses-permission android_name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android_allowBackup="true"
        android_icon="@mipmap/ic_launcher"
        android_label="@string/app_name"
        android_roundIcon="@mipmap/ic_launcher_round"
        android_supportsRtl="true"
        android_theme="@style/AppTheme">
        <activity android_name=".MainActivity">
            <intent-filter>
                <action android_name="android.intent.action.MAIN" />

                <category android_name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
Download

Hier sind Referenzressourcen:

No. Ort Link
1. GitHub Direkter Download
2. GitHub Durchsuchen
3. YouTube Videoanleitung
4. YouTube ProgrammingWizards TV Channel

Beispiel 2: Kotlin Android einfacher DownloadManager Beispiel

Ein einfaches Open Source Kotlin Downloadmanager Beispiel, das für absolute Anfänger geeignet ist.

Schritt 1: Projekt erstellen

Beginnen Sie mit der Erstellung eines leeren AndroidStudio-Projekts.

Schritt 2: Abhängigkeiten

Für dieses Projekt wird keine spezielle Bibliothek eines Drittanbieters benötigt.

Schritt 3: Layout entwerfen

Entwerfen Sie das Layout der MainActivity, indem Sie eine Textansicht in einem ConstraintLayout wie unten gezeigt hinzufügen:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Schritt 4: Code schreiben

Beginnen Sie mit dem Hinzufügen von Importen:

import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.opengl.Visibility
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log

Erstellen Sie MainActivity durch Erweiterung von AppCompatActivity:

class MainActivity : AppCompatActivity() {

Definieren Sie eine Download-ID:

    var downloadid: Long = 0

Override onCreate() callback:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

Erstellen Sie einen annonymen BroadcastReceiver und überschreiben Sie darin onReceive() wie folgt:

        val new = object: BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent?) {
                val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
                if (id == downloadid) Log.d("DOWNLOAD", "DONE")
            }
        }

Erstelle eine Download Uri:

        val uri = Uri.parse("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf")

Initialisiere einen DownloadRequest:

        val request = DownloadManager.Request(uri).setDescription("DummyFile").setTitle("Dummy").setAllowedOverMetered(true).setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)

Stellen Sie den Download in die Warteschlange:

        val location = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
        downloadid = location.enqueue(request)

Registrieren Sie den BroadcastReceiver:

        registerReceiver(new, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))

Hier ist der vollständige Code:

MainActivity.kt

import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.opengl.Visibility
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log

class MainActivity : AppCompatActivity() {

    var downloadid: Long = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val new = object: BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent?) {
                val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
                if (id == downloadid) Log.d("DOWNLOAD", "DONE")
            }
        }

        val uri = Uri.parse("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf")

        val request = DownloadManager.Request(uri).setDescription("DummyFile").setTitle("Dummy").setAllowedOverMetered(true).setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)

        val location = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
        downloadid = location.enqueue(request)

        registerReceiver(new, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
    }
}

Schritt 5: Berechtigungen hinzufügen

Fügen Sie in Ihrem AndroidManifest die folgenden Berechtigungen hinzu:

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>

Run

Kopieren Sie den Code oder laden Sie ihn über den unten stehenden Link herunter, bauen Sie ihn und führen Sie ihn aus.

Referenz

Hier sind die Referenzlinks:

Herunterladen Beispiel
Folgen code author

Beispiel 3: Kotlin Android – Dynamischer Download

In diesem Beispiel lernen Sie, wie man von einem beliebigen Link herunterladen kann. Der Link wird zur Laufzeit über einen EditText bereitgestellt.

Schritt 1: Projekt erstellen

Beginnen Sie mit der Erstellung eines leeren AndroidStudio-Projekts.

Schritt 2: Abhängigkeiten

Für dieses Projekt werden keine Abhängigkeiten von Drittanbietern benötigt.

Schritt 3: Layout entwerfen

Fügen Sie einen EditText und einen Button in das Layout Ihrer Hauptaktivität ein:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/tilLink"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"

        android:hint="Введите ссылку"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/etLink"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </com.google.android.material.textfield.TextInputLayout>

    <com.google.android.material.button.MaterialButton
        android:id="@+id/btnLoad"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="load"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tilLink" />

</androidx.constraintlayout.widget.ConstraintLayout>

Schritt 4: Code schreiben

Beginnen Sie mit dem Hinzufügen von Importen zu Ihrer MainActivity.kt wie folgt:

import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.view.Gravity
import android.widget.PopupMenu
import android.widget.Toast
import com.google.android.material.textfield.TextInputEditText

Erstellen Sie die Aktivität:

class MainActivity : AppCompatActivity() {

Definieren Sie Instanzfelder:

    private var binding: ActivityMainBinding? = null
    private var dm: DownloadManager? = null

Erstellen Sie eine annonyme BroadcastReceiver-Klasse und implementieren Sie die Methode onReceive() wie folgt:

    private val broadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val action = intent?.action
            if (DownloadManager.ACTION_DOWNLOAD_COMPLETE == action) {
                Toast.makeText(context, "Download Completed", Toast.LENGTH_SHORT).show()
            }
        }
    }

Richten Sie Ereignishandler ein:

    private fun setupListeners() {
        binding?.btnLoad?.setOnLongClickListener {
            val popup = PopupMenu(this, it)
            popup.inflate(R.menu.popup)
            popup.show()
            download()
            false
        }
    }

Hier ist die Funktion, die das Element herunterlädt:

    private fun download() {
        dm?.enqueue(
                DownloadManager.Request(Uri.parse(LINK_VIDEO))
                        .setAllowedNetworkTypes(
                                DownloadManager.Request.NETWORK_MOBILE or
                                        DownloadManager.Request.NETWORK_WIFI
                        )
                        .setTitle("Download File.mp4")
                        .setDescription("This is very important file")
                        .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
//                        .setDestinationInExternalFilesDir(
//                                applicationContext , Environment.DIRECTORY_DOWNLOADS,   "managerDownload24.mp4"
//                        )
                        .setDestinationInExternalPublicDir(
                                Environment.DIRECTORY_DOWNLOADS,
                                "managerDownload24"
                        )
        )
    }

Deregistriere den BroadcastReceiver in der Funktion onCreate():

    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(broadcastReceiver)
    }

Hier ist der vollständige Code:

MainActivity.kt

import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.view.Gravity
import android.widget.PopupMenu
import android.widget.Toast
import com.google.android.material.textfield.TextInputEditText
import ru.trinitydigital.downloadmanager.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private var binding: ActivityMainBinding? = null
    private var dm: DownloadManager? = null

    private val broadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val action = intent?.action
            if (DownloadManager.ACTION_DOWNLOAD_COMPLETE == action) {
                Toast.makeText(context, "Download Completed", Toast.LENGTH_SHORT).show()
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding?.root)
        registerReceiver(broadcastReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
        dm = getSystemService(DOWNLOAD_SERVICE) as DownloadManager

        setupListeners()
    }

    private fun setupListeners() {
        binding?.btnLoad?.setOnLongClickListener {
            val popup = PopupMenu(this, it)
            popup.inflate(R.menu.popup)
            popup.show()
            download()
            false
        }
    }

    private fun download() {
        dm?.enqueue(
                DownloadManager.Request(Uri.parse(LINK_VIDEO))
                        .setAllowedNetworkTypes(
                                DownloadManager.Request.NETWORK_MOBILE or
                                        DownloadManager.Request.NETWORK_WIFI
                        )
                        .setTitle("Download File.mp4")
                        .setDescription("This is very important file")
                        .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
//                        .setDestinationInExternalFilesDir(
//                                applicationContext , Environment.DIRECTORY_DOWNLOADS,   "managerDownload24.mp4"
//                        )
                        .setDestinationInExternalPublicDir(
                                Environment.DIRECTORY_DOWNLOADS,
                                "managerDownload24"
                        )
        )
    }

    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(broadcastReceiver)
    }

    companion object {
        private const val LINK_VIDEO = "https://images.unsplash.com/photo-1569974507005-6dc61f97fb5c?ixid=MXwxMjA3fDB8MHxzZWFyY2h8MXx8anBnfGVufDB8fDB8&ixlib=rb-1.2.1&auto=format&fit=crop&w=900&q=60"
    }
}

Android Manifest

Fügen Sie in der AndroidManifest.xml die folgenden Berechtigungen hinzu:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Run

Kopieren Sie den Code oder laden Sie ihn über den unten stehenden Link herunter, bauen Sie ihn und führen Sie ihn aus.

Referenz

Hier sind die Referenzlinks:

Nummer Link
1. Download Beispiel
2. Follow code author

Beispiel 4: Kotlin DownloadManager mit Laufzeitberechtigungen und Coroutinen

Hier ist ein weiteres in Kotlin geschriebenes DownloadManager-Beispiel. Dieses verwendet Kotlin Coroutines. Es beinhaltet auch die Überprüfung der notwendigen Berechtigungen zur Laufzeit vor dem Download.

Schritt 1: Projekt erstellen

Beginnen Sie mit der Erstellung eines leeren AndroidStudio-Projekts.

Schritt 2: Abhängigkeiten

Es werden keine Abhängigkeiten von Drittanbietern verwendet.

Schritt 3: Layout entwerfen

Entwerfen Sie ein einfaches Layout mit einer Schaltfläche und einer Textansicht:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerVertical="true"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:id="@+id/text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:padding="12dp"
            android:textColor="@color/black"
            android:textSize="25sp" />

        <Button
            android:id="@+id/download_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:padding="12dp"
            android:text="DOWNLOAD PDF"
            android:textColor="@android:color/white" />

    </LinearLayout>

</RelativeLayout>

Schritt 4: Code schreiben

Beginnen Sie mit dem Hinzufügen von Importen:

import android.Manifest
import android.annotation.TargetApi
import android.app.DownloadManager
import android.content.Context
import android.content.pm.PackageManager
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File

Erweitern Sie die AppCompatActivity.

class MainActivity : AppCompatActivity() {

Definieren Sie dann eine Download-URL als Instanzfeld:

    private var imageUrl = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"

Überschreiben Sie die onCreate():

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

Wenn die Download-Schaltfläche angeklickt wird, prüfen wir vor dem Starten des Downloads die Berechtigung:

        download_btn.setOnClickListener {
            // After API 23 (Marshmallow) and lower Android 10 you need to ask for permission first before save an image
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                askPermissions()
            } else {
                downloadImage(imageUrl)
            }
        }

Wenn die Erlaubnis erteilt wird, starten wir den Download.

Hier ist die Funktion, um den Download des Bildes zu starten:

    private fun downloadImage(url: String) {
        val downloadManager = this.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager

        val downloadUri = Uri.parse(url)

        val request = DownloadManager.Request(downloadUri).apply {
            setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
                .setAllowedOverRoaming(false)
                .setTitle(url.substring(url.lastIndexOf("/") + 1))
                .setDescription("abc")
                .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                .setDestinationInExternalPublicDir(
                    Environment.DIRECTORY_DOWNLOADS,
                    url.substring(url.lastIndexOf("/") + 1)
                )

        }
        //use when just to download the file with getting status
        //downloadManager.enqueue(request)

        val downloadId = downloadManager.enqueue(request)
        val query = DownloadManager.Query().setFilterById(downloadId)

        lifecycleScope.launchWhenStarted {
            var lastMsg: String = ""
            var downloading = true
            while (downloading) {
                val cursor: Cursor = downloadManager.query(query)
                cursor.moveToFirst()
                if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
                    downloading = false
                }
                val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
                val msg: String? = statusMessage(url, File(Environment.DIRECTORY_DOWNLOADS), status)
                Log.e("DownloadManager", " Status is :$msg")
                if (msg != lastMsg) {
                    withContext(Dispatchers.Main) {
                        // Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
                        text_view.text = msg
                        //Log.e("DownloadManager", "Status is :$msg")
                    }
                    lastMsg = msg ?: ""
                }
                cursor.close()
            }
        }
    }

Hier ist die Funktion, die den Download-Status konstruiert und als String zurückgibt, der dem Benutzer angezeigt werden kann:

    private fun statusMessage(url: String, directory: File, status: Int): String? {
        var msg = ""
        msg = when (status) {
            DownloadManager.STATUS_FAILED -> "Download has been failed, please try again"
            DownloadManager.STATUS_PAUSED -> "Paused"
            DownloadManager.STATUS_PENDING -> "Pending"
            DownloadManager.STATUS_RUNNING -> "Downloading..."
            DownloadManager.STATUS_SUCCESSFUL -> "PDF downloaded successfully in $directory" + File.separator + url.substring(
                url.lastIndexOf("/") + 1
            )
            else -> "There's nothing to download"
        }
        return msg
    }

Mit der folgenden Funktion können Sie die notwendigen Berechtigungen abfragen, bevor wir mit dem Download fortfahren:

    @TargetApi(Build.VERSION_CODES.M)
    fun askPermissions() {
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            // Permission is not granted
            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(
                    this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
                )
            ) {
                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.
                AlertDialog.Builder(this)
                    .setTitle("Permission required")
                    .setMessage("Permission required to save photos from the Web.")
                    .setPositiveButton("Allow") { dialog, id ->
                        ActivityCompat.requestPermissions(
                            this,
                            arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                            MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE
                        )
                        finish()
                    }
                    .setNegativeButton("Deny") { dialog, id -> dialog.cancel() }
                    .show()
            } else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(
                    this,
                    arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                    MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE
                )
                // MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE is an
                // app-defined int constant. The callback method gets the
                // result of the request.

            }
        } else {
            // Permission has already been granted
            downloadImage(imageUrl)
        }
    }

Anschließend wird die Berechtigungsanfrage mit dem folgenden Callback bearbeitet:

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE -> {
                // If request is cancelled, the result arrays are empty.
                if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                    // permission was granted, yay!
                    // Download the Image
                    downloadImage(imageUrl)
                } else {
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.

                }
                return
            }
            // Add other 'when' lines to check for other
            // permissions this app might request.
            else -> {
                // Ignore all other requests.
            }
        }
    }

Hier ist der vollständige Code:

MainActivity.kt

import android.Manifest
import android.annotation.TargetApi
import android.app.DownloadManager
import android.content.Context
import android.content.pm.PackageManager
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File

class MainActivity : AppCompatActivity() {
    private var imageUrl = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
    //private var imageUrl = "http://10.0.2.2:8087/getFile"

    //private var imageUrl = "https://www.orimi.com/pdf-test.pdf"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        download_btn.setOnClickListener {
            //http://localhost:8087/getFile
            //downloadImage("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf")
            //downloadImage("http://localhost:8087/getFile")
            // After API 23 (Marshmallow) and lower Android 10 you need to ask for permission first before save an image
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                askPermissions()
            } else {
                downloadImage(imageUrl)
            }
        }
    }

    private fun downloadImage(url: String) {
        //val directory = File(Environment.DIRECTORY_PICTURES)

//        if (!directory.exists()) {
//            directory.mkdirs()
//        }

        val downloadManager = this.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager

        val downloadUri = Uri.parse(url)

        val request = DownloadManager.Request(downloadUri).apply {
            setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
                .setAllowedOverRoaming(false)
                .setTitle(url.substring(url.lastIndexOf("/") + 1))
                .setDescription("abc")
                .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                .setDestinationInExternalPublicDir(
                    Environment.DIRECTORY_DOWNLOADS,
                    url.substring(url.lastIndexOf("/") + 1)
                )

        }
        //use when just to download the file with getting status
        //downloadManager.enqueue(request)

        val downloadId = downloadManager.enqueue(request)
        val query = DownloadManager.Query().setFilterById(downloadId)

        lifecycleScope.launchWhenStarted {
            var lastMsg: String = ""
            var downloading = true
            while (downloading) {
                val cursor: Cursor = downloadManager.query(query)
                cursor.moveToFirst()
                if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
                    downloading = false
                }
                val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
                val msg: String? = statusMessage(url, File(Environment.DIRECTORY_DOWNLOADS), status)
                Log.e("DownloadManager", " Status is :$msg")
                if (msg != lastMsg) {
                    withContext(Dispatchers.Main) {
                        // Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
                        text_view.text = msg
                        //Log.e("DownloadManager", "Status is :$msg")
                    }
                    lastMsg = msg ?: ""
                }
                cursor.close()
            }
        }
    }

    private fun statusMessage(url: String, directory: File, status: Int): String? {
        var msg = ""
        msg = when (status) {
            DownloadManager.STATUS_FAILED -> "Download has been failed, please try again"
            DownloadManager.STATUS_PAUSED -> "Paused"
            DownloadManager.STATUS_PENDING -> "Pending"
            DownloadManager.STATUS_RUNNING -> "Downloading..."
            DownloadManager.STATUS_SUCCESSFUL -> "PDF downloaded successfully in $directory" + File.separator + url.substring(
                url.lastIndexOf("/") + 1
            )
            else -> "There's nothing to download"
        }
        return msg
    }

    @TargetApi(Build.VERSION_CODES.M)
    fun askPermissions() {
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            // Permission is not granted
            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(
                    this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
                )
            ) {
                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.
                AlertDialog.Builder(this)
                    .setTitle("Permission required")
                    .setMessage("Permission required to save photos from the Web.")
                    .setPositiveButton("Allow") { dialog, id ->
                        ActivityCompat.requestPermissions(
                            this,
                            arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                            MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE
                        )
                        finish()
                    }
                    .setNegativeButton("Deny") { dialog, id -> dialog.cancel() }
                    .show()
            } else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(
                    this,
                    arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                    MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE
                )
                // MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE is an
                // app-defined int constant. The callback method gets the
                // result of the request.

            }
        } else {
            // Permission has already been granted
            downloadImage(imageUrl)
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE -> {
                // If request is cancelled, the result arrays are empty.
                if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                    // permission was granted, yay!
                    // Download the Image
                    downloadImage(imageUrl)
                } else {
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.

                }
                return
            }
            // Add other 'when' lines to check for other
            // permissions this app might request.
            else -> {
                // Ignore all other requests.
            }
        }
    }

    companion object {
        private const val MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1
    }
}

Run

Kopieren Sie den Code oder laden Sie ihn über den unten stehenden Link herunter, erstellen Sie ihn und führen Sie ihn aus.

Referenz

Hier sind die Referenzlinks:

Download Beispiel
Folgen Code-Autor