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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章