/* * Copyright (C) 2013 WhiteCat 白猫 (www.thinkandroid.cn) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ta.util.download; import android.os.Environment; import android.text.TextUtils; import java.io.File; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue; import com.ta.common.TAStringUtils; import com.ta.util.TALogger; import com.ta.util.http.AsyncHttpClient; import com.ta.util.http.AsyncHttpResponseHandler; import com.ta.util.http.FileHttpResponseHandler; public class DownloadManager extends Thread { private static final int MAX_handler_COUNT = 100; private static final int MAX_DOWNLOAD_THREAD_COUNT = 3; private handlerQueue mhandlerQueue; private List<AsyncHttpResponseHandler> mDownloadinghandlers; private List<AsyncHttpResponseHandler> mPausinghandlers; private AsyncHttpClient syncHttpClient; private Boolean isRunning = false; private static final String SDCARD_ROOT = Environment .getExternalStorageDirectory().getAbsolutePath() + "/"; public static final String FILE_ROOT = SDCARD_ROOT + "thinkandroid/"; private DownLoadCallback mDownLoadCallback; private String rootPath = ""; private static DownloadManager downloadManager; public static DownloadManager getDownloadManager() { if (downloadManager == null) { downloadManager = new DownloadManager(FILE_ROOT); } return downloadManager; } public static DownloadManager getDownloadManager(String rootPath) { if (downloadManager == null) { downloadManager = new DownloadManager(rootPath); } return downloadManager; } private DownloadManager() { this(FILE_ROOT); } private DownloadManager(String rootPath) { this.rootPath = rootPath; mhandlerQueue = new handlerQueue(); mDownloadinghandlers = new ArrayList<AsyncHttpResponseHandler>(); mPausinghandlers = new ArrayList<AsyncHttpResponseHandler>(); syncHttpClient = new AsyncHttpClient(); if (!TAStringUtils.isEmpty(rootPath)) { File rootFile = new File(rootPath); if (!rootFile.exists()) { rootFile.mkdir(); } } } public String getRootPath() { if (TAStringUtils.isEmpty(rootPath)) { rootPath = FILE_ROOT; } return rootPath; } public void setDownLoadCallback(DownLoadCallback downLoadCallback) { this.mDownLoadCallback = downLoadCallback; } public void startManage() { isRunning = true; this.start(); if (mDownLoadCallback != null) { mDownLoadCallback.sendStartMessage(); } // checkUncompletehandlers(); } @SuppressWarnings("deprecation") public void close() { isRunning = false; pauseAllHandler(); if (mDownLoadCallback != null) { mDownLoadCallback.sendStopMessage(); } this.stop(); } public boolean isRunning() { return isRunning; } @Override public void run() { super.run(); while (isRunning) { FileHttpResponseHandler handler = (FileHttpResponseHandler) mhandlerQueue .poll(); if (handler != null) { mDownloadinghandlers.add(handler); handler.setInterrupt(false); syncHttpClient.download(handler.getUrl(), handler); } } } public void addHandler(String url) { if (getTotalhandlerCount() >= MAX_handler_COUNT) { if (mDownLoadCallback != null) { mDownLoadCallback.sendFailureMessage(url, "任务列表已满"); } return; } if (TextUtils.isEmpty(url) || hasHandler(url)) { // 任务中存在这个任务,或者任务不满足要求 return; } try { addHandler(newAsyncHttpResponseHandler(url)); } catch (MalformedURLException e) { e.printStackTrace(); } } private void addHandler(AsyncHttpResponseHandler handler) { broadcastAddHandler(((FileHttpResponseHandler) handler).getUrl()); mhandlerQueue.offer(handler); if (!this.isAlive()) { this.startManage(); } } private void broadcastAddHandler(String url) { broadcastAddHandler(url, false); } private void broadcastAddHandler(String url, boolean isInterrupt) { if (mDownLoadCallback != null) { mDownLoadCallback.sendAddMessage(url, false); } } public void reBroadcastAddAllhandler() { FileHttpResponseHandler handler; for (int i = 0; i < mDownloadinghandlers.size(); i++) { handler = (FileHttpResponseHandler) mDownloadinghandlers.get(i); broadcastAddHandler(handler.getUrl(), handler.isInterrupt()); } for (int i = 0; i < mhandlerQueue.size(); i++) { handler = (FileHttpResponseHandler) mhandlerQueue.get(i); broadcastAddHandler(handler.getUrl()); } for (int i = 0; i < mPausinghandlers.size(); i++) { handler = (FileHttpResponseHandler) mPausinghandlers.get(i); broadcastAddHandler(handler.getUrl()); } } public boolean hasHandler(String url) { FileHttpResponseHandler handler; for (int i = 0; i < mDownloadinghandlers.size(); i++) { handler = (FileHttpResponseHandler) mDownloadinghandlers.get(i); if (handler.getUrl().equals(url)) { return true; } } for (int i = 0; i < mhandlerQueue.size(); i++) { handler = (FileHttpResponseHandler) mhandlerQueue.get(i); if (handler.getUrl().equals(url)) { return true; } } return false; } public FileHttpResponseHandler getHandler(String url) { FileHttpResponseHandler handler = null; for (int i = 0; i < mDownloadinghandlers.size(); i++) { handler = (FileHttpResponseHandler) mDownloadinghandlers.get(i); } for (int i = 0; i < mhandlerQueue.size(); i++) { handler = (FileHttpResponseHandler) mhandlerQueue.get(i); } return handler; } public AsyncHttpResponseHandler gethandler(int position) { if (position >= mDownloadinghandlers.size()) { return mhandlerQueue.get(position - mDownloadinghandlers.size()); } else { return mDownloadinghandlers.get(position); } } public int getQueuehandlerCount() { return mhandlerQueue.size(); } public int getDownloadinghandlerCount() { return mDownloadinghandlers.size(); } public int getPausinghandlerCount() { return mPausinghandlers.size(); } public int getTotalhandlerCount() { return getQueuehandlerCount() + getDownloadinghandlerCount() + getPausinghandlerCount(); } public void checkUncompletehandlers() { List<String> urlList = DownLoadConfigUtil.getURLArray(); if (urlList.size() >= 0) { for (int i = 0; i < urlList.size(); i++) { addHandler(urlList.get(i)); } } } public synchronized void pauseHandler(String url) { FileHttpResponseHandler handler; for (int i = 0; i < mDownloadinghandlers.size(); i++) { handler = (FileHttpResponseHandler) mDownloadinghandlers.get(i); if (handler != null && handler.getUrl().equals(url)) { pausehandler(handler); } } } public synchronized void pauseAllHandler() { AsyncHttpResponseHandler handler; for (int i = 0; i < mhandlerQueue.size(); i++) { handler = mhandlerQueue.get(i); mhandlerQueue.remove(handler); mPausinghandlers.add(handler); } for (int i = 0; i < mDownloadinghandlers.size(); i++) { handler = mDownloadinghandlers.get(i); if (handler != null) { pausehandler(handler); } } } public synchronized void deleteHandler(String url) { FileHttpResponseHandler handler; for (int i = 0; i < mDownloadinghandlers.size(); i++) { handler = (FileHttpResponseHandler) mDownloadinghandlers.get(i); if (handler != null && handler.getUrl().equals(url)) { File file = handler.getFile(); if (file.exists()) file.delete(); File tempFile = handler.getTempFile(); if (tempFile.exists()) { tempFile.delete(); } handler.setInterrupt(true); completehandler(handler); return; } } for (int i = 0; i < mhandlerQueue.size(); i++) { handler = (FileHttpResponseHandler) mhandlerQueue.get(i); if (handler != null && handler.getUrl().equals(url)) { mhandlerQueue.remove(handler); } } for (int i = 0; i < mPausinghandlers.size(); i++) { handler = (FileHttpResponseHandler) mPausinghandlers.get(i); if (handler != null && handler.getUrl().equals(url)) { mPausinghandlers.remove(handler); } } } public synchronized void continueHandler(String url) { FileHttpResponseHandler handler; for (int i = 0; i < mPausinghandlers.size(); i++) { handler = (FileHttpResponseHandler) mPausinghandlers.get(i); if (handler != null && handler.getUrl().equals(url)) { continuehandler(handler); } } } public synchronized void pausehandler(AsyncHttpResponseHandler handler) { FileHttpResponseHandler fileHttpResponseHandler = (FileHttpResponseHandler) handler; if (handler != null) { fileHttpResponseHandler.setInterrupt(true); // move to pausing list String url = fileHttpResponseHandler.getUrl(); try { mDownloadinghandlers.remove(handler); handler = newAsyncHttpResponseHandler(url); mPausinghandlers.add(handler); } catch (MalformedURLException e) { e.printStackTrace(); } } } public synchronized void continuehandler(AsyncHttpResponseHandler handler) { if (handler != null) { mPausinghandlers.remove(handler); mhandlerQueue.offer(handler); } } public synchronized void completehandler(AsyncHttpResponseHandler handler) { if (mDownloadinghandlers.contains(handler)) { DownLoadConfigUtil.clearURL(mDownloadinghandlers.indexOf(handler)); mDownloadinghandlers.remove(handler); if (mDownLoadCallback != null) { mDownLoadCallback .sendFinishMessage(((FileHttpResponseHandler) handler) .getUrl()); } } } private AsyncHttpResponseHandler newAsyncHttpResponseHandler(String url) throws MalformedURLException { FileHttpResponseHandler handler = new FileHttpResponseHandler(url, rootPath, TAStringUtils.getFileNameFromUrl(url)) { @Override public void onProgress(long totalSize, long currentSize, long speed) { // TODO Auto-generated method stub super.onProgress(totalSize, currentSize, speed); if (mDownLoadCallback != null) { mDownLoadCallback.sendLoadMessage(this.getUrl(), totalSize, currentSize, speed); } } @Override public void onSuccess(String content) { // TODO Auto-generated method stub if (mDownLoadCallback != null) { mDownLoadCallback.sendSuccessMessage(this.getUrl()); } } public void onFinish() { completehandler(this); } public void onStart() { DownLoadConfigUtil.storeURL(mDownloadinghandlers.indexOf(this), getUrl()); } @Override public void onFailure(Throwable error) { // TODO Auto-generated method stub TALogger.d(DownloadManager.this, "Throwable"); if (error != null) { if (mDownLoadCallback != null) { mDownLoadCallback.sendFailureMessage(this.getUrl(), error.getMessage()); } } // completehandler(this); } }; return handler; } private class handlerQueue { private Queue<AsyncHttpResponseHandler> handlerQueue; public handlerQueue() { handlerQueue = new LinkedList<AsyncHttpResponseHandler>(); } public void offer(AsyncHttpResponseHandler handler) { handlerQueue.offer(handler); } public AsyncHttpResponseHandler poll() { AsyncHttpResponseHandler handler = null; while (mDownloadinghandlers.size() >= MAX_DOWNLOAD_THREAD_COUNT || (handler = handlerQueue.poll()) == null) { try { Thread.sleep(1000); // sleep } catch (InterruptedException e) { e.printStackTrace(); } } return handler; } public AsyncHttpResponseHandler get(int position) { if (position >= size()) { return null; } return ((LinkedList<AsyncHttpResponseHandler>) handlerQueue) .get(position); } public int size() { return handlerQueue.size(); } @SuppressWarnings("unused") public boolean remove(int position) { return handlerQueue.remove(get(position)); } public boolean remove(AsyncHttpResponseHandler handler) { return handlerQueue.remove(handler); } } }