Android平台HTTP断点续传的实现
来源:互联网 发布:墨脱公路沥青路面数据 编辑:程序博客网 时间:2024/05/22 10:11
HTTP对断点续传提供了良好的支持,具体来说,要实现单线程断点续传,需要考虑以下问题:
(1)我们需要如何去下载文件,因为很多时候因为网络差、程序被kill掉等原因,文件无法一次下载完,我们需要继续发起下载文件的HTTP请求,这个时候不需要从头开始下,只需要告诉服务器,我们要从哪里开始下,哪里结束,可以通过设置“Range”字段的属性来实现。例如:
httpUrl.setRequestProperty("Range", "bytes=" + mCurrentDownloadLength + "-" + mFileTotalSize);
(2)需要保存文件的下载进度,这个我最开始尝试着使用SharedPreferences保存进度,经过测试后发现使用该方法保存的进度不一定准确,可能的原因是在保持的时候程序中断了,比较可靠的方式是获取文件的大小,用.length()方法。
(3)如何从指定的位置开始写文件,使用RandomAccessFile即可。
(4)由于在弱网环境下,下载的文件可能会出错,所以对下载的文件需要进行MD5值校验。
(5)此外,我们下载时,也需要知道文件的总大小,这样不用每次启动下载时,都进行MD5值校验是否下载完成,这个可以通过HTTP的请求实现。
具体的实现代码不复杂,部分代码如下所示:
public class DownloadTask extends Thread { private URL mDownloadUrl; private Activity mActivity; private String mZipFilePathStr; // 保存用户设置的so目录 public static String mUserBaiduNaviSDK_SO = null; // 需要下载的文件的总大小 private int mFileTotalSize; private int mCurrentDownloadLength = 0; private DownloadCallBack mCallback; // 每次读取的文件大小 private int mBlockSize = 4 * 1024; private SharedPreferences mSharedPref; private int timeout = 50 * 1000; // 连接超时时间 public DownloadTask(Activity activity, String sdcardRootPath, String appFolderName) { this.mActivity = activity; } public DownloadTask(Activity activity, String sdcardRootPath, String appFolderName, URL downloadUrl, DownloadCallBack callback) { this.mActivity = activity; this.mDownloadUrl = downloadUrl; this.mCallback = callback; } @Override public void run() { mSharedPref = mActivity.getPreferences(Context.MODE_PRIVATE); // String str = sdcardRootPath + File.separator + appFolderName + File.separator + "1.txt"; init(); if (mCurrentDownloadLength < mFileTotalSize) { try { HttpURLConnection httpUrl = (HttpURLConnection) mDownloadUrl.openConnection(); if (httpUrl == null) { return ; } setRequest(httpUrl); downloadFile(httpUrl); mCallback.downloadWorkOver(); } catch (Exception e) { return ; } } } private void init() { mFileTotalSize = getTotalFileSize(); mCurrentDownloadLength = getCurrentDownloadLength(); } /* * */ private int getCurrentDownloadLength() { File file = new File(ZipUtils.getTmpZipFile()); mCurrentDownloadLength = file.length(); LogUtil.e("dingbbin", "dingbbin getCurrentDownloadLength is " + mCurrentDownloadLength); return mCurrentDownloadLength; } /* * 获取需要更新的文件的大小 */ private int getTotalFileSize() { // return 8038626; HttpURLConnection urlConnection = null; int length = 0; try { urlConnection = (HttpURLConnection) mDownloadUrl.openConnection(); urlConnection.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg," + " application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument," + " application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel," + " application/vnd.ms-powerpoint, application/msword, */*"); urlConnection.setRequestProperty("Referer", mDownloadUrl.toString()); urlConnection.setRequestProperty("Connection", "Keep-Alive"); urlConnection.setRequestProperty("Accept-Encoding", "identity"); int status = urlConnection.getResponseCode(); if (status == 200) { length = urlConnection.getContentLength(); } } catch (IOException e) { e.printStackTrace(); } finally { if (urlConnection != null) { urlConnection.disconnect(); } } return length; } private void setRequest(HttpURLConnection httpUrl) throws ProtocolException { httpUrl.setConnectTimeout(timeout); httpUrl.setRequestMethod("GET"); // 设置请求方法 httpUrl.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg," + " application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument," + " application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel," + " application/vnd.ms-powerpoint, application/msword, */*"); httpUrl.setRequestProperty("Referer", mDownloadUrl.toString()); httpUrl.setRequestProperty("Charset", "UTF-8"); httpUrl.setRequestProperty("Accept-Encoding", "identity"); // 设置开始和结束范围 // int endPos = fileTotalSize; httpUrl.setRequestProperty("Range", "bytes=" + mCurrentDownloadLength + "-" + mFileTotalSize); httpUrl.setRequestProperty("Connection", "Keep-Alive"); } private void downloadFile(HttpURLConnection httpUrl) { InputStream inStream = null; RandomAccessFile accessFile = null; try { inStream = httpUrl.getInputStream(); byte[] buffer = new byte[mBlockSize]; int offset = 0; accessFile = new RandomAccessFile(ZipUtils.getTmpZipFile(), "rwd"); // 定位到pos位置 accessFile.seek(mCurrentDownloadLength); while ((offset = inStream.read(buffer, 0, mBlockSize)) != -1) { accessFile.write(buffer, 0, offset); // 更新已经下载的大小 mCurrentDownloadLength += offset; LogUtil.e("dingbbin", "dingbbin current length is " + mCurrentDownloadLength); } if (mCurrentDownloadLength >= mFileTotalSize) { // download finish, rename file ZipUtils.getTmpZipFile().renameTo(ZipUtils.getZipFile()); resetLength(); } } catch (IOException e) { e.printStackTrace(); } finally { if (null != inStream) { try { inStream.close(); } catch (IOException e) { LogUtil.e("", e.toString()); } } if (null != accessFile) { try { accessFile.close(); } catch (IOException e) { LogUtil.e("", e.toString()); } } if (httpUrl != null) { httpUrl.disconnect(); } } } private void resetLength() { Editor editor = mSharedPref.edit(); editor.putInt(DynamicLoadConstants.NAVI_DOWNLOAD_LENGTH, 0); editor.commit(); } private void unzipFile() { try { ZipUtils.decompress(ZipUtils.getZipFile(), new File(ZipUtils.getDownloadSoDir())); } catch (Exception e) { e.printStackTrace(); } // 删除下载的文件 ZipUtils.getZipFile().delete(); } public interface DownloadCallBack { public void downloadWorkOver(); }}需要注意的地方有2个,就是我们在获取文件总大小和下载文件时,发下Java和Android的实现不太一样,具体来说,同样的代码,同样的API,在Java环境中可以正常获取大小,可以实现断点续传,但是在Android上就不行,需要设置urlConnection.setRequestProperty("Accept-Encoding", "identity")才可以,具体的原因我也是不甚明白。
0 0
- Android平台HTTP断点续传的实现
- 在Android平台下通过HTTP协议实现断点续传下载。
- Android平台下通过HTTP协议实现断点续传下载
- Java实现HTTP的断点续传
- HTTP实现断点续传的方式
- android--http协议多线程断点续传下载的实现
- android--http协议多线程断点续传下载的实现
- Android断点续传的实现
- Android通过HTTP协议实现断点续传下载
- Android通过HTTP协议实现断点续传下载
- Android通过HTTP协议实现断点续传下
- Android通过HTTP协议实现断点续传下载
- JAVA如何实现HTTP的断点续传
- JAVA如何实现HTTP的断点续传
- JAVA如何实现HTTP的断点续传
- PHP实现HTTP断点续传下载的方法
- PHP实现HTTP断点续传的方法
- 实现HTTP断点续传
- Java中为什么finally语句块一定会被执行?
- hdoj 2111 Saving HDU 【贪心】
- 解决U盘1KB快捷方式病毒(暴风一号)方法
- servlet路径问题
- Unity优化大全(十)之 Memory - Mono的托管内存
- Android平台HTTP断点续传的实现
- c++字符串学习
- php去除字符串中指定字符
- PHP:const和define的区别
- 留念
- HTML5 Canvas烟花特效 场景十分华丽
- Android toolbar阴影悬浮高亮效果
- 线段树求解区间最大最小值(模板)
- 浏览器识别(包括呈现引擎,浏览器版本,操作系统,移动设备)