断点续传

来源:互联网 发布:gas mask for mac 编辑:程序博客网 时间:2024/06/06 05:49
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" /><uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>//添加xutils包
import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import java.util.ArrayList;import java.util.List;

public class Dao {    private static Dao dao=null;    private Context context;    private  Dao(Context context) {        this.context=context;    }    public static  Dao getInstance(Context context){        if(dao==null){            dao=new Dao(context);        }        return dao;    }    public  SQLiteDatabase getConnection() {        SQLiteDatabase sqliteDatabase = null;        try {            sqliteDatabase= new DBHelper(context).getReadableDatabase();        } catch (Exception e) {        }        return sqliteDatabase;    }    /**     * 查看数据库中是否有数据     */    public synchronized boolean isHasInfors(String urlstr) {        SQLiteDatabase database = getConnection();        int count = -1;        Cursor cursor = null;        try {            String sql = "select count(*)  from download_info where url=?";            cursor = database.rawQuery(sql, new String[] { urlstr });            if (cursor.moveToFirst()) {                count = cursor.getInt(0);            }        } catch (Exception e) {            e.printStackTrace();        } finally {            if (null != database) {                database.close();            }            if (null != cursor) {                cursor.close();            }        }        return count == 0;    }    /**     * 保存 下载的具体信息     */    public synchronized void saveInfos(List<DownloadInfo> infos) {        SQLiteDatabase database = getConnection();        try {            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);            }        } catch (Exception e) {            e.printStackTrace();        } finally {            if (null != database) {                database.close();            }        }    }    /**     * 得到下载具体信息     */    public synchronized List<DownloadInfo> getInfos(String urlstr) {        List<DownloadInfo> list = new ArrayList<DownloadInfo>();        SQLiteDatabase database = getConnection();        Cursor cursor = null;        try {            String sql = "select thread_id, start_pos, end_pos,compelete_size,url from download_info where url=?";            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);            }        } catch (Exception e) {            e.printStackTrace();        } finally {            if (null != database) {                database.close();            }            if (null != cursor) {                cursor.close();            }        }        return list;    }    /**     * 更新数据库中的下载信息     */    public synchronized void updataInfos(int threadId, int compeleteSize, String urlstr) {        SQLiteDatabase database = getConnection();        try {            String sql = "update download_info set compelete_size=? where thread_id=? and url=?";            Object[] bindArgs = { compeleteSize, threadId, urlstr };            database.execSQL(sql, bindArgs);        } catch (Exception e) {            e.printStackTrace();        } finally {            if (null != database) {                database.close();            }        }    }    /**     * 下载完成后删除数据库中的数据     */    public synchronized void delete(String url) {        SQLiteDatabase database = getConnection();        try {            database.delete("download_info", "url=?", new String[] { url });        } catch (Exception e) {            e.printStackTrace();        } finally {            if (null != database) {                database.close();            }        }    }}
import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;public class DBHelper extends SQLiteOpenHelper{    //download.db-->数据库名    public DBHelper(Context context) {        super(context, "download.db", null, 1);    }    /**     * 在download.db数据库下创建一个download_info表存储下载信息     */    @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 db, int oldVersion, int newVersion) {    }}
 
import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.Button;import android.widget.TextView;import android.view.View.OnClickListener;import java.util.List;import java.util.Map;public class DownLoadAdapter extends BaseAdapter{    private LayoutInflater mInflater;    private List<Map<String, String>> data;    private Context context;    private OnClickListener click;    public DownLoadAdapter(Context context,List<Map<String, String>> data) {        this.context=context;        mInflater = LayoutInflater.from(context);        this.data=data;    }    public void refresh(List<Map<String, String>> data) {        this.data=data;        this.notifyDataSetChanged();    }    public void setOnclick(OnClickListener click) {        this.click=click;    }    @Override    public int getCount() {        return data.size();    }    @Override    public Object getItem(int position) {        return data.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(final int position, View convertView, ViewGroup parent) {        final Map<String, String> bean=data.get(position);        ViewHolder holder = null;        if (convertView == null) {            convertView = mInflater.inflate(R.layout.list_item, null);            holder = new ViewHolder();            holder.resouceName=(TextView) convertView.findViewById(R.id.tv_resouce_name);            holder.startDownload=(Button) convertView.findViewById(R.id.btn_start);            holder.pauseDownload=(Button) convertView.findViewById(R.id.btn_pause);            convertView.setTag(holder);        } else {            holder = (ViewHolder) convertView.getTag();        }        holder.resouceName.setText(bean.get("name"));        return convertView;    }    public OnClickListener getClick() {        return click;    }    public void setClick(OnClickListener click) {        this.click = click;    }    private class ViewHolder {        public TextView resouceName;        public Button startDownload;        public Button pauseDownload;    }}
import android.content.Context;import android.os.Handler;import android.os.Message;import android.util.Log;import java.io.File;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;import java.util.ArrayList;import java.util.List;public class Downloader {    private String urlstr;// 下载的地址    private String localfile;// 保存路径    private int threadcount;// 线程数    private Handler mHandler;// 消息处理器    private int fileSize;// 所要下载的文件的大小    private Context context;    private List<DownloadInfo> infos;// 存放下载信息类的集合    private static final int INIT = 1;//定义三种下载的状态:初始化状态,正在下载状态,暂停状态    private static final int DOWNLOADING = 2;    private static final int PAUSE = 3;    private int state = INIT;    public Downloader(String urlstr, String localfile, int threadcount,                      Context context, Handler mHandler) {        this.urlstr = urlstr;        this.localfile = localfile;        this.threadcount = threadcount;        this.mHandler = mHandler;        this.context = context;    }    /**     *判断是否正在下载     */    public boolean isdownloading() {        return state == DOWNLOADING;    }    /**     * 得到downloader里的信息     * 首先进行判断是否是第一次下载,如果是第一次就要进行初始化,并将下载器的信息保存到数据库中     * 如果不是第一次下载,那就要从数据库中读出之前下载的信息(起始位置,结束为止,文件大小等),并将下载信息返回给下载器     */    public LoadInfo getDownloaderInfors() {        if (isFirst(urlstr)) {            Log.v("TAG", "isFirst");            init();            int range = fileSize / threadcount;            infos = new ArrayList<DownloadInfo>();            for (int i = 0; i < threadcount - 1; i++) {                DownloadInfo info = new DownloadInfo(i, i * range, (i + 1)* range - 1, 0, urlstr);                infos.add(info);            }            DownloadInfo info = new DownloadInfo(threadcount - 1,(threadcount - 1) * range, fileSize - 1, 0, urlstr);            infos.add(info);            //保存infos中的数据到数据库            Dao.getInstance(context).saveInfos(infos);            //创建一个LoadInfo对象记载下载器的具体信息            LoadInfo loadInfo = new LoadInfo(fileSize, 0, urlstr);            return loadInfo;        } else {            //得到数据库中已有的urlstr的下载器的具体信息            infos = Dao.getInstance(context).getInfos(urlstr);            Log.v("TAG", "not isFirst size=" + infos.size());            int size = 0;            int compeleteSize = 0;            for (DownloadInfo info : infos) {                compeleteSize += info.getCompeleteSize();                size += info.getEndPos() - info.getStartPos() + 1;            }            return new LoadInfo(size, compeleteSize, urlstr);        }    }    /**     * 初始化     */    private void init() {        try {            URL url = new URL(urlstr);            HttpURLConnection connection = (HttpURLConnection) url.openConnection();            connection.setConnectTimeout(5000);            connection.setRequestMethod("GET");            fileSize = connection.getContentLength();            File file = new File(localfile);            if (!file.exists()) {                file.createNewFile();            }            // 本地访问文件            RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");            accessFile.setLength(fileSize);            accessFile.close();            connection.disconnect();        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * 判断是否是第一次 下载     */    private boolean isFirst(String urlstr) {        return Dao.getInstance(context).isHasInfors(urlstr);    }    /**     * 利用线程开始下载数据     */    public void download() {        if (infos != null) {            if (state == DOWNLOADING)                return;            state = DOWNLOADING;            for (DownloadInfo info : infos) {                new MyThread(info.getThreadId(), info.getStartPos(),                        info.getEndPos(), info.getCompeleteSize(),                        info.getUrl()).start();            }        }    }    public class MyThread extends Thread {        private int threadId;        private int startPos;        private int endPos;        private int compeleteSize;        private String urlstr;        public MyThread(int threadId, int startPos, int endPos,                        int compeleteSize, String urlstr) {            this.threadId = threadId;            this.startPos = startPos;            this.endPos = endPos;            this.compeleteSize = compeleteSize;            this.urlstr = urlstr;        }        @Override        public void run() {            HttpURLConnection connection = null;            RandomAccessFile randomAccessFile = null;            InputStream is = null;            try {                URL url = new URL(urlstr);                connection = (HttpURLConnection) url.openConnection();                connection.setConnectTimeout(5000);                connection.setRequestMethod("GET");                // 设置范围,格式为Range:bytes x-y;                connection.setRequestProperty("Range", "bytes="+(startPos + compeleteSize) + "-" + endPos);                randomAccessFile = new RandomAccessFile(localfile, "rwd");                randomAccessFile.seek(startPos + compeleteSize);                // 将要下载的文件写到保存在保存路径下的文件中                is = connection.getInputStream();                byte[] buffer = new byte[4096];                int length = -1;                while ((length = is.read(buffer)) != -1) {                    randomAccessFile.write(buffer, 0, length);                    compeleteSize += length;                    // 更新数据库中的下载信息                    Dao.getInstance(context).updataInfos(threadId, compeleteSize, urlstr);                    // 用消息将下载信息传给进度条,对进度条进行更新                    Message message = Message.obtain();                    message.what = 1;                    message.obj = urlstr;                    message.arg1 = length;                    mHandler.sendMessage(message);                    if (state == PAUSE) {                        return;                    }                }            } catch (Exception e) {                e.printStackTrace();            }        }    } //删除数据库中urlstr对应的下载器信息    public void delete(String urlstr) {        Dao.getInstance(context).delete(urlstr);    }    //设置暂停    public void pause() {        state = PAUSE;    }    //重置下载状态    public void reset() {        state = INIT;    }}
        public class DownloadInfo {    private int threadId;//下载器id    private int startPos;//开始点    private int endPos;//结束点    private int compeleteSize;//完成度    private String 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 LoadInfo {    public int fileSize;//文件大小    private int complete;//完成度    private String urlstring;//下载器标识    public LoadInfo(int fileSize, int complete, String urlstring) {        this.fileSize = fileSize;        this.complete = complete;        this.urlstring = urlstring;    }    public LoadInfo() {    }    public int getFileSize() {        return fileSize;    }    public void setFileSize(int fileSize) {        this.fileSize = fileSize;    }    public int getComplete() {        return complete;    }    public void setComplete(int complete) {        this.complete = complete;    }    public String getUrlstring() {        return urlstring;    }    public void setUrlstring(String urlstring) {        this.urlstring = urlstring;    }    @Override    public String toString() {        return "LoadInfo [fileSize=" + fileSize + ", complete=" + complete                + ", urlstring=" + urlstring + "]";    }}

import android.app.ListActivity;import android.os.AsyncTask;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.widget.Button;import android.widget.LinearLayout;import android.widget.LinearLayout.LayoutParams;import android.widget.ProgressBar;import android.widget.TextView;import android.widget.Toast;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;public class MainActivity extends ListActivity {    // 固定下载的资源路径,这里可以设置网络上的地址    private static final String URL = "http://download.haozip.com/";    // 固定存放下载的音乐的路径:SD卡目录下    private static final String SD_PATH = "/mnt/sdcard/";    // 存放各个下载器    private Map<String, Downloader> downloaders = new HashMap<String, Downloader>();    // 存放与下载器对应的进度条    private Map<String, ProgressBar> ProgressBars = new HashMap<String, ProgressBar>();    /**     * 利用消息处理机制适时更新进度条     */    private Handler mHandler = new Handler() {        public void handleMessage(Message msg) {            if (msg.what == 1) {                String url = (String) msg.obj;                int length = msg.arg1;                ProgressBar bar = ProgressBars.get(url);                if (bar != null) {                    // 设置进度条按读取的length长度更新                    bar.incrementProgressBy(length);                    if (bar.getProgress() == bar.getMax()) {                        LinearLayout layout = (LinearLayout) bar.getParent();                        TextView resouceName=(TextView)layout.findViewById(R.id.tv_resouce_name);                        Toast.makeText(MainActivity.this, "["+resouceName.getText()+"]下载完成!", Toast.LENGTH_SHORT).show();                        // 下载完成后清除进度条并将map中的数据清空                        layout.removeView(bar);                        ProgressBars.remove(url);                        downloaders.get(url).delete(url);                        downloaders.get(url).reset();                        downloaders.remove(url);                        Button btn_start=(Button)layout.findViewById(R.id.btn_start);                        Button btn_pause=(Button)layout.findViewById(R.id.btn_pause);                        btn_pause.setVisibility(View.GONE);                        btn_start.setVisibility(View.GONE);                    }                }            }        }    };    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        showListView();    }    // 显示listView,这里可以随便添加    private void showListView() {        List<Map<String, String>> data = new ArrayList<Map<String, String>>();        Map<String, String> map = new HashMap<String, String>();        map.put("name", "haozip_v3.1.exe");        data.add(map);        map = new HashMap<String, String>();        map.put("name", "haozip_v3.1_hj.exe");        data.add(map);        map = new HashMap<String, String>();        map.put("name", "haozip_v2.8_x64_tiny.exe");        data.add(map);        map = new HashMap<String, String>();        map.put("name", "haozip_v2.8_tiny.exe");        data.add(map);        DownLoadAdapter adapter=new DownLoadAdapter(this,data);        setListAdapter(adapter);    }    /**     * 响应开始下载按钮的点击事件     */    public void startDownload(View v) {        // 得到textView的内容        LinearLayout layout = (LinearLayout) v.getParent();        String resouceName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();        String urlstr = URL + resouceName;        String localfile = SD_PATH + resouceName;        //设置下载线程数为4,这里是我为了方便随便固定的        String threadcount = "4";        DownloadTask downloadTask=new DownloadTask(v);        downloadTask.execute(urlstr,localfile,threadcount);    };    class DownloadTask extends AsyncTask<String, Integer, LoadInfo> {        Downloader downloader=null;        View v=null;        String urlstr=null;        public DownloadTask(final View v){            this.v=v;        }        @Override        protected void onPreExecute() {            Button btn_start=(Button)((View)v.getParent()).findViewById(R.id.btn_start);            Button btn_pause=(Button)((View)v.getParent()).findViewById(R.id.btn_pause);            btn_start.setVisibility(View.GONE);            btn_pause.setVisibility(View.VISIBLE);        }        @Override        protected LoadInfo doInBackground(String... params) {            urlstr=params[0];            String localfile=params[1];            int threadcount=Integer.parseInt(params[2]);            // 初始化一个downloader下载器            downloader = downloaders.get(urlstr);            if (downloader == null) {                downloader = new Downloader(urlstr, localfile, threadcount, MainActivity.this, mHandler);                downloaders.put(urlstr, downloader);            }            if (downloader.isdownloading())                return null;            // 得到下载信息类的个数组成集合            return downloader.getDownloaderInfors();        }        @Override        protected void onPostExecute(LoadInfo loadInfo) {            if(loadInfo!=null){                // 显示进度条                showProgress(loadInfo, urlstr, v);                // 调用方法开始下载                downloader.download();            }        }    };    /**     * 显示进度条     */    private void showProgress(LoadInfo loadInfo, String url, View v) {        ProgressBar bar = ProgressBars.get(url);        if (bar == null) {            bar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);            bar.setMax(loadInfo.getFileSize());            bar.setProgress(loadInfo.getComplete());            ProgressBars.put(url, bar);            LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, 5);            ((LinearLayout) ((LinearLayout) v.getParent()).getParent()).addView(bar, params);        }    }    /**     * 响应暂停下载按钮的点击事件     */    public void pauseDownload(View v) {        LinearLayout layout = (LinearLayout) v.getParent();        String resouceName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();        String urlstr = URL + resouceName;        downloaders.get(urlstr).pause();        Button btn_start=(Button)((View)v.getParent()).findViewById(R.id.btn_start);        Button btn_pause=(Button)((View)v.getParent()).findViewById(R.id.btn_pause);        btn_pause.setVisibility(View.GONE);        btn_start.setVisibility(View.VISIBLE);    }}
//布局
<ListView android:id="@android:id/list"    android:layout_width="fill_parent"    android:layout_height="fill_parent"></ListView>

<LinearLayout    android:orientation="horizontal"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:layout_marginBottom="5dip">    <TextView        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_weight="1"        android:text="aaaaaa"        android:id="@+id/tv_resouce_name"/>    <Button        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_weight="1"        android:text="下载"        android:id="@+id/btn_start"        android:onClick="startDownload"/>    <Button        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_weight="1"        android:text="暂停"        android:visibility="gone"        android:id="@+id/btn_pause"        android:onClick="pauseDownload"/></LinearLayout>