android 下载管理器简介

DownloadManager是android提供的一个系统服务,用于处理长期运行的HTTP下载。客户端可以将一个URI代表的一个网络资源文件下载到指定的目录。DownloadManager将会在后台执行下载任务,处理所有的HTTP交互,在下载失败或系统重启后继续下载任务。

DownloadManager的使用非常简单,当客户端需要发起一个下载任务时,需要创建一个DownloadManager.Request对象,并进行必要的设置:

String downloadUrl = "http://192.168.1.33/20131227_141739.mp4";
Uri downloadUri = Uri.parse(downloadUrl);
DownloadManager.Request request = new DownloadManager.Request(downloadUri);

// 仅WiFi下允许下载
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);

// 漫游时不下载,防止产生漫游费用
request.setAllowedOverRoaming(false);

// 下载文件描述
request.setDescription("Downloading 20131227_141739.mp4");

// 下载存储路径
// 文件将存放在外部存储的确实download文件内,如果无此文件夹,创建之,如果有,下面将返回false。
// 不同的手机不同Android版本的SD卡的挂载点可能会不一样,因此通过系统方式获取。
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir();
request.setDestinationInExternalPublicDir("/download/", "20131227_142027.mp4");

// 下载文件类型
String extension = MimeTypeMap.getFileExtensionFromUrl(downloadUrl);
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
request.setMimeType(mimeType);
// 设置UI是否可见
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
// 下载标题
request.setTitle("20131227_141739.mp4");
request.setVisibleInDownloadsUi(false);

创建完成request后,需要将该request提交给DownloadManager,

mDownloadId = mDownloadManager.enqueue(request);


返回的下载ID可以用来查询下载任务的执行状态,成功或失败。客户端需要创建一个DownloadManager.Query对象进行查询:

DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(mDownloadId);
Cursor cursor = mDownloadManager.query(query);
if (cursor.moveToFirst()) {
	int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
	switch (status) {
	case DownloadManager.STATUS_FAILED:
		text = "download failed";
		break;
	case DownloadManager.STATUS_PAUSED:
		text = "download paused";
		break;
	case DownloadManager.STATUS_PENDING:
		text = "download pending";
		break;
	case DownloadManager.STATUS_RUNNING:
		text = "download running";
		break;
	case DownloadManager.STATUS_SUCCESSFUL:
		text = "download successful";
		break;
	default:
		break;
	}
}
cursor.close();
Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();

要删除某一个下载任务,可以调用DownloadManager的remove方法:

mDownloadManager.remove(mDownloadId);

可以使用DownloadManager.ACTION_VIEW_DOWNLOADS来启动一个activity来查看所有下载任务:

startActivity(new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS));

如果客户端要监听任务的下载状态,或用户点击通知栏的点击事件,则需要注册一个receiver,来监听DownloadManager.ACTION_DOWNLOAD_COMPLETE和DownloadManager.ACTION_NOTIFICATION_CLICKED两个广播:

private BroadcastReceiver mReceiver = new BroadcastReceiver() {

	@Override
	public void onReceive(Context context, Intent intent) {
		if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {                
			long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
			Toast.makeText(MainActivity.this, id + " Finished", Toast.LENGTH_SHORT).show();
		} else if (intent.getAction().equals(DownloadManager.ACTION_NOTIFICATION_CLICKED)) {
			long[] ids = intent.getLongArrayExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS);
			Toast.makeText(MainActivity.this, StringUtils.join(ids, ',') + " clicked", Toast.LENGTH_SHORT).show();
		}
	}
};
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
intentFilter.addAction(DownloadManager.ACTION_NOTIFICATION_CLICKED);
registerReceiver(mReceiver, intentFilter);

至此,基本的下载任务就完成了。

完整代码如下:

package com.example.downloadmanager;

import org.apache.commons.lang3.StringUtils;

import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.MimeTypeMap;
import android.widget.Toast;

public class MainActivity extends Activity {
    private long mDownloadId = 0;
    private DownloadManager mDownloadManager = null;
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {                
                long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
                Toast.makeText(MainActivity.this, id + " Finished", Toast.LENGTH_SHORT).show();
            } else if (intent.getAction().equals(DownloadManager.ACTION_NOTIFICATION_CLICKED)) {
                long[] ids = intent.getLongArrayExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS);
                Toast.makeText(MainActivity.this, StringUtils.join(ids, ',') + " clicked", Toast.LENGTH_SHORT).show();
            }
        }
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDownloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
        
        findViewById(R.id.btn_start_download).setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                String downloadUrl = "http://192.168.1.33/20131227_141739.mp4";
                Uri downloadUri = Uri.parse(downloadUrl);
                DownloadManager.Request request = new DownloadManager.Request(downloadUri);
                
                // 仅WiFi下允许下载
                request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
                
                // 漫游时不下载,防止产生漫游费用
                request.setAllowedOverRoaming(false);
                
                // 下载文件描述
                request.setDescription("Downloading 20131227_141739.mp4");
                
                // 下载存储路径
                // 文件将存放在外部存储的确实download文件内,如果无此文件夹,创建之,如果有,下面将返回false。
                // 不同的手机不同Android版本的SD卡的挂载点可能会不一样,因此通过系统方式获取。
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir();
                request.setDestinationInExternalPublicDir("/download/", "20131227_142027.mp4");
                
                // 下载文件类型
                String extension = MimeTypeMap.getFileExtensionFromUrl(downloadUrl);
                String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
                request.setMimeType(mimeType);
                // 设置UI是否可见
                request.allowScanningByMediaScanner();
                request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
                // 下载标题
                request.setTitle("20131227_141739.mp4");
                request.setVisibleInDownloadsUi(false);
                mDownloadId = mDownloadManager.enqueue(request);
            }
        });
        
        findViewById(R.id.btn_query_status).setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                String text = "";
                DownloadManager.Query query = new DownloadManager.Query();
                query.setFilterById(mDownloadId);
                Cursor cursor = mDownloadManager.query(query);
                if (cursor.moveToFirst()) {
                    int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
                    switch (status) {
                    case DownloadManager.STATUS_FAILED:
                        text = "download failed";
                        break;
                    case DownloadManager.STATUS_PAUSED:
                        text = "download paused";
                        break;
                    case DownloadManager.STATUS_PENDING:
                        text = "download pending";
                        break;
                    case DownloadManager.STATUS_RUNNING:
                        text = "download running";
                        break;
                    case DownloadManager.STATUS_SUCCESSFUL:
                        text = "download successful";
                        break;
                    default:
                        break;
                    }
                }
                cursor.close();
                Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();
            }
        });
        
        findViewById(R.id.btn_view_log).setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                MainActivity.this.startActivity(new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS));
            }
        });
        
        findViewById(R.id.btn_stop_download).setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                mDownloadManager.remove(mDownloadId);
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
        intentFilter.addAction(DownloadManager.ACTION_NOTIFICATION_CLICKED);
        registerReceiver(mReceiver, intentFilter);
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mReceiver);
    }
}

需要说明的是,DownloadManager提供的下载功能非常简单,可能无法满足实际的需求,比如没有断点续传功能,没有暂停和继续。幸运的是已经有开源的库帮我们实现了这些功能,DownloadProvider就是其中一个,其github地址为:

https://github.com/yxl/DownloadProvider.git

你可能感兴趣的:(android,断点续传,DownloadManager)