断点下载续传—支持断点续传 ,后台有服务来下载文件。
来源:互联网 发布:js赋值给input 编辑:程序博客网 时间:2024/06/05 20:40
分析思路:
开发下载文件的要求有两点:1.支持断点续传 2.后台有服务来下载文件。
1、复制xutils.jar到项目中 libs 点击下载
2、复制 核心类 到你的app文件下
DownloadInfo支持记录保存 。核心类下载
DownloadService有服务支持好处是所有activity关闭,下载不被中断。
DownloadManager作用。用来支持常见的下载操作。
配置服务。调用DownloadManager编写业务逻辑 下载 暂停 续传
核心类展示
DownloadInfo
public class DownloadInfo { public DownloadInfo() { } private long id; //一个应用只有一个appId 可以根据appId进行存储断点.方便下次查找断点 private String appId; public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } @Transient private HttpHandler<File> handler; private HttpHandler.State state; private String downloadUrl; private String fileName; private String fileSavePath; private long progress; private long fileLength; private boolean autoResume; private boolean autoRename; public long getId() { return id; } public void setId(long id) { this.id = id; } public HttpHandler<File> getHandler() { return handler; } public void setHandler(HttpHandler<File> handler) { this.handler = handler; } public HttpHandler.State getState() { return state; } public void setState(HttpHandler.State state) { this.state = state; } public String getDownloadUrl() { return downloadUrl; } public void setDownloadUrl(String downloadUrl) { this.downloadUrl = downloadUrl; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public String getFileSavePath() { return fileSavePath; } public void setFileSavePath(String fileSavePath) { this.fileSavePath = fileSavePath; } public long getProgress() { return progress; } public void setProgress(long progress) { this.progress = progress; } public long getFileLength() { return fileLength; } public void setFileLength(long fileLength) { this.fileLength = fileLength; } public boolean isAutoResume() { return autoResume; } public void setAutoResume(boolean autoResume) { this.autoResume = autoResume; } public boolean isAutoRename() { return autoRename; } public void setAutoRename(boolean autoRename) { this.autoRename = autoRename; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof DownloadInfo)) return false; DownloadInfo that = (DownloadInfo) o; if (id != that.id) return false; return true; } @Override public int hashCode() { return (int) (id ^ (id >>> 32)); }}
DownloadService
public class DownloadService extends Service { private static DownloadManager DOWNLOAD_MANAGER; public static DownloadManager getDownloadManager(Context appContext) { if (!DownloadService.isServiceRunning(appContext)) { Intent downloadSvr = new Intent(appContext,DownloadService.class); appContext.startService(downloadSvr); } if (DownloadService.DOWNLOAD_MANAGER == null) { DownloadService.DOWNLOAD_MANAGER = new DownloadManager(appContext); } return DOWNLOAD_MANAGER; } public DownloadService() { super(); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); } @Override public void onDestroy() { if (DOWNLOAD_MANAGER != null) { try { DOWNLOAD_MANAGER.stopAllDownload(); DOWNLOAD_MANAGER.backupDownloadInfoList(); } catch (DbException e) { LogUtils.e(e.getMessage(), e); } } super.onDestroy(); } public static boolean isServiceRunning(Context context) { boolean isRunning = false; ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningServiceInfo> serviceList = activityManager.getRunningServices(Integer.MAX_VALUE); if (serviceList == null || serviceList.size() == 0) { return false; } for (int i = 0; i < serviceList.size(); i++) { if (serviceList.get(i).service.getClassName().equals(DownloadService.class.getName())) { isRunning = true; break; } } return isRunning; }}
DownloadManager
public class DownloadManager { private List<DownloadInfo> downloadInfoList; private int maxDownloadThread = 3; private Context mContext; private DbUtils db; /* package */ DownloadManager(Context appContext) { ColumnConverterFactory.registerColumnConverter(HttpHandler.State.class, new HttpHandlerStateConverter()); mContext = appContext; db = DbUtils.create(mContext);// xUtils.db try { downloadInfoList = db.findAll(Selector.from(DownloadInfo.class)); } catch (DbException e) { LogUtils.e(e.getMessage(), e); } if (downloadInfoList == null) { downloadInfoList = new ArrayList<DownloadInfo>(); } } public int getDownloadInfoListCount() { return downloadInfoList.size(); } public DownloadInfo getDownloadInfo(int index) { return downloadInfoList.get(index); } /*** * 方法 按照应用appId查找断点记录 * * @param appId * @return */ public DownloadInfo getDownloadInfoByAppId(String appId) { for (DownloadInfo item : downloadInfoList) { if (TextUtils.equals(item.getAppId(), appId)) { return item;// 返回指定appId的断点记录 } } return null; } public void addNewDownload(String appId, String url, String fileName, String target, boolean autoResume, boolean autoRename, final RequestCallBack<File> callback) throws DbException { final DownloadInfo downloadInfo = new DownloadInfo(); downloadInfo.setAppId(appId); downloadInfo.setDownloadUrl(url); downloadInfo.setAutoRename(autoRename); downloadInfo.setAutoResume(autoResume); downloadInfo.setFileName(fileName); downloadInfo.setFileSavePath(target); HttpUtils http = new HttpUtils(); http.configRequestThreadPoolSize(maxDownloadThread); HttpHandler<File> handler = http.download(url, target, autoResume, autoRename, new ManagerCallBack(downloadInfo, callback)); downloadInfo.setHandler(handler); downloadInfo.setState(handler.getState()); downloadInfoList.add(downloadInfo); db.saveBindingId(downloadInfo); } public void resumeDownload(int index, final RequestCallBack<File> callback) throws DbException { final DownloadInfo downloadInfo = downloadInfoList.get(index); resumeDownload(downloadInfo, callback); } public void resumeDownload(DownloadInfo downloadInfo, final RequestCallBack<File> callback) throws DbException { HttpUtils http = new HttpUtils(); http.configRequestThreadPoolSize(maxDownloadThread); HttpHandler<File> handler = http.download(downloadInfo.getDownloadUrl(), downloadInfo.getFileSavePath(), downloadInfo.isAutoResume(), downloadInfo.isAutoRename(), new ManagerCallBack(downloadInfo, callback)); downloadInfo.setHandler(handler); downloadInfo.setState(handler.getState()); db.saveOrUpdate(downloadInfo); } public void removeDownload(int index) throws DbException { DownloadInfo downloadInfo = downloadInfoList.get(index); removeDownload(downloadInfo); } public void removeDownload(DownloadInfo downloadInfo) throws DbException { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null && !handler.isCancelled()) { handler.cancel(); } // 从下载的断点记录集合中移除断点记录(内存) downloadInfoList.remove(downloadInfo); // 从数据库删除。 db.delete(downloadInfo); // 下载一半的文件?100M 55M String fileSavePath = downloadInfo.getFileSavePath(); // 如果存在下载一半的文件,由于下次找不到断点记录,没法续传,直接删除这个文件节省sd空间. File file = new File(fileSavePath); if (file.exists()) { file.delete(); } } public void stopDownload(int index) throws DbException { DownloadInfo downloadInfo = downloadInfoList.get(index); stopDownload(downloadInfo); } public void stopDownload(DownloadInfo downloadInfo) throws DbException { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null && !handler.isCancelled()) { handler.cancel(); } else { downloadInfo.setState(HttpHandler.State.CANCELLED); } db.saveOrUpdate(downloadInfo); } public void stopAllDownload() throws DbException { for (DownloadInfo downloadInfo : downloadInfoList) { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null && !handler.isCancelled()) { handler.cancel(); } else { downloadInfo.setState(HttpHandler.State.CANCELLED); } } db.saveOrUpdateAll(downloadInfoList); } public void backupDownloadInfoList() throws DbException { for (DownloadInfo downloadInfo : downloadInfoList) { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null) { downloadInfo.setState(handler.getState()); } } db.saveOrUpdateAll(downloadInfoList); } public int getMaxDownloadThread() { return maxDownloadThread; } public void setMaxDownloadThread(int maxDownloadThread) { this.maxDownloadThread = maxDownloadThread; } public class ManagerCallBack extends RequestCallBack<File> { private DownloadInfo downloadInfo; private RequestCallBack<File> baseCallBack; public RequestCallBack<File> getBaseCallBack() { return baseCallBack; } public void setBaseCallBack(RequestCallBack<File> baseCallBack) { this.baseCallBack = baseCallBack; } private ManagerCallBack(DownloadInfo downloadInfo, RequestCallBack<File> baseCallBack) { this.baseCallBack = baseCallBack; this.downloadInfo = downloadInfo; } @Override public Object getUserTag() { if (baseCallBack == null) return null; return baseCallBack.getUserTag(); } @Override public void setUserTag(Object userTag) { if (baseCallBack == null) return; baseCallBack.setUserTag(userTag); } @Override public void onStart() { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null) { downloadInfo.setState(handler.getState()); } try { db.saveOrUpdate(downloadInfo); } catch (DbException e) { LogUtils.e(e.getMessage(), e); } if (baseCallBack != null) { baseCallBack.onStart(); } } @Override public void onCancelled() { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null) { downloadInfo.setState(handler.getState()); } try { db.saveOrUpdate(downloadInfo); } catch (DbException e) { LogUtils.e(e.getMessage(), e); } if (baseCallBack != null) { baseCallBack.onCancelled(); } } @Override public void onLoading(long total, long current, boolean isUploading) { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null) { downloadInfo.setState(handler.getState()); } downloadInfo.setFileLength(total); downloadInfo.setProgress(current); try { db.saveOrUpdate(downloadInfo); } catch (DbException e) { LogUtils.e(e.getMessage(), e); } if (baseCallBack != null) { baseCallBack.onLoading(total, current, isUploading); } } @Override public void onSuccess(ResponseInfo<File> responseInfo) { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null) { downloadInfo.setState(handler.getState()); } try { db.saveOrUpdate(downloadInfo); } catch (DbException e) { LogUtils.e(e.getMessage(), e); } if (baseCallBack != null) { baseCallBack.onSuccess(responseInfo); } } @Override public void onFailure(HttpException error, String msg) { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null) { downloadInfo.setState(handler.getState()); } try { db.saveOrUpdate(downloadInfo); } catch (DbException e) { LogUtils.e(e.getMessage(), e); } if (baseCallBack != null) { baseCallBack.onFailure(error, msg); } } } private class HttpHandlerStateConverter implements ColumnConverter<HttpHandler.State> { @Override public HttpHandler.State getFieldValue(Cursor cursor, int index) { return HttpHandler.State.valueOf(cursor.getInt(index)); } @Override public HttpHandler.State getFieldValue(String fieldStringValue) { if (fieldStringValue == null) return null; return HttpHandler.State.valueOf(fieldStringValue); } @Override public Object fieldValue2ColumnValue(HttpHandler.State fieldValue) { return fieldValue.value(); } @Override public ColumnDbType getColumnDbType() { return ColumnDbType.INTEGER; } }}
代码使用实现:
//获取DownloadManager对象 DownloadManager mg = DownloadService.getDownloadManager(MyApp.getContext()); //按钮BtnDownload的点击事件 BtnDownload.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { //查询指定应用下载记录(断点 progress) DownloadInfo downloadInfo = mg.getDownloadInfoByAppId(data.id + ""); //判断是否有下载记录,有就是续传 没有就是开始下载 if (downloadInfo == null) { //参数1 appId应用编号 String appId = data.id + ""; //参数2 下载地址 String url = ApiUrls.DOWNLOAD + data.downloadUrl; //参数3 文件名 String fileName = data.name; //参数4 保存的绝对路径 String target = Environment.getExternalStorageDirectory().getAbsolutePath() + "/market/" + data.packageName + ".apk"; //参数5 是否支持断点 boolean autoResume = true; //参数6 是否重命名 boolean autoRename = false; //参数回调对象,处理界面更新业务逻辑 mg.addNewDownload(appId, url, fileName, target, autoResume, autoRename, callback); } else { //继续传输 //载按钮点击事件 //loading当前出入下载状态 if (downloadInfo.getState() == HttpHandler.State.LOADING) { mg.stopDownload(downloadInfo); part5BtnDownload.setText("继续"); } else { mg.resumeDownload(downloadInfo, callback); } } }catch(Exception e){e.printStackTrace();} } });
由于整个下载过程没有界面更新,用户不知道下载进度,所以编写进度更新的业务逻辑。编写在CallBack空方法里面
RequestCallBack<File> callback= new RequestCallBack<File>(){ //下载过程中进度变化 @Override public void onLoading(long total, long current, boolean isUploading) { super.onLoading(total, current, isUploading); //设置进度条的进度文本 //设置进度条最大值、设置当前进度 if(total==0){total=1;} int percent = (int) (current*100f/total+0.5f); BtnDownload.setText(percent+"%"); PbarProgress.setMax(100);//PbarProgress进度条 PbarProgress.setProgress(percent); } @Override public void onSuccess(ResponseInfo<File> responseInfo) { part5BtnDownload.setText("安装"); part5PbarProgress.setMax(100); part5PbarProgress.setProgress(100); //调用隐式意图安装 ApkUtil.install((Activity) context,responseInfo.result.getAbsolutePath()); } @Override public void onFailure(HttpException e, String s) { part5BtnDownload.setText("继续"); } };
/** *APK安装工具类 */public class ApkUtil { public static void install(Activity activity,String target){ //Intent :开启服务或者打开页面 Intent intent = new Intent(); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setAction("android.intent.action.VIEW"); intent.addCategory("android.intent.category.DEFAULT"); String type = "application/vnd.android.package-archive"; // http://www.itheima.com f /mnt/sdcard Uri data = Uri.parse("file:///" + target); intent.setDataAndType(data, type); activity.startActivity(intent); }}
进入页面需要进行回显(把断点记录下来,设置给界面)
private void resumeDownLoadInfo(String appId) { //5.1获取断点记录 DownloadInfo downloadInfo = mg.getDownloadInfoByAppId(appId); if (downloadInfo == null) { part5BtnDownload.setText("下载"); part5PbarProgress.setMax(100); part5PbarProgress.setProgress(0); } else { //5.2计算百分比 long total = downloadInfo.getFileLength(); if (total == 0) { total = 1; } int percent = (int) (downloadInfo.getProgress() * 100f / total + 0.5f); part5PbarProgress.setMax(100); part5PbarProgress.setProgress(percent); if (downloadInfo.getState() == HttpHandler.State.LOADING) { part5BtnDownload.setText(percent + "%"); } else { part5BtnDownload.setText("继续"); } } }
0 0
- 断点下载续传—支持断点续传 ,后台有服务来下载文件。
- 断点下载文件(断点续传)
- iphone断点下载,断点续传
- iphone断点下载,断点续传
- 断点下载/断点续传
- Swift 下载文件 支持断点下载
- Android下载服务类(支持断点续传、多线程下载)
- 利用Winsock下载文件(支持断点续传)
- 让自定义文件下载支持断点续传
- 利用Winsock下载文件(支持断点续传)
- 支持断点续传的PHP文件下载类
- php下载远程文件(支持断点续传)
- C#实现文件下载,支持断点续传
- C#实现文件下载,支持断点续传
- php 支持断点续传的文件下载类
- 单线程支持断点续传文件下载
- php 支持断点续传的文件下载类
- php 支持断点续传的文件下载类
- 按值传递的意义
- 更快实现Android多级树形选择列表
- 03 - 微信小程序实例开发 - 问答机器人
- 用两种方式实现单实例(Java版)
- HMM预测妹子心情
- 断点下载续传—支持断点续传 ,后台有服务来下载文件。
- Configure FTP with IIS Manager Authentication in IIS 7
- 04 - 微信小程序实例开发 - 笑话大全
- 树莓派3点亮一盏LED(Python)
- zoj2176
- 方法
- jquery事件绑定
- h5根据坐标解析地址信息
- 最常用的控件ListView简单使用