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) ; }}
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
- Android 文件下载
- Android 文件下载
- android文件下载!download!
- android 文件下载
- android:文件下载
- Android 多线程文件下载
- android 文件的下载
- Android文件下载 HttpURLConnection
- 文件下载(java) android
- android 之文件下载
- android文件下载!download!
- Android文件下载
- Android之文件下载
- Android之文件下载
- android apk文件下载
- Android中的文件下载
- android 下载文件类
- Android开发 --- 文件下载
- CATideLayer使用
- 0423学习总结(各种指针)
- 不使用"+"," -"操作符完成加法运算
- VS2008开发FFmpeg应用
- python初级教程:入门详解
- Android 文件下载
- 《统计学习方法》学习笔记(6)-- 决策树-附代码(sklearn)
- 软件测试基础——fault、error and failure
- Android WebView加载https网页(亲测)
- Java setReuseAddress
- 开发Android 项目需用到的jar包,开源工具类,plugins等
- 0425
- 前端必学-----AJax--笔记---01
- Golang runtime 浅析