android 下载之断点续传

实现步骤:
        1. 开启服务 + 新线程获取文件大小
        2. 获取文件大小后 开启新线程 开始下载 在下载之前先查询数据库是否有该条“下载URL“的下载记录 如果有获取断点位置 继续下载 如果没有则按新文件下载。
        3.所使用到的新内容:RandomAccess 特殊的输出流 可以在任意位置进行写入操作 。在第一次获取文件大小时 判断状态为HttpURLConnection.HTTP_OK(200)
           文件下载时 需使用HttpUlRLConnection.HTTP_PARTIAL(206)

MainActivity Code

 @Override
    public void onClick(View view) {
        intent =new Intent(this,DownLoadService.class);
        switch (view.getId()){
            case R.id.down:
                intent.setAction(DownLoadService.ACTION_START);
                intent.putExtra("fileinfo",fileInfo);
                startService(intent);
                break;
            case R.id.pause:
                intent.setAction(DownLoadService.ACTION_STOP);
                intent.putExtra("fileinfo",fileInfo);
                startService(intent);
                break;
        }
    }

    /*
    * 根据广播传入的进度 更新UI进度值
    * */
    BroadcastReceiver receiver=new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if(intent.getAction().equals(DownLoadService.ACTION_UPDATE)){
                int finished = intent.getIntExtra("finished",0);
                progressBar.setProgress(finished);
            }
        }
    };

DownLoadService Code

public class DownLoadService extends Service {

    public static final String DOWN_LOAD_PATCH  = Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"download"+File.separator;
    public static final String ACTION_START="ACTION_START";
    public static final String ACTION_STOP="ACTION_STOP";
    public static final String ACTION_UPDATE="ACTION_UPDATE";
    public static final int MSG_INIT = 001;

    public DownLoadTask task;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        FileInfo fileInfo= (FileInfo) intent.getSerializableExtra("fileinfo");
        //启动初始化线程
        if(intent.getAction().equals(ACTION_START)){
            new InitThread(fileInfo).start();
        }
        //停止下载
        if(intent.getAction().equals(ACTION_STOP)){
            if(task!=null){
                task.isPause=true;
            }
        }
        return super.onStartCommand(intent, flags, startId);
    }

    Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MSG_INIT:
                    FileInfo fileInfo = (FileInfo) msg.obj;
                    //启动下载任务
                    task=new DownLoadTask(DownLoadService.this,fileInfo);
                    task.download();
                    break;
            }
        }
    };

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    class InitThread extends Thread{

        public FileInfo fileinfo;

        public InitThread(FileInfo fileInfo){
            this.fileinfo=fileInfo;
        }

        @Override
        public void run() {
            //连接网络文件 获取文件长度后 本地创建文件长度
            HttpURLConnection urlConnection=null;
            RandomAccessFile randomAccessFile=null;
            URL url= null;
            try {
                url = new URL(fileinfo.getUrl());
                urlConnection=(HttpURLConnection) url.openConnection();
                urlConnection.setRequestMethod("GET");
                urlConnection.setReadTimeout(3000);
                urlConnection.setConnectTimeout(5000);
                urlConnection.setDoOutput(true);
                int length=-1;
                if(urlConnection.getResponseCode()==HttpURLConnection.HTTP_OK){
                    //获取文件长度
                    length=urlConnection.getContentLength();
                }
                if(length<0){
                    return ;
                }
                File dir=new File(DOWN_LOAD_PATCH);
                //判断路径是否存在
                if(!dir.exists()){
                    //如果不存在就创建
                    dir.mkdir();
                }
                File file=new File(dir,fileinfo.getFilename());
                //特殊输出流 在任意位置进行写入操作 方面后面的断点续传
                randomAccessFile=new RandomAccessFile(file,"rwd");
                //设置文件长度
                randomAccessFile.setLength(length);

                fileinfo.setLength(length);
                //通过该线程获取到文件长度后 调用下载进程
                handler.obtainMessage(MSG_INIT,fileinfo).sendToTarget();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                urlConnection.disconnect();
                try {
                    randomAccessFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

DownLoadTask Code

public class DownLoadTask {
    public Context context;
    public FileInfo fileInfo;
    public DB_interface db;
    public boolean isPause=false;

    public DownLoadTask(Context context, FileInfo fileInfo) {
        this.context = context;
        this.fileInfo = fileInfo;
        db=new db_manager(context);
    }

    public  void download(){
        //读取数据库的线程信息
        List<ThreadInfo> threadInfos = db.getThreads(fileInfo.getUrl());
        System.out.println(threadInfos);
        ThreadInfo threadInfo=null;
        if(threadInfos.size()==0){
            //初始化线程信息对象
            threadInfo=new ThreadInfo(fileInfo.getLength(),0,fileInfo.getId(),0,fileInfo.getUrl(),fileInfo.getFilename());
        }else{
            threadInfo=threadInfos.get(0);
        }
        DownLoadThread downLoadThread=new DownLoadThread(threadInfo);
        downLoadThread.start();
    }

    //下载线程
    class DownLoadThread extends Thread{
        private ThreadInfo threadInfo;
        private HttpURLConnection connection;
        private int mFinished=0;
        private InputStream inputStream;
        private RandomAccessFile randomAccessFile;

        public DownLoadThread(ThreadInfo threadInfo) {
            this.threadInfo = threadInfo;
        }

        @Override
        public void run() {
            //数据库插入线程下载信息
            if(!db.isExists(threadInfo.getUrl(), threadInfo.getId())){
                //如果不存在 则向数据库插入数据
                db.insertThread(threadInfo);
            }

            try {
                URL url=new URL(threadInfo.getUrl());
                connection=(HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setConnectTimeout(5000);
                //设置下载位置
                int start= threadInfo.getStart()+ threadInfo.getFinished();
                System.out.println("start===="+threadInfo.getFinished());
                long time = System.currentTimeMillis();
                connection.setRequestProperty("Range","bytes="+start+"-"+ threadInfo.getEnd());
                //设置文件写入文职
                File file=new File(DownLoadService.DOWN_LOAD_PATCH+ threadInfo.getName());
                randomAccessFile=new RandomAccessFile(file,"rw");
                randomAccessFile.seek(start);
                Intent intent=new Intent(DownLoadService.ACTION_UPDATE);
                mFinished+= threadInfo.getFinished();
                //开始下载
                if(connection.getResponseCode()==HttpURLConnection.HTTP_PARTIAL){
                    //读取数据
                    inputStream= connection.getInputStream();
                    byte[] bytes=new byte[3*1024];
                    int len=-1;
                    while ((len=inputStream.read(bytes))!=-1){
                        //读取数据 开始下载
                        randomAccessFile.write(bytes,0,len);
                        //下载进度广播为activity
                        mFinished+=len;
                        //判断时间差 发送广播通知
                        if(System.currentTimeMillis()-time>500){
                            time=System.currentTimeMillis();
                            intent.putExtra("finished",mFinished*100/ fileInfo.getLength());
                            context.sendBroadcast(intent);
                        }
                        if(isPause){
                            //暂停下载
                            System.out.println("pause "+mFinished);
                            db.updateThread(threadInfo.getUrl(),threadInfo.getId(),mFinished);
                            return;
                        }
                    }
                    //删除线程信息
                    db.deleteThread(threadInfo.getUrl(),threadInfo.getId());
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                connection.disconnect();
                try {
                    inputStream.close();
                    randomAccessFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值