package com.novel.read.service; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.text.TextUtils; import androidx.annotation.Nullable; import com.mango.mangolib.event.EventManager; import com.novel.read.R; import com.novel.read.base.BaseService; import com.novel.read.event.DeleteResponseEvent; import com.novel.read.event.DeleteTaskEvent; import com.novel.read.event.RxBus; import com.novel.read.http.AccountManager; import com.novel.read.model.db.BookChapterBean; import com.novel.read.model.db.DownloadTaskBean; import com.novel.read.model.db.dbManage.BookManager; import com.novel.read.model.db.dbManage.BookRepository; import com.novel.read.utlis.LocalManageUtil; import com.novel.read.utlis.LogUtils; import com.novel.read.utlis.NetworkUtils; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; /** * Created by newbiechen on 17-5-10. */ public class DownloadService extends BaseService { private static final String TAG = "DownloadService"; //加载状态 private static final int LOAD_ERROR = -1; private static final int LOAD_NORMAL = 0; private static final int LOAD_PAUSE = 1; private static final int LOAD_DELETE = 2; //正在加载时候,用户删除收藏书籍的情况。 //下载状态 public static final int STATUS_CONTINUE = DownloadTaskBean.STATUS_LOADING; public static final int STATUS_PAUSE = DownloadTaskBean.STATUS_PAUSE; //线程池 private final ExecutorService mSingleExecutor = Executors.newSingleThreadExecutor(); //加载队列 private final List mDownloadTaskQueue = Collections.synchronizedList(new ArrayList<>()); //Handler private Handler mHandler; //包含所有的DownloadTask private List mDownloadTaskList; private OnDownloadListener mDownloadListener; private boolean isBusy = false; private boolean isCancel = false; @Override protected void attachBaseContext(Context base) { super.attachBaseContext(LocalManageUtil.setLocal(base)); } @Override public void onCreate() { super.onCreate(); mHandler = new Handler(getMainLooper()); //从数据库中获取所有的任务 mDownloadTaskList = BookRepository .getInstance() .getDownloadTaskList(); } @Nullable @Override public IBinder onBind(Intent intent) { return new TaskBuilder(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { //接受创建的DownloadTask Disposable disposable = RxBus.getInstance() .toObservable(DownloadTaskBean.class) .observeOn(AndroidSchedulers.mainThread()) .subscribe( (event) -> { //判断任务是否为轮询标志 //判断任务是否存在,并修改任务 if (TextUtils.isEmpty(event.getBookId()) || !checkAndAlterDownloadTask(event)) { addToExecutor(event); } } ); addDisposable(disposable); //是否删除数据的问题 Disposable deleteDisp = RxBus.getInstance() .toObservable(DeleteTaskEvent.class) .observeOn(AndroidSchedulers.mainThread()) .subscribe( (event) -> { //判断是否该数据存在加载列表中 boolean isDelete = true; for (DownloadTaskBean bean : mDownloadTaskQueue) { if (bean.getBookId().equals(event.getCollBook().getId())) { isDelete = false; break; } } //如果不存在则删除List中的task if (isDelete) { // Iterator taskIt = mDownloadTaskList.iterator(); while (taskIt.hasNext()) { DownloadTaskBean task = taskIt.next(); if (task.getBookId().equals(event.getCollBook().getId())) { taskIt.remove(); } } } //返回状态 RxBus.getInstance().post(new DeleteResponseEvent(isDelete, event.getCollBook())); } ); addDisposable(deleteDisp); return super.onStartCommand(intent, flags, startId); } /** * 1. 查看是否任务已存在 * 2. 修改DownloadTask的 taskName 和 list * * @return */ private boolean checkAndAlterDownloadTask(DownloadTaskBean newTask) { boolean isExist = false; for (DownloadTaskBean downloadTask : mDownloadTaskList) { //如果不相同则不往下执行,往下执行都是存在相同的情况 if (!downloadTask.getTaskName().equals(newTask.getTaskName())) continue; if (downloadTask.getStatus() == DownloadTaskBean.STATUS_FINISH) { //判断是否newTask是已完成 if (downloadTask.getLastChapter() == newTask.getLastChapter()) { isExist = true; //发送回去已缓存 postMessage(getString(R.string.cached)); } //判断,是否已完成的章节的起始点比新Task大,如果更大则表示新Task中的该章节已被加载,所以需要剪切 else if (downloadTask.getLastChapter() > (newTask.getLastChapter() - newTask.getBookChapterList().size())) { if (downloadTask.getLastChapter() > newTask.getLastChapter()) { isExist = true; //发送回去已缓存 postMessage(getString(R.string.cached)); } else { //删除掉已经完成的章节 List remainChapterBeans = newTask.getBookChapterList().subList(downloadTask.getLastChapter(), newTask.getLastChapter()); String taskName = newTask.getTaskName() + getString(R.string.download_chapter_scope, downloadTask.getLastChapter(), newTask.getLastChapter()); //重置任务 newTask.setBookChapters(remainChapterBeans); newTask.setTaskName(taskName); //发送添加到任务的提示 postMessage(getString(R.string.cache_success)); } } } //表示该任务已经在 下载、等待、暂停、网络错误中 else { isExist = true; //发送回去:已经在加载队列中。 postMessage(getString(R.string.task_exist)); } } //重置名字 if (!isExist) { String taskName = newTask.getTaskName() + getString(R.string.download_chapter_scope, 1, newTask.getLastChapter()); newTask.setTaskName(taskName); postMessage(getString(R.string.cache_success)); } return isExist; } private void addToExecutor(DownloadTaskBean taskEvent) { //判断是否为轮询请求 if (!TextUtils.isEmpty(taskEvent.getBookId())) { if (!mDownloadTaskList.contains(taskEvent)) { //加入总列表中,表示创建,修改CollBean的状态。 mDownloadTaskList.add(taskEvent); } // 添加到下载队列 mDownloadTaskQueue.add(taskEvent); } // 从队列顺序取出第一条下载 if (mDownloadTaskQueue.size() > 0 && !isBusy) { isBusy = true; executeTask(mDownloadTaskQueue.get(0)); } } private void executeTask(DownloadTaskBean taskEvent) { Runnable runnable = () -> { taskEvent.setStatus(DownloadTaskBean.STATUS_LOADING); int result = LOAD_NORMAL; List bookChapterBeans = taskEvent.getBookChapters(); //调用for循环,下载数据 //todo // for (int i=taskEvent.getCurrentChapter(); i { //TODO:这里文件的名字用的是BookChapter的title,而不是chapter的title。 //原因是Chapter的title可能重复,但是BookChapter的title不会重复 //BookChapter的title = 卷名 + 章节名 chapter 的 title 就是章节名。。 BookRepository.getInstance().saveChapterInfo(folderName, bean.getTitle(), chapterInfo.getBody()); }, e -> { //当前进度加载错误(这里需要判断是什么问题,根据相应的问题做出相应的回答) LogUtils.e(e); //设置加载结果 result[0] = LOAD_ERROR; } ); addDisposable(disposable); return result[0]; } private void postDownloadChange(DownloadTaskBean task, int status, String msg) { if (mDownloadListener != null && msg != null) { int position = mDownloadTaskList.indexOf(task); //通过handler,切换回主线程 mHandler.post(() -> mDownloadListener.onDownloadChange( position, status, msg) ); } } private void postMessage(String msg) { // RxBus.getInstance().post(new DownloadMessage(msg)); EventManager.Companion.getInstance().postEvent(new DownloadMessage(msg)); } private void post(DownloadTaskBean task) { RxBus.getInstance().post(task); } @Override public boolean onUnbind(Intent intent) { mDownloadListener = null; return super.onUnbind(intent); } class TaskBuilder extends Binder implements IDownloadManager { @Override public List getDownloadTaskList() { return Collections.unmodifiableList(mDownloadTaskList); } @Override public void setOnDownloadListener(OnDownloadListener listener) { mDownloadListener = listener; } @Override public void setDownloadStatus(String taskName, int status) { //修改某个Task的状态 switch (status) { //加入缓存队列 case DownloadTaskBean.STATUS_WAIT: for (int i = 0; i < mDownloadTaskList.size(); ++i) { DownloadTaskBean bean = mDownloadTaskList.get(i); if (taskName.equals(bean.getTaskName())) { bean.setStatus(DownloadTaskBean.STATUS_WAIT); mDownloadListener.onDownloadResponse(i, DownloadTaskBean.STATUS_WAIT); addToExecutor(bean); break; } } break; //从缓存队列中删除 case DownloadTaskBean.STATUS_PAUSE: Iterator it = mDownloadTaskQueue.iterator(); while (it.hasNext()) { DownloadTaskBean bean = it.next(); if (bean.getTaskName().equals(taskName)) { if (bean.getStatus() == DownloadTaskBean.STATUS_LOADING && bean.getTaskName().equals(taskName)) { isCancel = true; break; } else { bean.setStatus(DownloadTaskBean.STATUS_PAUSE); mDownloadTaskQueue.remove(bean); int position = mDownloadTaskList.indexOf(bean); mDownloadListener.onDownloadResponse(position, DownloadTaskBean.STATUS_PAUSE); break; } } } break; } } @Override public void setAllDownloadStatus(int status) { //修改所有Task的状态 } //首先判断是否在加载队列中。 //如果在加载队列中首先判断是否正在下载, //然后判断是否在完成队列中。 } @Override public void onDestroy() { super.onDestroy(); } public interface IDownloadManager { List getDownloadTaskList(); void setOnDownloadListener(OnDownloadListener listener); void setDownloadStatus(String taskName, int status); void setAllDownloadStatus(int status); } public interface OnDownloadListener { /** * @param pos : Task在item中的位置 * @param status : Task的状态 * @param msg: 传送的Msg */ void onDownloadChange(int pos, int status, String msg); /** * 回复 */ void onDownloadResponse(int pos, int status); } }