多线程断点续传
2016-06-15 13:13
204 查看
一、定义UI
二、定义实体类
FileInfo:id、url、fileName、length、progress,实现Serializable接口
ThreadInfo:id、url、start、stop、progress
三、向Service传递参数
将要下载的文件信息实体从Activity传递到Service
Service里面定义两个Action,分别标识开始和暂停
在onStartCommand方法中接收传过来的FileInfo
四、使用线程进行初始化
开启服务后,如果是ACTION_START,子线程访问网络获取文件长度,在本地创建一个文件,并使用Handler将文件信息返回给主线程。
子线程类有一个成员变量是一个FileInfo对象,是该子线程所要初始化的下载文件,创建子线程时通过构造方法传进来。
五、创建数据库和数据访问接口
创建数据库辅助类
数据访问接口
数据访问接口实现
六、数据下载类
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.it.zjhz.downloaddemo.MainActivity"> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文件名称" /> <ProgressBar android:id="@+id/pb_progress" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/tv_name" style="@android:style/Widget.ProgressBar.Horizontal"/> <Button android:id="@+id/btn_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="开始" android:layout_below="@+id/pb_progress" android:layout_toLeftOf="@+id/btn_stop"/> <Button android:id="@+id/btn_stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="暂停" android:layout_below="@+id/pb_progress" android:layout_alignParentRight="true"/> </RelativeLayout>
二、定义实体类
FileInfo:id、url、fileName、length、progress,实现Serializable接口
ThreadInfo:id、url、start、stop、progress
三、向Service传递参数
将要下载的文件信息实体从Activity传递到Service
Intent intent = new Intent(MainActivity.this, DownloadService.class); intent.setAction(DownloadService.ACTION_START); intent.putExtra("fileInfo", fileInfo); startService(intent);
Service里面定义两个Action,分别标识开始和暂停
public static final String ACTION_START = "ACTION_START"; public static final String ACTION_STOP = "ACTION_STOP";
在onStartCommand方法中接收传过来的FileInfo
if (ACTION_START.equals(intent.getAction())) { FileInfo fileInfo = (FileInfo) intent.getSerializableExtra("fileInfo"); Log.i("StartFileInfo",fileInfo.toString()); } else if (ACTION_STOP.equals(intent.getAction())) { FileInfo fileInfo = (FileInfo) intent.getSerializableExtra("fileInfo"); Log.i("stopFileInfo",fileInfo.toString()); }
四、使用线程进行初始化
开启服务后,如果是ACTION_START,子线程访问网络获取文件长度,在本地创建一个文件,并使用Handler将文件信息返回给主线程。
子线程类有一个成员变量是一个FileInfo对象,是该子线程所要初始化的下载文件,创建子线程时通过构造方法传进来。
/** * 初始化子线程 */ class InitThread extends Thread { private FileInfo mFileInfo; public InitThread(FileInfo mFileInfo) { this.mFileInfo = mFileInfo; } @Override public void run() { super.run(); HttpURLConnection conn = null; RandomAccessFile raf = null; try { URL url = new URL(mFileInfo.getUrl()); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); int length = -1; if (conn.getResponseCode() == 200) { length = conn.getContentLength(); } if (length < 0) { return; } //创建本地文件 File dir = new File("/data/data/" + getPackageName() + 4000 "/downloads/"); if (!dir.exists()) { dir.mkdir(); } File file = new File(dir, mFileInfo.getFileName()); raf = new RandomAccessFile(file, "rwd"); //设置文件长度 raf.setLength(length); //将获取文件长度之后的FileInfo回传到主线程 mFileInfo.setLength(length); mHandler.obtainMessage(MSG_INIT, mFileInfo).sendToTarget(); } catch (Exception e) { e.printStackTrace(); } finally { try { conn.disconnect(); raf.close(); } catch (Exception e) { e.printStackTrace(); } } } }
Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case MSG_INIT: FileInfo fileInfo = (FileInfo) msg.obj; Log.i("InitfileInfo", fileInfo.toString()); break; default: break; } } };
五、创建数据库和数据访问接口
创建数据库辅助类
private static final String DB_NAME = "download.db"; private static final int VERSION = 1; private static final String SQL_CREATE = "create table thread_info(_id integer primary key autoincrement," + "thread_id integer,url text,start integer,stop integer,progress integer)"; private static final String SQL_DROP = "drop table if exists thread_info"; public DBHelper(Context context) { super(context, DB_NAME, null, VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(SQL_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL(SQL_DROP); db.execSQL(SQL_CREATE); } }
数据访问接口
public interface ThreadDao { public void insertThread(ThreadInfo threadInfo); public void deleteThread(String url,int thread_id); public void updateThread(String ul,int thread_id,int progress); public List<ThreadInfo> getThreads(String url); public boolean isExists(String ul,int thread_id); }
数据访问接口实现
public class ThreadDaoImpl implements ThreadDao { private DBHelper dbHelper; public ThreadDaoImpl(Context context) { dbHelper = new DBHelper(context); } @Override public void insertThread(ThreadInfo threadInfo) { SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("thread_id", threadInfo.getId()); values.put("url", threadInfo.getUrl()); values.put("start", threadInfo.getStart()); values.put("stop", threadInfo.getStop()); values.put("progress", threadInfo.getProgress()); db.insert("thread_info", null, values); db.close(); } @Override public void deleteThread(String url, int thread_id) { SQLiteDatabase db = dbHelper.getWritableDatabase(); db.delete("thread_info", "url = ? and thread_id = ?", new String[]{url, thread_id + ""}); db.close(); } @Override public void updateThread(String url, int thread_id, int progress) { SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("progress", progress); db.update("thread_info", values, "url = ? and thread_id = ?", new String[]{url, thread_id + ""}); db.close(); } @Override public List<ThreadInfo> getThreads(String url) { List<ThreadInfo> list = new ArrayList<>(); SQLiteDatabase db = dbHelper.getWritableDatabase(); Cursor cursor = db.rawQuery("select * from thread_info where url = ?", new String[]{url}); while (cursor.moveToNext()) { ThreadInfo threadInfo = new ThreadInfo(); threadInfo.setId(cursor.getInt(cursor.getColumnIndex("thread_id"))); threadInfo.setUrl(cursor.getString(cursor.getColumnIndex("url"))); threadInfo.setStart(cursor.getInt(cursor.getColumnIndex("start"))); threadInfo.setStop(cursor.getInt(cursor.getColumnIndex("stop"))); threadInfo.setProgress(cursor.getInt(cursor.getColumnIndex("progress"))); list.add(threadInfo); } cursor.close(); db.close(); return list; } @Override public boolean isExists(String url, int thread_id) { SQLiteDatabase db = dbHelper.getWritableDatabase(); Cursor cursor = db.rawQuery("select * from thread_info where url = ? and thread_id = ?", new String[]{url, thread_id + ""}); boolean result = cursor.moveToNext(); cursor.close(); db.close(); return result; } }
六、数据下载类
相关文章推荐
- eclipse工具常用快捷键总结
- 【十三】分数的重载,倒数
- Suricata+PF_RING安装详解
- DBOpenHelper.java,用于将复制到raw文件夹下的数据库文件读取并保存到databases文件夹中。
- [LeetCode][14]Longest Common Prefix解析 两种算法和底层源码的深入对比-Java实现
- 计算机概论
- 让Apache Shiro保护你的应用
- java 中 用到的jdbc 调用存储过程,与hibernate 调用存储过程
- CodeForces 235B Let's Play Osu!(概率dp)
- eclipse发布web项目到tomcat
- 使用Apriori算法进行关联分析
- JAVASCRIPT 格式化日期
- 【十三】分数的重载,加减乘除以及比较
- column cannot be null mysql
- struts2验证码实现
- Dism 错误: 1450
- Jenkins连接svn报E170001错误的解决办法
- Java中的ThreadLocal的使用--学习笔记
- 【Swift】iOS导航栏错乱的原因
- POJ1953