ANDROID笔记:多线程断点下载

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" />

 

 

 

你可能感兴趣的:(android)