Android 安卓下载管理器完成

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21477493/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 04:38:38  来源:igfitidea点击:

Android download manager completed

androidandroid-download-manager

提问by Msmit1993

Small question about the download manager in android. It's the first time I'm working with it and have successfully downloaded multiple files and opened them. But my question is how do i check if the download completed.

关于android下载管理器的小问题。这是我第一次使用它并成功下载多个文件并打开它们。但我的问题是如何检查下载是否完成。

The situation is I download a PDF file and open it, and usually the file is so small it complets before opening. But if the file is somewhat bigger how do I check if the download manager is finished with the download before opening it.

情况是我下载了一个 PDF 文件并打开它,通常文件很小,它在打开之前就完成了。但是如果文件有点大,我如何在打开之前检查下载管理器是否已完成下载。

How I download:

我如何下载:

Intent intent = getIntent();
DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
Uri Download_Uri = Uri.parse(intent.getStringExtra("Document_href"));
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);

//Restrict the types of networks over which this download may proceed.
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
//Set whether this download may proceed over a roaming connection.
request.setAllowedOverRoaming(false);
//Set the title of this download, to be displayed in notifications.
request.setTitle(intent.getStringExtra("Document_title"));
//Set the local destination for the downloaded file to a path within the application's external files directory
request.setDestinationInExternalFilesDir(this,Environment.DIRECTORY_DOWNLOADS,intent.getStringExtra("Document_title") + ".pdf");
//Enqueue a new download and same the referenceId
Long downloadReference = downloadManager.enqueue(request);

How I open the file

我如何打开文件

Uri uri = Uri.parse("content://com.app.applicationname/" + "/Download/" + intent.getStringExtra("Document_title") + ".pdf");
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(uri, "application/pdf");
target.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

startActivity(target);

So somewhere between downloading and opening the file I want a if statement to check if it should continue or wait for the file.

所以在下载和打开文件之间的某个地方,我想要一个 if 语句来检查它是否应该继续或等待文件。

回答by Vaibhav Agarwal

A broadcast is sent by the DownloadManagerwhenever a download completes, so you need to register a broadcast receiver with the appropriate intent action( ACTION_DOWNLOAD_COMPLETE ) to catch this broadcast:

DownloadManager每当下载完成时都会发送广播,因此您需要使用适当的意图操作( ACTION_DOWNLOAD_COMPLETE )注册广播接收器以捕获此广播:

To register receiver

注册接收者

registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

and a BroadcastReciever handler

和一个 BroadcastReciever 处理程序

BroadcastReceiver onComplete=new BroadcastReceiver() {
    public void onReceive(Context ctxt, Intent intent) {
        // your code
    }
};

You can also create AsyncTask to handle the downloading of big files

您还可以创建 AsyncTask 来处理大文件的下载

Create a download dialog of some sort to display downloading in notification area and than handle the opening of the file:

创建某种下载对话框以在通知区域显示下载并处理文件的打开:

protected void openFile(String fileName) {
    Intent install = new Intent(Intent.ACTION_VIEW);
    install.setDataAndType(Uri.fromFile(new File(fileName)),"MIME-TYPE");
    startActivity(install);
}

you can also check the sample link

您还可以查看示例链接

Sample Code

示例代码

回答by IrshadKumail

Courtesy: Android DonwnloadManager Example

礼貌:Android DonwnloadManager 示例

The accepted answer is not completely correct. Receiving ACTION_DOWNLOAD_COMPLETE broadcast doesnt mean your download is complete. Note that ACTION_DOWNLOAD_COMPLETE is broadcasted by DownloadManager when any download is completed. It doesnt necessarily mean it is the same download which you are waiting for

接受的答案并不完全正确。收到 ACTION_DOWNLOAD_COMPLETE 广播并不意味着您的下载已完成。请注意,当任何下载完成时,DownloadManager 会广播 ACTION_DOWNLOAD_COMPLETE。这并不一定意味着它与您正在等待的下载相同

Solution is to save the download id returned by enqueue() when starting the download. This long download id is unique across the system and can be used to check the download status

解决方法是在开始下载时保存enqueue()返回的下载id。这个长下载 id 在整个系统中是唯一的,可用于检查下载状态

DownloadManager downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
long downloadID = downloadManager.enqueue(request);// enqueue puts the download request in the queue.

You can be notified when your download is complete by following three steps

您可以通过以下三个步骤在下载完成时收到通知

Create a BroadcastReceiver as shown in snippet below.Inside the receiver we just check if the received broadcast is for our download by matching the received download id with our enqueued download.

创建一个 BroadcastReceiver,如下面的片段所示。在接收器中,我们只是通过将接收到的下载 ID 与我们排队的下载进行匹配来检查接收到的广播是否适合我们的下载。

private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
       @Override
       public void onReceive(Context context, Intent intent) {
           //Fetching the download id received with the broadcast
           long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
           //Checking if the received broadcast is for our enqueued download by matching download id
           if (downloadID == id) {
               Toast.makeText(MainActivity.this, "Download Completed", Toast.LENGTH_SHORT).show();
           }
       }
   };

Once the BroadcastReceiver is created you can register for ACTION_DOWNLOAD_COMPLETE in the onCreate method of your activity.

创建 BroadcastReceiver 后,您可以在活动的 onCreate 方法中注册 ACTION_DOWNLOAD_COMPLETE。

@Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       registerReceiver(onDownloadComplete,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

   }

It is also important that you unregister the BroadcastReceiver in onDestroy. This ensures you only listen for this broadcast as long as the activity is active

在 onDestroy 中注销 BroadcastReceiver 也很重要。这确保您只在活动处于活动状态时收听此广播

@Override
  public void onDestroy() {
      super.onDestroy();
      unregisterReceiver(onDownloadComplete);
  }

I urge your to read the complete example here

我敦促您在此处阅读完整的示例

回答by Louie Bertoncin

I have spent over a week researching how to download and open files with the DownloadManager and never quite found an answer that was completely perfect for me, so it was up to me to take bits and pieces to find what worked. I made sure to document my code to the best of my ability. If there are any questions, please feel free to leave them in the comments below the answer.

我花了一个多星期研究如何使用 DownloadManager 下载和打开文件,但从来没有找到一个对我来说完全完美的答案,所以我需要花点时间找出有效的方法。我确保尽我所能记录我的代码。如果有任何问题,请随时将它们留在答案下方的评论中。

Also, don't forget to add this line to your AndroidManifest.xml file!!

另外,不要忘记将此行添加到您的 AndroidManifest.xml 文件中!!

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

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

My download manager:

我的下载管理器:

import android.app.DownloadManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Environment;
import android.webkit.CookieManager;
import android.webkit.DownloadListener;
import android.widget.Toast;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MyDownloadListener implements DownloadListener {
    private Context mContext;
    private DownloadManager mDownloadManager;
    private long mDownloadedFileID;
    private DownloadManager.Request mRequest;

    public MyDownloadListener(Context context) {
        mContext = context;
        mDownloadManager = (DownloadManager) mContext
            .getSystemService(Context.DOWNLOAD_SERVICE);
    }

    @Override
    public void onDownloadStart(String url, String userAgent, String
        contentDisposition, final String mimetype, long contentLength) {

        // Function is called once download completes.
        BroadcastReceiver onComplete = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                // Prevents the occasional unintentional call. I needed this.
                if (mDownloadedFileID == -1)
                    return;
                Intent fileIntent = new Intent(Intent.ACTION_VIEW);

                // Grabs the Uri for the file that was downloaded.
                Uri mostRecentDownload =
                    mDownloadManager.getUriForDownloadedFile(mDownloadedFileID);
                // DownloadManager stores the Mime Type. Makes it really easy for us.
                String mimeType =
                    mDownloadManager.getMimeTypeForDownloadedFile(mDownloadedFileID);
                fileIntent.setDataAndType(mostRecentDownload, mimeType);
                fileIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                try {
                    mContext.startActivity(fileIntent);
                } catch (ActivityNotFoundException e) {
                    Toast.makeText(mContext, "No handler for this type of file.",
                        Toast.LENGTH_LONG).show();
                }
                // Sets up the prevention of an unintentional call. I found it necessary. Maybe not for others.
                mDownloadedFileID = -1;
            }
        };
        // Registers function to listen to the completion of the download.
        mContext.registerReceiver(onComplete, new
            IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

        mRequest = new DownloadManager.Request(Uri.parse(url));
        // Limits the download to only over WiFi. Optional.
        mRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
        // Makes download visible in notifications while downloading, but disappears after download completes. Optional.
        mRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
        mRequest.setMimeType(mimetype);

        // If necessary for a security check. I needed it, but I don't think it's mandatory.
        String cookie = CookieManager.getInstance().getCookie(url);
        mRequest.addRequestHeader("Cookie", cookie);

        // Grabs the file name from the Content-Disposition
        String filename = null;
        Pattern regex = Pattern.compile("(?<=filename=\").*?(?=\")");
        Matcher regexMatcher = regex.matcher(contentDisposition);
        if (regexMatcher.find()) {
            filename = regexMatcher.group();
        }

        // Sets the file path to save to, including the file name. Make sure to have the WRITE_EXTERNAL_STORAGE permission!!
        mRequest.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, filename);
        // Sets the title of the notification and how it appears to the user in the saved directory.
        mRequest.setTitle(filename);

        // Adds the request to the DownloadManager queue to be executed at the next available opportunity.
        mDownloadedFileID = mDownloadManager.enqueue(mRequest);
    }
}

Simply add this to your existing WebView by adding this line to your WebView class:

通过将此行添加到您的 WebView 类,只需将其添加到您现有的 WebView 中:

webView.setDownloadListener(new MyDownloadListener(webView.getContext()));

webView.setDownloadListener(new MyDownloadListener(webView.getContext()));

回答by ebernie

You need not create file just to view it. The URI in COLUMN_LOCAL_URI can be used in setDataAndType(). See example below.

您无需创建文件即可查看它。COLUMN_LOCAL_URI 中的 URI 可用于 setDataAndType()。请参阅下面的示例。

 int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
 String downloadedPackageUriString = cursor.getString(uriIndex);
 Intent open = new Intent(Intent.ACTION_VIEW);
 open.setDataAndType(Uri.parse(downloadedPackageUriString), mimeType);
 open.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
 startActivity(open);