GreenDao实现多线程下载与断点续传

来源:互联网 发布:淘宝话费充值 编辑:程序博客网 时间:2024/06/01 07:38

这个Demo实现的是使用Greendao断点续传,多线程下载。

首先GreenDao集成可以参考我的另外一篇博客,还算详细吧点我

这个是项目结构图:


集成好之后就可以写代码了,别说话,看代码。

User.java

@Entitypublic class User {    @Id    private Long id;    private Integer thread_id;    private Integer start_pos;    private Integer end_pos;    private Integer compelete_size;    private String url;    public String getUrl() {        return this.url;    }    public void setUrl(String url) {        this.url = url;    }    public Integer getCompelete_size() {        return this.compelete_size;    }    public void setCompelete_size(Integer compelete_size) {        this.compelete_size = compelete_size;    }    public Integer getEnd_pos() {        return this.end_pos;    }    public void setEnd_pos(Integer end_pos) {        this.end_pos = end_pos;    }    public Integer getStart_pos() {        return this.start_pos;    }    public void setStart_pos(Integer start_pos) {        this.start_pos = start_pos;    }    public Integer getThread_id() {        return this.thread_id;    }    public void setThread_id(Integer thread_id) {        this.thread_id = thread_id;    }    public Long getId() {        return this.id;    }    public void setId(Long id) {        this.id = id;    }    @Generated(hash = 2041931179)    public User(Long id, Integer thread_id, Integer start_pos, Integer end_pos,            Integer compelete_size, String url) {        this.id = id;        this.thread_id = thread_id;        this.start_pos = start_pos;        this.end_pos = end_pos;        this.compelete_size = compelete_size;        this.url = url;    }    @Generated(hash = 586692638)    public User() {    }}
gen包下面是自己生成的就不说了。

DownloadSqlTool.java

public class DownlaodSqlTool {    /**     * 创建下载的具体信息     */    public void insertInfos(List<DownloadInfo> infos) {        for (DownloadInfo info : infos) {            User user = new User(null, info.getThreadId(), info.getStartPos(), info.getEndPos(), info.getCompeleteSize(), info.getUrl());            userDao.insert(user);        }    }    /**     * 得到下载具体信息     */    public List<DownloadInfo> getInfos(String urlstr) {        List<DownloadInfo> list = new ArrayList<DownloadInfo>();        List<User> list1 = userDao.queryBuilder().where(UserDao.Properties.Url.eq(urlstr)).build().list();        for (User user : list1) {            DownloadInfo infoss = new DownloadInfo(                    user.getThread_id(), user.getStart_pos(), user.getEnd_pos(),                    user.getCompelete_size(), user.getUrl());            Log.d("main-----", infoss.toString());            list.add(infoss);        }        return list;    }    /**     * 更新数据库中的下载信息     */    public void updataInfos(int threadId, int compeleteSize, String urlstr) {        User user = userDao.queryBuilder()                .where(UserDao.Properties.Thread_id.eq(threadId), UserDao.Properties.Url.eq(urlstr)).build().unique();        user.setCompelete_size(compeleteSize);        userDao.update(user);    }    /**     * 下载完成后删除数据库中的数据     */    public void delete(String url) {        userDao.deleteAll();    }}

DownloadHttpTool.java

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();    }    //在开始下载之前需要调用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;    }    public void delete() {        compelete();        File file = new File(localPath + "/" + fileName);        file.delete();    }    public void compelete() {        sqlTool.delete(urlstr);    }    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();                }            }        }    }}


DownloadInfo.java

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                + "]";    }}

DownloadUtil.java

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();    }}

App.java

public class App extends Application {    public static UserDao userDao;    @Override    public void onCreate() {        super.onCreate();        DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(this, "lenvess.db", null);        DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb());        DaoSession daoSession = daoMaster.newSession();        userDao = daoSession.getUserDao();    }}
MainActivity.java

public class MainActivity extends AppCompatActivity {    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_main);        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_22ca37a6ea9011e5acaaf51d105342e3.f20.mp4";        String localPath = Environment.getExternalStorageDirectory()                .getAbsolutePath() + "/local2";        mDownloadUtil = new DownloadUtil(2, localPath, "adc.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();            }        });    }}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout 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"    android:orientation="vertical"    tools:context="jc.com.duandianxuchuan.MainActivity">    <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:layout_below="@+id/textView"        android:layout_marginRight="8dp"        android:max="100"        android:progress="100"        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="暂停" /></LinearLayout>
清单文件配置权限,还有Application文件

    <uses-permission android:name="android.permission.INTERNET"/>    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
这里就算完了。。。。

最后把GitHub地址给大家吧!Demo地址

原创粉丝点击