安卓開發入門之系統下載管理工具DownloadManager-第一部分(翻譯)

原文鏈接
https://blog.stylingandroid.com/downloadmanager-part-1/
安卓開發入門之系統下載管理工具DownloadManager-第一部分
http://blog.csdn.net/zhangxiangliang2/article/details/73691449
安卓開發入門之系統下載管理工具DownloadManager-第二部分
http://blog.csdn.net/zhangxiangliang2/article/details/73693134
安卓開發入門之系統下載管理工具DownloadManager-第三部分
http://blog.csdn.net/zhangxiangliang2/article/details/73695167
安卓開發中的一個普遍需求是從網絡下載文件到設備,此係列三部分研究DownloadManager類是如何以一種極其簡單的方式解決該需求的。
首先,我們要知道DownloadManager類起始於API9,儘管該API有少許毛病,但是其已經很穩定了。

讓我們開始吧騷年!
新建工程,在Activity裏面添加我們下載按鈕,點擊後下載一個PDF文件到本地並打開。
DownloadManager的主要邏輯在Downloader對象中實現,並且在文件下載完成後回調FileDownloaded()方法。同時,要在Activity銷燬的時候調用
UnRegistered()方法。這就是所有要注意的事項。下面是代碼:

public class MainActivity extends AppCompatActivity implements Downloader.Listener {
    private static final String URI_STRING = "http://www.cbu.edu.zm/downloads/pdf-sample.pdf";

    private Button download;

    private Downloader downloader;

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

        download = (Button) findViewById(R.id.download);
        download.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                downloadOrCancel();
            }
        });
        downloader = Downloader.newInstance(this);
    }

    void downloadOrCancel() {
        if (downloader.isDownloading()) {
            cancel();
        } else {
            download();
        }
        updateUi();
    }

    private void cancel() {
        downloader.cancel();
    }

    private void download() {
        Uri uri = Uri.parse(URI_STRING);
        downloader.download(uri);
    }

    @Override
    public void fileDownloaded(Uri uri, String mimeType) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(uri, mimeType);
        startActivity(intent);
        updateUi();
    }

    @Override
    public Context getContext() {
        return getApplicationContext();
    }

    private void updateUi() {
        if (downloader.isDownloading()) {
            download.setText(R.string.cancel);
        } else {
            download.setText(R.string.download);
        }
    }

    @Override
    protected void onDestroy() {
        downloader.unregister();//這麼做是因爲我們無法保證用戶退出app的時候已經下載完成,
                //除此之外,退出app後還可以繼續下載,這樣就不用創建後臺service來下載了
        super.onDestroy();
    }
}

運行結果:
iamge

源碼下載
https://github.com/StylingAndroid/DownloadManager/tree/Part1

原文鏈接
https://blog.stylingandroid.com/downloadmanager-part-1/

怎麼樣?是不是簡單易用?
如果你滿足於此,下面的內容你可以不用看了。
DownloadManager類究竟做了什麼來實現如此神奇的效果呢?
讓我們潛入Downloader類的源碼,附有詳細的註釋。

class Downloader implements DownloadReceiver.Listener {
    private final Listener listener;
    private final DownloadManager downloadManager;

    private DownloadReceiver receiver = null;

    private long downloadId = -1;

    static Downloader newInstance(Listener listener) {
        Context context = listener.getContext();
        DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);//獲取DownloadManager實例
        return new Downloader(downloadManager, listener);
    }

    Downloader(DownloadManager downloadManager, Listener listener) {
        this.downloadManager = downloadManager;
        this.listener = listener;
    }

    void download(Uri uri) {
        if (!isDownloading()) {
            register();//首先註冊BroadcastReceiver用來通知下載完成 
            DownloadManager.Request request = new DownloadManager.Request(uri);//通過傳參uri獲取DownloadManager.Request
            downloadId = downloadManager.enqueue(request);//通過enqueue將該request放入隊列,並且獲取下載請求的唯一ID
        }
    }

    boolean isDownloading() {
        return downloadId >= 0;
    }

    void register() {
        if (receiver == null && isDownloading()) {
            receiver = new DownloadReceiver(this);
            receiver.register(listener.getContext());
        }
    }
    @Override
    public void downloadComplete(long completedDownloadId) {//下載完成後調用此方法
        if (downloadId == completedDownloadId) {//首先檢查ID是否我們的下載ID,如果是,再通過下面代碼拿到結果,下面代碼同樣適用於多個併發下載
            DownloadManager.Query query = new DownloadManager.Query();
            query.setFilterById(downloadId);
            downloadId = -1;
            unregister();
            Cursor cursor = downloadManager.query(query);
            while (cursor.moveToNext()) {
                getFileInfo(cursor);
            }
            cursor.close();
        }
    }

    void unregister() {
        if (receiver != null) {
            receiver.unregister(listener.getContext());//反註冊BroadcastReceiver
        }
        receiver = null;
    }

    private void getFileInfo(Cursor cursor) {
        int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
        if (status == DownloadManager.STATUS_SUCCESSFUL) {//通過檢查status屬性來判斷是否下載成功,當然還有其他屬性供我們自定義,
            Long id = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID));
            Uri uri = downloadManager.getUriForDownloadedFile(id);//獲取uri
            String mimeType = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_MEDIA_TYPE));//獲取MIME類型
            listener.fileDownloaded(uri, mimeType);
        }
    }

    void cancel() {
        if (isDownloading()) {
            downloadManager.remove(downloadId);//通過downloadId來取消下載
            downloadId = -1;
            unregister();
        }
    }

    interface Listener {
        void fileDownloaded(Uri uri, String mimeType);
        Context getContext();
    }
}

再看看BroadcastReceiver,看代碼註釋

class DownloadReceiver extends BroadcastReceiver {
    private final Listener listener;

    DownloadReceiver(Listener listener) {
        this.listener = listener;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
        listener.downloadComplete(downloadId);
    }

    public void register(Context context) {
        IntentFilter downloadFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);//註冊類型DownloadManager.ACTION_DOWNLOAD_COMPLETE
                //我們將能獲取下載成功事件,我們還可以註冊其他事件,比如說用戶點擊下載通知後跳轉到我們的app頁面
 context.registerReceiver(this, downloadFilter); } 
public void unregister(Context context)
 { context.unregisterReceiver(this); } 
interface Listener { void downloadComplete(long downloadId); }}

下一篇文章中,我們將進一步探索DownloadManager類,並且見識到許多很有用的方法,期待吧。。。

原文鏈接
https://blog.stylingandroid.com/downloadmanager-part-1/
安卓開發入門之系統下載管理工具DownloadManager-第一部分
http://blog.csdn.net/zhangxiangliang2/article/details/73691449
安卓開發入門之系統下載管理工具DownloadManager-第二部分
http://blog.csdn.net/zhangxiangliang2/article/details/73693134
安卓開發入門之系統下載管理工具DownloadManager-第三部分
http://blog.csdn.net/zhangxiangliang2/article/details/73695167

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