• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > 7.3.3 Android 文件下载(2)

7.3.3 Android 文件下载(2)

作者:coder-pig 字体:[增加 减小] 来源:互联网 时间:2017-05-22

coder-pig通过本文主要向大家介绍了npp 7.3.3 installer,notepad 7.3.3,notepad plus 7.3.3,电视直播7.3.3,oracle 7.3.3等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

本节引言:

本节给大家带来的Android中的多线程断点续传的代码解析,呵呵,为什么叫解析呢?因为我 也写不出来,( ╯□╰ )!先来说说断点的意思吧!所谓的断点就是:使用数据库记录每天线程所 下载的进度!每次启动时根据线程id查询某线程的下载进度,在继续下载!听上去蛮简单的, 要你写十有八九写不出,这很正常,所以本节看懂最好,看不懂也没什么,会用和改就好! 好的,开始本节内容~


Android多线程断点下载的代码流程解析:

运行效果图:

实现流程全解析:


Step 1:创建一个用来记录线程下载信息的表

创建数据库表,于是乎我们创建一个数据库的管理器类,继承SQLiteOpenHelper类 重写onCreate()与onUpgrade()方法,我们创建的表字段如下:

DBOpenHelper.java:

package com.jay.example.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DBOpenHelper extends SQLiteOpenHelper {
  public DBOpenHelper(Context context) {
    super(context, "downs.db", null, 1);
  }
  @Override
  public void onCreate(SQLiteDatabase db) {
    //数据库的结构为:表名:filedownlog 字段:id,downpath:当前下载的资源,
    //threadid:下载的线程id,downlength:线程下载的最后位置
    db.execSQL("CREATE TABLE IF NOT EXISTS filedownlog " +
        "(id integer primary key autoincrement," +
        " downpath varchar(100)," +
        " threadid INTEGER, downlength INTEGER)");
  }
  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    //当版本号发生改变时调用该方法,这里删除数据表,在实际业务中一般是要进行数据备份的
    db.execSQL("DROP TABLE IF EXISTS filedownlog");
    onCreate(db);
  }

}

Step 2:创建一个数据库操作类

我们需要创建什么样的方法呢?

  • ①我们需要一个根据URL获得每条线程当前下载长度的方法
  • ②接着,当我们的线程新开辟后,我们需要往数据库中插入与该线程相关参数的方法
  • ③还要定义一个可以实时更新下载文件长度的方法
  • ④我们线程下载完,还需要根据线程id,删除对应记录的方法

FileService.java

package com.jay.example.db;

import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

/*
 * 该类是一个业务bean类,完成数据库的相关操作
 * */

public class FileService {
  //声明数据库管理器
  private DBOpenHelper openHelper;
  
  //在构造方法中根据上下文对象实例化数据库管理器
  public FileService(Context context) {
    openHelper = new DBOpenHelper(context);
  }
  
  /**
   * 获得指定URI的每条线程已经下载的文件长度
   * @param path
   * @return 
   * */
  public Map<Integer, Integer> getData(String path)
  {
    //获得可读数据库句柄,通常内部实现返回的其实都是可写的数据库句柄
    SQLiteDatabase db = openHelper.getReadableDatabase();
    //根据下载的路径查询所有现场的下载数据,返回的Cursor指向第一条记录之前
    Cursor cursor = db.rawQuery("select threadid, downlength from filedownlog where downpath=?",
        new String[]{path});
    //建立一个哈希表用于存放每条线程已下载的文件长度
    Map<Integer,Integer> data = new HashMap<Integer, Integer>();
    //从第一条记录开始遍历Cursor对象
    cursor.moveToFirst();
    while(cursor.moveToNext())
    {
      //把线程id与该线程已下载的长度存放到data哈希表中
      data.put(cursor.getInt(0), cursor.getInt(1));
      data.put(cursor.getInt(cursor.getColumnIndexOrThrow("threadid")),
          cursor.getInt(cursor.getColumnIndexOrThrow("downlength")));
    }
    cursor.close();//关闭cursor,释放资源;
    db.close();
    return data;
  }
  
  /**
   * 保存每条线程已经下载的文件长度
   * @param path 下载的路径
   * @param map 现在的di和已经下载的长度的集合
  */
  public void save(String path,Map<Integer,Integer> map)
  {
    SQLiteDatabase db = openHelper.getWritableDatabase();
    //开启事务,因为此处需要插入多条数据
    db.beginTransaction();
    try{
      //使用增强for循环遍历数据集合
      for(Map.Entry<Integer, Integer> entry : map.entrySet())
      {
        //插入特定下载路径特定线程ID已经下载的数据
        db.execSQL("insert into filedownlog(downpath, threadid, downlength) values(?,?,?)",
            new Object[]{path, entry.getKey(), entry.getValue()});
      }
      //设置一个事务成功的标志,如果成功就提交事务,如果没调用该方法的话那么事务回滚
      //就是上面的数据库操作撤销
      db.setTransactionSuccessful();
    }finally{
      //结束一个事务
      db.endTransaction();
    }
    db.close();
  }
  
  /**
   * 实时更新每条线程已经下载的文件长度
   * @param path
   * @param map
   */
  public void update(String path,int threadId,int pos)
  {
    SQLiteDatabase db = openHelper.getWritableDatabase();
    //更新特定下载路径下特定线程已下载的文件长度
    db.execSQL("update filedownlog set downlength=? where downpath=? and threadid=?",
        new Object[]{pos, path, threadId});
    db.close();
  }
  
  
  /**
   *当文件下载完成后,删除对应的下载记录
   *@param path 
   */
  public void delete(String path)
  {
    SQLiteDatabase db = openHelper.getWritableDatabase();
    db.execSQL("delete from filedownlog where downpath=?", new Object[]{path});
    db.close();
  }
  
}

Step 3:创建一个文件下载器类

好了,数据库管理器与操作类都完成了接着就该弄一个文件下载器类了,在该类中又要完成 什么操作呢?要做的事就多了:

①定义一堆变量,核心是线程池threads和同步集合ConcurrentHashMap,用于缓存线程下载长度的
②定义一个获取线程池中线程数的方法;
③定义一个退出下载的方法,
④获取当前文件大小的方法
⑤累计当前已下载长度的方法,这里需要添加一个synchronized关键字,用来解决并发访问的问题
⑥更新指定线程最后的下载位置,同样也需要用同步
⑦在构造方法中完成文件下载,线程开辟等操作
⑧获取文件名的方法:先截取提供的url最后的'/'后面的字符串,如果获取不到,再从头字段查找,还是 找不到的话,就使用网卡标识数字+cpu的唯一数字生成一个16个字节的二进制作为文件名
⑨开始下载文件的方法
⑩获取http响应头字段的方法
?打印http头字段的方法
12.打印日志信息的方法

FileDownloadered.java:

package com.jay.example.service;

import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;
import android.util.Log;





import com.jay.example.db.FileService;

public class FileDownloadered {
  
  private static final String TAG = "文件下载类";  //设置一个查log时的一个标志
  private static final int RESPONSEOK = 200;    //设置响应码为200,代表访问成功
  private FileService fileService;        //获取本地数据库的业务Bean
  private boolean exited;             //停止下载的标志
  private Context context;            //程序的上下文对象
  private int downloadedSize = 0;               //已下载的文件长度
  private int fileSize = 0;           //开始的文件长度
  private DownloadThread[] threads;        //根据线程数设置下载的线程池
  private File saveFile;              //数据保存到本地的文件中
  private Map<Integer, Integer> data = new ConcurrentHashMap<Integer, Integer>();  //缓存个条线程的下载的长度
  private int block;              



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 7.3.3 Android 文件下载(2)

相关文章

  • 2017-05-26《Android权威编程指南(The Big Nerd Ranch Guide)(第二版)》12.4挑战练习,bignerdranch
  • 2017-05-26Android移动APP开发笔记——Cordova(PhoneGap)通过CordovaPlugin插件调用 Activity 实例,phonegapcordova
  • 2017-05-26Atitit.android js 的键盘按键检测Back键Home键和Menu键事件,atitit.androidmenu
  • 2017-05-26pull解析器: 反序列化与序列化,pull序列化
  • 2017-05-26Android:应用宝省流量更新
  • 2017-05-26Socket for android 简单实例,socketandroid
  • 2017-05-26android:Activity数据传递之基本数据类型
  • 2017-05-26Android中Window添加View的底层原理
  • 2017-05-26【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新,androidtinker
  • 2017-05-26安卓中Paint类和Canvas类的方法汇总,安卓中canvas

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 关于Android发送短信获取送达报告的问题,android发送短信
    • HBase Java编程示例
    • Android APK免安装启动
    • android沉浸式状态栏、变色状态栏、透明状态栏、修改状态栏颜色及透明
    • android之仿微信双击放大字体及滑动冲突,文本显示不全,android放大字体
    • 如何编写高效的android代码
    • 【读书笔记】【Android 开发艺术探索】第3章 View 的事件体系
    • 自动完成文本框(AutoCompleteTextView与MultiAutoCompleteTextView)关联适配器,文本框autocomplete
    • Kotlin的数据类:节省很多行代码(KAD 10),kotlin很多行
    • linux和android调试工具介绍及方法汇总

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有