package com.mgw.member.manager; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import android.content.Context; import android.content.Intent; import android.net.Uri; import com.mgw.member.bean.AppInfo; import com.mgw.member.bean.DownloadInfo; import com.mgw.member.http.HttpHelper; import com.mgw.member.http.HttpHelper.HttpResult; import com.mgw.member.uitls.IOUtils; import com.mgw.member.uitls.LogUtils; import com.mgw.member.uitls.UIUtils; /** * 下载html包,并且管理html * @author Administrator * */ public class DownloadManager { public static final int STATE_NONE = 0; /** 等待中 */ public static final int STATE_WAITING = 1; /** 下载中 */ public static final int STATE_DOWNLOADING = 2; /** 暂停 */ public static final int STATE_PAUSED = 3; /** 下载完毕 */ public static final int STATE_DOWNLOADED = 4; /** 下载失败 */ public static final int STATE_ERROR = 5; private static DownloadManager instance; private DownloadManager() { } /** 用于记录下载信息,如果是正式项目,需要持久化保存 */ private Map<Long, DownloadInfo> mDownloadMap = new ConcurrentHashMap<Long, DownloadInfo>(); /** 用于记录观察者,当信息发送了改变,需要通知他们 */ private List<DownloadObserver> mObservers = new ArrayList<DownloadObserver>(); /** 用于记录所有下载的任务,方便在取消下载时,通过id能找到该任务进行删除 */ private Map<Long, DownloadTask> mTaskMap = new ConcurrentHashMap<Long, DownloadTask>(); public static synchronized DownloadManager getInstance() { if (instance == null) { instance = new DownloadManager(); } return instance; } /** 注册观察者 */ public void registerObserver(DownloadObserver observer) { synchronized (mObservers) { if (!mObservers.contains(observer)) { mObservers.add(observer); } } } /** 反注册观察者 */ public void unRegisterObserver(DownloadObserver observer) { synchronized (mObservers) { if (mObservers.contains(observer)) { mObservers.remove(observer); } } } /** 当下载状态发送改变的时候回调 */ public void notifyDownloadStateChanged(DownloadInfo info) { synchronized (mObservers) { for (DownloadObserver observer : mObservers) { observer.onDownloadStateChanged(info); } } } /** 当下载进度发送改变的时候回调 */ public void notifyDownloadProgressed(DownloadInfo info) { synchronized (mObservers) { for (DownloadObserver observer : mObservers) { observer.onDownloadProgressed(info); } } } /** 下载,需要传入一个appInfo对象 */ public synchronized void download(AppInfo appInfo) { // 先判断是否有这个app的下载信息 DownloadInfo info = mDownloadMap.get(appInfo.getId()); if (info == null) {// 如果没有,则根据appInfo创建一个新的下载信息 info = DownloadInfo.clone(appInfo); mDownloadMap.put(appInfo.getId(), info); } // 判断状态是否为STATE_NONE、STATE_PAUSED、STATE_ERROR。只有这3种状态才能进行下载,其他状态不予处理 if (info.getDownloadState() == STATE_NONE || info.getDownloadState() == STATE_PAUSED || info.getDownloadState() == STATE_ERROR) { // 下载之前,把状态设置为STATE_WAITING,因为此时并没有产开始下载,只是把任务放入了线程池中,当任务真正开始执行时,才会改为STATE_DOWNLOADING info.setDownloadState(STATE_WAITING); notifyDownloadStateChanged(info);// 每次状态发生改变,都需要回调该方法通知所有观察者 DownloadTask task = new DownloadTask(info);// 创建一个下载任务,放入线程池 mTaskMap.put(info.getId(), task); ThreadManager.getDownloadPool().execute(task); } } /** 暂停下载 */ public synchronized void pause(AppInfo appInfo) { stopDownload(appInfo); DownloadInfo info = mDownloadMap.get(appInfo.getId());// 找出下载信息 if (info != null) {// 修改下载状态 info.setDownloadState(STATE_PAUSED); notifyDownloadStateChanged(info); } } /** 取消下载,逻辑和暂停类似,只是需要删除已下载的文件 */ public synchronized void cancel(AppInfo appInfo) { stopDownload(appInfo); DownloadInfo info = mDownloadMap.get(appInfo.getId());// 找出下载信息 if (info != null) {// 修改下载状态并删除文件 info.setDownloadState(STATE_NONE); notifyDownloadStateChanged(info); info.setCurrentSize(0); File file = new File(info.getPath()); file.delete(); } } /** 安装应用 */ public synchronized void install(AppInfo appInfo) { stopDownload(appInfo); DownloadInfo info = mDownloadMap.get(appInfo.getId());// 找出下载信息 if (info != null) {// 发送安装的意图 Intent installIntent = new Intent(Intent.ACTION_VIEW); installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); installIntent.setDataAndType(Uri.parse("file://" + info.getPath()), "application/vnd.android.package-archive"); UIUtils.getContext().startActivity(installIntent); } notifyDownloadStateChanged(info); } /** 启动应用,启动应用是最后一个 */ public synchronized void open(AppInfo appInfo) { try { Context context = UIUtils.getContext(); // 获取启动Intent Intent intent = context.getPackageManager() .getLaunchIntentForPackage(appInfo.getPackageName()); context.startActivity(intent); } catch (Exception e) { LogUtils.e(e); } } /** 如果该下载任务还处于线程池中,且没有执行,先从线程池中移除 */ private void stopDownload(AppInfo appInfo) { DownloadTask task = mTaskMap.remove(appInfo.getId());// 先从集合中找出下载任务 if (task != null) { ThreadManager.getDownloadPool().cancel(task);// 然后从线程池中移除 } } /** 获取下载信息 */ public synchronized DownloadInfo getDownloadInfo(long id) { return mDownloadMap.get(id); } /** 下载任务 */ public class DownloadTask implements Runnable { private DownloadInfo info; public DownloadTask(DownloadInfo info) { this.info = info; } @Override public void run() { info.setDownloadState(STATE_DOWNLOADING);// 先改变下载状态 notifyDownloadStateChanged(info); File file = new File(info.getPath());// 获取下载文件 HttpResult httpResult = null; InputStream stream = null; if (info.getCurrentSize() == 0 || !file.exists() || file.length() != info.getCurrentSize()) { // 如果文件不存在,或者进度为0,或者进度和文件长度不相符,就需要重新下载 info.setCurrentSize(0); file.delete(); httpResult = HttpHelper.download(HttpHelper.URL + "download?name=" + info.getUrl()); } else { // 文件存在且长度和进度相等,采用断点下载 httpResult = HttpHelper.download(HttpHelper.URL + "download?name=" + info.getUrl() + "&range=" + info.getCurrentSize()); } if (httpResult == null || (stream = httpResult.getInputStream()) == null) { info.setDownloadState(STATE_ERROR);// 没有下载内容返回,修改为错误状态 notifyDownloadStateChanged(info); } else { FileOutputStream fos = null; try { fos = new FileOutputStream(file, true); int count = -1; byte[] buffer = new byte[1024]; while (((count = stream.read(buffer)) != -1) && info.getDownloadState() == STATE_DOWNLOADING) { // 每次读取到数据后,都需要判断是否为下载状态,如果不是,下载需要终止,如果是,则刷新进度 fos.write(buffer, 0, count); fos.flush(); info.setCurrentSize(info.getCurrentSize() + count); notifyDownloadProgressed(info);// 刷新进度 } } catch (Exception e) { LogUtils.e(e);// 出异常后需要修改状态并删除文件 info.setDownloadState(STATE_ERROR); notifyDownloadStateChanged(info); info.setCurrentSize(0); file.delete(); } finally { IOUtils.close(fos); if (httpResult != null) { httpResult.close(); } } // 判断进度是否和app总长度相等 if (info.getCurrentSize() == info.getAppSize()) { info.setDownloadState(STATE_DOWNLOADED); notifyDownloadStateChanged(info); } else if (info.getDownloadState() == STATE_PAUSED) {// 判断状态 notifyDownloadStateChanged(info); } else { info.setDownloadState(STATE_ERROR); notifyDownloadStateChanged(info); info.setCurrentSize(0);// 错误状态需要删除文件 file.delete(); } } mTaskMap.remove(info.getId()); } } public interface DownloadObserver { public void onDownloadStateChanged(DownloadInfo info); public void onDownloadProgressed(DownloadInfo info); } }