zoukankan      html  css  js  c++  java
  • 安卓 下载多线程带进度条

    当我们学完java中多线程的下载后,能够将它移植到我们的安卓中来。以下是详细实现源代码:

    DownActivity.java

    [java] view plaincopy
    1. package com.example.downloads;  
    2.   
    3. import java.io.File;  
    4. import java.io.IOException;  
    5. import java.io.RandomAccessFile;  
    6. import java.net.HttpURLConnection;  
    7. import java.net.MalformedURLException;  
    8. import java.net.URL;  
    9. import com.example.downloads.utils.DownLoadThread;  
    10. import android.os.Bundle;  
    11. import android.os.Environment;  
    12. import android.os.Handler;  
    13. import android.os.Message;  
    14. import android.annotation.SuppressLint;  
    15. import android.app.Activity;  
    16. import android.text.TextUtils;  
    17. import android.view.Menu;  
    18. import android.view.View;  
    19. import android.widget.EditText;  
    20. import android.widget.ProgressBar;  
    21. import android.widget.TextView;  
    22. import android.widget.Toast;  
    23.   
    24. public class DownActivity extends Activity {  
    25.     // 声明控件  
    26.     // 路径与线程数量  
    27.     public EditText et_url, et_num;  
    28.     // 进度条  
    29.     public static ProgressBar pb_thread;  
    30.     // 显示运行进度的操作  
    31.     public TextView tv_pb;  
    32.     // 线程的数量  
    33.     public static int threadNum = 3;  
    34.     // 每一个线程负责下载的大小  
    35.     public int blockSize;  
    36.     public static int threadCount;// 数量  
    37.     // 訪问的path  
    38.     public String path;  
    39.     public static boolean flag = true;  
    40.     // 记录进度条的值  
    41.     public static int pb_count = 0;  
    42.     public static Handler handler;  
    43.     public static final int TEXTVALUE = 1;  
    44.     public static int pb_num = 0;  
    45.     public static int size = 0;  
    46.   
    47.     @Override  
    48.     protected void onCreate(Bundle savedInstanceState) {  
    49.         super.onCreate(savedInstanceState);  
    50.         setContentView(R.layout.activity_down);  
    51.         et_url = (EditText) findViewById(R.id.et_path);  
    52.         et_num = (EditText) findViewById(R.id.et_threadNum);  
    53.         pb_thread = (ProgressBar) findViewById(R.id.pb_down);  
    54.         tv_pb = (TextView) findViewById(R.id.tv_pb);  
    55.         handler = new Handler() {  
    56.             @SuppressLint("HandlerLeak")  
    57.             @Override  
    58.             public void handleMessage(Message msg) {  
    59.                 super.handleMessage(msg);  
    60.                 switch (msg.what) {  
    61.                 case TEXTVALUE:  
    62.                     System.out.println("-------" + DownActivity.pb_count  
    63.                             + "//////" + DownActivity.size);  
    64.                     // 改变TEXTView  
    65.                     pb_num = (DownActivity.pb_count * 100) / DownActivity.size;  
    66.                     tv_pb.setText("当前进度是+" + pb_num + "%");  
    67.                       
    68.                     break;  
    69.   
    70.                 default:  
    71.                     break;  
    72.                 }  
    73.             }  
    74.   
    75.         };  
    76.   
    77.     }  
    78.   
    79.     @Override  
    80.     public boolean onCreateOptionsMenu(Menu menu) {  
    81.         // Inflate the menu; this adds items to the action bar if it is present.  
    82.         getMenuInflater().inflate(R.menu.main, menu);  
    83.         return true;  
    84.     }  
    85.   
    86.     public void downLoad(View v) {  
    87.         DownActivity.flag = true;  
    88.         DownActivity.pb_count = 0;  
    89.   
    90.         path = et_url.getText().toString();  
    91.         String threadNum_et = et_num.getText().toString();  
    92.   
    93.         if (TextUtils.isEmpty(path) || TextUtils.isEmpty(threadNum_et)) {  
    94.             Toast.makeText(this"不能为空", Toast.LENGTH_LONG).show();  
    95.             return;  
    96.         }  
    97.         Toast.makeText(this"url:" + path + "--" + threadNum_et,  
    98.                 Toast.LENGTH_LONG).show();  
    99.         // 转换成数字  
    100.         threadNum = Integer.valueOf(threadNum_et);  
    101.         new Thread(new Runnable() {  
    102.             @Override  
    103.             public void run() {  
    104.                 try {  
    105.                     // 创建出URL对象  
    106.                     URL url = new URL(path);  
    107.                     // 创建出 HttpURLConnection对象  
    108.                     HttpURLConnection httpURLConnection = (HttpURLConnection) url  
    109.                             .openConnection();  
    110.   
    111.                     // 设置 发请求发送的方式  
    112.                     httpURLConnection.setRequestMethod("GET");  
    113.                     // 设置请求是否超时时间  
    114.                     httpURLConnection.setConnectTimeout(5000);  
    115.                     // 设置  
    116.                     httpURLConnection  
    117.                             .setRequestProperty("User-Agent",  
    118.                                     " Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");  
    119.   
    120.                     // 是否响应成功  
    121.                     if (httpURLConnection.getResponseCode() == 200) {  
    122.                         // 获取文件的大小  
    123.                         size = httpURLConnection.getContentLength();  
    124.                         System.out.println("文件的大小" + size);  
    125.                         // 设置进度条的最大值  
    126.                         pb_thread.setMax(size);  
    127.   
    128.                         // 创建文件 //保存到SD卡上  
    129.   
    130.                         // 首先推断是否拥有sdcard  
    131.                         if (Environment.getExternalStorageState().equals(  
    132.                                 Environment.MEDIA_MOUNTED)) {  
    133.                             // 获取sdCard文件文件夹对象  
    134.                             File sdFile = Environment  
    135.                                     .getExternalStorageDirectory();  
    136.                             // 创建文件对象  
    137.                             File file = new File(sdFile, "youdao.exe");  
    138.   
    139.                             RandomAccessFile accessFile = new RandomAccessFile(  
    140.                                     file, "rwd");  
    141.                             // 设置文件的大小  
    142.                             accessFile.setLength(size);  
    143.                             // 每一个线程下载的大小  
    144.                             blockSize = size / threadNum;  
    145.                             // 开三个线程 操作此文件  
    146.                             for (int i = 1; i <= threadNum; i++) {  
    147.                                 // 1 2 3  
    148.                                 // 计算出每一个线程開始的位置  
    149.                                 int startSize = (i - 1) * blockSize;  
    150.                                 // 结束位置  
    151.                                 int endSize = (i) * blockSize;  
    152.                                 // 当线程是最后一个线程的时候  
    153.                                 if (i == threadNum) {  
    154.                                     // 推断文件的大小是否大于计算出来的结束位置  
    155.                                     if (size > endSize) {  
    156.                                         // 结束位置 等于 文件的大小  
    157.                                         endSize = size;  
    158.                                     }  
    159.                                 }  
    160.                                 // 为每一个线程创建一个随机的读取  
    161.                                 RandomAccessFile threadAccessFile = new RandomAccessFile(  
    162.                                         file, "rwd");  
    163.                                 new Thread(new DownLoadThread(i,  
    164.                                         threadAccessFile, startSize, endSize,  
    165.                                         path)).start();  
    166.                             }  
    167.   
    168.                         }  
    169.   
    170.                     }  
    171.   
    172.                 } catch (MalformedURLException e) {  
    173.                       
    174.                     e.printStackTrace();  
    175.                 } catch (IOException e) {  
    176.                       
    177.                     e.printStackTrace();  
    178.                 }  
    179.   
    180.             }  
    181.   
    182.         }).start();  
    183.     }  
    184.   
    185.     /** 
    186.      * 暂停操作 
    187.      *  
    188.      * @param v 
    189.      */  
    190.     public void downPause(View v) {  
    191.         Toast.makeText(this"暂停", Toast.LENGTH_LONG).show();  
    192.   
    193.         this.flag = false;  
    194.   
    195.     }  
    196.   
    197. }  


    DownLoadThread.java

    [java] view plaincopy
    1. package com.example.downloads.utils;  
    2.   
    3. import java.io.File;  
    4. import java.io.FileInputStream;  
    5. import java.io.FileOutputStream;  
    6. import java.io.IOException;  
    7. import java.io.InputStream;  
    8. import java.io.RandomAccessFile;  
    9. import java.net.HttpURLConnection;  
    10. import java.net.MalformedURLException;  
    11. import java.net.URL;  
    12.   
    13. import com.example.downloads.DownActivity;  
    14.   
    15. import android.os.Environment;  
    16.   
    17.   
    18.   
    19. public class DownLoadThread implements Runnable {  
    20.   
    21.       
    22.     public RandomAccessFile accessFile; // 每一个线程 都拥有一个accessFile的文件对象 线程1 线程2 线程3  
    23.   
    24.     // 线程下载文件的起始位置  
    25.     public int startSize;  
    26.     public int endSize;  
    27.   
    28.     // 文件下载的path路径  
    29.     public String path;  
    30.   
    31.     public int threadId; // 线程的标识  
    32.   
    33.     public DownLoadThread(int threadId, RandomAccessFile accessFile,  
    34.             int startSize, int endSize, String path) {  
    35.   
    36.         this.threadId = threadId;  
    37.         this.accessFile = accessFile;  
    38.         this.startSize = startSize;  
    39.         this.endSize = endSize;  
    40.         this.path = path;  
    41.     }  
    42.   
    43.     @Override  
    44.     public void run() {  
    45.         // 运行run方法  
    46.         try {  
    47.   
    48.             // 创建文件到SD卡上去  
    49.   
    50.             // 首先推断是否拥有sdcard  
    51.             if (Environment.getExternalStorageState().equals(  
    52.                     Environment.MEDIA_MOUNTED)) {  
    53.                 // 获取sdCard文件文件夹对象  
    54.                 File sdFile = Environment.getExternalStorageDirectory();  
    55.                 File threadFile = new File(sdFile, threadId + ".txt");  
    56.   
    57.                 if (threadFile.exists()) {  
    58.   
    59.                     // 读取该文件的内容  
    60.                     // 创建文件的输入流对象  
    61.                     FileInputStream fis = new FileInputStream(threadFile);  
    62.                     // 採用工具类读取  
    63.                     byte data[] = StreamTools.isToData(fis);  
    64.                     // 转化成字符串  
    65.                     String threadLen = new String(data);  
    66.   
    67.                     if ((threadLen != null) && (!"".equals(threadLen))) {  
    68.                         startSize = Integer.valueOf(threadLen);  
    69.   
    70.                         // 解决 416bug的错误  
    71.                         if (startSize > endSize) {  
    72.                             startSize = endSize - 1;  
    73.                         }  
    74.                     }  
    75.   
    76.                 }  
    77.   
    78.                 // 创建文件  
    79.   
    80.                 // 创建URL对象  
    81.                 URL url = new URL(path);  
    82.                 // 创建HttpURLConnection对象  
    83.                 HttpURLConnection httpURLConnection = (HttpURLConnection) url  
    84.                         .openConnection();  
    85.                 // 设置请求的头  
    86.   
    87.                 httpURLConnection.setRequestMethod("GET");  
    88.                 // 设置请求是否超时时间  
    89.                 httpURLConnection.setConnectTimeout(5000);  
    90.                 // 设置  
    91.                 httpURLConnection  
    92.                         .setRequestProperty("User-Agent",  
    93.                                 " Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");  
    94.   
    95.                 // 关键的设置  
    96.                 httpURLConnection.setRequestProperty("Range""bytes="  
    97.                         + startSize + "-" + endSize);  
    98.   
    99.                 // 输出当前线程  
    100.                 System.out.println("当前线程" + threadId + " 下载開始位置:" + startSize  
    101.                         + " 下载结束位置:" + endSize);  
    102.                 // 响应成功  
    103.   
    104.                 // 设置随机读取文件的 開始位置  
    105.                 accessFile.seek(startSize);  
    106.                 // 获取对应流对象  
    107.                 InputStream is = httpURLConnection.getInputStream();  
    108.                 // 创建输出流对象  
    109.   
    110.                 byte buffer[] = new byte[1024];  
    111.                 int len = 0;  
    112.                 int threadTotal = 0;// 每一个线程下载后保存记录 /  
    113.                 while ((len = is.read(buffer)) != -1) {  
    114.                     accessFile.write(buffer, 0, len);  
    115.                     threadTotal += len;// 记录你写入的长度 //xml文件  
    116.   
    117.                     //改变进度条:  
    118.                     setProgressBar(len);  
    119.                     // 通过文件记录文件下载的长度  
    120.                     FileOutputStream fos = new FileOutputStream(threadFile);  
    121.                     fos.write((threadTotal + "").getBytes());  
    122.                     fos.flush();  
    123.                     fos.close();  
    124.                     //发送handler消息  
    125.                     DownActivity.handler.sendEmptyMessage(DownActivity.TEXTVALUE);  
    126.                     if(!DownActivity.flag){  
    127.                         return;  
    128.                     }  
    129.   
    130.                 }  
    131.                 accessFile.close();  
    132.                 is.close();  
    133.                 System.out.println(threadId + "线程运行完成");  
    134.   
    135.                 // 线程操作  
    136.                 synchronized (DownActivity.class) {  
    137.                     DownActivity.threadCount++;  
    138.                     if (DownActivity.threadCount >= DownActivity.threadNum) {  
    139.                         for (int i = 1; i <= DownActivity.threadNum; i++) {  
    140.                             // 获取sdCard上的文件  
    141.                             File deleteFile = new File(sdFile, i + ".txt");  
    142.                             if (deleteFile.exists()) {  
    143.                                 // 文件删除  
    144.                                 deleteFile.delete();  
    145.                             }  
    146.                         }  
    147.                     }  
    148.                 }  
    149.             }  
    150.         } catch (MalformedURLException e) {  
    151.             // TODO Auto-generated catch block  
    152.             e.printStackTrace();  
    153.         } catch (IOException e) {  
    154.             // TODO Auto-generated catch block  
    155.             e.printStackTrace();  
    156.         }  
    157.   
    158.     }  
    159.   
    160.       
    161.       
    162.       
    163.     public synchronized void setProgressBar(int len){  
    164.         DownActivity.pb_count+=len;  
    165.         DownActivity.pb_thread.setProgress(DownActivity.pb_count);  
    166.     }  
    167.       
    168.       
    169.       
    170. }  


    StreamTools.java

    [java] view plaincopy
    1. package com.example.downloads.utils;  
    2.   
    3. import java.io.ByteArrayOutputStream;  
    4. import java.io.IOException;  
    5. import java.io.InputStream;  
    6.   
    7. public class StreamTools {  
    8.   
    9.       
    10.     public static byte[] isToData(InputStream is) throws IOException{  
    11.         // 字节输出流  
    12.         ByteArrayOutputStream bops = new ByteArrayOutputStream();  
    13.         // 读取数据的缓存区  
    14.         byte buffer[] = new byte[1024];  
    15.         // 读取长度的记录  
    16.         int len = 0;  
    17.         // 循环读取  
    18.         while ((len = is.read(buffer)) != -1) {  
    19.             bops.write(buffer, 0, len);  
    20.         }  
    21.         // 把读取的内容转换成byte数组  
    22.         byte data[] = bops.toByteArray();  
    23.           
    24.         bops.flush();  
    25.         bops.close();  
    26.         is.close();  
    27.         return data;  
    28.     }  
    29. }  


    strings.xml

    [html] view plaincopy
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <resources>  
    3.   
    4.     <string name="app_name">downloads</string>  
    5.     <string name="action_settings">Settings</string>  
    6.     <string name="tv_down">文件下载的地址</string>  
    7.     <string name="tv_threadNum">线程数量</string>  
    8.     <string name="tv_num">0%</string>  
    9.     <string name="btn_text">下载</string>  
    10.     <string name="btn_pause">暂停</string>  
    11.     <string name="et_path">http://172.22.64.8:8080/doudou/youdao.exe</string>  
    12.     <string name="et_threadNum">3</string>  
    13.   
    14. </resources>  

    布局文件:

    [html] view plaincopy
    1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    2.     xmlns:tools="http://schemas.android.com/tools"  
    3.     android:layout_width="match_parent"  
    4.     android:layout_height="match_parent"  
    5.     android:paddingBottom="@dimen/activity_vertical_margin"  
    6.     android:paddingLeft="@dimen/activity_horizontal_margin"  
    7.     android:paddingRight="@dimen/activity_horizontal_margin"  
    8.     android:paddingTop="@dimen/activity_vertical_margin"  
    9.     tools:context=".DownActivity" >  
    10.   
    11.     <TextView  
    12.         android:id="@+id/textView1"  
    13.         android:layout_width="wrap_content"  
    14.         android:layout_height="wrap_content"  
    15.         android:layout_alignParentLeft="true"  
    16.         android:layout_alignParentTop="true"  
    17.         android:text="@string/tv_down" />  
    18.   
    19.     <EditText  
    20.         android:id="@+id/et_path"  
    21.         android:layout_width="wrap_content"  
    22.         android:layout_height="wrap_content"  
    23.         android:layout_alignParentLeft="true"  
    24.         android:layout_alignParentRight="true"  
    25.         android:layout_below="@+id/textView1"  
    26.         android:ems="10"  
    27.         android:inputType="none"  
    28.         android:text="@string/et_path" >  
    29.   
    30.         <requestFocus />  
    31.     </EditText>  
    32.   
    33.     <TextView  
    34.         android:id="@+id/textView2"  
    35.         android:layout_width="wrap_content"  
    36.         android:layout_height="wrap_content"  
    37.         android:layout_alignParentLeft="true"  
    38.         android:layout_below="@+id/et_path"  
    39.         android:text="@string/tv_threadNum" />  
    40.   
    41.     <EditText  
    42.         android:id="@+id/et_threadNum"  
    43.         android:layout_width="wrap_content"  
    44.         android:layout_height="wrap_content"  
    45.         android:layout_alignLeft="@+id/textView2"  
    46.         android:layout_alignRight="@+id/et_path"  
    47.         android:layout_below="@+id/textView2"  
    48.         android:ems="10"  
    49.         android:inputType="number"  
    50.         android:text="@string/et_threadNum" />  
    51.   
    52.     <ProgressBar  
    53.         android:id="@+id/pb_down"  
    54.         style="?

      android:attr/progressBarStyleHorizontal"  

    55.         android:layout_width="wrap_content"  
    56.         android:layout_height="wrap_content"  
    57.         android:layout_alignLeft="@+id/et_threadNum"  
    58.         android:layout_alignRight="@+id/et_threadNum"  
    59.         android:layout_below="@+id/et_threadNum"  
    60.         android:layout_marginTop="14dp" />  
    61.   
    62.     <TextView  
    63.         android:id="@+id/tv_pb"  
    64.         android:layout_width="wrap_content"  
    65.         android:layout_height="wrap_content"  
    66.         android:layout_alignRight="@+id/textView1"  
    67.         android:layout_below="@+id/pb_down"  
    68.         android:layout_marginTop="24dp"  
    69.         android:text="@string/tv_num" />  
    70.   
    71.     <Button  
    72.         android:id="@+id/btn_down"  
    73.         android:layout_width="wrap_content"  
    74.         android:layout_height="wrap_content"  
    75.         android:layout_alignLeft="@+id/pb_down"  
    76.         android:layout_below="@+id/tv_pb"  
    77.         android:layout_marginTop="32dp"  
    78.         android:onClick="downLoad"  
    79.         android:text="@string/btn_text" />  
    80.   
    81.     <Button  
    82.         android:id="@+id/button1"  
    83.         android:layout_width="wrap_content"  
    84.         android:layout_height="wrap_content"  
    85.         android:layout_alignLeft="@+id/btn_down"  
    86.         android:layout_below="@+id/btn_down"  
    87.         android:layout_marginTop="16dp"  
    88.         android:onClick="downPause"  
    89.         android:text="@string/btn_pause" />  
    90.   
    91. </RelativeLayout>  

    效果例如以下:


    最后要注意的是别忘了在项目清单文件里增加权限:

    [html] view plaincopy
    1. <!-- SDCard权限 -->  
    2.     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />  
    3.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
    4.     <!-- 訪问网络的权限 -->  
    5.     <uses-permission android:name="android.permission.INTERNET" />  

    1. http://blog.csdn.net/sgx425021234/article/details/9191963
  • 相关阅读:
    python调用ggsci.exe程序
    confluence安装
    nginx优化
    ELKstack搭建
    zabbix 安装
    python requests
    小程序消息推送
    shell
    rar 解压
    ubuntu 安装部分设置U盘启动系统安装盘操作
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5203446.html
Copyright © 2011-2022 走看看