Android之断点续传下载

断点续传下载,顾名思义,那就是我们在一次下载未结束时,退出下载,第二次下载时会接着第一次下载的进度继续下载。那么怎么记录第一次下载的数据呢,这里肯定就要用到数据库了。下面就是我创建数据库的一个SQLiteOpenHelper类。用来首次运行时创建数据库。

DBHelper类:

 1 package cn.yj3g.DBHelper;
 2
 3 import android.content.Context;
 4 import android.database.sqlite.SQLiteDatabase;
 5 import android.database.sqlite.SQLiteOpenHelper;
 6
 7     /**
 8      * 建立一个数据库帮助类
 9      */
10 public class DBHelper extends SQLiteOpenHelper {
11     //download.db-->数据库名
12     public DBHelper(Context context) {
13         super(context, "download.db", null, 1);
14     }
15
16     /**
17      * 在download.db数据库下创建一个download_info表存储下载信息
18      */
19     @Override
20     public void onCreate(SQLiteDatabase db) {
21         db.execSQL("create table download_info(_id integer PRIMARY KEY AUTOINCREMENT, thread_id integer, "
22                 + "start_pos integer, end_pos integer, compelete_size integer,url char)");
23     }
24     @Override
25     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
26
27     }
28
29 }

下面来看主界面的布局,在这里,我只设计了一个ListView来显示下载的音乐的名称,和一个开始下载按钮和一个暂停按钮。

布局文件如下:

main.xml:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:orientation="vertical"
 4     android:layout_width="fill_parent"
 5     android:layout_height="fill_parent"
 6     android:id="@+id/llRoot">
 7     <ListView android:id="@android:id/list"
 8         android:layout_width="fill_parent"
 9         android:layout_height="fill_parent">
10     </ListView>
11 </LinearLayout>

list_item.xml:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3            android:orientation="vertical"
 4            android:layout_width="fill_parent"
 5            android:layout_height="wrap_content">
 6     <LinearLayout
 7            android:orientation="horizontal"
 8            android:layout_width="fill_parent"
 9            android:layout_height="wrap_content"
10            android:layout_marginBottom="5dip">
11         <TextView
12             android:layout_width="fill_parent"
13             android:layout_height="wrap_content"
14             android:layout_weight="1"
15             android:id="@+id/tv_resouce_name"/>
16         <Button
17             android:layout_width="fill_parent"
18             android:layout_height="wrap_content"
19             android:layout_weight="1"
20             android:text="下载"
21             android:id="@+id/btn_start"
22             android:onClick="startDownload"/>
23         <Button
24             android:layout_width="fill_parent"
25             android:layout_height="wrap_content"
26             android:layout_weight="1"
27             android:text="暂停"
28             android:id="@+id/btn_pause"
29             android:onClick="pauseDownload"/>
30       </LinearLayout>
31 </LinearLayout>

主界面运行效果如下:

下面我们来看具体实现下载的方法。首先,我们要定义一个记录在下载时各个时期的数据的类,这里我创建了一个DownloadInfo类来记录。代码如下:

DownloadInfo:

 1 package cn.yj3g.entity;
 2 /**
 3  *创建一个下载信息的实体类
 4  */
 5 public class DownloadInfo {
 6     private int threadId;//下载器id
 7     private int startPos;//开始点
 8     private int endPos;//结束点
 9     private int compeleteSize;//完成度
10     private String url;//下载器网络标识
11     public DownloadInfo(int threadId, int startPos, int endPos,
12             int compeleteSize,String url) {
13         this.threadId = threadId;
14         this.startPos = startPos;
15         this.endPos = endPos;
16         this.compeleteSize = compeleteSize;
17         this.url=url;
18     }
19     public DownloadInfo() {
20     }
21     public String getUrl() {
22         return url;
23     }
24     public void setUrl(String url) {
25         this.url = url;
26     }
27     public int getThreadId() {
28         return threadId;
29     }
30     public void setThreadId(int threadId) {
31         this.threadId = threadId;
32     }
33     public int getStartPos() {
34         return startPos;
35     }
36     public void setStartPos(int startPos) {
37         this.startPos = startPos;
38     }
39     public int getEndPos() {
40         return endPos;
41     }
42     public void setEndPos(int endPos) {
43         this.endPos = endPos;
44     }
45     public int getCompeleteSize() {
46         return compeleteSize;
47     }
48     public void setCompeleteSize(int compeleteSize) {
49         this.compeleteSize = compeleteSize;
50     }
51
52     @Override
53     public String toString() {
54         return "DownloadInfo [threadId=" + threadId
55                 + ", startPos=" + startPos + ", endPos=" + endPos
56                 + ", compeleteSize=" + compeleteSize +"]";
57     }
58 }

在下载时,我们有进度条来显示进度,怎么确定进度条的进度,大小和起始位置呢?这里我定义了一个LoadInfo类来记录下载器详细信息。代码如下:

LoadInfo:

 1 package cn.yj3g.entity;
 2 /**
 3  *自定义的一个记载下载器详细信息的类
 4  */
 5 public class LoadInfo {
 6     public int fileSize;//文件大小
 7     private int complete;//完成度
 8     private String urlstring;//下载器标识
 9     public LoadInfo(int fileSize, int complete, String urlstring) {
10         this.fileSize = fileSize;
11         this.complete = complete;
12         this.urlstring = urlstring;
13     }
14     public LoadInfo() {
15     }
16     public int getFileSize() {
17         return fileSize;
18     }
19     public void setFileSize(int fileSize) {
20         this.fileSize = fileSize;
21     }
22     public int getComplete() {
23         return complete;
24     }
25     public void setComplete(int complete) {
26         this.complete = complete;
27     }
28     public String getUrlstring() {
29         return urlstring;
30     }
31     public void setUrlstring(String urlstring) {
32         this.urlstring = urlstring;
33     }
34     @Override
35     public String toString() {
36         return "LoadInfo [fileSize=" + fileSize + ", complete=" + complete
37                 + ", urlstring=" + urlstring + "]";
38     }
39 }

下面是最最重要的一步,那就是定义一个下载器来进行下载了,这里我就不多说,具体解释在代码中都有注解,我就直接将代码附下,供大家研究参考

Downloader:

  1 package cn.yj3g.service;
  2
  3 import java.io.File;
  4 import java.io.InputStream;
  5 import java.io.RandomAccessFile;
  6 import java.net.HttpURLConnection;
  7 import java.net.URL;
  8 import java.util.ArrayList;
  9 import java.util.List;
 10 import android.content.Context;
 11 import android.os.Handler;
 12 import android.os.Message;
 13 import android.util.Log;
 14 import cn.yj3g.Dao.Dao;
 15 import cn.yj3g.entity.DownloadInfo;
 16 import cn.yj3g.entity.LoadInfo;
 17
 18 public class Downloader {
 19     private String urlstr;// 下载的地址
 20     private String localfile;// 保存路径
 21     private int threadcount;// 线程数
 22     private Handler mHandler;// 消息处理器
 23     private Dao dao;// 工具类
 24     private int fileSize;// 所要下载的文件的大小
 25     private List<DownloadInfo> infos;// 存放下载信息类的集合
 26     private static final int INIT = 1;//定义三种下载的状态:初始化状态,正在下载状态,暂停状态
 27     private static final int DOWNLOADING = 2;
 28     private static final int PAUSE = 3;
 29     private int state = INIT;
 30
 31     public Downloader(String urlstr, String localfile, int threadcount,
 32             Context context, Handler mHandler) {
 33         this.urlstr = urlstr;
 34         this.localfile = localfile;
 35         this.threadcount = threadcount;
 36         this.mHandler = mHandler;
 37         dao = new Dao(context);
 38     }
 39     /**
 40      *判断是否正在下载
 41      */
 42     public boolean isdownloading() {
 43         return state == DOWNLOADING;
 44     }
 45     /**
 46      * 得到downloader里的信息
 47      * 首先进行判断是否是第一次下载,如果是第一次就要进行初始化,并将下载器的信息保存到数据库中
 48      * 如果不是第一次下载,那就要从数据库中读出之前下载的信息(起始位置,结束为止,文件大小等),并将下载信息返回给下载器
 49      */
 50     public LoadInfo getDownloaderInfors() {
 51         if (isFirst(urlstr)) {
 52             Log.v("TAG", "isFirst");
 53             init();
 54             int range = fileSize / threadcount;
 55             infos = new ArrayList<DownloadInfo>();
 56             for (int i = 0; i < threadcount - 1; i++) {
 57                 DownloadInfo info = new DownloadInfo(i, i * range, (i + 1)* range - 1, 0, urlstr);
 58                 infos.add(info);
 59             }
 60             DownloadInfo info = new DownloadInfo(threadcount - 1,(threadcount - 1) * range, fileSize - 1, 0, urlstr);
 61             infos.add(info);
 62             //保存infos中的数据到数据库
 63             dao.saveInfos(infos);
 64             //创建一个LoadInfo对象记载下载器的具体信息
 65             LoadInfo loadInfo = new LoadInfo(fileSize, 0, urlstr);
 66             return loadInfo;
 67         } else {
 68             //得到数据库中已有的urlstr的下载器的具体信息
 69             infos = dao.getInfos(urlstr);
 70             Log.v("TAG", "not isFirst size=" + infos.size());
 71             int size = 0;
 72             int compeleteSize = 0;
 73             for (DownloadInfo info : infos) {
 74                 compeleteSize += info.getCompeleteSize();
 75                 size += info.getEndPos() - info.getStartPos() + 1;
 76             }
 77             return new LoadInfo(size, compeleteSize, urlstr);
 78         }
 79     }
 80
 81     /**
 82      * 初始化
 83      */
 84     private void init() {
 85         try {
 86             URL url = new URL(urlstr);
 87             HttpURLConnection connection = (HttpURLConnection) url.openConnection();
 88             connection.setConnectTimeout(5000);
 89             connection.setRequestMethod("GET");
 90             fileSize = connection.getContentLength();
 91
 92             File file = new File(localfile);
 93             if (!file.exists()) {
 94                 file.createNewFile();
 95             }
 96             // 本地访问文件
 97             RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
 98             accessFile.setLength(fileSize);
 99             accessFile.close();
100             connection.disconnect();
101         } catch (Exception e) {
102             e.printStackTrace();
103         }
104     }
105
106     /**
107      * 判断是否是第一次 下载
108      */
109     private boolean isFirst(String urlstr) {
110         return dao.isHasInfors(urlstr);
111     }
112
113     /**
114      * 利用线程开始下载数据
115      */
116     public void download() {
117         if (infos != null) {
118             if (state == DOWNLOADING)
119                 return;
120             state = DOWNLOADING;
121             for (DownloadInfo info : infos) {
122                 new MyThread(info.getThreadId(), info.getStartPos(),
123                         info.getEndPos(), info.getCompeleteSize(),
124                         info.getUrl()).start();
125             }
126         }
127     }
128
129     public class MyThread extends Thread {
130         private int threadId;
131         private int startPos;
132         private int endPos;
133         private int compeleteSize;
134         private String urlstr;
135
136         public MyThread(int threadId, int startPos, int endPos,
137                 int compeleteSize, String urlstr) {
138             this.threadId = threadId;
139             this.startPos = startPos;
140             this.endPos = endPos;
141             this.compeleteSize = compeleteSize;
142             this.urlstr = urlstr;
143         }
144         @Override
145         public void run() {
146             HttpURLConnection connection = null;
147             RandomAccessFile randomAccessFile = null;
148             InputStream is = null;
149             try {
150                 URL url = new URL(urlstr);
151                 connection = (HttpURLConnection) url.openConnection();
152                 connection.setConnectTimeout(5000);
153                 connection.setRequestMethod("GET");
154                 // 设置范围,格式为Range:bytes x-y;
155                 connection.setRequestProperty("Range", "bytes="+(startPos + compeleteSize) + "-" + endPos);
156
157                 randomAccessFile = new RandomAccessFile(localfile, "rwd");
158                 randomAccessFile.seek(startPos + compeleteSize);
159                 // 将要下载的文件写到保存在保存路径下的文件中
160                 is = connection.getInputStream();
161                 byte[] buffer = new byte[4096];
162                 int length = -1;
163                 while ((length = is.read(buffer)) != -1) {
164                     randomAccessFile.write(buffer, 0, length);
165                     compeleteSize += length;
166                     // 更新数据库中的下载信息
167                     dao.updataInfos(threadId, compeleteSize, urlstr);
168                     // 用消息将下载信息传给进度条,对进度条进行更新
169                     Message message = Message.obtain();
170                     message.what = 1;
171                     message.obj = urlstr;
172                     message.arg1 = length;
173                     mHandler.sendMessage(message);
174                     if (state == PAUSE) {
175                         return;
176                     }
177                 }
178             } catch (Exception e) {
179                 e.printStackTrace();
180             } finally {
181                 try {
182                     is.close();
183                     randomAccessFile.close();
184                     connection.disconnect();
185                     dao.closeDb();
186                 } catch (Exception e) {
187                     e.printStackTrace();
188                 }
189             }
190
191         }
192     }
193     //删除数据库中urlstr对应的下载器信息
194     public void delete(String urlstr) {
195         dao.delete(urlstr);
196     }
197     //设置暂停
198     public void pause() {
199         state = PAUSE;
200     }
201     //重置下载状态
202     public void reset() {
203         state = INIT;
204     }
205 }

在这边下载器类的定义中,我们用到了许多关于进行数据库操作的方法,这里我定义了一个数据库工具类,来提供这些方法,代码如下:

Dao:

 1 package cn.yj3g.Dao;
 2
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import android.content.Context;
 6 import android.database.Cursor;
 7 import android.database.sqlite.SQLiteDatabase;
 8 import cn.yj3g.DBHelper.DBHelper;
 9 import cn.yj3g.entity.DownloadInfo;
10
11 /**
12  *
13  * 一个业务类
14  */
15 public class Dao {
16     private DBHelper dbHelper;
17
18     public Dao(Context context) {
19         dbHelper = new DBHelper(context);
20     }
21
22     /**
23      * 查看数据库中是否有数据
24      */
25     public boolean isHasInfors(String urlstr) {
26         SQLiteDatabase database = dbHelper.getReadableDatabase();
27         String sql = "select count(*)  from download_info where url=?";
28         Cursor cursor = database.rawQuery(sql, new String[] { urlstr });
29         cursor.moveToFirst();
30         int count = cursor.getInt(0);
31         cursor.close();
32         return count == 0;
33     }
34
35     /**
36      * 保存 下载的具体信息
37      */
38     public void saveInfos(List<DownloadInfo> infos) {
39         SQLiteDatabase database = dbHelper.getWritableDatabase();
40         for (DownloadInfo info : infos) {
41             String sql = "insert into download_info(thread_id,start_pos, end_pos,compelete_size,url) values (?,?,?,?,?)";
42             Object[] bindArgs = { info.getThreadId(), info.getStartPos(),
43                     info.getEndPos(), info.getCompeleteSize(), info.getUrl() };
44             database.execSQL(sql, bindArgs);
45         }
46     }
47
48     /**
49      * 得到下载具体信息
50      */
51     public List<DownloadInfo> getInfos(String urlstr) {
52         List<DownloadInfo> list = new ArrayList<DownloadInfo>();
53         SQLiteDatabase database = dbHelper.getReadableDatabase();
54         String sql = "select thread_id, start_pos, end_pos,compelete_size,url from download_info where url=?";
55         Cursor cursor = database.rawQuery(sql, new String[] { urlstr });
56         while (cursor.moveToNext()) {
57             DownloadInfo info = new DownloadInfo(cursor.getInt(0),
58                     cursor.getInt(1), cursor.getInt(2), cursor.getInt(3),
59                     cursor.getString(4));
60             list.add(info);
61         }
62         cursor.close();
63         return list;
64     }
65
66     /**
67      * 更新数据库中的下载信息
68      */
69     public void updataInfos(int threadId, int compeleteSize, String urlstr) {
70         SQLiteDatabase database = dbHelper.getReadableDatabase();
71         String sql = "update download_info set compelete_size=? where thread_id=? and url=?";
72         Object[] bindArgs = { compeleteSize, threadId, urlstr };
73         database.execSQL(sql, bindArgs);
74     }
75     /**
76      * 关闭数据库
77      */
78     public void closeDb() {
79         dbHelper.close();
80     }
81
82     /**
83      * 下载完成后删除数据库中的数据
84      */
85     public void delete(String url) {
86         SQLiteDatabase database = dbHelper.getReadableDatabase();
87         database.delete("download_info", "url=?", new String[] { url });
88         database.close();
89     }
90 }

下来就是要进行下载和暂停按钮的响应事件了。具体代码和解释如下。

MainActivity:

  1 package cn.yj3g.AndroidDownload;
  2
  3 import java.util.ArrayList;
  4 import java.util.HashMap;
  5 import java.util.List;
  6 import java.util.Map;
  7 import android.app.ListActivity;
  8 import android.os.Bundle;
  9 import android.os.Handler;
 10 import android.os.Message;
 11 import android.view.View;
 12 import android.widget.LinearLayout;
 13 import android.widget.LinearLayout.LayoutParams;
 14 import android.widget.ProgressBar;
 15 import android.widget.SimpleAdapter;
 16 import android.widget.TextView;
 17 import android.widget.Toast;
 18 import cn.yj3g.entity.LoadInfo;
 19 import cn.yj3g.service.Downloader;
 20
 21 public class MainActivity extends ListActivity {
 22     // 固定下载的资源路径,这里可以设置网络上的地址
 23     private static final String URL = "http://192.168.1.105:8080/struts2_net/";
 24     // 固定存放下载的音乐的路径:SD卡目录下
 25     private static final String SD_PATH = "/mnt/sdcard/";
 26     // 存放各个下载器
 27     private Map<String, Downloader> downloaders = new HashMap<String, Downloader>();
 28     // 存放与下载器对应的进度条
 29     private Map<String, ProgressBar> ProgressBars = new HashMap<String, ProgressBar>();
 30     /**
 31      * 利用消息处理机制适时更新进度条
 32      */
 33     private Handler mHandler = new Handler() {
 34         public void handleMessage(Message msg) {
 35             if (msg.what == 1) {
 36                 String url = (String) msg.obj;
 37                 int length = msg.arg1;
 38                 ProgressBar bar = ProgressBars.get(url);
 39                 if (bar != null) {
 40                     // 设置进度条按读取的length长度更新
 41                     bar.incrementProgressBy(length);
 42                     if (bar.getProgress() == bar.getMax()) {
 43                         Toast.makeText(MainActivity.this, "下载完成!", 0).show();
 44                         // 下载完成后清除进度条并将map中的数据清空
 45                         LinearLayout layout = (LinearLayout) bar.getParent();
 46                         layout.removeView(bar);
 47                         ProgressBars.remove(url);
 48                         downloaders.get(url).delete(url);
 49                         downloaders.get(url).reset();
 50                         downloaders.remove(url);
 51
 52                     }
 53                 }
 54             }
 55         }
 56     };
 57     @Override
 58     public void onCreate(Bundle savedInstanceState) {
 59         super.onCreate(savedInstanceState);
 60         setContentView(R.layout.main);
 61         showListView();
 62     }
 63     // 显示listView,这里可以随便添加音乐
 64     private void showListView() {
 65         List<Map<String, String>> data = new ArrayList<Map<String, String>>();
 66         Map<String, String> map = new HashMap<String, String>();
 67         map.put("name", "mm.mp3");
 68         data.add(map);
 69         map = new HashMap<String, String>();
 70         map.put("name", "pp.mp3");
 71         data.add(map);
 72         map = new HashMap<String, String>();
 73         map.put("name", "tt.mp3");
 74         data.add(map);
 75         map = new HashMap<String, String>();
 76         map.put("name", "You.mp3");
 77         data.add(map);
 78         SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.list_item, new String[] { "name" },
 79                 new int[] { R.id.tv_resouce_name });
 80         setListAdapter(adapter);
 81     }
 82     /**
 83      * 响应开始下载按钮的点击事件
 84      */
 85     public void startDownload(View v) {
 86         // 得到textView的内容
 87         LinearLayout layout = (LinearLayout) v.getParent();
 88         String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();
 89         String urlstr = URL + musicName;
 90         String localfile = SD_PATH + musicName;
 91         //设置下载线程数为4,这里是我为了方便随便固定的
 92         int threadcount = 4;
 93         // 初始化一个downloader下载器
 94         Downloader downloader = downloaders.get(urlstr);
 95         if (downloader == null) {
 96             downloader = new Downloader(urlstr, localfile, threadcount, this, mHandler);
 97             downloaders.put(urlstr, downloader);
 98         }
 99         if (downloader.isdownloading())
100             return;
101         // 得到下载信息类的个数组成集合
102         LoadInfo loadInfo = downloader.getDownloaderInfors();
103         // 显示进度条
104         showProgress(loadInfo, urlstr, v);
105         // 调用方法开始下载
106         downloader.download();
107     }
108
109     /**
110      * 显示进度条
111      */
112     private void showProgress(LoadInfo loadInfo, String url, View v) {
113         ProgressBar bar = ProgressBars.get(url);
114         if (bar == null) {
115             bar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
116             bar.setMax(loadInfo.getFileSize());
117             bar.setProgress(loadInfo.getComplete());
118             ProgressBars.put(url, bar);
119             LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, 5);
120             ((LinearLayout) ((LinearLayout) v.getParent()).getParent()).addView(bar, params);
121         }
122     }
123     /**
124      * 响应暂停下载按钮的点击事件
125      */
126     public void pauseDownload(View v) {
127         LinearLayout layout = (LinearLayout) v.getParent();
128         String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();
129         String urlstr = URL + musicName;
130         downloaders.get(urlstr).pause();
131     }
132 }

最后我们要在清单文件中添加权限,一个是访问网络的权限,一个是往SD卡写数据的权限。代码如下:

 <uses-permission android:name="android.permission.INTERNET"/>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

这样我们就实现了文件的断点续传下载功能。具体效果图如下:

时间: 2024-11-10 00:23:52

Android之断点续传下载的相关文章

android 多线程断点续传下载 三

今天跟大家一起分享下android开发中比较难的一个环节,可能很多人看到这个标题就会感觉头很大,的确如果没有良好的编码能力和逻辑思维,这块是很难搞明白的,前面2次总结中已经为大家分享过有关技术的一些基本要领,我们先一起简单回顾下它的基本原理. http://blog.csdn.net/shimiso/article/details/6763664  android 多线程断点续传下载 一 http://blog.csdn.net/shimiso/article/details/6763986 

android 多线程断点续传下载 二

在上一节中,我们简单介绍了如何创建多任务下载,但那种还不能拿来实用,这一集我们重点通过代码为大家展示如何创建多线程断点续传下载,这在实际项目中很常用. main.xml: [html] view plaincopy <?xml version="1.0" encoding="utf-8"?>   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&

android 多线程断点续传下载

http://blog.csdn.net/shimiso/article/details/6763986 多线程断点续传下载,这在实际项目中很常用. main.xml: [html] view plaincopy <?xml version="1.0" encoding="utf-8"?>   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q

Android多线程断点续传下载示例详解

一.概述 在上一篇博文<Android多线程下载示例>中,我们讲解了如何实现Android的多线程下载功能,通过将整个文件分成多个数据块,开启多个线程,让每个线程分别下载一个相应的数据块来实现多线程下载的功能.多线程下载中,可以将下载这个耗时的操作放在子线程中执行,即不阻塞主线程,又符合Android开发的设计规范. 但是当下载的过程当中突然出现手机卡死,或者网络中断,手机电量不足关机的现象,这时,当手机可以正常使用后,如果重新下载文件,似乎不太符合大多数用户的心理期望,那如何实现当手机可以正

android 多线程断点续传下载 一

想做一个下载功能,当然理想的功能要支持多任务同时下载,断点续传的功能,我想一步一步来,首先困难摆在了多任务这里 开始我的思路是在一个Service中启动下载的流操作,然后通过Service中声明一个Activity中的Handler更新UI(比如进度条...) 可是我发现在Service中声明一个Activity中的Handler是做不到的(可能只是我做不到吧,无法申请内存) 于是,我决定在Activity中直接启动线程,让其运行,调用自身的Handler来更新UI,没想到在这个下载Activi

Android实现网络多线程断点续传下载

本示例介绍在Android平台下通过HTTP协议实现断点续传下载. 我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多线程断点需要什么功能? 1.多线程下载, 2.支持断点.   使用多线程的好处:使用多线程下载会提升文件下载的速度.那么多线程下载文件的过程是:    (1)首先获得下载文件的长度,然后设置本地文件的长度.       HttpURLConnection.getContentLength();//获

android 之断点续传详解三部曲之[二] → 断点续传下载

在上一篇中,我们简单介绍了如何创建多任务下载,但那种还不能拿来实用,这一集我们重点通过代码为大家展示如何创建多线程断点续传下载,这在实际项目中很常用. 和上一篇中一样,先来布局文件: main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" and

Android编程开发实现多线程断点续传下载器实例_Android

本文实例讲述了Android编程开发实现多线程断点续传下载器.分享给大家供大家参考,具体如下: 使用多线程断点续传下载器在下载的时候多个线程并发可以占用服务器端更多资源,从而加快下载速度,在下载过程中记录每个线程已拷贝数据的数量,如果下载中断,比如无信号断线.电量不足等情况下,这就需要使用到断点续传功能,下次启动时从记录位置继续下载,可避免重复部分的下载.这里采用数据库来记录下载的进度. 效果图:   断点续传 1.断点续传需要在下载过程中记录每条线程的下载进度 2.每次下载开始之前先读取数据库

Android实现网络多线程断点续传下载实例_Android

我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多线程断点需要什么功能? 1.多线程下载, 2.支持断点. 使用多线程的好处:使用多线程下载会提升文件下载的速度.那么多线程下载文件的过程是: (1)首先获得下载文件的长度,然后设置本地文件的长度. HttpURLConnection.getContentLength();//获取下载文件的长度 RandomAccessFile file = new RandomAc