andorid单线程断点续传下载

1.用途 : 学习android4大组件的良好实例 , 关键知识点有 :
a.Activity如何与Service交互数据;
b.下载为何要使用Service?Service处于后台组件,便于与多个Activity交互,即使app没有处于当前应用页面,也能进行下载;
c.保存当前下载文件的下载量
d.Service通过BroatCast广播更新UI数据;
e.非主线程通过Handler发送消息更新UI;
f.熟悉网络连接代码及文件处理;
2.实现:
a.主界面MainActivity定义下载和暂停下载任务,及定义广播;

public class MainActivity extends AppCompatActivity {

    private TextView mFileNameTv = null;
    private ProgressBar mPbgressBar = null;
    private Button mBtStart = null;
    private Button mBtEnd = null;


    BroadcastReceiver mReceiver = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mFileNameTv = (TextView) findViewById(R.id.tv_fileName);
        mPbgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mBtStart = (Button) findViewById(R.id.bt_start);
        mBtEnd = (Button) findViewById(R.id.bt_end);

        mPbgressBar.setMax(100);
        mFileNameTv.setText("mukewang.apk");

        mBtStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, DownloadService.class);
                intent.setAction(DownloadService.ACTION_START);
                FileInfo fileInfo = new FileInfo("http://www.imooc.com/mobile/mukewang.apk", "mukewang.apk", 0, 0);
                intent.putExtra("fileInfo", fileInfo);
                startService(intent);
            }
        });
        mBtEnd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, DownloadService.class);
                intent.setAction(DownloadService.ACTION_STOP);
                FileInfo fileInfo = new FileInfo("http://www.imooc.com/mobile/mukewang.apk", "mukewang.apk", 0, 0);
                intent.putExtra("fileInfo", fileInfo);
                startService(intent);
            }
        });

        mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (DownloadService.ACTION_UPDATE.equals(intent.getAction())) {
                    int progress = intent.getIntExtra("progress", 0);
                    mPbgressBar.setProgress(progress);
                }
            }
        };

        IntentFilter filter = new IntentFilter();
        filter.addAction(DownloadService.ACTION_UPDATE);
        registerReceiver(mReceiver, filter);

    }

    @Override
    protected void onDestroy() {
        if(mReceiver!=null)
        {
            unregisterReceiver(mReceiver);
        }
        super.onDestroy();
    }
}

b.定义下载文件实体类:

public class FileInfo implements Serializable{
    public FileInfo(String url, String fileName, int length, int finished) {
        this.url = url;
        this.fileName = fileName;
        this.length = length;
        this.finished = finished;
    }

    public FileInfo() {
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public int getFinished() {
        return finished;
    }

    public void setFinished(int finished) {
        this.finished = finished;
    }

    private String url;
    private String fileName;
    private int length;
    private int finished;

    @Override
    public String toString() {
        return "FileInfo{" +
                "url='" + url + '\'' +
                ", fileName='" + fileName + '\'' +
                ", length=" + length +
                ", finished=" + finished +
                '}';
    }
}

c.定义任务线程下载信息:

public class ThreadInfo {
    public String getUrl() {
        return url;
    }

    public ThreadInfo() {
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public int getStart() {
        return start;
    }

    public void setStart(int start) {
        this.start = start;
    }

    public int getEnd() {
        return end;
    }

    public void setEnd(int end) {
        this.end = end;
    }

    public int getFinished() {
        return finished;
    }

    public void setFinished(int finished) {
        this.finished = finished;
    }

    private String url;
    private int start;
    private int end;
    private int finished;

    public ThreadInfo(String url, int start, int end, int finished) {
        this.url = url;
        this.start = start;
        this.end = end;
        this.finished = finished;
    }


}

d.定义后台Service,新建下载线程:

public class ThreadInfo {
    public String getUrl() {
        return url;
    }

    public ThreadInfo() {
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public int getStart() {
        return start;
    }

    public void setStart(int start) {
        this.start = start;
    }

    public int getEnd() {
        return end;
    }

    public void setEnd(int end) {
        this.end = end;
    }

    public int getFinished() {
        return finished;
    }

    public void setFinished(int finished) {
        this.finished = finished;
    }

    private String url;
    private int start;
    private int end;
    private int finished;

    public ThreadInfo(String url, int start, int end, int finished) {
        this.url = url;
        this.start = start;
        this.end = end;
        this.finished = finished;
    }


}

e.定义数据库帮助类:

public class DbHelper extends SQLiteOpenHelper {

    public static final String DOWNLOAD_DB = "download.db";

    public DbHelper(Context context) {
        super(context, DOWNLOAD_DB, null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase database) {
        database.execSQL("create table thread_info(url text,start integer,end integer,finished integer)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase database, int i, int i1) {

        database.execSQL("drop table thread_info");
        database.execSQL("create table thread_info(url text,start integer,end integer,finished integer)");
    }
}

数据访问接口:

public interface ThreadDao {
    public void insertThread(ThreadInfo thread_info);
    public void deleteThread(String url);
    public void updateThread(String url,int finished);
    public ThreadInfo getThread(String url);

}

实现数据访问接口:

public class ThreadDaoImpl implements ThreadDao {

    private Context mContext;
    private DbHelper mDbHelper;

    public ThreadDaoImpl(Context context)
    {
        this.mContext = context;
        mDbHelper = new DbHelper(mContext);
    }

    @Override
    public void insertThread(ThreadInfo thread_info) {
        SQLiteDatabase database = mDbHelper.getWritableDatabase();
        database.execSQL("insert into thread_info (url ,start ,end ,finished) values ("+"'"+thread_info.getUrl()+"'"+","+
                thread_info.getStart()+","+thread_info.getEnd()+","+thread_info.getFinished()+")");
    }

    @Override
    public void deleteThread(String url) {
        SQLiteDatabase database = mDbHelper.getWritableDatabase();
        database.execSQL("delete from thread_info where url = "+"'"+url+"'");
    }

    @Override
    public void updateThread(String url,int finished) {
        SQLiteDatabase database = mDbHelper.getWritableDatabase();
        database.execSQL("update thread_info set finished = "+finished +" where url = "+"'"+url+"'");
    }

    @Override
    public ThreadInfo getThread(String url) {
        SQLiteDatabase database = mDbHelper.getWritableDatabase();
        Cursor cursor = database.query("thread_info", null, null, null, null, null, null);
        ThreadInfo thread_info = null;
        while (cursor.moveToNext()) {
             thread_info = new ThreadInfo();
            thread_info.setUrl(cursor.getString(0));
            thread_info.setStart(cursor.getInt(1));
            thread_info.setEnd(cursor.getInt(2));
            thread_info.setFinished(cursor.getInt(3));
        }
        return thread_info;
    }
}

f.下载任务线程类:

public class DownloadTask extends Thread {

    private ThreadInfo mThreadInfo;
    private ThreadDaoImpl mThreadDao;
    private Context mContext;
    private String mFileName;
    private int finished;
    public boolean isPause = false;

    public DownloadTask(Context context, FileInfo fileInfo)
    {
        this.mContext = context;
        mThreadDao = new ThreadDaoImpl(mContext);
        this.mFileName = fileInfo.getFileName();
        mThreadInfo = mThreadDao.getThread(fileInfo.getUrl());
        if(mThreadInfo == null)
        {
            mThreadInfo = new ThreadInfo();
            mThreadInfo.setUrl(fileInfo.getUrl());
            mThreadInfo.setStart(0);
            mThreadInfo.setEnd(fileInfo.getLength());
            mThreadInfo.setFinished(0);
            mThreadDao.insertThread(mThreadInfo);
        }
        finished = mThreadInfo.getStart() + mThreadInfo.getFinished();
    }
    @Override
    public void run() {
        //打开连接
        HttpURLConnection conn = null;
        RandomAccessFile accessFile = null;
        InputStream isput = null;
        try {
            URL url = new URL(mThreadInfo.getUrl());
            conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(3000);
            conn.setRequestMethod("GET");
            //设置下载位置
            conn.setRequestProperty("Range", "bytes="+(finished) + "-" + mThreadInfo.getEnd());
            accessFile = new RandomAccessFile(new File(DownloadService.DOWNLOAD_PATH+mFileName), "rwd");
            accessFile.seek(mThreadInfo.getStart() + mThreadInfo.getFinished());
            //读取并保存下载文件
            isput = conn.getInputStream();
            byte[] buffer = new byte[4096];
            int length = -1;
            long time = System.currentTimeMillis();
            while ((length = isput.read(buffer)) != -1) {
                if (isPause) {
                    mThreadDao.updateThread(mThreadInfo.getUrl(),finished);
                    return;
                }
                accessFile.write(buffer, 0, length);
                finished += length;
                // 更新数据库中的下载信息
               mThreadDao.updateThread(mThreadInfo.getUrl(),finished);

                if(System.currentTimeMillis() - time > 500) {
                    time = System.currentTimeMillis();
                    // 用消息将下载信息传给进度条,对进度条进行更新
                    Intent intent = new Intent();
                    intent.setAction(DownloadService.ACTION_UPDATE);
                    intent.putExtra("progress", finished * 100 / mThreadInfo.getEnd());
                    mContext.sendBroadcast(intent);
                }
            }
            mThreadDao.deleteThread(mThreadInfo.getUrl());
            } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                isput.close();
                conn.disconnect();
                accessFile.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

3.总结:通过该实例,建立宏观的android基本组件的认识;

猜你喜欢

转载自blog.csdn.net/yaonga/article/details/76269328
今日推荐