多线程下载

来源:互联网 发布:全友家私 知乎 编辑:程序博客网 时间:2024/06/03 17:28
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.INTERNET"/>




public class Main2Activity extends FragmentActivity {    private static final String TAG = MainActivity.class.getSimpleName();    private ProgressBar mProgressBar;    private Button start;    private Button pause;    private TextView total;    private int max;    private DownloadUtil mDownloadUtil;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main2);        total= (TextView) findViewById(R.id.textView);        start= (Button) findViewById(R.id.start);        pause= (Button) findViewById(R.id.delete);        mProgressBar= (ProgressBar) findViewById(R.id.progressBar);        String urlString = "http://2449.vod.myqcloud.com/2449_bfbbfa3cea8f11e5aac3db03cda99974.f20.mp4";        String localPath = Environment.getExternalStorageDirectory()                .getAbsolutePath() + "/local";        mDownloadUtil = new DownloadUtil(2, localPath, "f20.mp4", urlString,                this);        mDownloadUtil.setOnDownloadListener(new DownloadUtil.OnDownloadListener() {            @Override            public void downloadStart(int fileSize) {                // TODO Auto-generated method stub                Log.w(TAG, "fileSize::" + fileSize);                max = fileSize;                mProgressBar.setMax(fileSize);            }            @Override            public void downloadProgress(int downloadedSize) {                // TODO Auto-generated method stub                Log.w(TAG, "Compelete::" + downloadedSize);                mProgressBar.setProgress(downloadedSize);                total.setText((int) downloadedSize * 100 / max + "%");            }            @Override            public void downloadEnd() {                // TODO Auto-generated method stub                Log.w(TAG, "ENd");            }        });        start.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View arg0) {                // TODO Auto-generated method stub                mDownloadUtil.start();            }        });        pause.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View arg0) {                // TODO Auto-generated method stub                mDownloadUtil.pause();            }        });    }}


<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.example.lenovo.zhonghelianxi.view.Main2Activity">    <TextView        android:id="@+id/textView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentLeft="true"        android:layout_alignParentStart="true"        android:layout_alignParentTop="true"        android:layout_marginLeft="23dp"        android:layout_marginStart="23dp"        android:layout_marginTop="18dp"        android:text="TextView" />    <ProgressBar        android:id="@+id/progressBar"        style="?android:attr/progressBarStyleHorizontal"        android:layout_width="fill_parent"        android:layout_height="7.5dp"        android:max="100"        android:progress="100"        android:layout_marginRight="8dp"        android:layout_below="@+id/textView"        android:visibility="visible"/>    <Button        android:id="@+id/start"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_toEndOf="@+id/textView"        android:layout_toRightOf="@+id/textView"        android:text="下载" />    <Button        android:id="@+id/delete"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_marginLeft="48dp"        android:layout_marginStart="48dp"        android:layout_toEndOf="@+id/start"        android:layout_toRightOf="@+id/start"        android:text="暂停" /></RelativeLayout>




public class DownlaodSqlTool {    private DownLoadHelper dbHelper;    public DownlaodSqlTool(Context context){        dbHelper=new DownLoadHelper(context);    }    /**     * 创建下载的具体信息     */    public void insertInfos(List<DownloadInfo> infos) {        SQLiteDatabase database = dbHelper.getWritableDatabase();        for (DownloadInfo info : infos) {            String sql = "insert into download_info(thread_id,start_pos, end_pos,compelete_size,url) values (?,?,?,?,?)";            Object[] bindArgs = { info.getThreadId(), info.getStartPos(),                    info.getEndPos(), info.getCompeleteSize(), info.getUrl() };            database.execSQL(sql, bindArgs);        }    }    /**     * 得到下载具体信息     */    public List<DownloadInfo> getInfos(String urlstr) {        List<DownloadInfo> list = new ArrayList<DownloadInfo>();        SQLiteDatabase database = dbHelper.getWritableDatabase();        String sql = "select thread_id, start_pos, end_pos,compelete_size,url from download_info where url=?";        Cursor cursor = database.rawQuery(sql, new String[] { urlstr });        while (cursor.moveToNext()) {            DownloadInfo info = new DownloadInfo(cursor.getInt(0),                    cursor.getInt(1), cursor.getInt(2), cursor.getInt(3),                    cursor.getString(4));            list.add(info);        }        return list;    }    /**     * 更新数据库中的下载信息     */    public void updataInfos(int threadId, int compeleteSize, String urlstr) {        SQLiteDatabase database = dbHelper.getWritableDatabase();        String sql = "update download_info set compelete_size=? where thread_id=? and url=?";        Object[] bindArgs = { compeleteSize, threadId, urlstr };        database.execSQL(sql, bindArgs);    }    /**     * 关闭数据库     */    public void closeDb() {        dbHelper.close();    }    /**     * 下载完成后删除数据库中的数据     */    public void delete(String url) {        SQLiteDatabase database = dbHelper.getWritableDatabase();        database.delete("download_info", "url=?", new String[] { url });    }}


public class DownLoadHelper extends SQLiteOpenHelper{    private static final String SQL_NAME = "download.db";    private static final int DOWNLOAD_VERSION=1;    public DownLoadHelper(Context context) {        super(context, SQL_NAME, null, DOWNLOAD_VERSION);    }    @Override    public void onCreate(SQLiteDatabase db) {        db.execSQL("create table download_info(_id integer PRIMARY KEY AUTOINCREMENT, thread_id integer, "                + "start_pos integer, end_pos integer, compelete_size integer,url char)");    }    @Override    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {    }}



public class DownloadHttpTool {    /**     *     * 利用Http协议进行多线程下载具体实践类     */    private static final String TAG = DownloadHttpTool.class.getSimpleName();    private int threadCount;//线程数量    private String urlstr;//URL地址    private Context mContext;    private Handler mHandler;    private List<DownloadInfo> downloadInfos;//保存下载信息的类    private String localPath;//目录    private String fileName;//文件名    private int fileSize;    private DownlaodSqlTool sqlTool;//文件信息保存的数据库操作类    private enum Download_State {        Downloading, Pause, Ready;//利用枚举表示下载的三种状态    }    private Download_State state = Download_State.Ready;//当前下载状态    private int globalCompelete = 0;//所有线程下载的总数    public DownloadHttpTool(int threadCount, String urlString,                            String localPath, String fileName, Context context, Handler handler) {        super();        this.threadCount = threadCount;        this.urlstr = urlString;        this.localPath = localPath;        this.mContext = context;        this.mHandler = handler;        this.fileName = fileName;        sqlTool = new DownlaodSqlTool(mContext);    }    //在开始下载之前需要调用ready方法进行配置    public void ready() {        Log.w(TAG, "ready");        globalCompelete = 0;        downloadInfos = sqlTool.getInfos(urlstr);        if (downloadInfos.size() == 0) {            initFirst();        } else {            File file = new File(localPath + "/" + fileName);            if (!file.exists()) {                sqlTool.delete(urlstr);                initFirst();            } else {                fileSize = downloadInfos.get(downloadInfos.size() - 1)                        .getEndPos();                for (DownloadInfo info : downloadInfos) {                    globalCompelete += info.getCompeleteSize();                }                Log.w(TAG, "globalCompelete:::" + globalCompelete);            }        }    }    public void start() {        Log.w(TAG, "start");        if (downloadInfos != null) {            if (state == Download_State.Downloading) {                return;            }            state = Download_State.Downloading;            for (DownloadInfo info : downloadInfos) {                Log.v(TAG, "startThread");                new DownloadThread(info.getThreadId(), info.getStartPos(),                        info.getEndPos(), info.getCompeleteSize(),                        info.getUrl()).start();            }        }    }    public void pause() {        state = Download_State.Pause;        sqlTool.closeDb();    }    public void delete(){        compelete();        File file = new File(localPath + "/" + fileName);        file.delete();    }    public void compelete() {        sqlTool.delete(urlstr);        sqlTool.closeDb();    }    public int getFileSize() {        return fileSize;    }    public int getCompeleteSize() {        return globalCompelete;    }    //第一次下载初始化    private void initFirst() {        Log.w(TAG, "initFirst");        try {            URL url = new URL(urlstr);            HttpURLConnection connection = (HttpURLConnection) url                    .openConnection();            connection.setConnectTimeout(5000);            connection.setRequestMethod("GET");            fileSize = connection.getContentLength();            Log.w(TAG, "fileSize::" + fileSize);            File fileParent = new File(localPath);            if (!fileParent.exists()) {                fileParent.mkdir();            }            File file = new File(fileParent, fileName);            if (!file.exists()) {                file.createNewFile();            }            // 本地访问文件            RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");            accessFile.setLength(fileSize);            accessFile.close();            connection.disconnect();        } catch (Exception e) {            e.printStackTrace();        }        int range = fileSize / threadCount;        downloadInfos = new ArrayList<DownloadInfo>();        for (int i = 0; i < threadCount - 1; i++) {            DownloadInfo info = new DownloadInfo(i, i * range, (i + 1) * range                    - 1, 0, urlstr);            downloadInfos.add(info);        }        DownloadInfo info = new DownloadInfo(threadCount - 1, (threadCount - 1)                * range, fileSize - 1, 0, urlstr);        downloadInfos.add(info);        sqlTool.insertInfos(downloadInfos);    }    //自定义下载线程    private class DownloadThread extends Thread {        private int threadId;        private int startPos;        private int endPos;        private int compeleteSize;        private String urlstr;        private int totalThreadSize;        public DownloadThread(int threadId, int startPos, int endPos,                              int compeleteSize, String urlstr) {            this.threadId = threadId;            this.startPos = startPos;            this.endPos = endPos;            totalThreadSize = endPos - startPos + 1;            this.urlstr = urlstr;            this.compeleteSize = compeleteSize;        }        @Override        public void run() {            HttpURLConnection connection = null;            RandomAccessFile randomAccessFile = null;            InputStream is = null;            try {                randomAccessFile = new RandomAccessFile(localPath + "/"                        + fileName, "rwd");                randomAccessFile.seek(startPos + compeleteSize);                URL url = new URL(urlstr);                connection = (HttpURLConnection) url.openConnection();                connection.setConnectTimeout(5000);                connection.setRequestMethod("GET");                connection.setRequestProperty("Range", "bytes="                        + (startPos + compeleteSize) + "-" + endPos);                is = connection.getInputStream();                byte[] buffer = new byte[1024];                int length = -1;                while ((length = is.read(buffer)) != -1) {                    randomAccessFile.write(buffer, 0, length);                    compeleteSize += length;                    Message message = Message.obtain();                    message.what = threadId;                    message.obj = urlstr;                    message.arg1 = length;                    mHandler.sendMessage(message);                    sqlTool.updataInfos(threadId, compeleteSize, urlstr);                    Log.w(TAG, "Threadid::" + threadId + "    compelete::"                            + compeleteSize + "    total::" + totalThreadSize);                    if (compeleteSize >= totalThreadSize) {                        break;                    }                    if (state != Download_State.Downloading) {                        break;                    }                }            } catch (Exception e) {                e.printStackTrace();            } finally {                try {                    if (is != null) {                        is.close();                    }                    randomAccessFile.close();                    connection.disconnect();                } catch (Exception e) {                    e.printStackTrace();                }            }        }    }}





public class DownloadInfo {   /**    * 保存每个下载线程下载信息类    *     */      private int threadId;// 下载器id   private int startPos;// 开始点   private int endPos;// 结束点   private int compeleteSize;// 完成度   private String url;// 下载文件的URL地址      public DownloadInfo(int threadId, int startPos, int endPos,         int compeleteSize, String url) {      this.threadId = threadId;      this.startPos = startPos;      this.endPos = endPos;      this.compeleteSize = compeleteSize;      this.url = url;   }   public DownloadInfo() {   }   public String getUrl() {      return url;   }   public void setUrl(String url) {      this.url = url;   }   public int getThreadId() {      return threadId;   }   public void setThreadId(int threadId) {      this.threadId = threadId;   }   public int getStartPos() {      return startPos;   }   public void setStartPos(int startPos) {      this.startPos = startPos;   }   public int getEndPos() {      return endPos;   }   public void setEndPos(int endPos) {      this.endPos = endPos;   }   public int getCompeleteSize() {      return compeleteSize;   }   public void setCompeleteSize(int compeleteSize) {      this.compeleteSize = compeleteSize;   }   @Override   public String toString() {      return "DownloadInfo [threadId=" + threadId + ", startPos=" + startPos            + ", endPos=" + endPos + ", compeleteSize=" + compeleteSize            + "]";   }}



/** * 将下载方法封装在此类 * 提供下载,暂停,删除,以及重置的方法 */public class DownloadUtil {     private DownloadHttpTool mDownloadHttpTool;    private OnDownloadListener onDownloadListener;     private int fileSize;    private int downloadedSize = 0;     @SuppressLint("HandlerLeak")    private Handler mHandler = new Handler() {         @Override        public void handleMessage(Message msg) {            // TODO Auto-generated method stub            super.handleMessage(msg);            int length = msg.arg1;            synchronized (this) {//加锁保证已下载的正确性                downloadedSize += length;            }            if (onDownloadListener != null) {                onDownloadListener.downloadProgress(downloadedSize);            }            if (downloadedSize >= fileSize) {                mDownloadHttpTool.compelete();                if (onDownloadListener != null) {                    onDownloadListener.downloadEnd();                }            }        }     };     public DownloadUtil(int threadCount, String filePath, String filename,            String urlString, Context context) {         mDownloadHttpTool = new DownloadHttpTool(threadCount, urlString,                filePath, filename, context, mHandler);    }     //下载之前首先异步线程调用ready方法获得文件大小信息,之后调用开始方法    public void start() {        new AsyncTask<Void,Void,Void>() {             @Override            protected Void doInBackground(Void... arg0) {                // TODO Auto-generated method stub                mDownloadHttpTool.ready();                return null;            }             @Override            protected void onPostExecute(Void result) {                // TODO Auto-generated method stub                super.onPostExecute(result);                fileSize = mDownloadHttpTool.getFileSize();                downloadedSize = mDownloadHttpTool.getCompeleteSize();                Log.w("Tag", "downloadedSize::" + downloadedSize);                if (onDownloadListener != null) {                    onDownloadListener.downloadStart(fileSize);                }                mDownloadHttpTool.start();            }        }.execute();    }     public void pause() {        mDownloadHttpTool.pause();    }         public void delete(){        mDownloadHttpTool.delete();    }     public void reset(){        mDownloadHttpTool.delete();        start();    }         public void setOnDownloadListener(OnDownloadListener onDownloadListener) {        this.onDownloadListener = onDownloadListener;    }     //下载回调接口    public interface OnDownloadListener {        public void downloadStart(int fileSize);         public void downloadProgress(int downloadedSize);//记录当前所有线程下总和         public void downloadEnd();    }}













原创粉丝点击