单一文件的断点续传

来源:互联网 发布:太原高达软件 编辑:程序博客网 时间:2024/05/18 00:58

很久没有更新博客了,最近公司的项目也没那么赶了,就照着慕课网的视频,把断点续传的代码敲了一遍,,调了半天,其中的坑也只有自己敲过才知道.为了今后方便,我现在把所有的代码都粘在下面了.
运行的效果如下:
这里写图片描述
这个才是
这里写图片描述
首先是我的代码目录结构
这里写图片描述

FileInfos主要是记录要下载的文件信息private int id;    private String url;    private String fileName;    private int length;    private int finished;ThreadInfo类是记录线程信息private int id;    private String url;    private int start;    private int end;    private int finished;DBHelper创建我的数据库,单例模式private static final String DB_NAME="download.db";    public static DBHelper helper;    private static String SQL_CREATE="create table if not exists thread_info(_id integer primary key autoincrement,thread_id integer," +                        "url text,start integer,end integer,finished integer)";    private static String SQL_DROP="drop table if exists thread_info";    public static synchronized DBHelper getInstance(Context mContext)    {        if (helper==null)        {            helper=new DBHelper(mContext,DB_NAME,null,1);        }        return helper;    }    private DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {        super(context, name, factory, version);    }    @Override    public void onCreate(SQLiteDatabase db) {        db.execSQL(SQL_CREATE);    }    @Override    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {    } **数据访问接口的实现 * Created by Administrator on 2017/7/19. */public class ThreadDaoImp implements ThreadDao{    private DBHelper helper;    public ThreadDaoImp(Context context) {        helper=DBHelper.getInstance(context);    }    @Override    public void insertThread(ThreadInfos threadInfos) {        SQLiteDatabase db = helper.getReadableDatabase();        db.execSQL("insert into thread_info(thread_id,url,start,end,finished) values (?,?,?,?,?)",                new Object[]{threadInfos.getId(),threadInfos.getUrl(),threadInfos.getStart(),threadInfos.getEnd(),threadInfos.getFinished()});        db.close();    }    @Override    public void deleteThread(String url, int thredId) {        SQLiteDatabase db = helper.getReadableDatabase();        db.execSQL("delete from thread_info where url= ? and thread_id= ?",                new Object[]{url,thredId});        db.close();    }    @Override    public void updateThread(String url, int threadId, int finished) {        SQLiteDatabase db = helper.getReadableDatabase();        db.execSQL("update thread_info set finished = ? where url= ? and thread_id= ?",                new Object[]{finished,url,threadId});        db.close();    }    @Override    public List<ThreadInfos> getThreads(String url) {        SQLiteDatabase db = helper.getReadableDatabase();        List<ThreadInfos> list=new ArrayList<>();        Cursor cursor = db.rawQuery("select * from thread_info where url= ? ",                new String[]{url});        while (cursor.moveToNext())        {            ThreadInfos threadInfos = new ThreadInfos();            threadInfos.setId(cursor.getInt(cursor.getColumnIndex("thread_id")));            threadInfos.setUrl(cursor.getString(cursor.getColumnIndex("url")));            threadInfos.setStart(cursor.getInt(cursor.getColumnIndex("start")));            threadInfos.setEnd(cursor.getInt(cursor.getColumnIndex("end")));            threadInfos.setFinished(cursor.getInt(cursor.getColumnIndex("finished")));            list.add(threadInfos);        }        cursor.close();        db.close();        return list;    }    @Override    public boolean isExists(String url, int threadId) {        SQLiteDatabase db = helper.getReadableDatabase();        Cursor cursor = db.rawQuery("select * from thread_info where url= ? and thread_id= ?",                new String[]{url,threadId+""});        boolean exists=cursor.moveToNext();        cursor.close();        db.close();        return exists;    }}/**下载任务类 * Created by Administrator on 2017/7/19. */public class DownloadTask {    private Context context;    private FileInfos fileInfos;    private ThreadDaoImp threadDaoImp;    private int mFinished=0;    public boolean isPaused;    public DownloadTask(Context context, FileInfos fileInfos) {        this.context = context;        this.fileInfos = fileInfos;        threadDaoImp=new ThreadDaoImp(context);    }    public void download()    {        //读取数据库的线程信息        List<ThreadInfos> list = threadDaoImp.getThreads(fileInfos.getUrl());        ThreadInfos threadInfos=null;        if (list.size()==0)        {            //初始化线程信息对象            threadInfos = new ThreadInfos(0,fileInfos.getUrl(),0,fileInfos.getLength(),0);            //创建子线程进行下载            new DownloadThread(threadInfos).start();        }        else        {            for (int i = 0; i < list.size(); i++) {                threadInfos=list.get(i);                new DownloadThread(threadInfos).start();            }        }    }    //下载线程    class DownloadThread extends Thread{        private ThreadInfos threadInfos;        public DownloadThread(ThreadInfos threadInfos) {            this.threadInfos = threadInfos;        }        @Override        public void run() {            super.run();            //先数据库插入线程信息            if (!threadDaoImp.isExists(threadInfos.getUrl(),threadInfos.getId()))            {                threadDaoImp.insertThread(threadInfos);            }            RandomAccessFile raf=null;            try {                URL url = new URL(threadInfos.getUrl());                HttpURLConnection conn = (HttpURLConnection) url.openConnection();                //conn.connect();                int length=-1;                //设置下载位置                int start=threadInfos.getStart()+threadInfos.getFinished();                conn.setRequestProperty("Range","bytes="+start+"-"+threadInfos.getEnd());                //设置文件写入位置                File file = new File(DownloadService.DOWNLOAD_PATH,fileInfos.getFileName());                raf = new RandomAccessFile(file, "rwd");                raf.seek(start);                Intent intent = new Intent();                intent.setAction(DownloadService.ACTION_UPDATE);                mFinished+=threadInfos.getFinished();                if (conn.getResponseCode()==206)                {                    //开始下载                    //读取数据                    InputStream input = conn.getInputStream();                    byte[] bytes = new byte[1024*4];                    long time=0;                    while ((length=input.read(bytes))!=-1)                    {                        //写入文件                        raf.write(bytes,0,length);                        //把下载进度通过广播发送给activity                        mFinished+=length;                        if (mFinished>=fileInfos.getLength())                        {                            mFinished=fileInfos.getLength();                        }                        if (System.currentTimeMillis()-time>300)                        {                            time=System.currentTimeMillis();                            intent.putExtra("progress",mFinished*100/fileInfos.getLength());                            context.sendBroadcast(intent);                        }                        //在下载暂停时,保存下载进度                        if (isPaused)                        {                            threadDaoImp.updateThread(threadInfos.getUrl(),threadInfos.getId(),mFinished);                            return;                        }                    }                    //下载完成后,删除线程信息                    threadDaoImp.deleteThread(threadInfos.getUrl(),threadInfos.getId());                }            } catch (MalformedURLException e) {                e.printStackTrace();            } catch (IOException e) {                e.printStackTrace();            }finally {                try {                    if (raf!=null)                    {                        raf.close();                    }                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}/**数据库访问接口 * Created by Administrator on 2017/7/19. */public interface ThreadDao {    //插入线程信息    public void insertThread(ThreadInfos threadInfos);    //删除线程    public void deleteThread(String url,int thredId);    //更新线程下载进度    public void updateThread(String url,int threadId,int finished);    //查询线程信息    public List<ThreadInfos> getThreads(String url);    //线程信息是否存在    public boolean isExists(String url,int threadId);}/** * Created by Administrator on 2017/7/19. */public class DownloadService extends Service{    public static final String DOWNLOAD_PATH= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()                                                    + File.separator+"demo";    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=0;    DownloadTask downloadTask;    public Handler handler=new Handler(){        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            switch (msg.what)            {                case 0:                    FileInfos fileInfos= (FileInfos) msg.obj;                    Log.d("==handler====","======="+fileInfos.toString());                    //启动下载任务                    downloadTask = new DownloadTask(DownloadService.this, fileInfos);                    downloadTask.download();                    break;                default:                    break;            }        }    };    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        //获取从activity中传递过来的信息        if (ACTION_START.equals(intent.getAction()))        {            FileInfos fileInfo = (FileInfos) intent.getSerializableExtra("fileInfo");            Log.d("==start====","======"+fileInfo.toString());            new InitThread(fileInfo).start();        }        else if (ACTION_STOP.equals(intent.getAction()))        {            FileInfos fileInfo = (FileInfos) intent.getSerializableExtra("fileInfo");            Log.d("==stop====","======"+fileInfo.toString());            if (downloadTask!=null)            {                downloadTask.isPaused=true;            }        }        return super.onStartCommand(intent, flags, startId);    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        return null;    }    class InitThread extends Thread{        FileInfos fileInfos;        public InitThread(FileInfos fileInfos) {            this.fileInfos = fileInfos;        }        @Override        public void run() {            super.run();            RandomAccessFile raf=null;            try {                //连接网络文件                URL url = new URL(fileInfos.getUrl());                HttpURLConnection conn = (HttpURLConnection) url.openConnection();                conn.connect();                int length=-1;                if (conn.getResponseCode()==200)                {                    //获得文件长度                    length=conn.getContentLength();                    if (length<=0)                    {                        return;                    }                    File dir=new File(DOWNLOAD_PATH);                    if (!dir.exists())                    {                        dir.mkdirs();                    }                    //在本地创建文件                    File file=new File(dir,fileInfos.getFileName());                    raf = new RandomAccessFile(file, "rwd");                    //设置文件长度                    raf.setLength(length);                }                fileInfos.setLength(length);                Message message = handler.obtainMessage();                message.what=MSG_INIT;                message.obj=fileInfos;                handler.sendMessage(message);            } catch (MalformedURLException e) {                e.printStackTrace();            } catch (IOException e) {                e.printStackTrace();            }finally {                try {                    if (raf!=null)                    {                        raf.close();                    }                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}public class MainActivity extends AppCompatActivity implements View.OnClickListener{    TextView textView;    ProgressBar progressBar;    Button start_bt,pause_bt;    FileInfos fileInfos;    MyBroadCastReceiver receiver;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        textView= (TextView) findViewById(R.id.textView);        progressBar= (ProgressBar) findViewById(R.id.progressBar);        start_bt= (Button) findViewById(R.id.start_bt);        pause_bt= (Button) findViewById(R.id.pause_bt);        initListener();        initFileInfo();        initData();    }    private void initData() {        //注册广播        receiver = new MyBroadCastReceiver();        IntentFilter intentFilter = new IntentFilter();        intentFilter.addAction(DownloadService.ACTION_UPDATE);        registerReceiver(receiver,intentFilter);        progressBar.setMax(50);        textView.setText(fileInfos.getFileName());    }    private void initFileInfo() {        //http://down.shouji.kuwo.cn/star/mobile/KuwoPlayerV3_ar_8.5.0.2_kw.apk        //http://www.imooc.com/video/7052        fileInfos = new FileInfos(0, "http://down.shouji.kuwo.cn/star/mobile/KuwoPlayerV3_ar_8.5.0.2_kw.apk",                                            "kuwo.apk", 0, 0);    }    private void initListener() {        start_bt.setOnClickListener(this);        pause_bt.setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch (v.getId())        {            case R.id.start_bt:                Intent intentStart = new Intent(this, DownloadService.class);                intentStart.setAction(DownloadService.ACTION_START);                intentStart.putExtra("fileInfo",fileInfos);                startService(intentStart);                break;            case R.id.pause_bt:                Intent intentStop = new Intent(this, DownloadService.class);                intentStop.setAction(DownloadService.ACTION_STOP);                intentStop.putExtra("fileInfo",fileInfos);                startService(intentStop);                break;            default:                break;        }    }    @Override    protected void onDestroy() {        super.onDestroy();        unregisterReceiver(receiver);    }    class MyBroadCastReceiver extends BroadcastReceiver{        @Override        public void onReceive(Context context, Intent intent) {            if (DownloadService.ACTION_UPDATE.equals(intent.getAction()))            {                int progress = intent.getIntExtra("progress", -1);                if (-1!=progress)                {                    progressBar.setProgress(progress);                }            }        }    }}其实还有个bug一直没解决,进度条在文件下载完成后,并没有走满,而且我在公有目录下新建的文件夹的时间显示是2012/00/00/00,,,如果解决了,记得给我留言告我一声啊!这里写代码片
原创粉丝点击