增加获取执行中的任务api

增加获取剩余时间的api
修复重构loader导致的m3u8问题
This commit is contained in:
laoyuyu
2020-01-07 21:56:35 +08:00
parent b1a2f232fa
commit 432ae1c145
37 changed files with 495 additions and 128 deletions

View File

@@ -41,6 +41,11 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable,
*/
@Ignore private int failNum = 0;
/**
* 剩余时间单位s
*/
@Ignore private int timeLeft = Integer.MAX_VALUE;
/**
* 扩展字段
*/
@@ -81,6 +86,18 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable,
*/
private long stopTime = 0;
/**
* 获取剩余时间单位s
* 如果是m3u8任务无法获取剩余时间m2u8任务如果需要获取剩余时间请设置文件长度{@link #setFileSize(long)}
*/
public int getTimeLeft() {
return timeLeft;
}
public void setTimeLeft(int timeLeft) {
this.timeLeft = timeLeft;
}
public boolean isComplete() {
return isComplete;
}

View File

@@ -156,10 +156,18 @@ public class RecordHelper {
: mTaskRecord.filePath);
ThreadRecord tr = mTaskRecord.threadRecords.get(0);
if (!file.exists()) {
ALog.w(TAG, String.format("文件【%s】不存在任务将重新开始", file.getPath()));
tr.startLocation = 0;
tr.isComplete = false;
tr.endLocation = mWrapper.getEntity().getFileSize();
// 目标文件
File targetFile = new File(mTaskRecord.filePath);
// 处理组合任务其中一个子任务完成的情况
if (tr.isComplete && targetFile.exists() && targetFile.length() == mWrapper.getEntity()
.getFileSize()) {
tr.isComplete = true;
} else {
ALog.w(TAG, String.format("文件【%s】不存在任务将重新开始", file.getPath()));
tr.startLocation = 0;
tr.isComplete = false;
tr.endLocation = mWrapper.getEntity().getFileSize();
}
} else if (file.length() > mWrapper.getEntity().getFileSize()) {
ALog.i(TAG, String.format("文件【%s】错误任务重新开始", file.getPath()));
FileUtil.deleteFile(file);

View File

@@ -46,7 +46,7 @@ public class SubThreadConfig {
public int peerIndex;
// 线程任务类型
public int threadType = TYPE_HTTP;
// 更新间隔,单位:毫秒
// 进度更新间隔,单位:毫秒
public long updateInterval = 1000;
/**

View File

@@ -272,8 +272,8 @@ public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader {
mListener.onComplete();
return;
}
startTimer();
handlerTask(looper);
startTimer();
Looper.loop();
}

View File

@@ -140,6 +140,13 @@ public abstract class BaseListener<ENTITY extends AbsEntity, TASK_WRAPPER extend
mEntity.setPercent((int) (mEntity.getFileSize() <= 0 ? 0
: mEntity.getCurrentProgress() * 100 / mEntity.getFileSize()));
}
if (mEntity.getFileSize() != 0) {
if (speed == 0) {
mEntity.setTimeLeft(Integer.MAX_VALUE);
} else {
mEntity.setTimeLeft((int) ((mEntity.getFileSize() - mEntity.getCurrentProgress()) / speed));
}
}
}
/**

View File

@@ -22,7 +22,6 @@ import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.group.GroupSendParams;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.task.DownloadGroupTask;
import com.arialyy.aria.exception.BaseException;
@@ -113,18 +112,25 @@ public class DownloadGroupListener
}
private void handleSubSpeed(DownloadEntity subEntity, long currentProgress) {
if (currentProgress == 0){
if (currentProgress == 0) {
subEntity.setSpeed(0);
subEntity.setConvertSpeed("0kb/s");
return;
}
long range = currentProgress - subEntity.getCurrentProgress() ;
subEntity.setSpeed(range);
long speed = currentProgress - subEntity.getCurrentProgress();
subEntity.setSpeed(speed);
subEntity.setConvertSpeed(
range <= 0 ? "" : String.format("%s/s", CommonUtil.formatFileSize(range)));
speed <= 0 ? "" : String.format("%s/s", CommonUtil.formatFileSize(speed)));
subEntity.setPercent((int) (subEntity.getFileSize() <= 0 ? 0
: subEntity.getCurrentProgress() * 100 / subEntity.getFileSize()));
subEntity.setCurrentProgress(currentProgress);
if (speed == 0) {
subEntity.setTimeLeft(Integer.MAX_VALUE);
} else {
subEntity.setTimeLeft(
(int) ((subEntity.getFileSize() - subEntity.getCurrentProgress()) / speed));
}
}
/**
@@ -150,8 +156,6 @@ public class DownloadGroupListener
subEntity.setPercent(100);
subEntity.setConvertSpeed("0kb/s");
subEntity.setSpeed(0);
ALog.i(TAG, String.format("任务【%s】完成将删除线程任务记录", mEntity.getKey()));
RecordUtil.delTaskRecord(subEntity.getFilePath(), IRecordHandler.TYPE_DOWNLOAD, false, false);
}
subEntity.update();
}

View File

@@ -41,7 +41,6 @@ import java.util.concurrent.TimeUnit;
*/
public abstract class AbsNormalLoader implements ILoaderVisitor, ILoader {
protected final String TAG = CommonUtil.getClassName(getClass());
;
private IEventListener mListener;
protected AbsTaskWrapper mTaskWrapper;
protected File mTempFile;
@@ -127,7 +126,6 @@ public abstract class AbsNormalLoader implements ILoaderVisitor, ILoader {
isRuning = true;
resetState();
onPostPre();
startTimer();
handleTask(looper);
Looper.loop();
}
@@ -149,7 +147,7 @@ public abstract class AbsNormalLoader implements ILoaderVisitor, ILoader {
/**
* 启动进度获取定时器
*/
private synchronized void startTimer() {
protected synchronized void startTimer() {
if (isBreak()) {
return;
}
@@ -157,25 +155,32 @@ public abstract class AbsNormalLoader implements ILoaderVisitor, ILoader {
mTimer = new ScheduledThreadPoolExecutor(1);
mTimer.scheduleWithFixedDelay(new Runnable() {
@Override public void run() {
if (mStateManager.isComplete()
|| mStateManager.isFail()
|| !isRunning()
|| isBreak()) {
//ALog.d(TAG, "isComplete = " + mStateManager.isComplete()
// + "; isFail = " + mStateManager.isFail()
// + "; isRunning = " + isRunning()
// + "; isBreak = " + isBreak());
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
closeTimer();
onDestroy();
} else if (mStateManager.getCurrentProgress() >= 0) {
mListener.onProgress(mStateManager.getCurrentProgress());
// 线程池中是不抛异常的没有日志很难定位问题需要手动try-catch
try {
if (mStateManager == null) {
ALog.e(TAG, "stateManager is null");
} else if (mStateManager.isComplete()
|| mStateManager.isFail()
|| !isRunning()
|| isBreak()) {
//ALog.d(TAG, "isComplete = " + mStateManager.isComplete()
// + "; isFail = " + mStateManager.isFail()
// + "; isRunning = " + isRunning()
// + "; isBreak = " + isBreak());
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
closeTimer();
onDestroy();
} else if (mStateManager.getCurrentProgress() >= 0) {
mListener.onProgress(mStateManager.getCurrentProgress());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, delayTimer(), mUpdateInterval, TimeUnit.MILLISECONDS);
}
public synchronized void closeTimer() {
private synchronized void closeTimer() {
if (mTimer != null && !mTimer.isShutdown()) {
mTimer.shutdown();
}

View File

@@ -125,6 +125,9 @@ public class NormalLoader extends AbsNormalLoader {
for (IThreadTask threadTask : getTaskList()) {
ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), threadTask);
}
// 启动定时器
startTimer();
}
@Override public long getCurrentProgress() {

View File

@@ -18,6 +18,7 @@ package com.arialyy.aria.core.task;
import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.IUtil;
import com.arialyy.aria.core.inf.TaskSchedulerType;
@@ -71,6 +72,25 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
return mUtil;
}
/**
* 获取剩余时间单位s
* 如果是m3u8任务无法获取剩余时间m2u8任务如果需要获取剩余时间请设置文件长度{@link AbsEntity#setFileSize(long)}
*/
public int getTimeLeft() {
return getTaskWrapper().getEntity().getTimeLeft();
}
/**
* 转换时间
* 时间1 小时,显示分秒,显示样式 00:20
* 时间 ≥1 小时,显示时分秒,显示样式 01:11:12
* 时间 ≥1 天,显示天时分,显示样式 1d 01:11
* 时间 ≥7 天,显示样式 ∞
*/
public String getConvertTimeLeft() {
return CommonUtil.formatTime(getTaskWrapper().getEntity().getTimeLeft());
}
/**
* 添加扩展数据 读取扩展数据{@link #getExpand(String)}
*/
@@ -194,12 +214,16 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
@Override public void start(int type) {
mSchedulerType = type;
mUtil = createUtil();
if (mUtil == null){
ALog.e(TAG, "任务工具创建失败");
return;
}
if (type == TaskSchedulerType.TYPE_START_AND_RESET_STATE) {
if (getUtil().isRunning()) {
ALog.e(TAG, String.format("任务【%s】重启失败", getTaskName()));
return;
}
mUtil = createUtil();
mUtil.start();
ALog.d(TAG, String.format("任务【%s】重启成功", getTaskName()));
return;
@@ -216,6 +240,11 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
}
@Override public void stop(int type) {
mUtil = createUtil();
if (mUtil == null){
ALog.e(TAG, "任务工具创建失败");
return;
}
isStop = true;
mSchedulerType = type;
getUtil().stop();
@@ -226,6 +255,11 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
}
@Override public void cancel(int type) {
mUtil = createUtil();
if (mUtil == null){
ALog.e(TAG, "任务工具创建失败");
return;
}
isCancel = true;
mSchedulerType = type;
getUtil().cancel();

View File

@@ -67,8 +67,8 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
private long mRangeProgress, mLastRangeProgress;
private IThreadTaskAdapter mAdapter;
private ThreadRecord mRecord;
private String mThreadNmae;
private long updateInterval = 1000; // 更新间隔
private String mThreadName;
private long updateInterval; // 更新间隔
private Thread mConfigThread = new Thread(new Runnable() {
@Override public void run() {
@@ -243,8 +243,8 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
}
@Override public String getThreadName() {
return mThreadNmae == null ? CommonUtil.getThreadName(getConfig().url, getThreadId())
: mThreadNmae;
return mThreadName == null ? (mThreadName =
CommonUtil.getThreadName(getConfig().url, getThreadId())) : mThreadName;
}
/**
@@ -287,7 +287,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
bundle.putLong(IThreadStateManager.DATA_THREAD_LOCATION, mRangeProgress);
msg.what = state;
int reqType = getConfig().threadType;
if (reqType == ITaskWrapper.M3U8_VOD || reqType == ITaskWrapper.M3U8_LIVE) {
if (reqType == SubThreadConfig.TYPE_M3U8_PEER) {
sendM3U8Info(state, msg);
}
@@ -299,10 +299,10 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
}
private void sendM3U8Info(int state, Message msg) {
Bundle bundle = msg.getData();
if (state != IThreadStateManager.STATE_UPDATE_PROGRESS) {
msg.obj = this;
}
Bundle bundle = msg.getData();
if ((state == IThreadStateManager.STATE_COMPLETE || state == IThreadStateManager.STATE_FAIL)) {
bundle.putString(ISchedulers.DATA_M3U8_URL, getConfig().url);
bundle.putString(ISchedulers.DATA_M3U8_PEER_PATH, getConfig().tempFile.getPath());
@@ -313,6 +313,8 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
@Override public synchronized void updateCompleteState() {
ALog.i(TAG, String.format("任务【%s】线程__%s__完成", getTaskWrapper().getKey(), mRecord.threadId));
writeConfig(true, mRecord.endLocation);
// 进度发送不是实时的,发送完成任务前,需要更新一次进度
sendRunningState();
updateState(IThreadStateManager.STATE_COMPLETE, null);
}
@@ -334,17 +336,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
}
// 不需要太频繁发送,以减少消息队列的压力
if (System.currentTimeMillis() - mLastSendProgressTime > updateInterval) {
Message msg = mStateHandler.obtainMessage();
Bundle b = msg.getData();
if (b == null) {
b = new Bundle();
msg.setData(b);
}
b.putString(IThreadStateManager.DATA_THREAD_NAME, getThreadName());
b.putLong(IThreadStateManager.DATA_ADD_LEN, mRangeProgress - mLastRangeProgress);
msg.what = IThreadStateManager.STATE_RUNNING;
msg.obj = mRangeProgress;
msg.sendToTarget();
sendRunningState();
mLastRangeProgress = mRangeProgress;
mLastSendProgressTime = System.currentTimeMillis();
}
@@ -358,6 +350,23 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
}
}
/**
* 发送执行中的数据
*/
private void sendRunningState() {
Message msg = mStateHandler.obtainMessage();
Bundle b = msg.getData();
if (b == null) {
b = new Bundle();
msg.setData(b);
}
b.putString(IThreadStateManager.DATA_THREAD_NAME, getThreadName());
b.putLong(IThreadStateManager.DATA_ADD_LEN, mRangeProgress - mLastRangeProgress);
msg.what = IThreadStateManager.STATE_RUNNING;
msg.obj = mRangeProgress;
msg.sendToTarget();
}
@Override
public long getThreadProgress() {
return mRangeProgress;

View File

@@ -48,6 +48,7 @@ import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
@@ -794,6 +795,39 @@ public class CommonUtil {
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "tb";
}
/**
* 转换时间
* 时间1 小时,显示分秒,显示样式 00:20
* 时间 ≥1 小时,显示时分秒,显示样式 01:11:12
* 时间 ≥1 天,显示天时分,显示样式 1d 01:11
* 时间 ≥7 天,显示样式 ∞
*
* @param seconds 单位为s的时间
*/
public static String formatTime(int seconds) {
String standardTime;
if (seconds <= 0) {
standardTime = "00:00";
} else if (seconds < 60) {
standardTime = String.format(Locale.getDefault(), "00:%02d", seconds % 60);
} else if (seconds < 3600) {
standardTime = String.format(Locale.getDefault(), "%02d:%02d", seconds / 60, seconds % 60);
} else if (seconds < 86400) {
standardTime =
String.format(Locale.getDefault(), "%02d:%02d:%02d", seconds / 3600, seconds % 3600 / 60,
seconds % 60);
} else if (seconds < 604800) {
standardTime =
String.format(Locale.getDefault(), "%dd %02d:%02d", seconds / 86400,
seconds % 86400 / 3600,
seconds % 3600);
} else {
standardTime = "";
}
return standardTime;
}
/**
* 通过文件名获取下载配置文件路径
*

View File

@@ -128,6 +128,7 @@ public class ComponentUtil {
break;
}
if (className == null) {
ALog.e(TAG, "不识别的类名:" + className);
return null;
}
T util = null;