单一文件的断点续传
来源:互联网 发布:太原高达软件 编辑:程序博客网 时间:2024/05/18 00:58
很久没有更新博客了,最近公司的项目也没那么赶了,就照着慕课网的视频,把断点续传的代码敲了一遍,,调了半天,其中的坑也只有自己敲过才知道.为了今后方便,我现在把所有的代码都粘在下面了.
运行的效果如下:
这个才是
首先是我的代码目录结构
FileInfos主要是记录要下载的文件信息private int id; private String url; private String fileName; private int length; private int finished;ThreadInfo类是记录线程信息private int id; private String url; private int start; private int end; private int finished;DBHelper创建我的数据库,单例模式private static final String DB_NAME="download.db"; public static DBHelper helper; private static String SQL_CREATE="create table if not exists thread_info(_id integer primary key autoincrement,thread_id integer," + "url text,start integer,end integer,finished integer)"; private static String SQL_DROP="drop table if exists thread_info"; public static synchronized DBHelper getInstance(Context mContext) { if (helper==null) { helper=new DBHelper(mContext,DB_NAME,null,1); } return helper; } private DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(SQL_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } **数据访问接口的实现 * Created by Administrator on 2017/7/19. */public class ThreadDaoImp implements ThreadDao{ private DBHelper helper; public ThreadDaoImp(Context context) { helper=DBHelper.getInstance(context); } @Override public void insertThread(ThreadInfos threadInfos) { SQLiteDatabase db = helper.getReadableDatabase(); db.execSQL("insert into thread_info(thread_id,url,start,end,finished) values (?,?,?,?,?)", new Object[]{threadInfos.getId(),threadInfos.getUrl(),threadInfos.getStart(),threadInfos.getEnd(),threadInfos.getFinished()}); db.close(); } @Override public void deleteThread(String url, int thredId) { SQLiteDatabase db = helper.getReadableDatabase(); db.execSQL("delete from thread_info where url= ? and thread_id= ?", new Object[]{url,thredId}); db.close(); } @Override public void updateThread(String url, int threadId, int finished) { SQLiteDatabase db = helper.getReadableDatabase(); db.execSQL("update thread_info set finished = ? where url= ? and thread_id= ?", new Object[]{finished,url,threadId}); db.close(); } @Override public List<ThreadInfos> getThreads(String url) { SQLiteDatabase db = helper.getReadableDatabase(); List<ThreadInfos> list=new ArrayList<>(); Cursor cursor = db.rawQuery("select * from thread_info where url= ? ", new String[]{url}); while (cursor.moveToNext()) { ThreadInfos threadInfos = new ThreadInfos(); threadInfos.setId(cursor.getInt(cursor.getColumnIndex("thread_id"))); threadInfos.setUrl(cursor.getString(cursor.getColumnIndex("url"))); threadInfos.setStart(cursor.getInt(cursor.getColumnIndex("start"))); threadInfos.setEnd(cursor.getInt(cursor.getColumnIndex("end"))); threadInfos.setFinished(cursor.getInt(cursor.getColumnIndex("finished"))); list.add(threadInfos); } cursor.close(); db.close(); return list; } @Override public boolean isExists(String url, int threadId) { SQLiteDatabase db = helper.getReadableDatabase(); Cursor cursor = db.rawQuery("select * from thread_info where url= ? and thread_id= ?", new String[]{url,threadId+""}); boolean exists=cursor.moveToNext(); cursor.close(); db.close(); return exists; }}/**下载任务类 * Created by Administrator on 2017/7/19. */public class DownloadTask { private Context context; private FileInfos fileInfos; private ThreadDaoImp threadDaoImp; private int mFinished=0; public boolean isPaused; public DownloadTask(Context context, FileInfos fileInfos) { this.context = context; this.fileInfos = fileInfos; threadDaoImp=new ThreadDaoImp(context); } public void download() { //读取数据库的线程信息 List<ThreadInfos> list = threadDaoImp.getThreads(fileInfos.getUrl()); ThreadInfos threadInfos=null; if (list.size()==0) { //初始化线程信息对象 threadInfos = new ThreadInfos(0,fileInfos.getUrl(),0,fileInfos.getLength(),0); //创建子线程进行下载 new DownloadThread(threadInfos).start(); } else { for (int i = 0; i < list.size(); i++) { threadInfos=list.get(i); new DownloadThread(threadInfos).start(); } } } //下载线程 class DownloadThread extends Thread{ private ThreadInfos threadInfos; public DownloadThread(ThreadInfos threadInfos) { this.threadInfos = threadInfos; } @Override public void run() { super.run(); //先数据库插入线程信息 if (!threadDaoImp.isExists(threadInfos.getUrl(),threadInfos.getId())) { threadDaoImp.insertThread(threadInfos); } RandomAccessFile raf=null; try { URL url = new URL(threadInfos.getUrl()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //conn.connect(); int length=-1; //设置下载位置 int start=threadInfos.getStart()+threadInfos.getFinished(); conn.setRequestProperty("Range","bytes="+start+"-"+threadInfos.getEnd()); //设置文件写入位置 File file = new File(DownloadService.DOWNLOAD_PATH,fileInfos.getFileName()); raf = new RandomAccessFile(file, "rwd"); raf.seek(start); Intent intent = new Intent(); intent.setAction(DownloadService.ACTION_UPDATE); mFinished+=threadInfos.getFinished(); if (conn.getResponseCode()==206) { //开始下载 //读取数据 InputStream input = conn.getInputStream(); byte[] bytes = new byte[1024*4]; long time=0; while ((length=input.read(bytes))!=-1) { //写入文件 raf.write(bytes,0,length); //把下载进度通过广播发送给activity mFinished+=length; if (mFinished>=fileInfos.getLength()) { mFinished=fileInfos.getLength(); } if (System.currentTimeMillis()-time>300) { time=System.currentTimeMillis(); intent.putExtra("progress",mFinished*100/fileInfos.getLength()); context.sendBroadcast(intent); } //在下载暂停时,保存下载进度 if (isPaused) { threadDaoImp.updateThread(threadInfos.getUrl(),threadInfos.getId(),mFinished); return; } } //下载完成后,删除线程信息 threadDaoImp.deleteThread(threadInfos.getUrl(),threadInfos.getId()); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { if (raf!=null) { raf.close(); } } catch (IOException e) { e.printStackTrace(); } } } }}/**数据库访问接口 * Created by Administrator on 2017/7/19. */public interface ThreadDao { //插入线程信息 public void insertThread(ThreadInfos threadInfos); //删除线程 public void deleteThread(String url,int thredId); //更新线程下载进度 public void updateThread(String url,int threadId,int finished); //查询线程信息 public List<ThreadInfos> getThreads(String url); //线程信息是否存在 public boolean isExists(String url,int threadId);}/** * Created by Administrator on 2017/7/19. */public class DownloadService extends Service{ public static final String DOWNLOAD_PATH= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + File.separator+"demo"; public static final String ACTION_START="ACTION_START"; public static final String ACTION_STOP="ACTION_STOP"; public static final String ACTION_UPDATE="ACTION_UPDATE"; public static final int MSG_INIT=0; DownloadTask downloadTask; public Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0: FileInfos fileInfos= (FileInfos) msg.obj; Log.d("==handler====","======="+fileInfos.toString()); //启动下载任务 downloadTask = new DownloadTask(DownloadService.this, fileInfos); downloadTask.download(); break; default: break; } } }; @Override public int onStartCommand(Intent intent, int flags, int startId) { //获取从activity中传递过来的信息 if (ACTION_START.equals(intent.getAction())) { FileInfos fileInfo = (FileInfos) intent.getSerializableExtra("fileInfo"); Log.d("==start====","======"+fileInfo.toString()); new InitThread(fileInfo).start(); } else if (ACTION_STOP.equals(intent.getAction())) { FileInfos fileInfo = (FileInfos) intent.getSerializableExtra("fileInfo"); Log.d("==stop====","======"+fileInfo.toString()); if (downloadTask!=null) { downloadTask.isPaused=true; } } return super.onStartCommand(intent, flags, startId); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } class InitThread extends Thread{ FileInfos fileInfos; public InitThread(FileInfos fileInfos) { this.fileInfos = fileInfos; } @Override public void run() { super.run(); RandomAccessFile raf=null; try { //连接网络文件 URL url = new URL(fileInfos.getUrl()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.connect(); int length=-1; if (conn.getResponseCode()==200) { //获得文件长度 length=conn.getContentLength(); if (length<=0) { return; } File dir=new File(DOWNLOAD_PATH); if (!dir.exists()) { dir.mkdirs(); } //在本地创建文件 File file=new File(dir,fileInfos.getFileName()); raf = new RandomAccessFile(file, "rwd"); //设置文件长度 raf.setLength(length); } fileInfos.setLength(length); Message message = handler.obtainMessage(); message.what=MSG_INIT; message.obj=fileInfos; handler.sendMessage(message); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { if (raf!=null) { raf.close(); } } catch (IOException e) { e.printStackTrace(); } } } }}public class MainActivity extends AppCompatActivity implements View.OnClickListener{ TextView textView; ProgressBar progressBar; Button start_bt,pause_bt; FileInfos fileInfos; MyBroadCastReceiver receiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView= (TextView) findViewById(R.id.textView); progressBar= (ProgressBar) findViewById(R.id.progressBar); start_bt= (Button) findViewById(R.id.start_bt); pause_bt= (Button) findViewById(R.id.pause_bt); initListener(); initFileInfo(); initData(); } private void initData() { //注册广播 receiver = new MyBroadCastReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(DownloadService.ACTION_UPDATE); registerReceiver(receiver,intentFilter); progressBar.setMax(50); textView.setText(fileInfos.getFileName()); } private void initFileInfo() { //http://down.shouji.kuwo.cn/star/mobile/KuwoPlayerV3_ar_8.5.0.2_kw.apk //http://www.imooc.com/video/7052 fileInfos = new FileInfos(0, "http://down.shouji.kuwo.cn/star/mobile/KuwoPlayerV3_ar_8.5.0.2_kw.apk", "kuwo.apk", 0, 0); } private void initListener() { start_bt.setOnClickListener(this); pause_bt.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.start_bt: Intent intentStart = new Intent(this, DownloadService.class); intentStart.setAction(DownloadService.ACTION_START); intentStart.putExtra("fileInfo",fileInfos); startService(intentStart); break; case R.id.pause_bt: Intent intentStop = new Intent(this, DownloadService.class); intentStop.setAction(DownloadService.ACTION_STOP); intentStop.putExtra("fileInfo",fileInfos); startService(intentStop); break; default: break; } } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); } class MyBroadCastReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { if (DownloadService.ACTION_UPDATE.equals(intent.getAction())) { int progress = intent.getIntExtra("progress", -1); if (-1!=progress) { progressBar.setProgress(progress); } } } }}其实还有个bug一直没解决,进度条在文件下载完成后,并没有走满,而且我在公有目录下新建的文件夹的时间显示是2012/00/00/00,,,如果解决了,记得给我留言告我一声啊!这里写代码片
阅读全文
0 0
- 单一文件的断点续传
- 文件的断点续传
- 文件的断点续传
- 大文件的断点续传
- 单一MDF文件的还原
- 单一入口文件的定义
- 对大文件的断点续传
- HTTP文件断点续传的原理
- HTTP文件断点续传的原理
- HTTP文件断点续传的原理
- 类文件的单一接口原则
- 如何实现文件的断点续传,文件下载
- 文件断点续传
- java实现文件的断点续传的下载
- 支持断点续传的PHP文件下载类
- 使用HASH算法实现文件的断点续传
- php 支持断点续传的文件下载类
- 用NSFileHandle实现文件的断点续传
- [asp.net mvc 奇淫巧技] 05
- 记一次sql server 性能调优,查询从20秒至2秒
- java--面向对象
- leetcode264-Ugly Number II
- 程序员必须逛的同性交友网站(GitHub)!
- 单一文件的断点续传
- angularjs 动态从后台获取下拉框的值
- opencv mat (matrix)数据结构
- Vue.js搭建移动端购物车界面-基本结构和数据渲染
- 根据backtrace_symbols查错误代码行号
- 新的历程
- HAWQ + MADlib 玩转数据挖掘之(三)——向量
- tensorflow-MNIST机器学习入门
- 排序算法之冒泡排序