读书人

[Android实例] Android之断点续传上载

发布时间: 2013-02-19 11:11:41 作者: rapoo

[Android实例] Android之断点续传下载
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

  • ? ? ? ? android:orientation="vertical" android:layout_width="fill_parent"
  • ? ? ? ? android:layout_height="fill_parent" android:weightSum="1">
  • ? ? ? ? <ListView android:id="@android:id/list" android:layout_height="wrap_content"
  • ? ? ? ? ? ? ? ? android:layout_width="match_parent" android:layout_weight="0.70"></ListView>
  • </LinearLayout>
  • 复制代码list_item.xml:
  • ? ? ? ? android:layout_width="fill_parent" android:orientation="vertical">
  • ? ? ? ? <LinearLayout android:layout_width="fill_parent"
  • ? ? ? ? ? ? ? ? android:id="@+id/linearLayout2" android:layout_height="wrap_content"
  • ? ? ? ? ? ? ? ? android:orientation="horizontal" android:layout_marginBottom="5dip">
  • ? ? ? ? ? ? ? ? <TextView android:layout_width="fill_parent"
  • ? ? ? ? ? ? ? ? ? ? ? ? android:layout_height="wrap_content" android:layout_weight="1"
  • ? ? ? ? ? ? ? ? ? ? ? ? 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:id="@+id/btn_pause" android:onClick="pauseDownload" />
  • ? ? ? ? </LinearLayout>
  • </LinearLayout>
  • 复制代码我们要定义一个记录在下载时各个时期的数据的类,这里我创建了一个DownloadInfo类来记录。代码如下:
    DownloadInfo:
  • ? ? ? ?? ?? ?? ?? ?? ?? ?+ ", startPos=" + startPos + ", endPos=" + endPos
  • ? ? ? ?? ?? ?? ?? ?? ?? ?+ ", compeleteSize=" + compeleteSize +"]";
  • ? ???}
  • }
  • 复制代码在下载时,我们有进度条来显示进度,怎么确定进度条的进度,大小和起始位置呢?这里我定义了一个LoadInfo类来记录下载器详细信息。代码如下:
    LoadInfo:
  • ? ? ? ?? ?? ?? ?? ?? ?? ?+ ", urlstring=" + urlstring + "]";
  • ? ???}
  • }
  • 复制代码下面是最最重要的一步,那就是定义一个下载器来进行下载了,这里我就不多说,具体解释在代码中都有注解,供大家研究参考。
    Downloader:
  • ? ? ? ? ? ? ? ? ? ? ? ? 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.isHasInfors(urlstr);
  • ? ? ? ? }
  • ? ? ? ? /**
  • ? ? ? ???* 114 * 利用线程开始下载数据 115
  • ? ? ? ???*/
  • ? ? ? ? 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.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();
  • ? ? ? ? ? ? ? ? ? ? ? ? } finally {
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? try {
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? is.close();
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? randomAccessFile.close();
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? connection.disconnect();
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dao.closeDb();
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } catch (Exception e) {
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
  • ? ? ? ? ? ? ? ? ? ? ? ? }
  • ? ? ? ? ? ? ? ? }
  • ? ? ? ? }
  • ? ? ? ? // 删除数据库中urlstr对应的下载器信息
  • ? ? ? ? public void delete(String urlstr) {
  • ? ? ? ? ? ? ? ? dao.delete(urlstr);
  • ? ? ? ? }
  • ? ? ? ? // 设置暂停
  • ? ? ? ? public void pause() {
  • ? ? ? ? ? ? ? ? state = PAUSE;
  • ? ? ? ? }
  • ? ? ? ? // 重置下载状态
  • ? ? ? ? public void reset() {
  • ? ? ? ? ? ? ? ? state = INIT;
  • ? ? ? ? }
  • }
  • 复制代码在这边下载器类的定义中,我们用到了许多关于进行数据库操作的方法,这里我定义了一个数据库工具类,来提供这些方法,代码如下:
    Dao:
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? new int[] { R.id.tv_resouce_name });
  • ? ? ? ? ? ? ? ? setListAdapter(adapter);
  • ? ? ? ? }
  • ? ? ? ? /**
  • ? ? ? ???* 83 * 响应开始下载按钮的点击事件 84
  • ? ? ? ???*/
  • ? ? ? ? public void startDownload(View v) {
  • ? ? ? ? ? ? ? ? // 得到textView的内容
  • ? ? ? ? ? ? ? ? LinearLayout layout = (LinearLayout) v.getParent();
  • ? ? ? ? ? ? ? ? String musicName = ((TextView) layout
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .findViewById(R.id.tv_resouce_name)).getText().toString();
  • ? ? ? ? ? ? ? ? String urlstr = URL + musicName;
  • ? ? ? ? ? ? ? ? String localfile = SD_PATH + musicName;
  • ? ? ? ? ? ? ? ? // 设置下载线程数为4,这里是我为了方便随便固定的
  • ? ? ? ? ? ? ? ? int threadcount = 4;
  • ? ? ? ? ? ? ? ? // 初始化一个downloader下载器
  • ? ? ? ? ? ? ? ? Downloader downloader = downloaders.get(urlstr);
  • ? ? ? ? ? ? ? ? if (downloader == null) {
  • ? ? ? ? ? ? ? ? ? ? ? ? downloader = new Downloader(urlstr, localfile, threadcount, this,
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mHandler);
  • ? ? ? ? ? ? ? ? ? ? ? ? downloaders.put(urlstr, downloader);
  • ? ? ? ? ? ? ? ? }
  • ? ? ? ? ? ? ? ? if (downloader.isdownloading())
  • ? ? ? ? ? ? ? ? ? ? ? ? return;
  • ? ? ? ? ? ? ? ? // 得到下载信息类的个数组成集合
  • ? ? ? ? ? ? ? ? LoadInfo loadInfo = downloader.getDownloaderInfors();
  • ? ? ? ? ? ? ? ? // 显示进度条
  • ? ? ? ? ? ? ? ? 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());
  • ? ? ? ? ? ? ? ? ? ? ? ? System.out.println(loadInfo.getFileSize()+"--"+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 musicName = ((TextView) layout
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .findViewById(R.id.tv_resouce_name)).getText().toString();
  • ? ? ? ? ? ? ? ? String urlstr = URL + musicName;
  • ? ? ? ? ? ? ? ? downloaders.get(urlstr).pause();
  • ? ? ? ? }
  • }
  • 复制代码最后我们需要在android Manifest.xml中添加这两个权限一个是访问internet的权限,另一个是写外存的权限。
    1. <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    2. ? ? <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    复制代码最后运行的效果图:


    万事俱备只欠东风啦!哈哈,我需要在我的web工程里放几个音乐文件。

    下载后得到的文件可在sdcard下面找到!

  • 读书人网 >Android

    热点推荐