1. 程式人生 > >Android開發中使用FileDownloader來實現檔案下載功能(總結一)

Android開發中使用FileDownloader來實現檔案下載功能(總結一)

今天研究了一下Android開發中檔案下載功能,記錄一下。

這篇部落格主要介紹第三方下載外掛:FileDownloader的單任務的使用方法,至於多工的後面會做補充記錄,再寫一篇博文。

效果圖如下:(虛擬機器連不上網)

1、首先是引用方法:

implementation 'com.liulishuo.filedownloader:library:1.7.4'

2、佈局檔案activity_test.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android
:layout_height="match_parent" android:orientation="vertical" android:padding="5dp" xmlns:android="http://schemas.android.com/apk/res/android"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/SecondDownLoad_tvDownLoadFileName"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下載檔名稱" android:layout_alignParentLeft="true" android:textStyle="bold" android:textSize="12dp" android:padding="10dp"/> <TextView android:id="@+id/SecondDownLoad_tvDownLoadSpeed" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="下載速度" android:textStyle="bold" android:textSize="12dp" android:layout_toLeftOf="@+id/SecondDownLoad_tvDownLoadDetail" android:layout_marginRight="10dp" android:padding="10dp"/> <TextView android:id="@+id/SecondDownLoad_tvDownLoadDetail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="檔案詳情" android:textStyle="bold" android:textSize="12dp" android:layout_alignParentRight="true" android:padding="10dp"/> </RelativeLayout> <LinearLayout android:layout_marginTop="10dp" android:id="@+id/SecondDownLoad_lLayoutDownLoad" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ProgressBar android:id="@+id/SecondDownLoad_pBarProgress" style="@style/Widget.AppCompat.ProgressBar.Horizontal" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_weight="1"/> <Button android:id="@+id/SecondDownLoad_btnStartDownLoad" android:layout_width="60dp" android:layout_height="40dp" android:textSize="12dp" android:layout_marginLeft="3dp" android:text="開始"/> <Button android:id="@+id/SecondDownLoad_btnStopDownLoad" android:layout_width="60dp" android:layout_height="40dp" android:textSize="12dp" android:text="刪除"/> </LinearLayout> </LinearLayout>

3、SecondDownLoadActivity.java的程式碼如下:

package com.deepreality.myfiledownloader;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.liulishuo.filedownloader.BaseDownloadTask;
import com.liulishuo.filedownloader.FileDownloadSampleListener;
import com.liulishuo.filedownloader.FileDownloader;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SecondDownLoadActivity extends AppCompatActivity implements View.OnClickListener {

    private Context mContext;
    private Button btnStartDownLoad, btnStopDownLoad;
    private TextView tvDownLoadFileName, tvDownLoadSpeed, tvDownLoadDetail;
    private ProgressBar pBar;
    private String LIULISHUO_APK_URL = "http://cdn.llsapp.com/android/LLS-v4.0-595-20160908-143200.apk";
    private String downLoadFileName;
    private String rootPath = "/mnt/sdcard/TestDownLoadFiles";
    private String downLoadFilePath;//下載檔案的儲存路徑(完整路徑,帶有檔名)
private String downLoadFileDirectory;//下載檔案的儲存資料夾路徑
private int downLoadId;//分配的下載程序編號
private boolean currentDownLoadState = false;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
//判斷android版本號,彈出申請許可權
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            showConfirmAppPermissions();
}

        FileDownloader.setup(this);
bindViews();
bindData();
}

    @Override
protected void onDestroy() {
        super.onDestroy();
FileDownloader.getImpl().pause(downLoadId);
}

    private void bindViews() {
        mContext = SecondDownLoadActivity.this;
btnStartDownLoad = findViewById(R.id.SecondDownLoad_btnStartDownLoad);
btnStopDownLoad = findViewById(R.id.SecondDownLoad_btnStopDownLoad);
tvDownLoadFileName = findViewById(R.id.SecondDownLoad_tvDownLoadFileName);
tvDownLoadSpeed = findViewById(R.id.SecondDownLoad_tvDownLoadSpeed);
tvDownLoadDetail = findViewById(R.id.SecondDownLoad_tvDownLoadDetail);
pBar = findViewById(R.id.SecondDownLoad_pBarProgress);
btnStartDownLoad.setOnClickListener(this);
btnStopDownLoad.setOnClickListener(this);
}

    private void bindData() {
        pBar.setMax(100);
downLoadFileName = regGetFileNameWithoutFileFormat(LIULISHUO_APK_URL, "apk") + ".apk";
tvDownLoadFileName.setText(downLoadFileName);
downLoadFilePath = rootPath + File.separator + "1" + File.separator + downLoadFileName;
downLoadFileDirectory = rootPath + File.separator + "1";
}

    @Override
public void onClick(View v) {
        switch (v.getId()) {
            case R.id.SecondDownLoad_btnStartDownLoad:{
                if (!getFileExist(downLoadFilePath)) {
                    currentDownLoadState = !currentDownLoadState;
                    if (currentDownLoadState) {
                        downLoadId = createDownloadTask(1).start();
btnStartDownLoad.setText("暫停");
} else {
                        FileDownloader.getImpl().pause(downLoadId);
btnStartDownLoad.setText("開始");
}
                } else {
                    Toast.makeText(mContext, "當前檔案已存在,請勿重新下載,浪費資源!", Toast.LENGTH_SHORT).show();
}
                break;
}
            case R.id.SecondDownLoad_btnStopDownLoad:{
                new File(downLoadFilePath).delete();
Toast.makeText(mContext, "" + downLoadFilePath + "】刪除成功", Toast.LENGTH_SHORT).show();
                break;
}
        }
    }

    //判斷當前檔案是否存在,如存在給出提示,如不存在,開始下載
public boolean getFileExist(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            return true;
}
        return false;
}

    //建立下載任務
private BaseDownloadTask createDownloadTask(final int position) {
        final ViewHolder tag;
        final String url;
        boolean isDir = false;
String path = "";
        switch (position) {
            case 1:
                url = LIULISHUO_APK_URL;
tag = new ViewHolder(new WeakReference<>(this), pBar, tvDownLoadDetail, tvDownLoadSpeed, position);
path = downLoadFilePath;
tag.setFilenameTv(tvDownLoadFileName);
                break;
            default:
                tag = null;
url = "";
                break;
}

        //建立單任務下載
BaseDownloadTask baseDownloadTask = FileDownloader.getImpl().create(url)
                .setPath(path, isDir)
                .setCallbackProgressTimes(300)
                .setMinIntervalUpdateSpeed(400)
                .setTag(tag)
                .setListener(new FileDownloadSampleListener() {

                    @Override
protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {
                        super.pending(task, soFarBytes, totalBytes);
((ViewHolder) task.getTag()).updatePending(task);
}

                    @Override
protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
                        super.progress(task, soFarBytes, totalBytes);
((ViewHolder) task.getTag()).updateProgress(soFarBytes, totalBytes,
task.getSpeed());
}

                    @Override
protected void error(BaseDownloadTask task, Throwable e) {
                        super.error(task, e);
((ViewHolder) task.getTag()).updateError(e, task.getSpeed());
}

                    @Override
protected void connected(BaseDownloadTask task, String etag, boolean isContinue, int soFarBytes, int totalBytes) {
                        super.connected(task, etag, isContinue, soFarBytes, totalBytes);
((ViewHolder) task.getTag()).updateConnected(etag, task.getFilename());
}

                    @Override
protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {
                        super.paused(task, soFarBytes, totalBytes);
((ViewHolder) task.getTag()).updatePaused(task.getSpeed());
}

                    @Override
protected void completed(BaseDownloadTask task) {
                        super.completed(task);
((ViewHolder) task.getTag()).updateCompleted(task);
}

                    @Override
protected void warn(BaseDownloadTask task) {
                        super.warn(task);
((ViewHolder) task.getTag()).updateWarn();
}
                });
        return baseDownloadTask;
}

    private class ViewHolder {
        private ProgressBar pb;
        private TextView detailTv;
        private TextView speedTv;
        private int position;
        private TextView filenameTv;
        private WeakReference<SecondDownLoadActivity> weakReferenceContext;
        public ViewHolder(WeakReference<SecondDownLoadActivity> weakReferenceContext,
                          final ProgressBar pb, final TextView detailTv, final TextView speedTv,
                          final int position) {
            this.weakReferenceContext = weakReferenceContext;
            this.pb = pb;
            this.detailTv = detailTv;
            this.position = position;
            this.speedTv = speedTv;
}

        //設定檔名
public void setFilenameTv(TextView filenameTv) {
            this.filenameTv = filenameTv;
}
        //更新下載速度
private void updateSpeed(int speed) {
            speedTv.setText(String.format("%dKB/s", speed));
}
        //更新進度條
public void updateProgress(final int sofar, final int total, final int speed) {
            if (total == -1) {
                // chunked transfer encoding data
pb.setIndeterminate(true);
} else {
                pb.setMax(total);
pb.setProgress(sofar);
}
            updateSpeed(speed);
            if (detailTv != null) {
                detailTv.setText(String.format("sofar: %dM  total: %dM", convertFileSize(sofar), convertFileSize(total)));
}
        }

        public int convertFileSize(int size) {
            size = size / 1024 / 1024;
            return size;
}

        //更新Pending時的UI(等待)
public void updatePending(BaseDownloadTask task) {
            if (filenameTv != null) {
                filenameTv.setText(task.getFilename());
}
        }
        //更新Pause時的UI(暫停)
public void updatePaused(final int speed) {
            //toast(String.format("paused %d", position));
updateSpeed(speed);
pb.setIndeterminate(false);
}
        //更新連線時的UI
public void updateConnected(String etag, String filename) {
            if (filenameTv != null) {
                filenameTv.setText(filename);
}
        }
        //更新出現警告時的UI
public void updateWarn() {
            //toast(String.format("warn %d", position));
pb.setIndeterminate(false);
}
        //更新出現錯誤時的UI
public void updateError(final Throwable ex, final int speed) {
            //toast(String.format("error %d %s", position, ex));
updateSpeed(speed);
pb.setIndeterminate(false);
ex.printStackTrace();
}
        //更新下載完成時的UI
public void updateCompleted(final BaseDownloadTask task) {
            toast(String.format("下載完成!儲存路徑為:【%s", task.getTargetFilePath()));
            if (detailTv != null) {
                detailTv.setText(String.format("sofar: %dM  total: %dM",
convertFileSize(task.getSmallFileSoFarBytes()), convertFileSize(task.getSmallFileTotalBytes())));
}
            updateSpeed(task.getSpeed());
pb.setIndeterminate(false);
pb.setMax(task.getSmallFileTotalBytes());
pb.setProgress(task.getSmallFileSoFarBytes());
}


    }

    public void toast(final String msg) {
        Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
}

    // 正則檢測url包含指定格式並獲取檔名(不帶檔案格式字尾)
public static String regGetFileNameWithoutFileFormat(String fileName, String fileFormat) {
        Pattern pat = Pattern.compile("(.android/)(.+?)(\\.)(" + fileFormat + ")");
Matcher m = pat.matcher(fileName);
        if(m.find()){
            return m.group(2);
}
        return null;
}

    // 7.0動態申請許可權
public void showConfirmAppPermissions() {
        if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
                PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            } else {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
        }
    }
}
至此,單任務下載完成,這個很簡單,記錄一下。主要是多工下載這塊,繼續研究一下。