【移动应用开发技术】Android 中怎么实现多任务多线程断点下载功能_第1页
【移动应用开发技术】Android 中怎么实现多任务多线程断点下载功能_第2页
【移动应用开发技术】Android 中怎么实现多任务多线程断点下载功能_第3页
【移动应用开发技术】Android 中怎么实现多任务多线程断点下载功能_第4页
【移动应用开发技术】Android 中怎么实现多任务多线程断点下载功能_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】Android中怎么实现多任务多线程断点下载功能

package

com.smart.db;

import

java.util.HashMap;

import

java.util.Map;

import

android.content.Context;

import

android.database.Cursor;

import

android.database.sqlite.SQLiteDatabase;

/**

*

业务bean

*

*/

public

class

FileService

{

private

DBOpenHelper

openHelper;

public

FileService(Context

context)

{

openHelper

=

new

DBOpenHelper(context);

}

/**

*

获取每条线程已经下载的文件长度

*

@param

path

*

@return

*/

public

Map<Integer,

Integer>

getData(String

path){

SQLiteDatabase

db

=

openHelper.getReadableDatabase();

Cursor

cursor

=

db.rawQuery("select

threadid,

downlength

from

SmartFileDownlog

where

downpath=?",

new

String[]{path});

Map<Integer,

Integer>

data

=

new

HashMap<Integer,

Integer>();

while(cursor.moveToNext()){

data.put(cursor.getInt(0),

cursor.getInt(1));

}

cursor.close();

db.close();

return

data;

}

/**

*

保存每条线程已经下载的文件长度

*

@param

path

*

@param

map

*/

public

void

save(String

path,

Map<Integer,

Integer>

map){//int

threadid,

int

position

SQLiteDatabase

db

=

openHelper.getWritableDatabase();

db.beginTransaction();

try{

for(Map.Entry<Integer,

Integer>

entry

:

map.entrySet()){

db.execSQL("insert

into

SmartFileDownlog(downpath,

threadid,

downlength)

values(?,?,?)",

new

Object[]{path,

entry.getKey(),

entry.getValue()});

}

db.setTransactionSuccessful();

}finally{

db.endTransaction();

}

db.close();

}

/**

*

实时更新每条线程已经下载的文件长度

*

@param

path

*

@param

map

*/

public

void

update(String

path,

Map<Integer,

Integer>

map){

SQLiteDatabase

db

=

openHelper.getWritableDatabase();

db.beginTransaction();

try{

for(Map.Entry<Integer,

Integer>

entry

:

map.entrySet()){

db.execSQL("update

SmartFileDownlog

set

downlength=?

where

downpath=?

and

threadid=?",

new

Object[]{entry.getValue(),

path,

entry.getKey()});

}

db.setTransactionSuccessful();

}finally{

db.endTransaction();

}

db.close();

}

/**

*

当文件下载完成后,删除对应的下载记录

*

@param

path

*/

public

void

delete(String

path){

SQLiteDatabase

db

=

openHelper.getWritableDatabase();

db.execSQL("delete

from

SmartFileDownlog

where

downpath=?",

new

Object[]{path});

db.close();

}

}

package

com.smart.impl;

import

java.io.File;

import

java.io.RandomAccessFile;

import

.HttpURLConnection;

import

.URL;

import

java.util.LinkedHashMap;

import

java.util.Map;

import

java.util.UUID;

import

java.util.concurrent.ConcurrentHashMap;

import

java.util.regex.Matcher;

import

java.util.regex.Pattern;

import

android.content.Context;

import

android.util.Log;

import

com.smart.db.FileService;

/**

*

文件下载器

*

@author

lihuoming@

*/

public

class

SmartFileDownloader

{

private

static

final

String

TAG

=

"SmartFileDownloader";

private

Context

context;

private

FileService

fileService;

/*

已下载文件长度

*/

private

int

downloadSize

=

0;

/*

原始文件长度

*/

private

int

fileSize

=

0;

/*

线程数

*/

private

SmartDownloadThread[]

threads;

/*

本地保存文件

*/

private

File

saveFile;

/*

缓存各线程下载的长度*/

private

Map<Integer,

Integer>

data

=

new

ConcurrentHashMap<Integer,

Integer>();

/*

每条线程下载的长度

*/

private

int

block;

/*

下载路径

*/

private

String

downloadUrl;

/**

*

获取线程数

*/

public

int

getThreadSize()

{

return

threads.length;

}

/**

*

获取文件大小

*

@return

*/

public

int

getFileSize()

{

return

fileSize;

}

/**

*

累计已下载大小

*

@param

size

*/

protected

synchronized

void

append(int

size)

{

downloadSize

+=

size;

}

/**

*

更新指定线程最后下载的位置

*

@param

threadId

线程id

*

@param

pos

最后下载的位置

*/

protected

void

update(int

threadId,

int

pos)

{

this.data.put(threadId,

pos);

}

/**

*

保存记录文件

*/

protected

synchronized

void

saveLogFile()

{

this.fileService.update(this.downloadUrl,

this.data);

}

/**

*

构建文件下载器

*

@param

downloadUrl

下载路径

*

@param

fileSaveDir

文件保存目录

*

@param

threadNum

下载线程数

*/

public

SmartFileDownloader(Context

context,

String

downloadUrl,

File

fileSaveDir,

int

threadNum)

{

try

{

this.context

=

context;

this.downloadUrl

=

downloadUrl;

fileService

=

new

FileService(this.context);

URL

url

=

new

URL(this.downloadUrl);

if(!fileSaveDir.exists())

fileSaveDir.mkdirs();

this.threads

=

new

SmartDownloadThread[threadNum];

HttpURLConnection

conn

=

(HttpURLConnection)

url.openConnection();

conn.setConnectTimeout(5*1000);

conn.setRequestMethod("GET");

conn.setRequestProperty("Accept",

"image/gif,

image/jpeg,

image/pjpeg,

image/pjpeg,

application/x-shockwave-flash,

application/xaml+xml,

application/vnd.ms-xpsdocument,

application/x-ms-xbap,

application/x-ms-application,

application/vnd.ms-excel,

application/vnd.ms-powerpoint,

application/msword,

*/*");

conn.setRequestProperty("Accept-Language",

"zh-CN");

conn.setRequestProperty("Referer",

downloadUrl);

conn.setRequestProperty("Charset",

"UTF-8");

conn.setRequestProperty("User-Agent",

"Mozilla/4.0

(compatible;

MSIE

8.0;

Windows

NT

5.2;

Trident/4.0;

.NET

CLR

1.1.4322;

.NET

CLR

2.0.50727;

.NET

CLR

3.0.04506.30;

.NET

CLR

3.0.4506.2152;

.NET

CLR

3.5.30729)");

conn.setRequestProperty("Connection",

"Keep-Alive");

conn.connect();

printResponseHeader(conn);

if

(conn.getResponseCode()==200)

{

this.fileSize

=

conn.getContentLength();//根据响应获取文件大小

if

(this.fileSize

<=

0)

throw

new

RuntimeException("Unkown

file

size

");

String

filename

=

getFileName(conn);

this.saveFile

=

new

File(fileSaveDir,

filename);/*

保存文件

*/

Map<Integer,

Integer>

logdata

=

fileService.getData(downloadUrl);

if(logdata.size()>0){

for(Map.Entry<Integer,

Integer>

entry

:

logdata.entrySet())

data.put(entry.getKey(),

entry.getValue());

}

this.block

=

(this.fileSize

%

this.threads.length)==0?

this.fileSize

/

this.threads.length

:

this.fileSize

/

this.threads.length

+

1;

if(this.data.size()==this.threads.length){

for

(int

i

=

0;

i

<

this.threads.length;

i++)

{

this.downloadSize

+=

this.data.get(i+1);

}

print("已经下载的长度"+

this.downloadSize);

}

}else{

throw

new

RuntimeException("server

no

response

");

}

}

catch

(Exception

e)

{

print(e.toString());

throw

new

RuntimeException("don't

connection

this

url");

}

}

/**

*

获取文件名

*/

private

String

getFileName(HttpURLConnection

conn)

{

String

filename

=

this.downloadUrl.substring(this.downloadUrl.lastIndexOf('/')

+

1);

if(filename==null

||

"".equals(filename.trim())){//如果获取不到文件名称

for

(int

i

=

0;;

i++)

{

String

mine

=

conn.getHeaderField(i);

if

(mine

==

null)

break;

if("content-disposition".equals(conn.getHeaderFieldKey(i).toLowerCase())){

Matcher

m

=

Ppile(".*filename=(.*)").matcher(mine.toLowerCase());

if(m.find())

return

m.group(1);

}

}

filename

=

UUID.randomUUID()+

".tmp";//默认取一个文件名

}

return

filename;

}

/**

*

开始下载文件

*

@param

listener

监听下载数量的变化,如果不需要了解实时下载的数量,可以设置为null

*

@return

已下载文件大小

*

@throws

Exception

*/

public

int

download(SmartDownloadProgressListener

listener)

throws

Exception{

try

{

RandomAccessFile

randOut

=

new

RandomAccessFile(this.saveFile,

"rw");

if(this.fileSize>0)

randOut.setLength(this.fileSize);

randOut.close();

URL

url

=

new

URL(this.downloadUrl);

if(this.data.size()

!=

this.threads.length){

this.data.clear();//清除数据

for

(int

i

=

0;

i

<

this.threads.length;

i++)

{

this.data.put(i+1,

0);

}

}

for

(int

i

=

0;

i

<

this.threads.length;

i++)

{

int

downLength

=

this.data.get(i+1);

if(downLength

<

this.block

&&

this.downloadSize<this.fileSize){

//该线程未完成下载时,继续下载

this.threads

=

new

SmartDownloadThread(this,

url,

this.saveFile,

this.block,

this.data.get(i+1),

i+1);

this.threads.setPriority(7);

this.threads.start();

}else{

this.threads

=

null;

}

}

this.fileService.save(this.downloadUrl,

this.data);

boolean

notFinish

=

true;//下载未完成

while

(notFinish)

{//

循环判断是否下载完毕

Thread.sleep(900);

notFinish

=

false;//假定下载完成

for

(int

i

=

0;

i

<

this.threads.length;

i++){

if

(this.threads

!=

null

&&

!this.threads.isFinish())

{

notFinish

=

true;//下载没有完成

if(this.threads.getDownLength()

==

-1){//如果下载失败,再重新下载

this.threads

=

new

SmartDownloadThread(this,

url,

this.saveFile,

this.block,

this.data.get(i+1),

i+1);

this.threads.setPriority(7);

this.threads.start();

}

}

}

if(listener!=null)

listener.onDownloadSize(this.downloadSize);

}

fileService.delete(this.downloadUrl);

}

catch

(Exception

e)

{

print(e.toString());

throw

new

Exception("file

download

fail");

}

return

this.downloadSize;

}

/**

*

获取Http响应头字段

*

@param

http

*

@return

*/

public

static

Map<String,

String>

getHttpResponseHeader(HttpURLConnection

http)

{

Map<String,

String>

header

=

new

LinkedHashMap<String,

String>();

for

(int

i

=

0;;

i++)

{

String

mine

=

http.getHeaderField(i);

if

(mine

==

null)

break;

header.put(http.getHeaderFieldKey(i),

mine);

}

return

header;

}

/**

*

打印Http头字段

*

@param

http

*/

public

static

void

printResponseHeader(HttpURLConnection

http){

Map<String,

String>

header

=

getHttpResponseHeader(http);

for(Map.Entry<String,

String>

entry

:

header.entrySet()){

String

key

=

entry.getKey()!=null

?

entry.getKey()+

":"

:

"";

print(key+

entry.getValue());

}

}

//打印日志

private

static

void

print(String

msg){

Log.i(TAG,

msg);

}

}

package

com.smart.impl;

import

java.io.File;

import

java.io.InputStream;

import

java.io.RandomAccessFile;

import

.HttpURLConnection;

import

.URL;

import

android.util.Log;

public

class

SmartDownloadThread

extends

Thread

{

private

static

final

String

TAG

=

"SmartDownloadThread";

private

File

saveFile;

private

URL

downUrl;

private

int

block;

/*

*下载开始位置

*/

private

int

threadId

=

-1;

private

int

downLength;

private

boolean

finish

=

false;

private

SmartFileDownloader

downloader;

public

SmartDownloadThread(SmartFileDownloader

downloader,

URL

downUrl,

File

saveFile,

int

block,

int

downLength,

int

threadId)

{

this.downUrl

=

downUrl;

this.saveFile

=

saveFile;

this.block

=

block;

this.downloader

=

downloader;

this.threadId

=

threadId;

this.downLength

=

downLength;

}

@Override

public

void

run()

{

if(downLength

<

block){//未下载完成

try

{

HttpURLConnection

http

=

(HttpURLConnection)

downUrl.openConnection();

http.setConnectTimeout(5

*

1000);

http.setRequestMethod("GET");

http.setRequestProperty("Accept",

"image/gif,

image/jpeg,

image/pjpeg,

image/pjpeg,

application/x-shockwave-flash,

application/xaml+xml,

application/vnd.ms-xpsdocument,

application/x-ms-xbap,

application/x-ms-application,

application/vnd.ms-excel,

application/vnd.ms-powerpoint,

application/msword,

*/*");

http.setRequestProperty("Accept-Language",

"zh-CN");

http.setRequestProperty("Referer",

downUrl.toString());

http.setRequestProperty("Charset",

"UTF-8");

int

startPos

=

block

*

(threadId

-

1)

+

downLength;//开始位置

int

endPos

=

block

*

threadId

-1;//结束位置

http.setRequestProperty("Range",

"bytes="

+

startPos

+

"-"+

endPos);//设置获取实体数据的范围

http.setRequestProperty("User-Agent",

"Mozilla/4.0

(compatible;

MSIE

8.0;

Windows

NT

5.2;

Trident/4.0;

.NET

CLR

1.1.4322;

.NET

CLR

2.0.50727;

.NET

CLR

3.0.04506.30;

.NET

CLR

3.0.4506.2152;

.NET

CLR

3.5.30729)");

http.setRequestProperty("Connection",

"Keep-Alive");

InputStream

inStream

=

http.getInputStream();

byte[]

buffer

=

new

byte[1024];

int

offset

=

0;

print("Thread

"

+

this.threadId

+

"

start

download

from

position

"+

startPos);

RandomAccessFile

threadfile

=

new

RandomAccessFile(this.saveFile,

"rwd");

threadfile.seek(startPos);

while

((offset

=

inStream.read(buffer,

0,

1024))

!=

-1)

{

threadfile.write(buffer,

0,

offset);

downLength

+=

offset;

downloader.update(this.threadId,

downLength);

downloader.saveLogFile();

downloader.append(offset);

}

threadfile.close();

inStream.close();

print("Thread

"

+

this.threadId

+

"

download

finish");

this.finish

=

true;

}

catch

(Exception

e)

{

this.downLength

=

-1;

print("Thread

"+

this.threadId+

":"+

e);

}

}

}

private

static

void

print(String

msg){

Log.i(TAG,

msg);

}

/**

*

下载是否完成

*

@return

*/

public

boolean

isFinish()

{

return

finish;

}

/**

*

已经下载的内容大小

*

@return

如果返回值为-1,代表下载失败

*/

public

long

getDownLength()

{

return

downLength;

}

}

package

com.smart.activoty.download;

import

java.io.File;

import

android.app.Activity;

import

android.os.Bundle;

import

android.os.Environment;

import

android.os.Handler;

import

android.os.Message;

import

android.view.View;

import

android.widget.Button;

import

android.widget.EditText;

import

android.widget.ProgressBar;

import

android.widget.TextView;

import

android.widget.Toast;

import

com.smart.impl.SmartDownloadProgressListener;

import

com.smart.impl.SmartFileDownloader;

public

class

SmartDownloadActivity

extends

Activity

{

private

ProgressBar

downloadbar;

private

EditText

pathText;

private

TextView

resultView;

private

Handler

handler

=

new

Handler(){

@Override//信息

public

void

handleMessage(Message

msg)

{

switch

(msg.what)

{

case

1:

int

size

=

msg.getData().getInt("size");

downloadbar.setProgress(size);

float

result

=

(float)downloadbar.getProgress()/

(float)downloadbar.getMax();

int

p

=

(int)(result*100);

resultView.setText(p+"%");

if(downloadbar.getProgress()==downloadbar.getMax())

Toast.makeText(SmartDownloadActivity.this,

R.string.success,

1).show();

break;

case

-1:

Toast.makeText(SmartDownloadActivity.this,

R.string.error,

1).show();

break;

}

}

};

@Override

public

void

onCreate(Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

Button

button

=

(Button)this.findViewById(R.id.button);

downlo

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论