zoukankan      html  css  js  c++  java
  • Android版多线程下载器核心代码分享

    首先给大家分享多线程下载核心类:

      1 package com.example.urltest;
      2 
      3 import java.io.IOException;
      4 import java.io.InputStream;
      5 import java.io.RandomAccessFile;
      6 import java.net.HttpURLConnection;
      7 import java.net.MalformedURLException;
      8 import java.net.URL;
      9 import java.net.URLDecoder;
     10 
     11 public class DownUtil {
     12     private String urlPath;
     13     private String defaultTargetPath;
     14     private int threadNum;
     15     private DownThread[] threads;
     16     private int fileSize = -100;
     17     private String fileName = "未知文件";
     18     private boolean isGetFileInformation = false;
     19 
     20     public DownUtil(String urlPath, int threadNum) {
     21         this.urlPath = urlPath;
     22         this.defaultTargetPath = "/mnt/sdcard/";
     23         this.threadNum = threadNum;
     24         this.threads = new DownThread[threadNum];
     25     }
     26 
     27     private HttpURLConnection connection() throws IOException {
     28 
     29         URL url = new URL(urlPath);
     30         HttpURLConnection connection = (HttpURLConnection) url.openConnection();
     31         connection.setConnectTimeout(5 * 1000);
     32         connection.setRequestMethod("GET");
     33         connection.setRequestProperty(
     34                 "Accept",
     35                 "image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
     36                         + "application/x-shockwave-flash, application/xaml+xml, "
     37                         + "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
     38                         + "application/x-ms-application, application/vnd.ms-excel, "
     39                         + "application/vnd.ms-powerpoint, application/msword, */*");
     40         connection.setRequestProperty("Accept-Language", "zh-CN");
     41         connection.setRequestProperty("Charset", "UTF-8");
     42         connection.setRequestProperty("Connection", "Keep-Alive");
     43 
     44         return connection;
     45     }
     46 
     47     public void getFileInformation() throws IOException {
     48 
     49         HttpURLConnection connection = connection();
     50 
     51         connection.setInstanceFollowRedirects(false);
     52 
     53         int status = connection.getResponseCode();
     54         if (status != -1) {
     55 
     56             if (status / 100 == 3) {// 当响应码是302时,说明可以获得重定向的资源地址
     57                 // 得到文件名(此方法不能正确的获取所有url的资源文件名)
     58                 String name = connection.getHeaderField("Location");
     59                 name = URLDecoder.decode(name.substring(name.lastIndexOf('/')), "UTF-8");
     60                 this.fileName = name;
     61             }
     62 
     63             // 得到文件大小
     64             this.fileSize = connection.getContentLength();
     65             if (fileSize <= 0) {
     66                 isGetFileInformation = false;
     67             } else {
     68                 isGetFileInformation = true;
     69             }
     70             connection.disconnect();
     71 
     72         } else {
     73 
     74             connection.disconnect();
     75             isGetFileInformation = false;
     76 
     77         }
     78 
     79     }
     80 
     81     public boolean download(String targetPath, String fileName) throws IOException {
     82 
     83         if (isGetFileInformation == false) {
     84             getFileInformation();
     85         }
     86 
     87         if (isGetFileInformation) {
     88 
     89             String absFilePath = targetPath + fileName;
     90 
     91             int currentPartSize = (fileSize / threadNum) + 1;// 每一部分需要下载的大小,注意此处加1是为了避免不能整除带来的误差
     92             RandomAccessFile file = new RandomAccessFile(absFilePath, "rw");
     93             file.setLength(fileSize);
     94             file.close();
     95             for (int i = 0; i < threadNum; i++) {
     96                 int startPos = i * currentPartSize;
     97                 RandomAccessFile currentPart = new RandomAccessFile(absFilePath, "rw");// 打开目标文件
     98                 currentPart.seek(startPos);
     99                 threads[i] = new DownThread(startPos, currentPartSize, currentPart);
    100                 threads[i].start();
    101 
    102             }
    103 
    104             return true;
    105         } else {
    106             return false;
    107 
    108         }
    109     }
    110 
    111     public boolean download() throws IOException {
    112         if (isGetFileInformation) {
    113 
    114             return download(this.defaultTargetPath, this.getFileName());
    115 
    116         } else {
    117             getFileInformation();
    118             return download(this.defaultTargetPath, this.getFileName());
    119 
    120         }
    121 
    122     }
    123 
    124     public double getCompleteRate() {
    125 
    126         int sumSize = 0;
    127         for (int i = 0; i < threadNum; i++) {
    128 
    129             sumSize += threads[i].length;
    130         }
    131 
    132         return sumSize * 1.0 / fileSize;
    133 
    134     }
    135 
    136     public String getDefaultTargetPath() {
    137         return defaultTargetPath;
    138     }
    139 
    140     public int getFileSize() {
    141         return fileSize;
    142     }
    143 
    144     public String getFileName() {
    145         return fileName;
    146     }
    147 
    148     public void setFileName(String fileName) {
    149         this.fileName = fileName;
    150     }
    151 
    152     public boolean isGetFileInformation() {
    153         return isGetFileInformation;
    154     }
    155 
    156     private class DownThread extends Thread {
    157         private int startPos;
    158         private int currentPartSize;
    159         private RandomAccessFile currentPart;
    160         int length; // 该线程已经下载的字节数
    161 
    162         public DownThread(int startPos, int currentPartSize, RandomAccessFile currentPart) {
    163 
    164             this.startPos = startPos;
    165             this.currentPartSize = currentPartSize;
    166             this.currentPart = currentPart;
    167         }
    168 
    169         @Override
    170         public void run() {
    171 
    172             try {
    173 
    174                 HttpURLConnection connection = connection();
    175                 int endPos = startPos + currentPartSize;
    176                 connection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos);// 使用http来设置一个文件的下载范围(startPos-endPos)
    177                 InputStream inStream = connection.getInputStream();
    178                 // inStream.skip(startPos); // skip函数有时候不起作用
    179                 byte[] buffer = new byte[1024];
    180                 int hasRead = 0;
    181                 while (length < currentPartSize && (hasRead = inStream.read(buffer)) > 0) {
    182 
    183                     currentPart.write(buffer, 0, hasRead);
    184                     length = length + hasRead;
    185 
    186                 }
    187 
    188                 inStream.close();
    189                 currentPart.close();
    190                 connection.disconnect();
    191 
    192             } catch (MalformedURLException e2) {
    193                 e2.printStackTrace();
    194             } catch (IOException e) {
    195                 e.printStackTrace();
    196             }
    197 
    198         }
    199 
    200     }
    201 
    202 }

    下面是界面的逻辑代码:

      1 package com.example.urltest;
      2 
      3 import android.app.Activity;
      4 import android.app.AlertDialog;
      5 import android.app.ProgressDialog;
      6 import android.content.DialogInterface;
      7 import android.os.Bundle;
      8 import android.os.Message;
      9 import android.view.View;
     10 import android.view.View.OnClickListener;
     11 import android.widget.Button;
     12 import android.widget.EditText;
     13 import android.widget.ProgressBar;
     14 import android.widget.TextView;
     15 import android.widget.Toast;
     16 
     17 import java.io.IOException;
     18 import java.util.Timer;
     19 import java.util.TimerTask;
     20 
     21 public class MultiThreadDown extends Activity {
     22     EditText url, target;
     23     Button downButton;
     24     ProgressBar bar;
     25     ProgressDialog progressDialog;
     26     View downView;
     27     DownUtil downUtil;
     28     private int mDownStatus;
     29     private int threadNum = 6; // 默认的线程数
     30     android.os.Handler handler = new android.os.Handler() {
     31 
     32         @Override
     33         public void handleMessage(Message msg) {
     34             if (msg.what == 0x123) {
     35                 bar.setProgress(mDownStatus);
     36                 if (mDownStatus >= 100) {
     37                     Toast.makeText(MultiThreadDown.this, "下载完成", Toast.LENGTH_SHORT).show();
     38                 }
     39                 // Log.i("csx", "" + mDownStatus);
     40 
     41             }
     42         }
     43 
     44     };
     45 
     46     @Override
     47     protected void onCreate(Bundle savedInstanceState) {
     48 
     49         super.onCreate(savedInstanceState);
     50         setContentView(R.layout.layout_down);
     51         url = (EditText) findViewById(R.id.url);
     52 
     53         downButton = (Button) findViewById(R.id.down);
     54         bar = (ProgressBar) findViewById(R.id.bar);
     55         progressDialog = new ProgressDialog(this);
     56         progressDialog.setTitle("尝试连接");
     57         progressDialog.setMessage("正在连接...");
     58         downButton.setOnClickListener(new DownButtonOnClickListener());
     59 
     60     }
     61 
     62     private class DownButtonOnClickListener implements OnClickListener {
     63 
     64         EditText targetFilePath, fileName;
     65         TextView fileSize;
     66         Thread connectionThread;
     67 
     68         public Thread instanceOfConnectionThread() {
     69             return new Thread() {
     70 
     71                 @Override
     72                 public void run() {
     73                     try {
     74                         downUtil.getFileInformation();
     75 
     76                     } catch (IOException e1) {
     77                         e1.printStackTrace();
     78                     }
     79 
     80                 }
     81 
     82             };
     83         }
     84 
     85         @Override
     86         public void onClick(View v) {
     87 
     88             String urlPath = url.getText().toString();
     89             if (urlPath == null || urlPath.equals("")) {
     90                 return;
     91             }
     92             progressDialog.show();
     93             downUtil = new DownUtil(urlPath, threadNum);
     94             connectionThread = instanceOfConnectionThread();
     95             connectionThread.start();
     96 
     97             int connectionNum = 3;
     98             while (!downUtil.isGetFileInformation() && connectionNum > 0) {// 循环请求连接,如果3次之后还没有连接成功,就退出
     99                 if (!connectionThread.isAlive()) {
    100                     connectionThread = null;
    101                     connectionThread = instanceOfConnectionThread();
    102                     connectionThread.start();
    103                     connectionNum--;
    104                 }
    105 
    106             }
    107 
    108             progressDialog.cancel();
    109             if (!downUtil.isGetFileInformation()) {
    110                 Toast.makeText(MultiThreadDown.this, "请求失败!", Toast.LENGTH_SHORT).show();
    111                 return;
    112             }
    113             downView = getLayoutInflater().inflate(R.layout.layout_download_view, null);
    114             targetFilePath = (EditText) downView.findViewById(R.id.editText_target_path);
    115             fileName = (EditText) downView.findViewById(R.id.editText_file_name);
    116             fileSize = (TextView) downView.findViewById(R.id.textView_file_size);
    117             targetFilePath.setText(downUtil.getDefaultTargetPath());
    118             fileName.setText(downUtil.getFileName());
    119             fileSize.append("" + ((double) downUtil.getFileSize()) / 1024 + "k");
    120 
    121             new AlertDialog.Builder(MultiThreadDown.this).setView(downView)
    122                     .setPositiveButton("确定", new DialogInterface.OnClickListener() {
    123 
    124                         @Override
    125                         public void onClick(DialogInterface dialog, int which) {
    126                             if (!downUtil.isGetFileInformation()) {
    127                                 dialog.dismiss();
    128                                 return;
    129                             }
    130                             final String path = targetFilePath.getText().toString();
    131                             final String name = fileName.getText().toString();
    132 
    133                             new Thread() {
    134 
    135                                 @Override
    136                                 public void run() {
    137                                     try {
    138                                         downUtil.download(path, name);
    139                                     } catch (IOException e) {
    140                                         // TODO Auto-generated catch block
    141                                         e.printStackTrace();
    142                                     }
    143 
    144                                     final Timer timer = new Timer();
    145                                     TimerTask task = new TimerTask() {
    146 
    147                                         @Override
    148                                         public void run() {
    149 
    150                                             mDownStatus = (int) (downUtil.getCompleteRate() * 100);
    151                                             handler.sendEmptyMessage(0x123);
    152                                             if (mDownStatus >= 100) {
    153                                                 timer.cancel();
    154                                             }
    155 
    156                                         }
    157                                     };
    158                                     timer.schedule(task, 0, 100);
    159 
    160                                 }
    161 
    162                             }.start();
    163 
    164                         }
    165                     }).setNegativeButton("取消", null)
    166                     .setTitle(downUtil.isGetFileInformation() ? "链接可用" : "链接不可用").show();
    167 
    168         }
    169     }
    170 
    171 }

    下面是主页面布局:layout_down.xml

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     android:orientation="vertical" >
     6 
     7     <ScrollView
     8         android:id="@+id/scrollView1"
     9         android:layout_width="match_parent"
    10         android:layout_height="wrap_content" >
    11 
    12         <LinearLayout
    13             android:layout_width="match_parent"
    14             android:layout_height="match_parent"
    15             android:orientation="vertical" >
    16 
    17             <TextView
    18                 android:layout_width="match_parent"
    19                 android:layout_height="wrap_content"
    20                 android:text="要下载的资源的URL:" />
    21 
    22             <EditText
    23                 android:id="@+id/url"
    24                 android:layout_width="match_parent"
    25                 android:layout_height="wrap_content"
    26                 android:text="在在这里输入URL" />
    27 
    28             <Button
    29                 android:id="@+id/down"
    30                 android:layout_width="match_parent"
    31                 android:layout_height="wrap_content"
    32                 android:text="下载" />
    33             <!-- 定义一个水平进度条,用于显示下载进度 -->
    34 
    35             <ProgressBar
    36                 android:id="@+id/bar"
    37                 style="?android:attr/progressBarStyleHorizontal"
    38                 android:layout_width="match_parent"
    39                 android:layout_height="wrap_content"
    40                 android:max="100" />
    41         </LinearLayout>
    42     </ScrollView>
    43 
    44 </LinearLayout>

    下面是下载选项dialog布局:layout_download_view.xml

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     android:orientation="vertical" >
     6 
     7     <TextView
     8         android:id="@+id/textView1"
     9         android:layout_width="wrap_content"
    10         android:layout_height="wrap_content"
    11         android:text="下载路径:" />
    12 
    13     <EditText
    14         android:id="@+id/editText_target_path"
    15         android:layout_width="match_parent"
    16         android:layout_height="wrap_content"
    17         android:ems="10" >
    18 
    19         <requestFocus />
    20     </EditText>
    21 
    22     <TextView
    23         android:id="@+id/textView2"
    24         android:layout_width="wrap_content"
    25         android:layout_height="wrap_content"
    26         android:text="文件名:" />
    27 
    28     <EditText
    29         android:id="@+id/editText_file_name"
    30         android:layout_width="match_parent"
    31         android:layout_height="wrap_content"
    32         android:maxLines="1"
    33         android:ems="10" />
    34 
    35     <TextView
    36         android:id="@+id/textView_file_size"
    37         android:layout_width="wrap_content"
    38         android:layout_height="wrap_content"
    39         android:text="文件大小:" />
    40 
    41 </LinearLayout>

    效果图如下:输入URL,点击下载弹出对话框,输入路径和文件名 点击确定开始下载

  • 相关阅读:
    mysql导出表的数据,在导入
    oracle数据迁移到mysql
    mybatis-使用generator反向数据库表并生成dao和mapping映射
    SQLserver单表数据导入导出
    java内省
    java反射
    springmvc文件上传
    Dubbo学习笔记8:Dubbo的集群容错与负载均衡策略
    Dubbo学习笔记7:Dubbo增强SPI与SPI中扩展点自动包装的实现原理
    Dubbo学习笔记6:Dubbo整体框架分析
  • 原文地址:https://www.cnblogs.com/csxcode/p/4229850.html
Copyright © 2011-2022 走看看