Android斷點續傳原理及實現

原理:利用HttpURLConnection進行從網站上下載文件時,我們可以利用HttpURLConnection的setRequestProperty()方法,對我們要讀取的字節部分進行控制,比如:

1.Range=0-100代表只讀取前100個字節。
2.Range=100-500代表讀取從第100個字節開始,讀到第500個字節為止。
3.Range=100-則代表從第100個字節開始讀取,一直讀取到文件末尾結束。

這樣我們就可以輕松的實現對文件的各部分的讀取了,我們只需要在暫停時記錄一下已經讀取到的位置,在重新開始的時候利用setRequestProperty()方法設置一下我們要讀取的字節位置即可。

這里還有一個問題就是我們應該怎樣將讀取到的字節流寫入文件中,由于File是不支持在指定處寫入字節的,因此我們這里要使用RandomAccessFile來進行字節流的寫入,RandomAccessFile有一個方法seek(long),允許我們指定要寫入的位置。

這樣兩者結合,就能夠輕易的實現文件的斷點續傳了。

多線程斷點續傳實現原理相同,只是利用多個線程同時下載,每個線程指定要下載的字節部分,寫入到文件的指定部分。故這里只給出了單線程斷點續傳下載的實現部分:

class SingleDownloadTask{

        private String filePath;
        private int contentLength;
        private int readLength;
        private RandomAccessFile file=null;
         private boolean isPause=false;
        private URL url;

         public boolean isDownloading() {
             return isDownloading;
         }

         private boolean isDownloading=false;

        private Handler mHandler=new Handler();

        public SingleDownloadTask(String urlStr,String filePath) {
            this.filePath=filePath;
            readLength=0;
            contentLength=0;
            try {
                url=new URL(urlStr);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
        }

        //download from pos
        public void download(){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    isDownloading=true;
                    HttpURLConnection conn=null;
                    InputStream is=null;
                    BufferedInputStream bis=null;
                    try {
                        file=new RandomAccessFile(filePath,"rw");
                        file.seek(readLength);
                        conn= (HttpURLConnection) url.openConnection();
                        if(readLength==0){
                            contentLength=conn.getContentLength();
                        }else{
                            conn.setRequestProperty("Range","bytes="+readLength+"-");
                        }
                        is=conn.getInputStream();
                        bis=new BufferedInputStream(is);
                        byte[] bytes=new byte[1024];
                        int len=0;
                        while (!isPause&&((len=bis.read(bytes,0,1024)))!=-1){
                            file.write(bytes,0,len);
                            readLength+=len;
                            mHandler.post(new Runnable() {
                                @Override
                                public void run() {
                                    float rate=((float)readLength)/contentLength;
                                    mProgressBar.setProgress((int) (100*rate));
                                    mTextView.setText((int)(100*rate)+"%");
                                }
                            });
                        }
                        isDownloading=false;
                        if (readLength>=contentLength){
                            mHandler.post(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(MainActivity.this, "文件下載成功,保存在"+filePath
                                            , Toast.LENGTH_SHORT).show();
                                    mImageView.setImageBitmap(BitmapFactory.decodeFile(filePath));
                                }
                            });
                        }
                        file.close();
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }finally {
                        if (bis!=null){
                            try {
                                bis.close();
                                if (is!=null){
                                    is.close();
                                }
                                if (conn!=null){
                                    conn.disconnect();
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }).start();
        }

        public void start(){
            isPause=false;
            download();
        }

        public void pause(){
            isPause=true;
        }

    }

完整的Demo地址

Demo:

來源:安卓巴士網

上一篇: 優秀的(Android)軟件工程師是如何練成的

下一篇: Android手機圖案鎖屏真的安全嗎

分享到: 更多
怎么买排列三赚钱 后二计划软件手机版 mg娱乐游戏检测 快速时时的套路 彩票平台双面盘 大小单双为什么一买就输 时时彩大底 江苏快三如何稳赚 psv必玩神作 北京pk10稳定版计划 幸运飞艇计划软件 app 时时彩个位单双判断 秒速时时采彩计划软件一期 打鱼输的倾家荡产 网上玩云南时时 体彩足彩投注截止时间