进度条是通过填充器导入pb.xml文件来显示的
java代码参照java栏目的多线程下载代码解释
package com.itheima.mutilethread;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;import java.util.ArrayList;import java.util.List;import android.app.Activity;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.text.TextUtils;import android.view.View;import android.widget.EditText;import android.widget.LinearLayout;import android.widget.ProgressBar;import android.widget.Toast;public class MainActivity extends Activity { protected static final int DOWNLOAD_ERROR = 1; private static final int THREAD_ERROR = 2; public static final int DWONLOAD_FINISH = 3; private EditText et_path; private EditText et_count; /** * 存放进度条的布局 */ private LinearLayout ll_container; /** * 进度条的集合 */ private Listpbs; /** * android下的消息处理器,在主线程创建,才可以更新ui */ private Handler handler = new Handler(){ public void handleMessage(Message msg) { switch (msg.what) { case DOWNLOAD_ERROR: Toast.makeText(getApplicationContext(), "下载失败", 0).show(); break; case THREAD_ERROR: Toast.makeText(getApplicationContext(), "下载失败,请重试", 0).show(); break; case DWONLOAD_FINISH: Toast.makeText(getApplicationContext(), "下载完成", 0).show(); break; } }; }; /** * 线程的数量 */ private int threadCount = 3; /** * 每个下载区块的大小 */ private long blocksize; /** * 正在运行的线程的数量 */ private int runningThreadCount; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_path = (EditText) findViewById(R.id.et_path); et_count = (EditText) findViewById(R.id.et_count); ll_container = (LinearLayout) findViewById(R.id.ll_container); } /** * 下载按钮的点击事件 * @param view */ public void downLoad(View view){ //下载文件的路径 final String path = et_path.getText().toString().trim(); if(TextUtils.isEmpty(path)){ Toast.makeText(this, "对不起下载路径不能为空", 0).show(); return; } String count = et_count.getText().toString().trim(); if(TextUtils.isEmpty(path)){ Toast.makeText(this, "对不起,线程数量不能为空", 0).show(); return; } threadCount = Integer.parseInt(count); //清空掉旧的进度条 ll_container.removeAllViews(); //在界面里面添加count个进度条 pbs = new ArrayList (); for(int j=0;j 0) {// 判断是否有记录 FileInputStream fis = new FileInputStream(positionFile); BufferedReader br = new BufferedReader( new InputStreamReader(fis)); // 获取当前线程上次下载的总大小是多少 String lasttotalstr = br.readLine(); int lastTotal = Integer.valueOf(lasttotalstr); System.out.println("上次线程" + threadId + "下载的总大小:" + lastTotal); startIndex += lastTotal; total += lastTotal;// 加上上次下载的总大小。 fis.close(); //存数据库。 //_id path threadid total } conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); conn.setConnectTimeout(5000); int code = conn.getResponseCode(); System.out.println("code=" + code); InputStream is = conn.getInputStream(); File file = new File(Environment.getExternalStorageDirectory(),getFileName(path)); RandomAccessFile raf = new RandomAccessFile(file, "rw"); // 指定文件开始写的位置。 raf.seek(startIndex); System.out.println("第" + threadId + "个线程:写文件的开始位置:" + String.valueOf(startIndex)); int len = 0; byte[] buffer = new byte[1024]; while ((len = is.read(buffer)) != -1) { RandomAccessFile rf = new RandomAccessFile(positionFile, "rwd"); raf.write(buffer, 0, len); total += len; rf.write(String.valueOf(total).getBytes()); rf.close(); //total是当前下载量 更新到进度条中 内部包装好了Message,所以这里是子线程也可以直接更新UI pbs.get(threadId-1).setProgress(total); } is.close(); raf.close(); } catch (Exception e) { e.printStackTrace(); Message msg = Message.obtain(); msg.what = THREAD_ERROR; handler.sendMessage(msg); } finally { // 只有所有的线程都下载完毕后 才可以删除记录文件。 synchronized (MainActivity.class) { System.out.println("线程" + threadId + "下载完毕了"); runningThreadCount--; if (runningThreadCount < 1) { System.out.println("所有的线程都工作完毕了。删除临时记录的文件"); for (int i = 1; i <= threadCount; i++) { File f = new File(Environment.getExternalStorageDirectory(),getFileName(path)+ i + ".txt"); System.out.println(f.delete()); } Message msg = Message.obtain(); msg.what = DWONLOAD_FINISH; handler.sendMessage(msg); } } } } } //http://192.168.1.100:8080/aa.exe private String getFileName(String path){ int start = path.lastIndexOf("/")+1; return path.substring(start); } }
访问网路和写sd卡的权限