Android 文件下载

来源:互联网 发布:战网无法连接网络 编辑:程序博客网 时间:2024/06/14 05:01

1、开启一个服务Service实现后台下载

2、通过线程池管理器实现并行下载数量控制

3、利用广播机制更新UI

4、利用网络请求库Ohttp3进行下载


创建一个下载任务类

/** * Created by familylove on 2017/4/24. * 下载文件任务类 */public class DownloadFileTask implements Callable<String> {    private File mDownloadFile;    private String mFileSize;    private String mFilePath;    private String mFileName;    private String mDownloadUrl;    private boolean mPause = false;    private DownloadListener mDownloadListener;    public DownloadFileTask(String fileName, String downloadUrl, String filePath, DownloadListener downloadListener) {        this.mFilePath = filePath;        this.mFileName = fileName;        this.mDownloadUrl = downloadUrl;        this.mDownloadListener = downloadListener;    }    @Override    public String call() throws Exception {        if (TextUtils.isEmpty(mFilePath) || TextUtils.isEmpty(mFileName))            return "path or name is empty";        char tempEnd = mFilePath.charAt(mFilePath.length() - 1);        if (tempEnd == '/') {            mDownloadFile = new File(mFilePath + mFileName + ".temp");        } else {            mDownloadFile = new File(mFilePath + File.separator + mFileName + ".temp");        }        if (mDownloadFile.exists()) {            long size = mDownloadFile.length();            mFileSize = "bytes=" + size + "-";        }        //设置输出流.        OutputStream outPutStream = null;        InputStream inputStream = null;        try {            OkHttpClient okHttpClient = new OkHttpClient.Builder().build();            Request request = null;            if (!TextUtils.isEmpty(mFileSize)) {                request = new Request.Builder().header("Range", mFileSize).url(mDownloadUrl).build();            } else {                request = new Request.Builder().url(mDownloadUrl).build();            }            Call call = okHttpClient.newCall(request);            //检测是否支持断点续传            Response response = call.execute();            ResponseBody responseBody = response.body();            String responeRange = response.headers().get("Content-Range");            if (responeRange == null || !responeRange.contains(Long.toString(mDownloadFile.length()))) {                //最后的标记为 true 表示下载的数据可以从上一次的位置写入,否则会清空文件数据.                outPutStream = new FileOutputStream(mDownloadFile, false);            } else {                outPutStream = new FileOutputStream(mDownloadFile, true);            }            inputStream = responseBody.byteStream();            //如果有下载过的历史文件,则把下载总大小设为 总数据大小+文件大小 . 否则就是总数据大小            if (TextUtils.isEmpty(mFileSize)) {                if (mDownloadListener != null)                    mDownloadListener.downloadTotalSize(mDownloadUrl, responseBody.contentLength());            } else {                if (mDownloadListener != null)                    mDownloadListener.downloadTotalSize(mDownloadUrl, responseBody.contentLength() + mDownloadFile.length());            }            int length;            //设置缓存大小            byte[] buffer = new byte[1024];            //开始写入文件            while ((length = inputStream.read(buffer)) != -1) {                if (!mPause) {                    outPutStream.write(buffer, 0, length);                    if (mDownloadListener != null)                        mDownloadListener.onDownloadSize(mDownloadUrl, mDownloadFile.length());                } else {                    return null;                }            }        } catch (Exception e) {            if (mDownloadListener!=null)                mDownloadListener.downloadFail(mDownloadUrl);            return null ;        } finally {            if (outPutStream != null) {//清空缓冲区                outPutStream.flush();                outPutStream.close();            }            if (inputStream != null)                inputStream.close();        }        //下载后重命名        mDownloadFile.renameTo(new File(mFilePath+File.separator+mFileName));        //下载完成        if (mDownloadListener != null)            mDownloadListener.onComplete(mDownloadUrl);        return null;    }    //停止下载    public void setPause(boolean pause) {        this.mPause = pause;    }    public interface DownloadListener {        public void downloadTotalSize(String tag, long totalSize);        public void onDownloadSize(String tag, long downloadFileSize);        public void onComplete(String tag);        public void downloadFail(String tag) ;    }}


创建一个服务 DownloadFileService

public class DownloadFileService extends Service {    private static final int MAX_DOWNLOAD_TASK = 2; //最大的下载任务    private LocalBroadcastManager mLocalBroadcastManager;    private OCThreadExecutor mOcThreadExecutor;    private Map<String, DownloadBean> mAllDownloadTask;  //任务管理列表    private int mRunningThread = 0;    private Map<String, DownloadFileTask> mDownloadFileTasks;    // 文件下载状态    public static final int DOWNLOAD_WRITING = 5;  //下载等待    public static final int DOWNLOAD_LOADING = 1;  // 正在下载    public static final int DOWNLOAD_PAUSE = 2;    // 下载暂停    public static final int DOWNLOAD_FAIL = 3;      // 下载失败    public static final int DOWNLOAD_SUCCESS = 4; // 下载成功    //更新所有的    public static final String DOWNLOAD_UPLOAD_ALL = "com.wb.download.update.all";    //更新一个    public static final String DOWNLOAD_UPLOAD_SINGLE = "com.wb.download.update.single";    //添加任务    public static final String DOWNLOAD_NEW_TASK = "com.wb.download.new.task";    public static final String DOWNLOAD_NAME = "download_name";    public static final String DOWNLOAD_PATH = "download_path";    public static final String DOWNLOAD_URL = "download_url";    public DownloadFileService() {    }    @Override    public void onCreate() {        super.onCreate();        if (mAllDownloadTask == null)            mAllDownloadTask = new HashMap<>();        if (mDownloadFileTasks == null)            mDownloadFileTasks = new HashMap<>();        if (mLocalBroadcastManager == null)            mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);        if (mOcThreadExecutor == null)            mOcThreadExecutor = new OCThreadExecutor(MAX_DOWNLOAD_TASK, "file_download_pool");    }    @Override    public IBinder onBind(Intent intent) {        return new DownLoadBind();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        String downloadName = "";        String downloadFilePath = "";        String downloadUrl = "";        if (intent == null || intent.getAction() == null)            return super.onStartCommand(intent, flags, startId);        String action = intent.getAction();        if (TextUtils.isEmpty(action)) {            return super.onStartCommand(intent, flags, startId);        }        if (action.equals(DOWNLOAD_NEW_TASK)) {            Bundle bundle = intent.getExtras();            if (bundle == null) {                return super.onStartCommand(intent, flags, startId);            }            downloadName = bundle.getString(DOWNLOAD_NAME);            downloadUrl = bundle.getString(DOWNLOAD_URL);            downloadFilePath = bundle.getString(DOWNLOAD_PATH);            checkTask(downloadName, downloadUrl, downloadFilePath);        }        return super.onStartCommand(intent, flags, startId);    }    /**     * 开始下一个下载任务     * 这个下载任务处于等待状态     *     * @param downloadBean     */    private void startNextTask(DownloadBean downloadBean) {        if (downloadBean == null)            return;        File downloadFile = new File(downloadBean.getPath() + File.separator + downloadBean.getName());        if (!downloadFile.exists()) {            switch (downloadBean.getStatus()) {                case DOWNLOAD_WRITING:                    startDownloadTask(downloadBean);                    break;            }        }    }    //检查预加载下载任务    private void checkTask(String downloadName, String downloadUrl, String downloadFilePath) {        if (TextUtils.isEmpty(downloadFilePath) || TextUtils.isEmpty(downloadName) || TextUtils.isEmpty(downloadUrl)) {            return;        }        if (downloadFilePath.charAt(downloadFilePath.length() - 1) == '/') {            downloadFilePath = downloadFilePath.substring(0, downloadFilePath.length() - 1);        }        File teFile = new File(downloadFilePath);        if (!teFile.exists()) {            boolean flag1 = teFile.mkdir();            if (!flag1) {                teFile.mkdirs();            }        }        DownloadBean downloadBean = null;        File downloadFile = new File(downloadFilePath + File.separator + downloadName);        if (downloadFile.exists()) {  // 已经下载了        } else {            if (mAllDownloadTask.containsKey(downloadUrl)) {                downloadBean = mAllDownloadTask.get(downloadUrl);                switch (downloadBean.getStatus()) {                    case DOWNLOAD_FAIL:                    case DOWNLOAD_PAUSE:                        downloadBean.setStatus(DOWNLOAD_WRITING);                        startDownloadTask(downloadBean);                        break;                }            } else {                downloadBean = new DownloadBean(downloadName, downloadFilePath, downloadUrl);                downloadBean.setStatus(DOWNLOAD_WRITING);                mAllDownloadTask.put(downloadUrl, downloadBean);                //开始下载                startDownloadTask(downloadBean);            }        }    }    /**     * 开始下载     *     * @param downloadBean     */    public void startDownloadTask(DownloadBean downloadBean) {        if (downloadBean == null)            return;        if (mRunningThread < MAX_DOWNLOAD_TASK) {            mRunningThread++;            DownloadFileTask downloadFileTask = new DownloadFileTask(downloadBean.getName(), downloadBean.getUrl(), downloadBean.getPath(), mDownloadListener);            mDownloadFileTasks.put(downloadBean.getUrl(), downloadFileTask);            downloadBean.setStatus(DOWNLOAD_LOADING);            mAllDownloadTask.put(downloadBean.getUrl(), downloadBean);            mOcThreadExecutor.submit(downloadFileTask,downloadBean.getUrl());        }        if (downloadBean.getStatus() == DOWNLOAD_PAUSE || downloadBean.getStatus() == DOWNLOAD_FAIL) {            downloadBean.setStatus(DOWNLOAD_WRITING);            mAllDownloadTask.put(downloadBean.getUrl(), downloadBean);        }        updateDownloadList();    }    //停止下载任务    public void stopDownloadTask(DownloadBean downloadBean) {        if (downloadBean == null)            return;        if (downloadBean.getStatus() == DOWNLOAD_LOADING) {            mRunningThread = mRunningThread - 1;            mDownloadFileTasks.get(downloadBean.getUrl()).setPause(true);            downloadBean.setStatus(DOWNLOAD_PAUSE);            mAllDownloadTask.put(downloadBean.getUrl(), downloadBean);            mOcThreadExecutor.removeTag(downloadBean.getUrl()) ;            mDownloadFileTasks.remove(downloadBean.getUrl()) ;        }        updateDownloadList();    }    public List<DownloadBean> getDownloadBeanList() {        if (mAllDownloadTask != null)            return new ArrayList<>(mAllDownloadTask.values());        else            return null;    }    // 更新列表    private void updateDownloadList() {        if (mLocalBroadcastManager != null) {            mLocalBroadcastManager.sendBroadcast(new Intent(DOWNLOAD_UPLOAD_ALL));            return;        }    }    //更新一个    private void updateItem(DownloadBean downloadBean) {        if (downloadBean != null && downloadBean.getTotalSize() > 0) {            if (mLocalBroadcastManager == null)                return;            int progressBarLength = (int) (((float) downloadBean.getDownloadSize() / downloadBean.getTotalSize()) * 100);            Intent intent = new Intent(DOWNLOAD_UPLOAD_SINGLE);            intent.putExtra("progressBarLength", progressBarLength);            intent.putExtra("downloadedSize", String.format("%.2f", downloadBean.getDownloadSize() / (1024.0 * 1024.0)));            intent.putExtra("totalSize", String.format("%.2f", downloadBean.getTotalSize() / (1024.0 * 1024.0)));            intent.putExtra("item", downloadBean);            mLocalBroadcastManager.sendBroadcast(intent);        }    }    public void downloadComplete(DownloadBean downloadBean) {        if (mLocalBroadcastManager != null) {            mLocalBroadcastManager.sendBroadcast(new Intent(DOWNLOAD_UPLOAD_ALL));            return;        }    }    private DownloadBean startNextDownloadBean() {        if (mAllDownloadTask != null) {            for (DownloadBean bean : mAllDownloadTask.values()) {                if (bean.getStatus() == DOWNLOAD_WRITING) {                    return bean;                }            }        }        return null;    }    //下载监听    private DownloadFileTask.DownloadListener mDownloadListener = new DownloadFileTask.DownloadListener() {        @Override        public void downloadTotalSize(String tag, long totalSize) {            mAllDownloadTask.get(tag).setTotalSize(totalSize);        }        @Override        public void onDownloadSize(String tag, long downloadFileSize) {            mAllDownloadTask.get(tag).setDownloadSize(downloadFileSize);            updateItem(mAllDownloadTask.get(tag));        }        @Override        public void onComplete(String tag) {            mRunningThread = mRunningThread - 1;            mDownloadFileTasks.remove(tag);            mOcThreadExecutor.removeTag(tag);            mAllDownloadTask.get(tag).setStatus(DOWNLOAD_SUCCESS);            if (mAllDownloadTask != null) {                startNextTask(startNextDownloadBean());            }            downloadComplete(mAllDownloadTask.get(tag));        }        @Override        public void downloadFail(String tag) {            mRunningThread = mRunningThread - 1;            mDownloadFileTasks.remove(tag);            mOcThreadExecutor.removeTag(tag);            mAllDownloadTask.get(tag).setStatus(DOWNLOAD_FAIL);            updateDownloadList();        }    };    public class DownLoadBind extends Binder {        public DownloadFileService getDownloadFileService() {            return DownloadFileService.this;        }    }}


在UI界面中通过 BroadcastReceiver    mUpdateBroadcastReceiver 刷新界面 

 

public class DownloadFileActivity extends AppCompatActivity {    private RecyclerView mRecycleViewDownload;    private OCDownloadAdapter mOcDownloadAdapter ;    private LocalBroadcastManager mLocalBroadcastManager ;    private ServiceConnection mServiceConnection ;    private DownloadFileService mDownloadFileService ;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_download);        mRecycleViewDownload = (RecyclerView) findViewById(R.id.recyclerDownload);        LinearLayoutManager layoutManager = new LinearLayoutManager(DownloadFileActivity.this) ;        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);        mRecycleViewDownload.setLayoutManager(layoutManager);        mOcDownloadAdapter = new OCDownloadAdapter(DownloadFileActivity.this) ;        mOcDownloadAdapter.setOnRecyclerViewClick(mOnRecyclerViewClick);        mRecycleViewDownload.setAdapter(mOcDownloadAdapter);        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this) ;        IntentFilter intentFilter = new IntentFilter() ;        intentFilter.addAction(DownloadFileService.DOWNLOAD_UPLOAD_ALL);        intentFilter.addAction(DownloadFileService.DOWNLOAD_UPLOAD_SINGLE);        mLocalBroadcastManager.registerReceiver(mUpdateBroadcastReceiver,intentFilter);        mServiceConnection = new ServiceConnection() {            @Override            public void onServiceConnected(ComponentName name, IBinder service) {                mDownloadFileService =  ((DownloadFileService.DownLoadBind)service).getDownloadFileService() ;                mOcDownloadAdapter.updateAllItem(mDownloadFileService.getDownloadBeanList());            }            @Override            public void onServiceDisconnected(ComponentName name) {                if (mLocalBroadcastManager!=null){                    mLocalBroadcastManager.unregisterReceiver(mUpdateBroadcastReceiver);                    return;                }            }        } ;        startService(new Intent(DownloadFileActivity.this,DownloadFileService.class)) ;        bindService(new Intent(DownloadFileActivity.this,DownloadFileService.class),mServiceConnection,BIND_AUTO_CREATE) ;        if (mDownloadFileService!=null){            mOcDownloadAdapter.updateAllItem(mDownloadFileService.getDownloadBeanList());        }    }    @Override    protected void onDestroy() {        super.onDestroy();        if (mLocalBroadcastManager!=null)            mLocalBroadcastManager.unregisterReceiver(mUpdateBroadcastReceiver);        unbindService(mServiceConnection);    }    private OnRecyclerViewClick<DownloadBean> mOnRecyclerViewClick = new OnRecyclerViewClick<DownloadBean>() {        @Override        public void onClick(DownloadBean object) {            if (object==null)                return;            if (object.getStatus() == DownloadFileService.DOWNLOAD_LOADING){                mDownloadFileService.stopDownloadTask(object);            }else {                mDownloadFileService.startDownloadTask(object);            }        }        @Override        public boolean onLongClick(DownloadBean object) {            return false;        }    } ;    private BroadcastReceiver mUpdateBroadcastReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            switch (intent.getAction()){                case DownloadFileService.DOWNLOAD_UPLOAD_ALL:                    mOcDownloadAdapter.updateAllItem(mDownloadFileService.getDownloadBeanList());                    break;                case DownloadFileService.DOWNLOAD_UPLOAD_SINGLE:                    DownloadBean bean = (DownloadBean) intent.getExtras().getSerializable("item") ;                    String downloadedSize = intent.getExtras().getString("downloadedSize");                    String totalSize = intent.getExtras().getString("totalSize");                    int progressLength = intent.getExtras().getInt("progressBarLength");                    if (bean!=null){                        if (mOcDownloadAdapter.getItemPosition(bean)>=0){                            View itemView = mRecycleViewDownload.getChildAt(mOcDownloadAdapter.getItemPosition(bean));                            if (itemView==null){                                Log.e("leBrace","itemView is empty") ;                            }else {                                TextView tvPress = (TextView)itemView.findViewById(R.id.tvProgress) ;                                ProgressBar progressBar = (ProgressBar)itemView.findViewById(R.id.progressBar) ;                                progressBar.setProgress(progressLength);                                //更新文字进度                                tvPress.setText(downloadedSize+"MB / "+totalSize+"MB");                                TextView tvDownloadFlag = (TextView)itemView.findViewById(R.id.tvDownloadFlag) ;                                switch (bean.getStatus()){                                    case DownloadFileService.DOWNLOAD_LOADING:                                        tvDownloadFlag.setText("下载中");                                        break;                                    case DownloadFileService.DOWNLOAD_FAIL:                                        tvDownloadFlag.setText("下载失败");                                        break;                                    case DownloadFileService.DOWNLOAD_SUCCESS:                                        tvDownloadFlag.setText("下载成功");                                        break;                                    case DownloadFileService.DOWNLOAD_WRITING:                                        tvDownloadFlag.setText("下载等待") ;                                        break;                                }                            }                        }else {                            //Toast.makeText(context,"",Toast.LENGTH_SHORT).show();                        }                    }                    break;            }        }    } ;}

 线程池管理类


/** * Created by familylove on 2017/4/20. * 线程池管理 */public class OCThreadExecutor extends  ThreadPoolExecutor{    private static LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(10) ;    private Map<String,Callable> mMapRunnable ;    public OCThreadExecutor(int maxDownloadSize,String poolName) {        super(maxDownloadSize, maxDownloadSize, 0L, TimeUnit.SECONDS, workQueue, new OCThreadFactory(poolName));        mMapRunnable = new HashMap<>() ;    }    //执行    public void submit(Callable callable , String taskTag){        synchronized (this){            if (TextUtils.isEmpty(taskTag))                return;            if (!mMapRunnable.containsKey(taskTag)){                mMapRunnable.put(taskTag,callable) ;                submit(callable) ;            }        }    }    //移除队列    public boolean removeTag(String taskTag){        boolean flag = false ;        if (TextUtils.isEmpty(taskTag))            return  flag;        if (mMapRunnable.containsKey(taskTag)){            if (mMapRunnable.remove(taskTag)!=null){                flag =  true ;            }else {                flag =  false ;            }        }        return flag ;    }    static class OCThreadFactory implements ThreadFactory{        private final String name ;        public OCThreadFactory(String name) {            this.name = name ;        }        public String getPoolName(){            return this.name ;        }        @Override        public Thread newThread(@NonNull Runnable r) {            return new OCThread(r,name);        }    }    static class OCThread extends Thread{        public OCThread(Runnable runnable,String name){            super(runnable,name);            setName(name);        }        @Override        public void run() {            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);            super.run();        }    }}

效果图如下







 




0 0
原创粉丝点击