【移動應(yīng)用開發(fā)技術(shù)】Android 中怎么實現(xiàn)多任務(wù)多線程斷點下載功能_第1頁
【移動應(yīng)用開發(fā)技術(shù)】Android 中怎么實現(xiàn)多任務(wù)多線程斷點下載功能_第2頁
【移動應(yīng)用開發(fā)技術(shù)】Android 中怎么實現(xiàn)多任務(wù)多線程斷點下載功能_第3頁
【移動應(yīng)用開發(fā)技術(shù)】Android 中怎么實現(xiàn)多任務(wù)多線程斷點下載功能_第4頁
【移動應(yīng)用開發(fā)技術(shù)】Android 中怎么實現(xiàn)多任務(wù)多線程斷點下載功能_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實現(xiàn)多任務(wù)多線程斷點下載功能

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;

/**

*

業(yè)務(wù)bean

*

*/

public

class

FileService

{

private

DBOpenHelper

openHelper;

public

FileService(Context

context)

{

openHelper

=

new

DBOpenHelper(context);

}

/**

*

獲取每條線程已經(jīng)下載的文件長度

*

@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;

}

/**

*

保存每條線程已經(jīng)下載的文件長度

*

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

}

/**

*

實時更新每條線程已經(jīng)下載的文件長度

*

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

}

/**

*

當(dāng)文件下載完成后,刪除對應(yīng)的下載記錄

*

@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;

/*

線程數(shù)

*/

private

SmartDownloadThread[]

threads;

/*

本地保存文件

*/

private

File

saveFile;

/*

緩存各線程下載的長度*/

private

Map<Integer,

Integer>

data

=

new

ConcurrentHashMap<Integer,

Integer>();

/*

每條線程下載的長度

*/

private

int

block;

/*

下載路徑

*/

private

String

downloadUrl;

/**

*

獲取線程數(shù)

*/

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

}

/**

*

構(gòu)建文件下載器

*

@param

downloadUrl

下載路徑

*

@param

fileSaveDir

文件保存目錄

*

@param

threadNum

下載線程數(shù)

*/

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();//根據(jù)響應(yīng)獲取文件大小

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("已經(jīng)下載的長度"+

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";//默認(rèn)取一個文件名

}

return

filename;

}

/**

*

開始下載文件

*

@param

listener

監(jiān)聽下載數(shù)量的變化,如果不需要了解實時下載的數(shù)量,可以設(shè)置為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();//清除數(shù)據(jù)

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){

//該線程未完成下載時,繼續(xù)下載

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)

{//

循環(huán)判斷是否下載完畢

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響應(yīng)頭字段

*

@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;//結(jié)束位置

http.setRequestProperty("Range",

"bytes="

+

startPos

+

"-"+

endPos);//設(shè)置獲取實體數(shù)據(jù)的范圍

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;

}

/**

*

已經(jīng)下載的內(nèi)容大小

*

@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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論