Android 는 AsyncTask 를 사용 하여 다 중 태 스 크 다 중 스 레 드 정지점 전송 다운 로드 를 실현 합 니 다.
하나
둘.
여기 서 아 날로 그 앱 다운 로드 는 하나의 Demo 를 실현 했다.하나의 인터페이스 만 있 기 때문에 다운 로드 를 Service 에 넣 지 않 고 Activity 에서 직접 만 들 었 다.정식 프로젝트 에서 다운 로드 는 모두 Service 에 넣 은 다음 에 BroadCast 를 통 해 인터페이스 업데이트 진 도 를 알 립 니 다.
코드 를 올 리 기 전에 데모 의 실행 효과 도 를 보 세 요.
다음은 코드 를 보 겠 습 니 다.이 파일 의 다운로드 정 의 는 다운 로 더 를 정의 하여 이 파일 을 다운로드 하 는 모든 스 레 드(일시 정지,다운로드 등)를 관리 합 니 다.Downloador 는 이 파일 의 특정한 시작 위 치 를 다운로드 하기 위해 3 개의 DownloadTask 를 만 듭 니 다.파일 의 크기 를 통 해 모든 스 레 드 가 다운로드 한 시작 과 끝 위 치 를 계산 하려 면 을 참고 하 십시오.
1.다운 로 더 클래스
package com.bbk.lling.multitaskdownload.downloador;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.bbk.lling.multitaskdownload.beans.AppContent;
import com.bbk.lling.multitaskdownload.beans.DownloadInfo;
import com.bbk.lling.multitaskdownload.db.DownloadFileDAO;
import com.bbk.lling.multitaskdownload.db.DownloadInfoDAO;
import com.bbk.lling.multitaskdownload.utils.DownloadUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* @Class: Downloador
* @Description:
* @author: lling(www.cnblogs.com/liuling)
* @Date: 2015/10/13
*/
public class Downloador {
public static final String TAG = "Downloador";
private static final int THREAD_POOL_SIZE = 9; // 9
private static final int THREAD_NUM = 3; // 3
private static final int GET_LENGTH_SUCCESS = 1;
public static final Executor THREAD_POOL_EXECUTOR = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
private List<DownloadTask> tasks;
private InnerHandler handler = new InnerHandler();
private AppContent appContent; //
private long downloadLength; //
private long fileLength;
private Context context;
private String downloadPath;
public Downloador(Context context, AppContent appContent) {
this.context = context;
this.appContent = appContent;
this.downloadPath = DownloadUtils.getDownloadPath();
}
/**
*
*/
public void download() {
if(TextUtils.isEmpty(downloadPath)) {
Toast.makeText(context, " SD ", Toast.LENGTH_SHORT).show();
return;
}
if(appContent == null) {
throw new IllegalArgumentException("download content can not be null");
}
new Thread() {
@Override
public void run() {
//
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(appContent.getUrl());
HttpResponse response = null;
try {
response = client.execute(request);
fileLength = response.getEntity().getContentLength();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} finally {
if (request != null) {
request.abort();
}
}
//
List<DownloadInfo> lists = DownloadInfoDAO.getInstance(context.getApplicationContext())
.getDownloadInfosByUrl(appContent.getUrl());
for (DownloadInfo info : lists) {
downloadLength += info.getDownloadLength();
}
//
DownloadFileDAO.getInstance(context.getApplicationContext()).insertDownloadFile(appContent);
Message.obtain(handler, GET_LENGTH_SUCCESS).sendToTarget();
}
}.start();
}
/**
* AsyncTask
*/
private void beginDownload() {
Log.e(TAG, "beginDownload" + appContent.getUrl());
appContent.setStatus(AppContent.Status.WAITING);
long blockLength = fileLength / THREAD_NUM;
for (int i = 0; i < THREAD_NUM; i++) {
long beginPosition = i * blockLength;//
long endPosition = (i + 1) * blockLength;//
if (i == (THREAD_NUM - 1)) {
endPosition = fileLength;// ,
}
DownloadTask task = new DownloadTask(i, beginPosition, endPosition, this, context);
task.executeOnExecutor(THREAD_POOL_EXECUTOR, appContent.getUrl());
if(tasks == null) {
tasks = new ArrayList<DownloadTask>();
}
tasks.add(task);
}
}
/**
*
*/
public void pause() {
for (DownloadTask task : tasks) {
if (task != null && (task.getStatus() == AsyncTask.Status.RUNNING || !task.isCancelled())) {
task.cancel(true);
}
}
tasks.clear();
appContent.setStatus(AppContent.Status.PAUSED);
DownloadFileDAO.getInstance(context.getApplicationContext()).updateDownloadFile(appContent);
}
/**
*
*/
protected synchronized void resetDownloadLength() {
this.downloadLength = 0;
}
/**
*
*
* @param size
*/
protected synchronized void updateDownloadLength(long size){
this.downloadLength += size;
//
int percent = (int)((float)downloadLength * 100 / (float)fileLength);
appContent.setDownloadPercent(percent);
if(percent == 100 || downloadLength == fileLength) {
appContent.setDownloadPercent(100); // , percent=99
appContent.setStatus(AppContent.Status.FINISHED);
DownloadFileDAO.getInstance(context.getApplicationContext()).updateDownloadFile(appContent);
}
Intent intent = new Intent(Constants.DOWNLOAD_MSG);
if(appContent.getStatus() == AppContent.Status.WAITING) {
appContent.setStatus(AppContent.Status.DOWNLOADING);
}
Bundle bundle = new Bundle();
bundle.putParcelable("appContent", appContent);
intent.putExtras(bundle);
context.sendBroadcast(intent);
}
protected String getDownloadPath() {
return downloadPath;
}
private class InnerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case GET_LENGTH_SUCCESS :
beginDownload();
break;
}
super.handleMessage(msg);
}
}
}
2,DownloadTask 클래스
package com.bbk.lling.multitaskdownload.downloador;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import com.bbk.lling.multitaskdownload.beans.DownloadInfo;
import com.bbk.lling.multitaskdownload.db.DownloadInfoDAO;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.MalformedURLException;
/**
* @Class: DownloadTask
* @Description: AsyncTask
* @author: lling(www.cnblogs.com/liuling)
* @Date: 2015/10/13
*/
public class DownloadTask extends AsyncTask<String, Integer , Long> {
private static final String TAG = "DownloadTask";
private int taskId;
private long beginPosition;
private long endPosition;
private long downloadLength;
private String url;
private Downloador downloador;
private DownloadInfoDAO downloadInfoDAO;
public DownloadTask(int taskId, long beginPosition, long endPosition, Downloador downloador,
Context context) {
this.taskId = taskId;
this.beginPosition = beginPosition;
this.endPosition = endPosition;
this.downloador = downloador;
downloadInfoDAO = DownloadInfoDAO.getInstance(context.getApplicationContext());
}
@Override
protected void onPreExecute() {
Log.e(TAG, "onPreExecute");
}
@Override
protected void onPostExecute(Long aLong) {
Log.e(TAG, url + "taskId:" + taskId + "executed");
// downloador.updateDownloadInfo(null);
}
@Override
protected void onProgressUpdate(Integer... values) {
// downloador
// downloador.updateDownloadLength(values[0]);
}
@Override
protected void onCancelled() {
Log.e(TAG, "onCancelled");
// downloador.updateDownloadInfo(null);
}
@Override
protected Long doInBackground(String... params) {
// : , cancel ,
if(isCancelled()) {
return null;
}
url = params[0];
if(url == null) {
return null;
}
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
HttpResponse response;
InputStream is;
RandomAccessFile fos = null;
OutputStream output = null;
DownloadInfo downloadInfo = null;
try {
//
File file = new File(downloador.getDownloadPath() + File.separator + url.substring(url.lastIndexOf("/") + 1));
//
downloadInfo = downloadInfoDAO.getDownloadInfoByTaskIdAndUrl(taskId, url);
//
// file.exists(), , , ,
if(file.exists() && downloadInfo != null) {
if(downloadInfo.isDownloadSuccess() == 1) {
//
return null;
}
beginPosition = beginPosition + downloadInfo.getDownloadLength();
downloadLength = downloadInfo.getDownloadLength();
}
if(!file.exists()) {
// task , , ,
downloador.resetDownloadLength();
}
// beginPosition endPosition
Header header_size = new BasicHeader("Range", "bytes=" + beginPosition + "-" + endPosition);
request.addHeader(header_size);
//
response = client.execute(request);
is = response.getEntity().getContent();
//
fos = new RandomAccessFile(file, "rw");
// size
fos.seek(beginPosition);
byte buffer [] = new byte[1024];
int inputSize = -1;
while((inputSize = is.read(buffer)) != -1) {
fos.write(buffer, 0, inputSize);
downloadLength += inputSize;
downloador.updateDownloadLength(inputSize);
// ,
if (isCancelled()) {
if(downloadInfo == null) {
downloadInfo = new DownloadInfo();
}
downloadInfo.setUrl(url);
downloadInfo.setDownloadLength(downloadLength);
downloadInfo.setTaskId(taskId);
downloadInfo.setDownloadSuccess(0);
//
downloadInfoDAO.insertDownloadInfo(downloadInfo);
return null;
}
}
} catch (MalformedURLException e) {
Log.e(TAG, e.getMessage());
} catch (IOException e) {
Log.e(TAG, e.getMessage());
} finally{
try{
if (request != null) {
request.abort();
}
if(output != null) {
output.close();
}
if(fos != null) {
fos.close();
}
} catch(Exception e) {
e.printStackTrace();
}
}
// , task
if(downloadInfo == null) {
downloadInfo = new DownloadInfo();
}
downloadInfo.setUrl(url);
downloadInfo.setDownloadLength(downloadLength);
downloadInfo.setTaskId(taskId);
downloadInfo.setDownloadSuccess(1);
//
downloadInfoDAO.insertDownloadInfo(downloadInfo);
return null;
}
}
Downloador 와 DownloadTask 는 이 예 의 핵심 코드 만 있 습 니 다.다음은 데이터베이스 에 관 한 것 입 니 다.정지점 전송 을 실현 하려 면 정지 할 때 모든 스 레 드 가 다운로드 한 위 치 를 기록 해 야 하기 때문에 다음 에 계속 다운로드 할 때 읽 기 편 합 니 다.여기에 두 개의 표 가 있 는데 하 나 는 각 파일 의 다운로드 상 태 를 저장 하 는 것 이 고 하 나 는 각 파일 에 대응 하 는 모든 스 레 드 의 다운로드 상 태 를 저장 하 는 것 이다.3、DBHelper
package com.bbk.lling.multitaskdownload.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* @Class: DBHelper
* @Description:
* @author: lling(www.cnblogs.com/liuling)
* @Date: 2015/10/14
*/
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, "download.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table download_info(_id INTEGER PRIMARY KEY AUTOINCREMENT, task_id INTEGER, "
+ "download_length INTEGER, url VARCHAR(255), is_success INTEGER)");
db.execSQL("create table download_file(_id INTEGER PRIMARY KEY AUTOINCREMENT, app_name VARCHAR(255), "
+ "url VARCHAR(255), download_percent INTEGER, status INTEGER)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
4.DownloadFileDAO,파일 다운로드 상태의 데이터베이스 작업 클래스
package com.bbk.lling.multitaskdownload.db;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import android.util.Log;
import com.bbk.lling.multitaskdownload.beans.AppContent;
import java.util.ArrayList;
import java.util.List;
/**
* @Class: DownloadFileDAO
* @Description:
* @author: lling(www.cnblogs.com/liuling)
* @Date: 2015/10/13
*/
public class DownloadFileDAO {
private static final String TAG = "DownloadFileDAO";
private static DownloadFileDAO dao=null;
private Context context;
private DownloadFileDAO(Context context) {
this.context=context;
}
synchronized public static DownloadFileDAO getInstance(Context context){
if(dao==null){
dao=new DownloadFileDAO(context);
}
return dao;
}
/**
*
* @return
*/
public SQLiteDatabase getConnection() {
SQLiteDatabase sqliteDatabase = null;
try {
sqliteDatabase= new DBHelper(context).getReadableDatabase();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return sqliteDatabase;
}
/**
*
* @param appContent
*/
public void insertDownloadFile(AppContent appContent) {
if(appContent == null) {
return;
}
// ,
if(getAppContentByUrl(appContent.getUrl()) != null) {
updateDownloadFile(appContent);
return;
}
SQLiteDatabase database = getConnection();
try {
String sql = "insert into download_file(app_name, url, download_percent, status) values (?,?,?,?)";
Object[] bindArgs = { appContent.getName(), appContent.getUrl(), appContent.getDownloadPercent()
, appContent.getStatus().getValue()};
database.execSQL(sql, bindArgs);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} finally {
if (null != database) {
database.close();
}
}
}
/**
* url
* @param url
* @return
*/
public AppContent getAppContentByUrl(String url) {
if(TextUtils.isEmpty(url)) {
return null;
}
SQLiteDatabase database = getConnection();
AppContent appContent = null;
Cursor cursor = null;
try {
String sql = "select * from download_file where url=?";
cursor = database.rawQuery(sql, new String[] { url });
if (cursor.moveToNext()) {
appContent = new AppContent(cursor.getString(1), cursor.getString(2));
appContent.setDownloadPercent(cursor.getInt(3));
appContent.setStatus(AppContent.Status.getByValue(cursor.getInt(4)));
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} finally {
if (null != database) {
database.close();
}
if (null != cursor) {
cursor.close();
}
}
return appContent;
}
/**
*
* @param appContent
*/
public void updateDownloadFile(AppContent appContent) {
if(appContent == null) {
return;
}
SQLiteDatabase database = getConnection();
try {
Log.e(TAG, "update download_file,app name:" + appContent.getName() + ",url:" + appContent.getUrl()
+ ",percent" + appContent.getDownloadPercent() + ",status:" + appContent.getStatus().getValue());
String sql = "update download_file set app_name=?, url=?, download_percent=?, status=? where url=?";
Object[] bindArgs = {appContent.getName(), appContent.getUrl(), appContent.getDownloadPercent()
, appContent.getStatus().getValue(), appContent.getUrl()};
database.execSQL(sql, bindArgs);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} finally {
if (null != database) {
database.close();
}
}
}
/**
*
* @return
*/
public List<AppContent> getAll() {
SQLiteDatabase database = getConnection();
List<AppContent> list = new ArrayList<AppContent>();
Cursor cursor = null;
try {
String sql = "select * from download_file";
cursor = database.rawQuery(sql, null);
while (cursor.moveToNext()) {
AppContent appContent = new AppContent(cursor.getString(1), cursor.getString(2));
appContent.setDownloadPercent(cursor.getInt(3));
appContent.setStatus(AppContent.Status.getByValue(cursor.getInt(4)));
list.add(appContent);
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} finally {
if (null != database) {
database.close();
}
if (null != cursor) {
cursor.close();
}
}
return list;
}
/**
* url
* @param url
*/
public void delByUrl(String url) {
if(TextUtils.isEmpty(url)) {
return;
}
SQLiteDatabase database = getConnection();
try {
String sql = "delete from download_file where url=?";
Object[] bindArgs = { url };
database.execSQL(sql, bindArgs);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} finally {
if (null != database) {
database.close();
}
}
}
}
5.DownloadInfoDAO,각 스 레 드 가 다운로드 상태 에 대응 하 는 데이터베이스 작업 클래스
package com.bbk.lling.multitaskdownload.db;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import android.util.Log;
import com.bbk.lling.multitaskdownload.beans.DownloadInfo;
import java.util.ArrayList;
import java.util.List;
/**
* @Class: DownloadInfoDAO
* @Description:
* @author: lling(www.cnblogs.com/liuling)
* @Date: 2015/10/13
*/
public class DownloadInfoDAO {
private static final String TAG = "DownloadInfoDAO";
private static DownloadInfoDAO dao=null;
private Context context;
private DownloadInfoDAO(Context context) {
this.context=context;
}
synchronized public static DownloadInfoDAO getInstance(Context context){
if(dao==null){
dao=new DownloadInfoDAO(context);
}
return dao;
}
/**
*
* @return
*/
public SQLiteDatabase getConnection() {
SQLiteDatabase sqliteDatabase = null;
try {
sqliteDatabase= new DBHelper(context).getReadableDatabase();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return sqliteDatabase;
}
/**
*
* @param downloadInfo
*/
public void insertDownloadInfo(DownloadInfo downloadInfo) {
if(downloadInfo == null) {
return;
}
// ,
if(getDownloadInfoByTaskIdAndUrl(downloadInfo.getTaskId(), downloadInfo.getUrl()) != null) {
updateDownloadInfo(downloadInfo);
return;
}
SQLiteDatabase database = getConnection();
try {
String sql = "insert into download_info(task_id, download_length, url, is_success) values (?,?,?,?)";
Object[] bindArgs = { downloadInfo.getTaskId(), downloadInfo.getDownloadLength(),
downloadInfo.getUrl(), downloadInfo.isDownloadSuccess()};
database.execSQL(sql, bindArgs);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} finally {
if (null != database) {
database.close();
}
}
}
public List<DownloadInfo> getDownloadInfosByUrl(String url) {
if(TextUtils.isEmpty(url)) {
return null;
}
SQLiteDatabase database = getConnection();
List<DownloadInfo> list = new ArrayList<DownloadInfo>();
Cursor cursor = null;
try {
String sql = "select * from download_info where url=?";
cursor = database.rawQuery(sql, new String[] { url });
while (cursor.moveToNext()) {
DownloadInfo info = new DownloadInfo();
info.setTaskId(cursor.getInt(1));
info.setDownloadLength(cursor.getLong(2));
info.setDownloadSuccess(cursor.getInt(4));
info.setUrl(cursor.getString(3));
list.add(info);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != database) {
database.close();
}
if (null != cursor) {
cursor.close();
}
}
return list;
}
/**
* taskid url
* @param taskId
* @param url
* @return
*/
public DownloadInfo getDownloadInfoByTaskIdAndUrl(int taskId, String url) {
if(TextUtils.isEmpty(url)) {
return null;
}
SQLiteDatabase database = getConnection();
DownloadInfo info = null;
Cursor cursor = null;
try {
String sql = "select * from download_info where url=? and task_id=?";
cursor = database.rawQuery(sql, new String[] { url, String.valueOf(taskId) });
if (cursor.moveToNext()) {
info = new DownloadInfo();
info.setTaskId(cursor.getInt(1));
info.setDownloadLength(cursor.getLong(2));
info.setDownloadSuccess(cursor.getInt(4));
info.setUrl(cursor.getString(3));
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} finally {
if (null != database) {
database.close();
}
if (null != cursor) {
cursor.close();
}
}
return info;
}
/**
*
* @param downloadInfo
*/
public void updateDownloadInfo(DownloadInfo downloadInfo) {
if(downloadInfo == null) {
return;
}
SQLiteDatabase database = getConnection();
try {
String sql = "update download_info set download_length=?, is_success=? where task_id=? and url=?";
Object[] bindArgs = { downloadInfo.getDownloadLength(), downloadInfo.isDownloadSuccess(),
downloadInfo.getTaskId(), downloadInfo.getUrl() };
database.execSQL(sql, bindArgs);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} finally {
if (null != database) {
database.close();
}
}
}
}
구체 적 인 인터페이스 와 사용 코드 는 코드 를 붙 이지 않 겠 습 니 다.코드 가 좀 많 습 니 다.필요 한 건 데모 소스 를 다운로드 해 보 세 요.아직 시간 이 많이 걸 리 지 않 았 기 때문에 안에 버그 가 있 을 수 밖 에 없습니다.만약 에 여러분 이 어떤 문 제 를 발견 하면 댓 글 을 남 겨 서 토론 하 는 것 을 환영 합 니 다.감사합니다!
원본 다운로드:AsyncTask 정지점 전송 실현
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Android Activity에서 YouTube 동영상을 전체 화면으로 표시Android 개발이었던 한 가지 과제는 다음과 같습니다. 하나의 활동에 WebView가 있습니다. 그 WebView의 내용은 YouTube 동영상을 임베드한 Iframe입니다. 당연히 WebView 화면의 재생 버...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.