4 行程式碼實現 Android 快速檔案下載

Marno發表於2016-06-29

寫在前面的廢話

下載檔案,幾乎是所有APP都會用到的功能!算了,還是不廢話了,直接開寫吧。。。

簡單使用

完成一個下載任務只需要4行程式碼,什麼斷點續傳,大檔案下載,通知欄進度顯示….都不需要你操心。

//建立下載任務,downloadUrl就是下載連結
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl));
//指定下載路徑和下載檔名
request.setDestinationInExternalPublicDir("/download/", fileName);
//獲取下載管理器
DownloadManager downloadManager= (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
//將下載任務加入下載佇列,否則不會進行下載
downloadManager.enqueue(request);

高階用法

  • 通過上面的程式碼大家也看出來了,我們使用的是系統提供的下載管理器進行下載,從API 9就開始支援了,所以不用擔心在相容問題
  • 既然是系統提供的,那麼肯定還有更加強大的用法,文章繼續

讓我們看DownloadManager的原始碼,提供了這麼多方法

DownloadManager的方法

DownloadManager.Request的方法

方法差不多就這些,已經比較全了,可以滿足我們絕大部分的使用場景。

實際使用

接下來我們就以APP應用內更新為例,講一下這些方法的使用

1.首先我們梳理下APP應用內更新的邏輯

APP應用內更新

2.接下來看具體實現,上程式碼

//使用系統下載器下載
private void downloadAPK(String versionUrl, String versionName) {
        //建立下載任務
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(versionUrl));
        request.setAllowedOverRoaming(false);//漫遊網路是否可以下載

        //設定檔案型別,可以在下載結束後自動開啟該檔案
        MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
        String mimeString = mimeTypeMap.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(versionUrl));
        request.setMimeType(mimeString);

        //在通知欄中顯示,預設就是顯示的
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
        request.setVisibleInDownloadsUi(true);

        //sdcard的目錄下的download資料夾,必須設定
        request.setDestinationInExternalPublicDir("/download/", versionName);
        //request.setDestinationInExternalFilesDir(),也可以自己制定下載路徑

        //將下載請求加入下載佇列
        downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
        //加入下載佇列後會給該任務返回一個long型的id,
        //通過該id可以取消任務,重啟任務等等,看上面原始碼中框起來的方法
        mTaskId = downloadManager.enqueue(request);

        //註冊廣播接收者,監聽下載狀態
        mContext.registerReceiver(receiver,
                new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

接下來是廣播接收器

    //廣播接受者,接收下載狀態
    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            checkDownloadStatus();//檢查下載狀態
        }
    };

檢查下載狀態

 //檢查下載狀態
    private void checkDownloadStatus() {
        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterById(mTaskId);//篩選下載任務,傳入任務ID,可變引數
        Cursor c = downloadManager.query(query);
        if (c.moveToFirst()) {
            int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
            switch (status) {
                case DownloadManager.STATUS_PAUSED:
                    MLog.i(">>>下載暫停");
                case DownloadManager.STATUS_PENDING:
                    MLog.i(">>>下載延遲");
                case DownloadManager.STATUS_RUNNING:
                    MLog.i(">>>正在下載");
                    break;
                case DownloadManager.STATUS_SUCCESSFUL
                    MLog.i(">>>下載完成");
                    //下載完成安裝APK
                    //downloadPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + File.separator + versionName;
                    installAPK(new File(downloadPath));
                    break;
                case DownloadManager.STATUS_FAILED:
                    MLog.i(">>>下載失敗");
                    break;
            }
        }
    }

安裝APK

    //下載到本地後執行安裝
    protected void installAPK(File file) {
        if (!file.exists()) return;
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri uri = Uri.parse("file://" + file.toString());
        intent.setDataAndType(uri, "application/vnd.android.package-archive");
        //在服務中開啟activity必須設定flag,後面解釋
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mContext.startActivity(intent);
    }

到此就完成了應用內更新APP的程式碼,但是有一些坑需要注意!

希望你可以看到最後這幾句,不然你也會被坑的!

1.雖然下載什麼的不需要自己操心了,但是建議還是將整個上面四段程式碼放在Service中執行,因為放在Activity中時,當使用者按home鍵後,即使下載完了,也不會彈出安裝介面

2.建議使用startService的方式啟動Service,這樣不會與Activity生命週期繫結,保證下載完後能順利安裝。

3.Service使用完後要及時地停掉!

相關文章