多线程断点续传

一、定义UI

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.it.zjhz.downloaddemo.MainActivity">

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="文件名称" />

    <ProgressBar
        android:id="@+id/pb_progress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tv_name"
     style="@android:style/Widget.ProgressBar.Horizontal"/>

    <Button
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="开始"
        android:layout_below="@+id/pb_progress"
        android:layout_toLeftOf="@+id/btn_stop"/>

    <Button
        android:id="@+id/btn_stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="暂停"
        android:layout_below="@+id/pb_progress"
        android:layout_alignParentRight="true"/>
</RelativeLayout>

二、定义实体类
FileInfo:id、url、fileName、length、progress,实现Serializable接口
ThreadInfo:id、url、start、stop、progress
三、向Service传递参数
将要下载的文件信息实体从Activity传递到Service

Intent intent = new Intent(MainActivity.this, DownloadService.class);
intent.setAction(DownloadService.ACTION_START);
intent.putExtra("fileInfo", fileInfo);
startService(intent);

Service里面定义两个Action,分别标识开始和暂停

public static final String ACTION_START = "ACTION_START";
public static final String ACTION_STOP = "ACTION_STOP";

在onStartCommand方法中接收传过来的FileInfo

if (ACTION_START.equals(intent.getAction())) {
            FileInfo fileInfo = (FileInfo) intent.getSerializableExtra("fileInfo");
            Log.i("StartFileInfo",fileInfo.toString());
        } else if (ACTION_STOP.equals(intent.getAction())) {
            FileInfo fileInfo = (FileInfo) intent.getSerializableExtra("fileInfo");
            Log.i("stopFileInfo",fileInfo.toString());
        }

四、使用线程进行初始化
开启服务后,如果是ACTION_START,子线程访问网络获取文件长度,在本地创建一个文件,并使用Handler将文件信息返回给主线程。
子线程类有一个成员变量是一个FileInfo对象,是该子线程所要初始化的下载文件,创建子线程时通过构造方法传进来。

/**
     * 初始化子线程
     */

    class InitThread extends Thread {

        private FileInfo mFileInfo;

        public InitThread(FileInfo mFileInfo) {
            this.mFileInfo = mFileInfo;
        }

        @Override
        public void run() {
            super.run();
            HttpURLConnection conn = null;
            RandomAccessFile raf = null;
            try {
                URL url = new URL(mFileInfo.getUrl());
                conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5000);
                conn.setReadTimeout(5000);
                int length = -1;
                if (conn.getResponseCode() == 200) {
                    length = conn.getContentLength();
                }
                if (length < 0) {
                    return;
                }
                //创建本地文件
                File dir = new File("/data/data/" + getPackageName() + "/downloads/");
                if (!dir.exists()) {
                    dir.mkdir();
                }
                File file = new File(dir, mFileInfo.getFileName());
                raf = new RandomAccessFile(file, "rwd");
                //设置文件长度
                raf.setLength(length);
                //将获取文件长度之后的FileInfo回传到主线程
                mFileInfo.setLength(length);
                mHandler.obtainMessage(MSG_INIT, mFileInfo).sendToTarget();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    conn.disconnect();
                    raf.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }
    }
Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MSG_INIT:
                    FileInfo fileInfo = (FileInfo) msg.obj;
                    Log.i("InitfileInfo", fileInfo.toString());
                    break;
                default:
                    break;
            }
        }
    };

五、创建数据库和数据访问接口
创建数据库辅助类


    private static final String DB_NAME = "download.db";
    private static final int VERSION = 1;
    private static final String SQL_CREATE = "create table thread_info(_id integer primary key autoincrement," +
            "thread_id integer,url text,start integer,stop integer,progress integer)";
    private static final String SQL_DROP = "drop table if exists thread_info";

    public DBHelper(Context context) {
        super(context, DB_NAME, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(SQL_CREATE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(SQL_DROP);
        db.execSQL(SQL_CREATE);
    }
}

数据访问接口

public interface ThreadDao {
    public void insertThread(ThreadInfo threadInfo);
    public void deleteThread(String url,int thread_id);
    public void updateThread(String ul,int thread_id,int progress);
    public List<ThreadInfo> getThreads(String url);
    public boolean isExists(String ul,int thread_id);
}

数据访问接口实现

public class ThreadDaoImpl implements ThreadDao {
    private DBHelper dbHelper;

    public ThreadDaoImpl(Context context) {
        dbHelper = new DBHelper(context);
    }

    @Override
    public void insertThread(ThreadInfo threadInfo) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put("thread_id", threadInfo.getId());
        values.put("url", threadInfo.getUrl());
        values.put("start", threadInfo.getStart());
        values.put("stop", threadInfo.getStop());
        values.put("progress", threadInfo.getProgress());
        db.insert("thread_info", null, values);
        db.close();
    }

    @Override
    public void deleteThread(String url, int thread_id) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        db.delete("thread_info", "url = ? and thread_id = ?", new String[]{url, thread_id + ""});
        db.close();
    }

    @Override
    public void updateThread(String url, int thread_id, int progress) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put("progress", progress);
        db.update("thread_info", values, "url = ? and thread_id = ?", new String[]{url, thread_id + ""});
        db.close();
    }

    @Override
    public List<ThreadInfo> getThreads(String url) {
        List<ThreadInfo> list = new ArrayList<>();
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        Cursor cursor = db.rawQuery("select * from thread_info where url = ?", new String[]{url});
        while (cursor.moveToNext()) {
            ThreadInfo threadInfo = new ThreadInfo();
            threadInfo.setId(cursor.getInt(cursor.getColumnIndex("thread_id")));
            threadInfo.setUrl(cursor.getString(cursor.getColumnIndex("url")));
            threadInfo.setStart(cursor.getInt(cursor.getColumnIndex("start")));
            threadInfo.setStop(cursor.getInt(cursor.getColumnIndex("stop")));
            threadInfo.setProgress(cursor.getInt(cursor.getColumnIndex("progress")));
            list.add(threadInfo);
        }
        cursor.close();
        db.close();
        return list;
    }

    @Override
    public boolean isExists(String url, int thread_id) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        Cursor cursor = db.rawQuery("select * from thread_info where url = ? and thread_id = ?", new String[]{url, thread_id + ""});
        boolean result = cursor.moveToNext();
        cursor.close();
        db.close();
        return result;
    }
}

六、数据下载类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值