在活动中显示下载管理器进度

我在我的活动中使用了Download Manager类来执行下载; 它工作正常,我的下一个任务是在我的活动中显示相同的进度百分比。 我不知道该怎么做。

我的代码到目前为止

public class DownloadSampleBook extends Activity{ private long enqueue; private DownloadManager dm; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sample_download); BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) { long downloadId = intent.getLongExtra( DownloadManager.EXTRA_DOWNLOAD_ID, 0); Query query = new Query(); query.setFilterById(enqueue); Cursor c = dm.query(query); if (c.moveToFirst()) { int columnIndex = c .getColumnIndex(DownloadManager.COLUMN_STATUS); if (DownloadManager.STATUS_SUCCESSFUL == c .getInt(columnIndex)) { view.setImageURI(Uri.parse(uriString)); } } } } }; registerReceiver(receiver, new IntentFilter( DownloadManager.ACTION_DOWNLOAD_COMPLETE)); } public void onClick(View view) { dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); Request request = new Request( Uri.parse("http://img.androidcookie.com/android/a.png")); enqueue = dm.enqueue(request); } public void showDownload(View view) { Intent i = new Intent(); i.setAction(DownloadManager.ACTION_VIEW_DOWNLOADS); startActivity(i); } } 

是否有任何方法可以提供进度下载百分比?

如果您正在寻找一种合适的方法来确定何时查询DownloadManager以获取进度更新,请考虑为uri content://downloads/my_downloads注册ContentObserver content://downloads/my_downloads

例:

 DownloadManager manager = (DownloadManager) getSystemService( Context.DOWNLOAD_SERVICE ); manager.enqueue( myRequest ); Uri myDownloads = Uri.parse( "content://downloads/my_downloads" ); getContentResolver().registerContentObserver( myDownloads, true, new DownloadObserver() ); ... public static class DownloadObserver extends ContentObserver { @Override public void onChange( boolean selfChange, Uri uri ) { Log.d( "DownloadObserver", "Download " + uri + " updated" ); } 

这会在收到长时间运行下载的每个块时产生以下输出

 D/DownloadObserver(15584): Download content://downloads/my_downloads/437 updated D/DownloadObserver(15584): Download content://downloads/my_downloads/437 updated D/DownloadObserver(15584): Download content://downloads/my_downloads/437 updated D/DownloadObserver(15584): Download content://downloads/my_downloads/437 updated 

其中’437’是您下载的ID。

请注意,这遵循android.provider.Downloads类中定义的内容URI,它似乎隐藏在框架中,并且可能无法在所有设备上一致地工作。 ( https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/provider/Downloads.java#89

您可以使用query方法query到目前为止下载的字节数以及需要下载的总字节数,其方法与查询示例代码中的状态非常相似。 获得这些值后,以百分比forms计算进度相当容易。

在收到新数据时,似乎没有任何方式可以通知您,因此您可以定期轮询下载管理器以确定要监视的任何下载的当前状态。

 Query query = new Query(); query.setfilterById(downloadId); Cursor c = dm.query(query); if (c.moveToFirst()) { int sizeIndex = c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES); int downloadedIndex = c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR); long size = c.getInt(sizeIndex); long downloaded = c.getInt(downloadedIndex); double progress = 0.0; if (size != -1) progress = downloaded*100.0/size; // At this point you have the progress as a percentage. } 

请注意,总大小最初为-1,只有在下载开始后才会填写。 所以在上面的示例代码中,我检查了-1,如果尚未设置大小,则将进度设置为0。

但是,在某些情况下,您可能会发现永远不会返回总大小(例如,在HTTP分块传输中,将不会有可以确定大小的Content-Length标头)。 如果您需要支持这种types的服务器,您应该向用户提供某种指示,表明下载正在进行,而不仅仅是一个停留在零的进度条。

我要求跟踪多个文件的下载。 经过大量的思考和实验,我想出了以下代码:

 private void startDownloadThread(final List list) { // Initializing the broadcast receiver ... mBroadCastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { mFinishedFilesFromNotif.add(intent.getExtras() .getLong(DownloadManager.EXTRA_DOWNLOAD_ID)); } }; IntentFilter intentFilter = new IntentFilter( "android.intent.action.DOWNLOAD_COMPLETE"); DownloadProgressUIFragment.this.getActivity().registerReceiver(mBroadCastReceiver, intentFilter); // initializing the download manager instance .... mDownloadManager = (DownloadManager) getActivity() .getSystemService(Context.DOWNLOAD_SERVICE); // adding files to the download manager list ... for(DownloadFile f: list) { mDownloadIds.add(FileUtils.addFileForDownloadInBkg(getApplicationContext(), f.getUrl(), f.getPath())); } // starting the thread to track the progress of the download .. mProgressThread = new Thread(new Runnable() { @Override public void run() { // Preparing the query for the download manager ... DownloadManager.Query q = new DownloadManager.Query(); long[] ids = new long[mDownloadIds.size()]; final List idsArrList= new ArrayList<>(); int i = 0; for (Long id: mDownloadIds) { ids[i++] = id; idsArrList.add(id); } q.setFilterById(ids); // getting the total size of the data ... Cursor c; while(true) { // check if the downloads are already completed ... // Here I have created a set of download ids from download manager to keep // track of all the files that are dowloaded, which I populate by creating // if(mFinishedFilesFromNotif.containsAll(idsArrList)) { isDownloadSuccess = true; // TODO - Take appropriate action. Download is finished successfully return; } // start iterating and noting progress .. c = mDownloadManager.query(q); if(c != null) { int filesDownloaded = 0; float fileFracs = 0f; // this stores the fraction of all the files in // download final int columnTotalSize = c.getColumnIndex (DownloadManager.COLUMN_TOTAL_SIZE_BYTES); final int columnStatus = c.getColumnIndex(DownloadManager.COLUMN_STATUS); //final int columnId = c.getColumnIndex(DownloadManager.COLUMN_ID); final int columnDwnldSoFar = c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR); while (c.moveToNext()) { // checking the progress .. if(c.getInt(columnStatus) == DownloadManager.STATUS_SUCCESSFUL) { filesDownloaded++; } // If the file is partially downloaded, take its fraction .. else if(c.getInt(columnTotalSize) > 0) { fileFracs += ((c.getInt(columnDwnldSoFar) * 1.0f) / c.getInt(columnTotalSize)); } else if(c.getInt(columnStatus) == DownloadManager.STATUS_FAILED) { // TODO - Take appropriate action. Error in downloading one of the // files. return; } } c.close(); // calculate the progress to show ... float progress = (filesDownloaded + fileFracs)/ids.length; // setting the progress text and bar... final int percentage = Math.round(progress * 100.0f); final String txt = "Loading ... " + percentage + "%"; // Show the progress appropriately ... } } } }); mProgressThread.start(); } 

排队到文件的function是:

 public static long addFileForDownloadInBkg(Context context, String url, String savePath) { Uri uri = Uri.parse(url); DownloadManager.Request request = new DownloadManager.Request(uri); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN); request.setDestinationUri(Uri.fromFile(new File(savePath))); final DownloadManager m = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); return m.enqueue(request); } 

基本上,我会单独收到已完成下载的每个文件的通知,然后将它们添加到一个基本上是帮助我确定所有下载是否已完成的集合中。 我根据文件数量和完成每个文件的分数来跟踪进度。 我希望这有帮助。