Android开发中使用FileDownloader来实现文件下载功能(总结一)

今天研究了一下Android开发中文件下载功能,记录一下。

这篇博客主要介绍第三方下载插件:FileDownloader的单任务的使用方法,至于多任务的后面会做补充记录,再写一篇博文。

效果图如下:(虚拟机连不上网)

Android开发中使用FileDownloader来实现文件下载功能(总结一)_第1张图片

1、首先是引用方法:

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

2、布局文件activity_test.xml如下:

xml version="1.0" encoding="utf-8"?>
    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">

            android:layout_width="match_parent"
        android:layout_height="wrap_content">

                    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"/>

                    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"/>

                    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"/>

    

            android:layout_marginTop="10dp"
        android:id="@+id/SecondDownLoad_lLayoutDownLoad"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

                    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"/>

        

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 weakReferenceContext;
        public ViewHolder(WeakReference 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);
            }
        }
    }
}
至此,单任务下载完成,这个很简单,记录一下。主要是多任务下载这块,继续研究一下。

你可能感兴趣的:(Android网络编程)