android实现断点续传

来源:互联网 发布:coc女王升级数据2017 编辑:程序博客网 时间:2024/06/10 04:39

1.Activity代码:

public class MainActivity extends ListActivity  {           // 固定下载的资源路径,这里可以设置网络上的地址            private static final String URL = "http://10.81.36.193:8080/";            // 固定存放下载的音乐的路径:SD卡目录下            private static final String SD_PATH = "/mnt/sdcard/";            // 存放各个下载器            private Map<String, Downloader> downloaders = new HashMap<String, Downloader>();            // 存放与下载器对应的进度条            private Map<String, ProgressBar> ProgressBars = new HashMap<String, ProgressBar>();            /**             * 利用消息处理机制适时更新进度条             */            private Handler mHandler = new Handler() {                public void handleMessage(Message msg) {                    if (msg.what == 1) {                        String url = (String) msg.obj;                        int length = msg.arg1;                        ProgressBar bar = ProgressBars.get(url);                        if (bar != null) {                            // 设置进度条按读取的length长度更新                            bar.incrementProgressBy(length);                            if (bar.getProgress() == bar.getMax()) {                                Toast.makeText(MainActivity.this, "下载完成!", 0).show();                                // 下载完成后清除进度条并将map中的数据清空                                LinearLayout layout = (LinearLayout) bar.getParent();                                layout.removeView(bar);                                ProgressBars.remove(url);                                downloaders.get(url).delete(url);                                downloaders.get(url).reset();                                downloaders.remove(url);                            }                        }                    }                }            };            @Override            public void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.activity_main);                showListView();                StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());                StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());            }            // 显示listView,这里可以随便添加音乐            private void showListView() {                List<Map<String, String>> data = new ArrayList<Map<String, String>>();                Map<String, String> map = new HashMap<String, String>();                map.put("name", "mm.mp3");                data.add(map);                map = new HashMap<String, String>();                map.put("name", "pp.mp3");                data.add(map);                map = new HashMap<String, String>();                map.put("name", "tt.mp3");                data.add(map);                map = new HashMap<String, String>();                map.put("name", "ou.mp3");                data.add(map);                SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.list_item, new String[] { "name" },                        new int[] { R.id.tv_resouce_name });                setListAdapter(adapter);            }            /**             * 响应开始下载按钮的点击事件             */            public void startDownload(View v) {                // 得到textView的内容                LinearLayout layout = (LinearLayout) v.getParent();                String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();                String urlstr = URL + musicName;                String localfile = SD_PATH + musicName;                //设置下载线程数为4,这里是我为了方便随便固定的                int threadcount = 4;                // 初始化一个downloader下载器                Downloader downloader = downloaders.get(urlstr);                if (downloader == null) {                    downloader = new Downloader(urlstr, localfile, threadcount, this, mHandler);                    downloaders.put(urlstr, downloader);                }                if (downloader.isdownloading())                   return;               // 得到下载信息类的个数组成集合               LoadInfo loadInfo = downloader.getDownloaderInfors();               // 显示进度条               showProgress(loadInfo, urlstr, v);               // 调用方法开始下载               downloader.download();           }           /**            * 显示进度条            */           private void showProgress(LoadInfo loadInfo, String url, View v) {               ProgressBar bar = ProgressBars.get(url);               if (bar == null) {                   bar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);                   bar.setMax(loadInfo.getFileSize());                   bar.setProgress(loadInfo.getComplete());                   ProgressBars.put(url, bar);                   LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, 5);                   ((LinearLayout) ((LinearLayout) v.getParent()).getParent()).addView(bar, params);               }           }           /**            * 响应暂停下载按钮的点击事件            */           public void pauseDownload(View v) {               LinearLayout layout = (LinearLayout) v.getParent();               String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();               String urlstr = URL + musicName;               downloaders.get(urlstr).pause();           }       }  

2.DBHelper代码:

/**   * 建立一个数据库帮助类   */  public class DBHelper extends SQLiteOpenHelper {      // download.db-->数据库名      public DBHelper(Context context) {          super(context, "download.db", null, 1);      }      /**       * 在download.db数据库下创建一个download_info表存储下载信息       */      @Override      public void onCreate(SQLiteDatabase db) {          db.execSQL("create table download_info(_id integer PRIMARY KEY AUTOINCREMENT, thread_id integer, "                  + "start_pos integer, end_pos integer, compelete_size integer,url char)");      }      @Override      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {      }  }  

3.DownloadInfo代码:

public class DownloadInfo {      private int threadId;// 下载器id      private int startPos;// 开始点      private int endPos;// 结束点      private int compeleteSize;// 完成度      private String url;// 下载器网络标识      /*省略get 和 set*/}  

3.LoadInfo代码:

public class LoadInfo {      public int fileSize;// 文件大小      private int complete;// 完成度      private String urlstring;// 下载器标识      /*省略get 和 set*/}

4.Downloader代码:

 public class Downloader {       private String urlstr;// 下载的地址       private String localfile;// 保存路径       private int threadcount;// 线程数       private Handler mHandler;// 消息处理器       private Dao dao;// 工具类       private int fileSize;// 所要下载的文件的大小       private List<DownloadInfo> infos;// 存放下载信息类的集合       private static final int INIT = 1;//定义三种下载的状态:初始化状态,正在下载状态,暂停状态       private static final int DOWNLOADING = 2;       private static final int PAUSE = 3;       private int state = INIT;      /**        *判断是否正在下载        */       public boolean isdownloading() {           return state == DOWNLOADING;       }       /**        * 得到downloader里的信息        * 首先进行判断是否是第一次下载,如果是第一次就要进行初始化,并将下载器的信息保存到数据库中        * 如果不是第一次下载,那就要从数据库中读出之前下载的信息(起始位置,结束为止,文件大小等),并将下载信息返回给下载器        */       public LoadInfo getDownloaderInfors() {           if (isFirst(urlstr)) {               Log.v("TAG", "isFirst");               init();               int range = fileSize / threadcount;               infos = new ArrayList<DownloadInfo>();               for (int i = 0; i < threadcount - 1; i++) {                   DownloadInfo info = new DownloadInfo(i, i * range, (i + 1)* range - 1, 0, urlstr);                   infos.add(info);               }               DownloadInfo info = new DownloadInfo(threadcount - 1,(threadcount - 1) * range, fileSize - 1, 0, urlstr);               infos.add(info);               //保存infos中的数据到数据库               dao.saveInfos(infos);               //创建一个LoadInfo对象记载下载器的具体信息               LoadInfo loadInfo = new LoadInfo(fileSize, 0, urlstr);               return loadInfo;           } else {               //得到数据库中已有的urlstr的下载器的具体信息               infos = dao.getInfos(urlstr);               Log.v("TAG", "not isFirst size=" + infos.size());               int size = 0;               int compeleteSize = 0;               for (DownloadInfo info : infos) {                   compeleteSize += info.getCompeleteSize();                   size += info.getEndPos() - info.getStartPos() + 1;               }               return new LoadInfo(size, compeleteSize, urlstr);           }       }       /**        * 初始化        */       private void init() {           try {               URL url = new URL(urlstr);               HttpURLConnection connection = (HttpURLConnection) url.openConnection();               connection.setConnectTimeout(5000);               connection.setRequestMethod("GET");               fileSize = connection.getContentLength();               File file = new File(localfile);               if (!file.exists()) {                   file.createNewFile();               }               // 本地访问文件               RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");               accessFile.setLength(fileSize);               accessFile.close();               connection.disconnect();           } catch (Exception e) {               e.printStackTrace();           }       }       /**        * 判断是否是第一次 下载        */       private boolean isFirst(String urlstr) {           return dao.isHasInfors(urlstr);       }       /**        * 利用线程开始下载数据        */       public void download() {           if (infos != null) {               if (state == DOWNLOADING)                   return;               state = DOWNLOADING;               for (DownloadInfo info : infos) {                   new MyThread(info.getThreadId(), info.getStartPos(),                           info.getEndPos(), info.getCompeleteSize(),                           info.getUrl()).start();               }           }       }       public class MyThread extends Thread {           private int threadId;           private int startPos;           private int endPos;           private int compeleteSize;           private String urlstr;           public MyThread(int threadId, int startPos, int endPos,                   int compeleteSize, String urlstr) {               this.threadId = threadId;               this.startPos = startPos;               this.endPos = endPos;               this.compeleteSize = compeleteSize;               this.urlstr = urlstr;           }           @Override           public void run() {               HttpURLConnection connection = null;               RandomAccessFile randomAccessFile = null;               InputStream is = null;               try {                   URL url = new URL(urlstr);                   connection = (HttpURLConnection) url.openConnection();                   connection.setConnectTimeout(5000);                   connection.setRequestMethod("GET");                   // 设置范围,格式为Range:bytes x-y;                   connection.setRequestProperty("Range", "bytes="+(startPos + compeleteSize) + "-" + endPos);                   randomAccessFile = new RandomAccessFile(localfile, "rwd");                   randomAccessFile.seek(startPos + compeleteSize);                   Log.i("RG", "connection--->>>"+connection);                   // 将要下载的文件写到保存在保存路径下的文件中                   is = connection.getInputStream();                   byte[] buffer = new byte[4096];                   int length = -1;                   while ((length = is.read(buffer)) != -1) {                       randomAccessFile.write(buffer, 0, length);                       compeleteSize += length;                       // 更新数据库中的下载信息                       dao.updataInfos(threadId, compeleteSize, urlstr);                       // 用消息将下载信息传给进度条,对进度条进行更新                       Message message = Message.obtain();                       message.what = 1;                       message.obj = urlstr;                       message.arg1 = length;                       mHandler.sendMessage(message);                       if (state == PAUSE) {                           return;                       }                   }               } catch (Exception e) {                   e.printStackTrace();               } finally {                   try {                       is.close();                       randomAccessFile.close();                       connection.disconnect();                       dao.closeDb();                   } catch (Exception e) {                       e.printStackTrace();                   }               }           }       }       //删除数据库中urlstr对应的下载器信息       public void delete(String urlstr) {           dao.delete(urlstr);       }       //设置暂停       public void pause() {           state = PAUSE;       }       //重置下载状态       public void reset() {          state = INIT;       }  }

5.Dao代码:

public class Dao {      private DBHelper dbHelper;      public Dao(Context context) {          dbHelper = new DBHelper(context);      }      /**       * 查看数据库中是否有数据       */      public boolean isHasInfors(String urlstr) {          SQLiteDatabase database = dbHelper.getReadableDatabase();          String sql = "select count(*)  from download_info where url=?";          Cursor cursor = database.rawQuery(sql, new String[] { urlstr });          cursor.moveToFirst();          int count = cursor.getInt(0);          cursor.close();          return count == 0;      }      /**       * 36 * 保存 下载的具体信息 37       */      public void saveInfos(List<DownloadInfo> infos) {          SQLiteDatabase database = dbHelper.getWritableDatabase();          for (DownloadInfo info : infos) {              String sql = "insert into download_info(thread_id,start_pos, end_pos,compelete_size,url) values (?,?,?,?,?)";              Object[] bindArgs = { info.getThreadId(), info.getStartPos(),                      info.getEndPos(), info.getCompeleteSize(), info.getUrl() };              database.execSQL(sql, bindArgs);          }      }      /**       * 得到下载具体信息       */      public List<DownloadInfo> getInfos(String urlstr) {          List<DownloadInfo> list = new ArrayList<DownloadInfo>();          SQLiteDatabase database = dbHelper.getReadableDatabase();          String sql = "select thread_id, start_pos, end_pos,compelete_size,url from download_info where url=?";          Cursor cursor = database.rawQuery(sql, new String[] { urlstr });          while (cursor.moveToNext()) {              DownloadInfo info = new DownloadInfo(cursor.getInt(0),                      cursor.getInt(1), cursor.getInt(2), cursor.getInt(3),                      cursor.getString(4));              list.add(info);          }          cursor.close();          return list;      }      /**       * 更新数据库中的下载信息       */      public void updataInfos(int threadId, int compeleteSize, String urlstr) {          SQLiteDatabase database = dbHelper.getReadableDatabase();          String sql = "update download_info set compelete_size=? where thread_id=? and url=?";          Object[] bindArgs = { compeleteSize, threadId, urlstr };          database.execSQL(sql, bindArgs);      }      /**       * 关闭数据库       */      public void closeDb() {          dbHelper.close();      }      /**       * 下载完成后删除数据库中的数据       */      public void delete(String url) {          SQLiteDatabase database = dbHelper.getReadableDatabase();          database.delete("download_info", "url=?", new String[] { url });          database.close();      }  }  

6.xml布局:

<?xml version="1.0" encoding="utf-8"?>    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"        android:orientation="vertical"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:id="@+id/llRoot">        <ListView android:id="@android:id/list"            android:layout_width="fill_parent"            android:layout_height="fill_parent">       </ListView>   </LinearLayout>  

7.item_list.xml布局:

<?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="fill_parent"      android:layout_height="wrap_content"      android:orientation="vertical" >      <LinearLayout          android:layout_width="fill_parent"          android:layout_height="wrap_content"          android:layout_marginBottom="5dip"          android:orientation="horizontal" >          <TextView              android:id="@+id/tv_resouce_name"              android:layout_width="fill_parent"              android:layout_height="wrap_content"              android:layout_weight="1" />          <Button              android:id="@+id/btn_start"              android:layout_width="fill_parent"              android:layout_height="wrap_content"              android:layout_weight="1"              android:onClick="startDownload"              android:text="下载" />          <Button              android:id="@+id/btn_pause"              android:layout_width="fill_parent"              android:layout_height="wrap_content"              android:layout_weight="1"              android:onClick="pauseDownload"              android:text="暂停" />      </LinearLayout>  </LinearLayout>  

8.注意点

记得加权限:

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

还有在3.0以上的版本记得加上这句话:

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());  

效果如下:
这里写图片描述

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 4周岁半幼儿便秘怎么办 没胃口不能吃辣怎么办 九个月宝宝缺锌怎么办 宝宝4 5天不吃饭怎么办 16个月宝宝不肯吃饭怎么办 儿童不吃饭很瘦怎么办 小孩吃饭吃的少怎么办 宝宝突然晚上不睡觉怎么办 l岁宝宝吃多了怎么办 3个月婴儿厌食怎么办 11个月婴儿厌食怎么办 7个月的婴儿厌食怎么办 小孩记忆不好读书记不住怎么办 9岁儿童不爱睡觉怎么办 6岁儿童不爱吃饭怎么办 2岁半宝宝不吃饭怎么办 一年级的孩子不爱学习怎么办 小孩不爱写作业怎么办啊 孩子不爱看书怎么办如何教育 2岁宝宝不爱看书怎么办 儿媳妇比儿子年龄大我不喜欢怎么办 不喜欢儿子却生了儿子怎么办 静不下心来看书怎么办 孩子爱玩不爱学怎么办 孩子爱玩不爱学习怎么办 孩子爱玩手机不爱学习怎么办 照四维宝宝太活泼了怎么办 胎宝宝太活泼了怎么办 7个月宝宝太活泼怎么办 我是个初中生不想上学怎么办 3岁宝宝不肯说话怎么办 两周宝宝不爱吃饭怎么办 小孩不喜欢吃水果蔬菜怎么办 孩子对学习不感兴趣怎么办 幼儿园老师不喜欢我孩子怎么办 孩子数学不主动思考问题怎么办 孩子做事慢磨蹭家长应该怎么办 孩子不写作业怎么办啊 对孩子在校被欺怎么办 二年级的孩子不爱学习怎么办 孩子不爱学习怎么办二年级