李娟
lijuan 1 year ago
parent d473e02d03
commit 797ece700a

@ -1,4 +1,3 @@
//Copyright (c) 2017. 章钦豪. All rights reserved.
package com.monke.monkeybook.service;
import android.app.NotificationManager;
@ -12,6 +11,7 @@ import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;
import com.hwangjr.rxbus.RxBus;
import com.hwangjr.rxbus.annotation.Subscribe;
import com.hwangjr.rxbus.annotation.Tag;
@ -30,7 +30,9 @@ import com.monke.monkeybook.dao.DbHelper;
import com.monke.monkeybook.dao.DownloadChapterBeanDao;
import com.monke.monkeybook.model.impl.WebBookModelImpl;
import com.monke.monkeybook.view.impl.MainActivity;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
@ -41,18 +43,24 @@ import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
// DownloadService类继承自Service用于处理书籍下载相关的业务逻辑如启动、暂停、取消下载等操作
public class DownloadService extends Service {
// 用于管理通知的显示和取消等操作
private NotificationManager notifyManager;
// 通知的唯一标识符
private int notifiId = 19931118;
// 标记是否开始下载
private Boolean isStartDownload = false;
// 标记是否已经初始化
private Boolean isInit = false;
// 服务创建时调用的方法
@Override
public void onCreate() {
super.onCreate();
}
// 服务销毁时调用的方法用于注销RxBus注册以及设置初始化标记为true
@Override
public void onDestroy() {
super.onDestroy();
@ -60,25 +68,31 @@ public class DownloadService extends Service {
isInit = true;
}
// 服务启动时调用的方法进行一些初始化操作如获取通知管理器、注册RxBus等
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!isInit) {
isInit = true;
// 获取系统的通知服务
notifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// 注册RxBus用于接收相关事件
RxBus.get().register(this);
}
return super.onStartCommand(intent, flags, startId);
}
// 用于绑定服务这里返回null表示不支持绑定
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
// 添加新的下载任务,将新的下载章节数据插入数据库,并根据下载状态决定是否开始下载
private void addNewTask(final List<DownloadChapterBean> newData) {
isStartDownload = true;
Observable.create(new ObservableOnSubscribe<Boolean>() {
// 在这个方法中执行将下载章节数据插入数据库的操作
@Override
public void subscribe(ObservableEmitter<Boolean> e) throws Exception {
DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().insertOrReplaceInTx(newData);
@ -86,9 +100,12 @@ public class DownloadService extends Service {
e.onComplete();
}
})
// 指定在主线程观察结果
.observeOn(AndroidSchedulers.mainThread())
// 指定在IO线程执行插入数据库操作
.subscribeOn(Schedulers.io())
.subscribe(new SimpleObserver<Boolean>() {
// 插入成功后如果当前没有正在下载则调用toDownload方法开始下载
@Override
public void onNext(Boolean value) {
if (!isDownloading) {
@ -103,30 +120,38 @@ public class DownloadService extends Service {
});
}
// 标记是否正在下载
private Boolean isDownloading = false;
// 下载失败时的重试次数
public static final int reTryTimes = 1;
// 开始下载的主要逻辑方法,查找待下载的章节并进行下载操作
private void toDownload() {
isDownloading = true;
if (isStartDownload) {
Observable.create(new ObservableOnSubscribe<DownloadChapterBean>() {
@Override
public void subscribe(ObservableEmitter<DownloadChapterBean> e) throws Exception {
// 获取书架上的书籍列表,按最后更新日期降序排列
List<BookShelfBean> bookShelfBeanList = DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().queryBuilder().orderDesc(BookShelfBeanDao.Properties.FinalDate).list();
if (bookShelfBeanList != null && bookShelfBeanList.size() > 0) {
if (bookShelfBeanList!= null && bookShelfBeanList.size() > 0) {
for (BookShelfBean bookItem : bookShelfBeanList) {
// 排除本地标签的书籍(可能表示已经下载好的本地书籍)
if (!bookItem.getTag().equals(BookShelfBean.LOCAL_TAG)) {
// 查询该书籍下待下载的章节列表,按章节索引升序排列,取第一个章节(即下一个要下载的章节)
List<DownloadChapterBean> downloadChapterList = DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().queryBuilder().where(DownloadChapterBeanDao.Properties.NoteUrl.eq(bookItem.getNoteUrl())).orderAsc(DownloadChapterBeanDao.Properties.DurChapterIndex).limit(1).list();
if (downloadChapterList != null && downloadChapterList.size() > 0) {
if (downloadChapterList!= null && downloadChapterList.size() > 0) {
e.onNext(downloadChapterList.get(0));
e.onComplete();
return;
}
}
}
// 如果没有待下载章节,删除所有下载章节记录
DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().deleteAll();
e.onNext(new DownloadChapterBean());
} else {
// 如果书架列表为空,同样删除所有下载章节记录
DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().deleteAll();
e.onNext(new DownloadChapterBean());
}
@ -138,12 +163,14 @@ public class DownloadService extends Service {
.subscribe(new SimpleObserver<DownloadChapterBean>() {
@Override
public void onNext(DownloadChapterBean value) {
if (value.getNoteUrl() != null && value.getNoteUrl().length() > 0) {
if (value.getNoteUrl()!= null && value.getNoteUrl().length() > 0) {
// 如果章节有有效的URL开始下载该章节
downloading(value, 0);
} else {
Observable.create(new ObservableOnSubscribe<Object>() {
@Override
public void subscribe(ObservableEmitter<Object> e) throws Exception {
// 如果章节URL为空删除所有下载章节记录
DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().deleteAll();
e.onNext(new Object());
e.onComplete();
@ -178,14 +205,17 @@ public class DownloadService extends Service {
}
}
// 具体下载章节的逻辑方法,处理下载过程中的重试、保存数据等操作
private void downloading(final DownloadChapterBean data, final int durTime) {
if (durTime < reTryTimes && isStartDownload) {
// 发送下载进度相关的事件,并显示通知
isProgress(data);
Observable.create(new ObservableOnSubscribe<BookContentBean>() {
@Override
public void subscribe(ObservableEmitter<BookContentBean> e) throws Exception {
// 查询数据库中是否已经存在该章节的内容
List<BookContentBean> result = DbHelper.getInstance().getmDaoSession().getBookContentBeanDao().queryBuilder().where(BookContentBeanDao.Properties.DurChapterUrl.eq(data.getDurChapterUrl())).list();
if (result != null && result.size() > 0) {
if (result!= null && result.size() > 0) {
e.onNext(result.get(0));
} else {
e.onNext(new BookContentBean());
@ -196,6 +226,7 @@ public class DownloadService extends Service {
@Override
public ObservableSource<BookContentBean> apply(final BookContentBean bookContentBean) throws Exception {
if (bookContentBean.getDurChapterUrl() == null || bookContentBean.getDurChapterUrl().length() <= 0) {
// 如果章节内容不存在通过WebBookModelImpl获取章节内容然后进行相关数据库操作插入内容、更新章节列表等
return WebBookModelImpl.getInstance().getBookContent(data.getDurChapterUrl(), data.getDurChapterIndex(), data.getTag()).map(new Function<BookContentBean, BookContentBean>() {
@Override
public BookContentBean apply(BookContentBean bookContentBean) throws Exception {
@ -208,6 +239,7 @@ public class DownloadService extends Service {
}
});
} else {
// 如果章节内容已经存在,直接删除下载章节记录并返回该章节内容
return Observable.create(new ObservableOnSubscribe<BookContentBean>() {
@Override
public void subscribe(ObservableEmitter<BookContentBean> e) throws Exception {
@ -224,18 +256,18 @@ public class DownloadService extends Service {
.subscribe(new SimpleObserver<BookContentBean>() {
@Override
public void onNext(BookContentBean value) {
if(isStartDownload){
if (isStartDownload) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if(isStartDownload){
if (isStartDownload) {
toDownload();
}else{
} else {
isPause();
}
}
},800);
}else{
}, 800);
} else {
isPause();
}
}
@ -252,6 +284,7 @@ public class DownloadService extends Service {
Observable.create(new ObservableOnSubscribe<Boolean>() {
@Override
public void subscribe(ObservableEmitter<Boolean> e) throws Exception {
// 如果重试次数超过限制或者下载失败,删除该下载章节记录
DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().delete(data);
e.onNext(true);
e.onComplete();
@ -262,18 +295,18 @@ public class DownloadService extends Service {
.subscribe(new SimpleObserver<Boolean>() {
@Override
public void onNext(Boolean value) {
if(isStartDownload){
if (isStartDownload) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if(isStartDownload){
if (isStartDownload) {
toDownload();
}else{
} else {
isPause();
}
}
},800);
}else{
}, 800);
} else {
isPause();
}
}
@ -281,7 +314,7 @@ public class DownloadService extends Service {
@Override
public void onError(Throwable e) {
e.printStackTrace();
if(!isStartDownload)
if (!isStartDownload)
isPause();
}
});
@ -290,16 +323,19 @@ public class DownloadService extends Service {
}
}
// 对外提供的启动下载的方法设置下载开始标记并调用toDownload方法
public void startDownload() {
isStartDownload = true;
toDownload();
}
// 对外提供的暂停下载的方法,设置下载暂停标记并取消所有通知
public void pauseDownload() {
isStartDownload = false;
notifyManager.cancelAll();
}
// 对外提供的取消下载的方法,先删除所有下载章节记录,然后暂停下载
public void cancelDownload() {
Observable.create(new ObservableOnSubscribe<Object>() {
@Override
@ -334,17 +370,18 @@ public class DownloadService extends Service {
});
}
// 处理下载暂停相关逻辑判断是否还有待下载章节根据情况发送相应的RxBus事件
private void isPause() {
isDownloading = false;
Observable.create(new ObservableOnSubscribe<DownloadChapterBean>() {
@Override
public void subscribe(ObservableEmitter<DownloadChapterBean> e) throws Exception {
List<BookShelfBean> bookShelfBeanList = DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().queryBuilder().orderDesc(BookShelfBeanDao.Properties.FinalDate).list();
if (bookShelfBeanList != null && bookShelfBeanList.size() > 0) {
if (bookShelfBeanList!= null && bookShelfBeanList.size() > 0) {
for (BookShelfBean bookItem : bookShelfBeanList) {
if (!bookItem.getTag().equals(BookShelfBean.LOCAL_TAG)) {
List<DownloadChapterBean> downloadChapterList = DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().queryBuilder().where(DownloadChapterBeanDao.Properties.NoteUrl.eq(bookItem.getNoteUrl())).orderAsc(DownloadChapterBeanDao.Properties.DurChapterIndex).limit(1).list();
if (downloadChapterList != null && downloadChapterList.size() > 0) {
if (downloadChapterList!= null && downloadChapterList.size() > 0) {
e.onNext(downloadChapterList.get(0));
e.onComplete();
return;
@ -364,9 +401,11 @@ public class DownloadService extends Service {
.subscribe(new SimpleObserver<DownloadChapterBean>() {
@Override
public void onNext(DownloadChapterBean value) {
if (value.getNoteUrl() != null && value.getNoteUrl().length() > 0){
if (value.getNoteUrl()!= null && value.getNoteUrl().length() > 0) {
// 如果还有待下载章节,发送暂停下载的监听事件
RxBus.get().post(RxBusTag.PAUSE_DOWNLOAD_LISTENER, new Object());
}else{
} else {
// 如果没有待下载章节,发送下载完成的监听事件
RxBus.get().post(RxBusTag.FINISH_DOWNLOAD_LISTENER, new Object());
}
}
@ -377,27 +416,43 @@ public class DownloadService extends Service {
}
});
}
// 方法作用处理下载进度相关操作发送下载进度相关信息到RxBus并创建和发送通知展示下载进度情况
// 参数downloadChapterBean表示下载章节相关的数据对象包含了如书籍名称、当前章节名称等信息
private void isProgress(DownloadChapterBean downloadChapterBean) {
// 通过RxBus发送下载进度监听器相关的事件传递下载章节数据对象以便其他地方能接收到并处理进度信息
RxBus.get().post(RxBusTag.PROGRESS_DOWNLOAD_LISTENER, downloadChapterBean);
// 创建一个意图用于启动主活动MainActivity这里的上下文是当前类所在的上下文环境
Intent mainIntent = new Intent(this, MainActivity.class);
// 根据创建的意图创建一个PendingIntent对象用于后续设置到通知中使得点击通知可以启动对应的活动
// 这里的请求码设置为0并且设置当有相同请求码的PendingIntent更新时更新当前的PendingIntent
PendingIntent mainPendingIntent = PendingIntent.getActivity(this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//创建 Notification.Builder 对象
// 创建 Notification.Builder 对象,用于构建通知
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
// 设置通知的小图标这里使用的是资源文件中定义的ic_launcher图标
.setSmallIcon(R.mipmap.ic_launcher)
//点击通知后自动清除
// 设置点击通知后自动清除该通知
.setAutoCancel(true)
.setContentTitle("正在下载:"+downloadChapterBean.getBookName())
.setContentText(downloadChapterBean.getDurChapterName()==null?" ":downloadChapterBean.getDurChapterName())
// 设置通知的标题,展示正在下载的书籍名称
.setContentTitle("正在下载:" + downloadChapterBean.getBookName())
// 根据当前章节名称是否为空来设置通知的内容文本,如果为空则设置为空格,否则设置为章节名称
.setContentText(downloadChapterBean.getDurChapterName() == null? " " : downloadChapterBean.getDurChapterName())
// 将前面创建的PendingIntent设置到通知中使得点击通知能启动对应的活动
.setContentIntent(mainPendingIntent);
//发送通知
// 使用通知管理器发送通知notifiId应该是预先定义好的通知的唯一标识用于区分不同的通知
notifyManager.notify(notifiId, builder.build());
}
// 方法作用完成下载相关的后续操作发送下载完成的事件到RxBus取消所有通知并弹出提示告知用户全部离线章节下载完成
private void finishDownload() {
// 通过RxBus发送下载完成监听器相关的事件传递一个空的Object对象作为完成下载的一种通知机制方便其他地方监听并处理完成下载的情况
RxBus.get().post(RxBusTag.FINISH_DOWNLOAD_LISTENER, new Object());
// 取消所有已发送的通知
notifyManager.cancelAll();
// 在主线程中执行以下代码块用于弹出一个短暂显示的Toast提示信息告知用户全部离线章节下载完成
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
@ -406,6 +461,8 @@ public class DownloadService extends Service {
});
}
// 方法作用响应RxBus中PAUSE_DOWNLOAD事件调用pauseDownload方法此处假设pauseDownload方法在别处定义用于暂停下载任务相关操作
// 该方法被标注为订阅RxBus中特定标签的事件并且在主线程中执行
@Subscribe(
thread = EventThread.MAIN_THREAD,
tags = {
@ -416,6 +473,8 @@ public class DownloadService extends Service {
pauseDownload();
}
// 方法作用响应RxBus中START_DOWNLOAD事件调用startDownload方法此处假设startDownload方法在别处定义用于启动下载任务相关操作
// 该方法被标注为订阅RxBus中特定标签的事件并且在主线程中执行
@Subscribe(
thread = EventThread.MAIN_THREAD,
tags = {
@ -426,6 +485,8 @@ public class DownloadService extends Service {
startDownload();
}
// 方法作用响应RxBus中CANCEL_DOWNLOAD事件调用cancelDownload方法此处假设cancelDownload方法在别处定义用于取消下载任务相关操作
// 该方法被标注为订阅RxBus中特定标签的事件并且在主线程中执行
@Subscribe(
thread = EventThread.MAIN_THREAD,
tags = {
@ -436,6 +497,9 @@ public class DownloadService extends Service {
cancelDownload();
}
// 方法作用响应RxBus中ADD_DOWNLOAD_TASK事件调用addNewTask方法此处假设addNewTask方法在别处定义用于添加新的下载任务相关操作
// 该方法接收一个DownloadChapterListBean类型的对象newData从其中获取具体的数据假设是下载任务列表数据传递给addNewTask方法进行处理
// 该方法被标注为订阅RxBus中特定标签的事件并且在主线程中执行
@Subscribe(
thread = EventThread.MAIN_THREAD,
tags = {
@ -444,5 +508,4 @@ public class DownloadService extends Service {
)
public void addTask(DownloadChapterListBean newData) {
addNewTask(newData.getData());
}
}
}
Loading…
Cancel
Save