1.布局文件:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".MainActivity" >    <TextView        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="请输入下载文件的路径" />    <EditText        android:id="@+id/et_path"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="http://192.168.1.100:8080/" />    <TextView        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="请输入线程的数量" />    <EditText        android:id="@+id/et_count"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:inputType="number"        android:text="3" />    <Button        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:onClick="downLoad"        android:text="下载" />    <LinearLayout        android:id="@+id/ll_container"        android:orientation="vertical"        android:layout_width="fill_parent"        android:layout_height="fill_parent" >    </LinearLayout></LinearLayout>进度条的布局:<?xml version="1.0" encoding="utf-8"?><ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/progressBar1"    style="?android:attr/progressBarStyleHorizontal"    android:layout_width="fill_parent"    android:layout_height="wrap_content" />业务逻辑代码的实现: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;//url路径    private EditText et_count;//线程数量    /** * 存放进度条的布局 */    private LinearLayout ll_container;    /** * 进度条的集合 */    private List<ProgressBar> pbs;    /** * 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<ProgressBar>();        for(int j=0;j<threadCount;j++){            ProgressBar pb = (ProgressBar) View.inflate(this, R.layout.pb, null);            ll_container.addView(pb);//把进度条添加到现行布局的容器中            pbs.add(pb);//把进度条添加到进度条集合中。        }        Toast.makeText(this, "开始下载", 0).show();        new Thread(){            public void run() {                try {                    URL url = new URL(path);                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();                    conn.setRequestMethod("GET");                    conn.setConnectTimeout(5000);                    int code = conn.getResponseCode();                    if (code == 200) {                        long size = conn.getContentLength();// 得到服务端返回的文件的大小                        System.out.println("服务器文件的大小:" + size);                        blocksize = size / threadCount;                        // 1.首先在本地创建一个大小跟服务器一模一样的空白文件。                        File file = new File(Environment.getExternalStorageDirectory(),getFileName(path));                        RandomAccessFile raf = new RandomAccessFile(file, "rw");                        raf.setLength(size);                        // 2.开启若干个子线程分别去下载对应的资源。                        runningThreadCount = threadCount;                        for (int i = 1; i <= threadCount; i++) {                            long startIndex = (i - 1) * blocksize;                            long endIndex = i * blocksize - 1;                            if (i == threadCount) {                                // 最后一个线程                                endIndex = size - 1;                            }                            System.out.println("开启线程:" + i + "下载的位置:" + startIndex + "~"                                    + endIndex);                            int threadSize = (int) (endIndex - startIndex);                            pbs.get(i-1).setMax(threadSize);                            new DownloadThread(path, i, startIndex, endIndex).start();                        }                    }                    conn.disconnect();                } catch (Exception e) {                    e.printStackTrace();                    Message msg = Message.obtain();                    msg.what = DOWNLOAD_ERROR;                    handler.sendMessage(msg);                }            };        }.start();    }    private class DownloadThread extends Thread {        private int threadId;        private long startIndex;        private long endIndex;        private String path;        public DownloadThread(String path, int threadId, long startIndex,                long endIndex) {            this.path = path;            this.threadId = threadId;            this.startIndex = startIndex;            this.endIndex = endIndex;        }        @Override        public void run() {            try {                // 当前线程下载的总大小                int total = 0;                //下载的进度信息存储到一个文本文件中。以线程id命名。                File positionFile = new File(Environment.getExternalStorageDirectory(),getFileName(path)+threadId + ".txt");                URL url = new URL(path);                HttpURLConnection conn = (HttpURLConnection) url                        .openConnection();                conn.setRequestMethod("GET");                // 接着从上一次的位置继续下载数据                if (positionFile.exists() && positionFile.length() > 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();                    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);    }

更多相关文章

  1. Android 编译提示R文件找不到
  2. 总结系列-Android的文件系统
  3. Android JNI学习笔记——so文件动态加载
  4. android.inputmethodservice.KeyboardView 自定义键盘 字体大小
  5. Android APK 文件自动安装
  6. Android读写文件二
  7. android ddms查看线程
  8. Android处理9.png文件流程
  9. Attribute is missing the Android namespace prefix——android

随机推荐

  1. Android(安卓)App开发基础篇—实现非阻塞
  2. 【Android】Navigation初试-基于官方demo
  3. Android AIDL使用详解 +整合应用
  4. ViewGroup之android:animateLayoutChange
  5. Android中Activity跳转和切换动画
  6. cocos2d-x编译到android平台后,增加返回键
  7. XmlPullParser.nextText() bug 好文章,使
  8. Android蓝牙设备的检测
  9. Android(java)学习笔记71:生产者和消费者之
  10. Android 添加同名通讯录自动合并的问题