zoukankan      html  css  js  c++  java
  • ANDROID笔记:多线程断点下载

    //mainActivity

    package com.example.multthreaddownload;
    
    import java.io.File;
    import java.io.IOException;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    
    import android.annotation.SuppressLint;
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.Handler;
    import android.os.Message;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ProgressBar;
    import android.widget.TextView;
    
    import com.example.multthreaddownload.DownLoadThread.DownLoadState;
    import com.example.multthreaddownload.util.Breakpoint;
    import com.example.multthreaddownload.util.MyPoint;
    
    /**
     * 主类 实现DownLoadState接口,用于控制下载线程的结束
     * 
     * @author Administrator
     * 
     */
    public class MainActivity extends Activity implements DownLoadState {
        private ProgressBar bar = null;
        private EditText text;
        private TextView textView;
        private int filelength = 0;
        // 下载状态
        private boolean isRunning = false;
        // 下载路径
        private File father = Environment.getExternalStorageDirectory();
        private File file = new File(father, "file.mp3");
        // 断点集合类
        private Breakpoint breakpoint = null;
        // 开始/暂停
        private boolean isPause = false;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
        }
    
        private void initView() {
            bar = (ProgressBar) findViewById(R.id.progressBar1);
            text = (EditText) findViewById(R.id.url);
            final Button button = (Button) findViewById(R.id.button1);
            textView = (TextView) findViewById(R.id.textView1);
            button.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (isRunning) {
                        isRunning = false;
                        isPause = true;
                        button.setText("开始");
                    } else {// 开始/继续下载
                        isRunning = true;
                        // 测试数据
                        text.setText("http://172.16.12.82:8080/AIAIAPP/file.mp3");
                        if (isPause) {
                            conntineDown();
                        } else {
                            startDown();
                        }
                        isPause = false;
                        button.setText("暂停");
                    }
                }
            });
        }
    
        /* 消息处理 */
        int len = 0;
        @SuppressLint("HandlerLeak")
        private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == 0x1) {
                    len = len + Integer.valueOf(msg.obj.toString());
                    bar.setProgress(len);
                    textView.setText(len + "/" + filelength);
                } else if (msg.what == 0x2) {
                    if (breakpoint == null) {// 单例模式
                        breakpoint = new Breakpoint(text.getText().toString(),
                                file.getAbsolutePath());
                    }
                    // 得到各个线程的断点
                    MyPoint myPoint = (MyPoint) msg.obj;
                    // 添加到断点集合类
                    breakpoint.add(myPoint);
                }
            }
        };
    
        /**
         * 下载线程
         */
        private void startDown() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    int threadNumber = 1;// 设置线程个数
                    URL url;
                    try {
                        url = new URL(text.getText().toString());
                        HttpURLConnection http = (HttpURLConnection) url
                                .openConnection();
                        filelength = http.getContentLength();// 获取下载文件的长度
                        // 设置进度条的最大值
                        bar.setMax(filelength);
                        System.out.println("文件长度:" + filelength);
                        // 每个线程需要下载的大小
                        int length = filelength / threadNumber;
                        for (int i = 0; i < threadNumber - 1; i++) {
                            new DownLoadThread().startDownload(MainActivity.this,
                                    i, text.getText().toString(), file, i * length,
                                    (i + 1) * length, handler);
                        }
                        // 最后一个线程下载剩余的空间
                        new DownLoadThread().startDownload(MainActivity.this, 4,
                                text.getText().toString(), file, (threadNumber - 1)
                                        * length, filelength, handler);
                        System.out.println("设置完毕");
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
    
                }
            }).start();
        }
    
        /**
         * 继续下载
         */
        private void conntineDown() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.err.println("继续下载");
                    System.err.println(breakpoint.get().size());
                    // 根据断点集合类中集合的大小生成下载线程
                    for (int i = 0; i < breakpoint.get().size(); i++) {
                        // 得到各个断点
                        MyPoint point = breakpoint.get().get(i);
                        // 下载开始点和结束点:point.startPos--->point.endPos
                        new DownLoadThread().startDownload(MainActivity.this, i,
                                breakpoint.url, new File(breakpoint.filePath),
                                point.startPos, point.endPos, handler);
                    }
                    // 清空断点记录
                    breakpoint.get().clear();
                }
            }).start();
        }
    
        /**
         * 实现接口,当返回的isRunning为false时,所有下载线程停止
         */
        @Override
        public boolean handle() {
            return isRunning;
        }
    
    }

    //下载工具类DownLoadThread

    package com.example.multthreaddownload;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.RandomAccessFile;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    
    import android.annotation.SuppressLint;
    import android.os.Handler;
    import android.os.Message;
    
    import com.example.multthreaddownload.util.MyPoint;
    
    /**
     * 下载线程
     * 
     * @author Administrator
     * 
     */
    public class DownLoadThread {
        private String urlString;
        private File file = null;
        private int startPos;
        private int endPos;
        // 用于将信息传递给主类
        private Handler handler;
        private int id = 0;
        // 控制线程的结束
        DownLoadState state = null;
    
        public void startDownload(DownLoadState state, int id, String urlString,
                File file, int startPos, int endPos, Handler handler) {
            this.state = state;
            this.id = id;
            this.urlString = urlString;
            this.file = file;
            this.startPos = startPos;
            this.endPos = endPos;
            this.handler = handler;
            // 启动下载线程
            new Thread(new myRunnable()).start();
        }
    
        private class myRunnable implements Runnable {
            @SuppressLint("SdCardPath")
            @Override
            public void run() {
                // {
                // Message msg = new Message();
                // msg.obj = "线程启动";
                // handler.sendMessage(msg);
                // }
                try {
                    // System.err.println(startPos + "--->" + endPos);
                    URL url = new URL(urlString);
                    // System.out.println("file.exists():" + file.exists());
                    // System.out.println(file.getAbsolutePath());
                    if (!file.exists()) {
                        file.createNewFile();
                    }
                    // System.out.println("file.exists():" + file.exists());
                    HttpURLConnection http = (HttpURLConnection) url
                            .openConnection();
                    // 请求时长
                    http.setConnectTimeout(5 * 1000);
                    http.setRequestMethod("GET");
                    http.setRequestProperty("Range", "bytes=" + startPos + "-"
                            + endPos);// 设置获取实体数据的范围
                    InputStream inStream = http.getInputStream();
                    byte[] buffer = new byte[1024];
                    int offset = 0;
                    RandomAccessFile threadfile = new RandomAccessFile(file, "rwd");
                    // 设置距离文件开头的指针偏移量(将文件读写指针移动至startPos位置)
                    threadfile.seek(startPos);
                    int len = 0;
                    // state.handle()控制循环(控制线程停止)
                    while (state.handle()
                            && (offset = inStream.read(buffer, 0, 1024)) != -1) {
                        threadfile.write(buffer, 0, offset);
                        len = len + offset;
                        {// 将下载进度传递给主类,控制进度条
                            Message msg = new Message();
                            msg.what = 0x1;
                            msg.obj = offset;
                            handler.sendMessage(msg);
                        }
                    }
                    // 当线程停止时,将断点信息船体给主类
                    if (!state.handle()) {
                        // System.err.println(id + "--" + startPos + "--"
                        // + (startPos + len) + "--" + endPos);
                        // System.err.println(id + "pause");
                        {
                            MyPoint point = new MyPoint((startPos + len), endPos);
                            Message msg = new Message();
                            msg.what = 0x2;
                            msg.obj = point;
                            handler.sendMessage(msg);
                        }
                    }
                    threadfile.close();
                    inStream.close();
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                {
                    Message msg = new Message();
                    msg.obj = "线程下载完毕";
                    handler.sendMessage(msg);
                }
            }
        }
    
        /**
         * 接口
         * 
         * @author Administrator
         * 
         */
        public interface DownLoadState {
            public boolean handle();
        }
    
    }

    //断点集合类

    package com.example.multthreaddownload.util;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    
    public class Breakpoint {
        public String url;
        public String filePath;
    
        public Breakpoint(String url, String filePath) {
            this.url = url;
            this.filePath = filePath;
        }
    
        private List<MyPoint> points = new ArrayList<MyPoint>();
    
        public void add(MyPoint point) {
            points.add(point);
        }
    
        public List<MyPoint> get() {
            return points;
        }
    
    }

    //断点类

    package com.example.multthreaddownload.util;
    
    public class MyPoint {
    
        public int startPos;
        public int endPos;
    
        public MyPoint(int startPos, int endPos) {
            this.startPos = startPos;
            this.endPos = endPos;
        }
    
    }

    界面XML文件

    <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity" >
    
        <Button
            android:id="@+id/button1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/url"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_marginBottom="156dp"
            android:text="下载" />
    
        <EditText
            android:id="@+id/url"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="33dp"
            android:ems="10"
            android:singleLine="true" >
    
            <requestFocus />
        </EditText>
    
        <ProgressBar
            android:id="@+id/progressBar1"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/url"
            android:layout_below="@+id/url"
            android:layout_marginTop="60dp" />
    
        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignRight="@+id/progressBar1"
            android:layout_below="@+id/progressBar1"
            android:layout_marginTop="20dp"
            android:textAppearance="?android:attr/textAppearanceLarge" />
    
    </RelativeLayout>

    //需要下列权限(有wifi权限是因为在真机上用wifi调试了)

        <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
        <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.WAKE_LOCK" />
        <!-- 在SDCard中创建与删除文件权限 -->
    
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  • 相关阅读:
    C#基础知识系列十(集合)
    C#基础知识系列九(对IEnumerable和IEnumerator接口的糊涂认识)
    C#基础知识系列八(const和readonly关键字)
    C#基础知识系列七(base、this、new、override、abstract、virtual、static)
    C#基础知识系列六(静态类和静态类成员)
    C#基础知识系列五(构造函数)
    C#基础知识系列四(运算符汇总)
    C#基础知识系列三(类和结构体、String和StringBuilder、equals和==)
    C#基础知识系列二(值类型和引用类型、可空类型、堆和栈、装箱和拆箱)
    C#基础知识系列一(goto、i++、三元运算符、ref和out、String和string、重载运算符)
  • 原文地址:https://www.cnblogs.com/afluy/p/3440883.html
Copyright © 2011-2022 走看看